如何在模板中转义输出?

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

How can I escape the output of a template?

问题

我如何转义由模板生成的HTML片段?就像这个例子中一样:

package main

import (
	"fmt"
	"html/template"
	"os"
)

// 我想要转义一个作为javascript变量存储的html片段。我该如何做到这一点?第二个输出是我想要使用模板生成的输出。

var tmpl = `{{define "main"}}<script>var xx = "{{template "html-snippet" .}}";</script>{{end}}{{define "html-snippet"}}<div>
	<img src="{{.}}">
</div>{{end}}`

func main() {
	t, err := template.New("fo").Parse(tmpl)
	if err != nil {
		fmt.Println(err)
		return
	}
	t.ExecuteTemplate(os.Stdout, "main", "some.jpg")
	fmt.Println("")
	fmt.Println(template.JSEscapeString(`<div>
	<img src="some.jpg">
</div>`))
}

在我的情况下,html/template不会自动转义。通过函数映射使用JSEscapeString也不起作用(或者我不知道如何使用),因为我不能像这样调用它{{jsescape (template "html-snippet" .)}},因为这不是一个字符串。

非常感谢。

英文:

How do I escape an HTML snippet generated by a template? Like in this example:

package main

import (
	&quot;fmt&quot;
	&quot;html/template&quot;
	&quot;os&quot;
)

// I want to escape a html snippet which is then stored as a 
// javascript variable. how can I do that? the second output 
// is the one i would like to generate with a template.

var tmpl = `{{define &quot;main&quot;}}&lt;script&gt;var xx = &quot;{{template &quot;html-snippet&quot; .}}&quot;;&lt;/script&gt;{{end}}{{define &quot;html-snippet&quot;}}&lt;div&gt;
	&lt;img src=&quot;{{.}}&quot;&gt;
&lt;/div&gt;{{end}}`

func main() {
	t, err := template.New(&quot;fo&quot;).Parse(tmpl)
	if err != nil {
		fmt.Println(err)
		return
	}
	t.ExecuteTemplate(os.Stdout, &quot;main&quot;, &quot;some.jpg&quot;)
	fmt.Println(&quot;&quot;)
	fmt.Println(template.JSEscapeString(`&lt;div&gt;
		&lt;img src=&quot;some.jpg&quot;&gt;
	&lt;/div`))
}

https://play.golang.org/p/TBJxYqokkU

html/template does not do it automatically in my case. JSEscapeString through a func map also does not work (or I don’t know how), because I cannot call it like this {{jsescape (template &quot;html-snippet&quot; .)}}, since this is not a string.

Many thanks

答案1

得分: 1

您可以注册一个执行可包含模板并将结果作为字符串返回的函数。然后,该字符串可以插入到其他模板中,自动应用适当的上下文敏感转义:

var tmpl = `{{define "main"}}<script>var xx = {{exect "html-snippet" .}};</script>{{end}}{{define "html-snippet"}}<div>
	<img src="{{.}}">
</div>{{end}}"

var t *template.Template

func exect(name string, data interface{}) string {
	buf := &bytes.Buffer{}
	if err := t.ExecuteTemplate(buf, name, data); err != nil {
		fmt.Println("Error:", err)
	}
	return buf.String()
}

func main() {
	t = template.Must(template.New("fo").Funcs(template.FuncMap{
		"exect": exect,
	}).Parse(tmpl))
	if err := t.ExecuteTemplate(os.Stdout, "main", "some.jpg"); err != nil {
		fmt.Println(err)
	}
}

输出结果(在Go Playground上尝试):

<script>var xx = "<div>
	<img src=\"some.jpg\">
</div>";</script>

或者更好的是:模板引擎允许您注册返回2个值(第二个值必须是错误)的函数,因此我们的exect()函数可以像这样:

func exect(name string, data interface{}) (string, error) {
	buf := &bytes.Buffer{}
	err := t.ExecuteTemplate(buf, name, data)
	return buf.String(), err
}

输出结果相同。在Go Playground上尝试这个版本。

英文:

You may register a function which executes the includable template and returns the result as a string. That string can then be inserted into the other template, proper context-sensitive escaping applied automatically:

var tmpl = `{{define &quot;main&quot;}}&lt;script&gt;var xx = {{exect &quot;html-snippet&quot; .}};&lt;/script&gt;{{end}}{{define &quot;html-snippet&quot;}}&lt;div&gt;
	&lt;img src=&quot;{{.}}&quot;&gt;
&lt;/div&gt;{{end}}`

var t *template.Template

func exect(name string, data interface{}) string {
	buf := &amp;bytes.Buffer{}
	if err := t.ExecuteTemplate(buf, name, data); err != nil {
		fmt.Println(&quot;Error:&quot;, err)
	}
	return buf.String()
}

func main() {
	t = template.Must(template.New(&quot;fo&quot;).Funcs(template.FuncMap{
		&quot;exect&quot;: exect,
	}).Parse(tmpl))
	if err := t.ExecuteTemplate(os.Stdout, &quot;main&quot;, &quot;some.jpg&quot;); err != nil {
		fmt.Println(err)
	}
}

Output (try it on the Go Playground):

&lt;script&gt;var xx = &quot;\u003cdiv\u003e\n\t\u003cimg src=\&quot;some.jpg\&quot;\u003e\n\u003c/div\u003e&quot;;&lt;/script&gt;

Or even better: the template engine allows you to register functions that return 2 values (second of which must be an error), so our exect() function may look like this:

func exect(name string, data interface{}) (string, error) {
	buf := &amp;bytes.Buffer{}
	err := t.ExecuteTemplate(buf, name, data)
	return buf.String(), err
}

Output is the same. Try this one on the Go Playground.

huangapple
  • 本文由 发表于 2016年12月20日 08:18:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/41233066.html
匿名

发表评论

匿名网友

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

确定