如何转义模板的输出?

How can I escape the output of a template?

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

package main

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

// 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 "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`))
}

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

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

非常感谢

您可以注册一个函数来执行可包含的模板,并且 return 将结果作为 string。然后可以将 string 插入到另一个模板中,自动应用适当的上下文相关转义:

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 = "\u003cdiv\u003e\n\t\u003cimg src=\"some.jpg\"\u003e\n\u003c/div\u003e";</script>

甚至更好:模板引擎允许您注册 return 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.

上试试这个