【问题标题】:Go template.ExecuteTemplate include htmlGo template.ExecuteTemplate 包含 html
【发布时间】:2013-08-11 19:04:42
【问题描述】:

我已遵循本教程:http://golang.org/doc/articles/wiki/final.go 并根据我的需要/想要对其进行了轻微修改。问题是我想在模板中支持 HTML。我意识到这是一个安全风险,但目前还不是问题。

页面渲染的结果:

<h1>this<strong>is</strong>a test</h1>

让我解释一下代码:

type Page struct {
    Title string
    Body  []byte
}

我想要的 HTML 数据存储在 Page.Body 中。这是[]byte 类型,这意味着我不能(或者我可以?)运行html/template.HTML(Page.Body),因为该函数需要一个字符串。

我有这个预渲染模板:

var (
    templates = template.Must(template.ParseFiles("tmpl/edit.html", "tmpl/view.html"))
)

而实际的ExecuteTemplate 看起来像这样:

err := templates.ExecuteTemplate(w, tmpl+".html", p)

其中 w 是 w http.ResponseWriter,tmpl 是 tmpl string,p 是 p *Page

最后我的'view.html'(模板)如下所示:

<h1>{{.Title}}</h1>
<p>[<a href="/edit/{{.Title}}">edit</a>]</p>
<div>{{printf "%s" .Body}}</div>

我尝试过的事情:

  • {{printf "%s" .Body | html}} 什么都不做
  • 我已经包含了github.com/russross/blackfriday(Markdown 处理器)并运行了p.Body = blackfriday.MarkdownCommon(p.Body),它可以正确地将 Markdown 转换为 HTML,但 HTML 仍然作为实体输出。
  • 编辑:我尝试了以下代码(我不知道为什么格式混乱),它仍然输出完全相同。

    var s template.HTML s = template.HTML(p.Body) p.Body = []byte(s)

非常感谢任何指导。如果我感到困惑,请提问,我可以修改我的问题。

【问题讨论】:

    标签: go go-templates


    【解决方案1】:

    将您的[]bytestring 转换为输入template.HTML(记录在here

    p.Body = template.HTML(s) // where s is a string or []byte
    

    然后,在您的模板中,只需:

    {{.Body}}
    

    它将被打印而不转义。

    编辑

    为了能够在页面正文中包含 HTML,您需要更改 Page 类型声明:

    type Page struct {
        Title string
        Body  template.HTML
    }
    

    然后分配给它。

    【讨论】:

    • 那行不通。我收到以下消息:cannot use "html/template".HTML(p.Body) (type "html/template".HTML) as type []byte in assignment
    • 不要只是复制粘贴并说它不起作用。您显然需要更改 Body 字段的类型,以便能够为其分配 template.HTML 类型的内容。
    • 请在我发表评论后立即查看我昨晚对我的问题所做的编辑。我确实更改了 Body 的类型,但仍然看到完全相同的结果。
    • 我添加了一个名为“noescape”的函数,它将字符串转换为template.HTML,然后在管道中将printf 转换为它。发挥神奇作用。
    • 当我传递字符串时,我花了几天时间对我的模板非常生气,但当我传递 html 字符串时却没有......谢谢!
    【解决方案2】:

    看看template.HTML 类型。它可用于封装已知的 HTML 安全片段(如 Markdown 的输出)。 “html/template”包不会转义这种类型。

    type Page struct {
        Title string
        Body template.HTML
    }
    
    page := &Page{
        Title: "Example",
        Body:  template.HTML(blackfriday.MarkdownCommon([]byte("foo bar")),
    }
    

    我通常编写自己的 func Markdown(text string) html.Template 方法,该方法使用适当的配置调用 blackfriday 并进行一些类型转换。另一种选择可能是在模板解析器中注册一个“html”函数,它允许您通过执行{{html .MySafeStr}} 之类的操作来输出任何值而不会进行任何转义。代码可能如下所示:

    var tmpl = template.Must(template.New("").Funcs(template.FuncMap{
        "html": func(value interface{}) template.HTML {
            return template.HTML(fmt.Sprint(value))
        },
    }).ParseFiles("file1.html", "file2.html"))
    

    【讨论】:

      【解决方案3】:

      我为模板创建了一个自定义函数如下:

      func noescape(str string) template.HTML {
          return template.HTML(str)
      }
      
      var fn = template.FuncMap{
          "noescape": noescape,
      }
      

      然后在你的模板上:

      {{ noescape $x.Body }}
      

      【讨论】:

        【解决方案4】:

        这是一种不需要对现有结构进行任何更改,并且对模板进行极少的附加更改的方法:

        更改这些行:

        var (
            templates = template.Must(template.ParseFiles("tmpl/edit.html", "tmpl/view.html"))
        )
        

        对此(包括一个函数映射,该函数将输出未转义的 HTML):

        var templates = template.Must(template.New("main").Funcs(template.FuncMap{
            "safeHTML": func(b []byte) template.HTML {
                return template.HTML(b)
            },
        }).ParseFiles("tmpl/edit.html", "tmpl/view.html"))
        

        然后只需从这里更改您的模板 HTML:

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

        对此(使用您的新功能):

        <div>{{ .Body | safeHTML }}</div>
        

        容易多了!

        【讨论】:

          【解决方案5】:

          我正在使用 Beego 和 React.js 并努力了几个小时试图让 JSX 解析器运行。结果 html/template 去除了 cmets,尤其是 js doc 块 /** @jsx React.DOM */.

          通过创建一个特殊的方法来将注释键入为 JS 并从模板中调用它来解决它。

          // Create a method in your controller (I'm using Beego)
          func jsxdoc()(out template.JS) {
              return template.JS(`/** @jsx React.DOM */`)
          }
          
          // Add method to your function map available to views
          beego.AddFuncMap("jsxdoc", jsxdoc)
          
          // In template
          <script type="text/jsx">
              {{ jsxdoc }}
              var CommentBox = React.createClass({
                render: function() {
                  return (
                    <div class="commentBox">
                      Hello, world! I am a CommentBox.
                    </div>
                  );
                }
              });
              React.renderComponent(
                <CommentBox />,
                document.getElementById('content')
              );
          </script>
          

          【讨论】:

            【解决方案6】:

            有关将 HTML 传递给模板的说明和更简单的方法,请参阅

            https://groups.google.com/forum/#!topic/golang-nuts/8L4eDkr5Q84

            只需通过 go 创建您的 HTML 字符串并将其传递到您的模板中,例如:

            Sout := ""
            .
            .
            
                Sout += fmt.Sprintf(`<tr><td>%s<td align=center>%.2f<td>%s<td>%s<td>%s<td>%s<td align=center>%d<td align=center>%d
                                <td align=center>%d`, AccountID, amount, remissiondetails, created, begins, ends,
                                freePDFs, freeinformants, freeSDQs)
            
            .
            .
                render(w, "templates/Waivers.html", map[string]interface{}{ "Body":template.HTML(Sout), })
            

            【讨论】:

              【解决方案7】:

              在我的例子中(我用Activity 的列表填充视图struct),我必须将属性Message string 更改为Message template.HTML。然后,在设置属性值时,我可以调用activity.Message = template.HTML("The &lt;b&gt;HTML&lt;/b&gt;")

              【讨论】:

                【解决方案8】:

                为什么不将[]byte 转换为字符串?你可以这样做:

                str := string(page.Body)
                

                【讨论】:

                • 我试过了,问题是 template.ExecuteTemplate 需要一个指向 Page 的指针,这要求它是 []byte 我尝试完全按照您提到的操作并收到以下错误:cannot use string(p.Body) (type string) as type []byte in assignment。同样,将我的结构更改为使用字符串而不是 []byte 在将内容保存到文件时会导致其他问题。
                猜你喜欢
                • 2022-01-27
                • 1970-01-01
                • 2020-11-08
                • 2022-07-12
                • 2017-12-07
                • 2011-03-09
                • 1970-01-01
                • 1970-01-01
                • 2015-05-08
                相关资源
                最近更新 更多