How to make html templates recognize a string as html in go

huangapple go评论89阅读模式
英文:

How to make html templates recognize a string as html in go

问题

我有一个来自Go文档教程的维基Web应用程序,想要添加一些内容。其中之一是在首页上列出所有维基条目的列表。我有一个HTML模板,看起来像这样:

<h1>这是维基的首页</h1>

<p>这是条目列表:</p>
<div>
	<ul>

		{{printf "%s" .Body}}
		
	</ul>
</div>

这是页面的处理程序:

func frontHandler(w http.ResponseWriter, r *http.Request){
	entries := getEntries()
	p := &Page{Title: "FrontPage", Body:  []byte(entries)}

	renderTemplate(w, "front", p)

}

我已经将条目列表格式化为适用于HTML的ul,它是一个字符串切片,连接成一个字节切片,格式如下:

<li><a href="/view/page1">page1</a></li>
<li><a href="/view/page2">page2</a></li>

等等,所以我想将其呈现为HTML,而不是像现在这样的纯文本。

我尝试将页面的body从字节切片更改为字符串,并且结果相同。我尝试更改如何渲染页面,以采用专门用于首页的不同结构体作为解决方法,但也没有效果。这是我渲染模板的方式:

func renderTemplate(w http.ResponseWriter, tmpl string, p *Page){
	err := templates.ExecuteTemplate(w, tmpl + ".html", p)
	if err != nil{
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

我还尝试了一些在.html文件中显示它的不同方法,而且都没有成功。

非常感谢任何帮助,如果需要更多信息,请告诉我。

英文:

I have a wiki web app from the go docs tutorial and want to add a few things. One of those things is a list of all wiki entries at the front page. I have a html template that looks like this:

&lt;h1&gt;This is the front page of the wiki&lt;/h1&gt;

&lt;p&gt;here is the list of entries:&lt;/p&gt;
&lt;div&gt;
	&lt;ul&gt;

		{{printf &quot;%s&quot; .Body}}
		
	&lt;/ul&gt;
&lt;/div&gt;

And here is the handler of the page

func frontHandler(w http.ResponseWriter, r *http.Request){
	entries := getEntries()
	p := &amp;Page{Title: &quot;FrontPage&quot;, Body:  []byte(entries)}

	renderTemplate(w, &quot;front&quot;, p)

}

I've formatted the list of entries to work as a ul in html, it is a splice of strings joined into one to convert it to a splice of bytes, it is formatted like this:

&lt;li&gt;&lt;a href=&quot;/view/page1&quot;&gt;page1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/view/page2&quot;&gt;page2&lt;/a&gt;&lt;/li&gt;

and so on, so i would like to render it as html instead of plain text like it is now.

I've tried changing how i pass the body of the page from a splice of bytes to a string and it had the same outcome. I tried changing how i render the page to take a different struct made specifically for the front page as a workaround but it also had no effect. Here is how i render the template

func renderTemplate(w http.ResponseWriter, tmpl string, p *Page){
	err := templates.ExecuteTemplate(w, tmpl + &quot;.html&quot;, p)
	if err != nil{
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

I've also tried a few different ways of showing it in the .html file instead of the {{printf &quot;%s&quot; .Body&quot;}} and I've been unsuccessful.

Any help is much appreciated, also let me know if i should provide more info.

答案1

得分: 1

你可以使用Typed strings

根据文档:

默认情况下,该软件包假定所有流水线都会生成纯文本字符串。它会添加必要的转义流水线阶段,以正确且安全地嵌入该纯文本字符串到适当的上下文中。
当数据值不是纯文本时,您可以通过标记其类型来确保它没有过度转义。
来自content.go的HTML、JS、URL和其他类型可以携带安全内容,免于转义。

示例:

base.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div>
      <ul>
        {{range .}}{{.}}{{end}} <!-- 循环遍历pipeline(.) -->
      </ul>
    </div>
  </body>
</html>

func frontHandler(w http.ResponseWriter, r *http.Request) {

	entry := []string{"<li><a href=\"/view/page1\">page1</a></li>", "<li><a href=\"/view/page2\">page2</a></li>"}
	tmpl, err := template.ParseFiles("base.html")
	if err != nil {
		log.Fatal("Unable to parse")
	}

    // template.HTML只接受一个字符串,因此我们循环遍历entry切片,并将切片值存储在`HTML`类型的htmlvalues中
	var htmlvalues []template.HTML 

	for _, n := range entry {
		htmlEncapsulate := template.HTML(n)
		htmlvalues = append(htmlvalues, htmlEncapsulate)
	}
	tmpl.Execute(w, htmlvalues)
英文:

You can use Typed strings

As per documentation:
>By default, this package assumes that all pipelines produce a plain text string. It adds escaping pipeline stages necessary to correctly and safely embed that plain text string in the appropriate context.
When a data value is not plain text, you can make sure it is not over-escaped by marking it with its type.
Types HTML, JS, URL, and others from content.go can carry safe content that is exempted from escaping.

Example:

base.html

&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
  &lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot; /&gt;
    &lt;meta http-equiv=&quot;X-UA-Compatible&quot; content=&quot;IE=edge&quot; /&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot; /&gt;
    &lt;title&gt;Document&lt;/title&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;div&gt;
      &lt;ul&gt;
        {{range .}}{{.}}{{end}} &lt;!-- Loop over the pipeline(.) --&gt;
      &lt;/ul&gt;
    &lt;/div&gt;
  &lt;/body&gt;
&lt;/html&gt;

func frontHandler(w http.ResponseWriter, r *http.Request) {

	entry := []string{&quot;&lt;li&gt;&lt;a href=\&quot;/view/page1\&quot;&gt;page1&lt;/a&gt;&lt;/li&gt;&quot;, &quot;&lt;li&gt;&lt;a href=\&quot;/view/page2\&quot;&gt;page2&lt;/a&gt;&lt;/li&gt;&quot;}
	tmpl, err := template.ParseFiles(&quot;base.html&quot;)
	if err != nil {
		log.Fatal(&quot;Unable to parse&quot;)
	}

    // template.HTML takes only one string, hence we loop over the entry slice 
    //and store the slice values in htmlvalues of `HTML` type
	var htmlvalues []template.HTML 

	for _, n := range entry {
		htmlEncapsulate := template.HTML(n)
		htmlvalues = append(htmlvalues, htmlEncapsulate)
	}
	tmpl.Execute(w, htmlvalues)

huangapple
  • 本文由 发表于 2022年7月29日 21:30:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/73167569.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定