英文:
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:
<h1>This is the front page of the wiki</h1>
<p>here is the list of entries:</p>
<div>
<ul>
{{printf "%s" .Body}}
</ul>
</div>
And here is the handler of the page
func frontHandler(w http.ResponseWriter, r *http.Request){
entries := getEntries()
p := &Page{Title: "FrontPage", Body: []byte(entries)}
renderTemplate(w, "front", 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:
<li><a href="/view/page1">page1</a></li>
<li><a href="/view/page2">page2</a></li>
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 + ".html", 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 "%s" .Body"}}
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
<!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}} <!-- Loop over the 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 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)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论