Go template.ExecuteTemplate include html

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

Go template.ExecuteTemplate include html

问题

我已经按照你给出的链接(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)

其中,whttp.ResponseWritertmplstringp*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)

非常感谢您的指导。如果我表达不清楚,请提问,我可以修改我的问题。

英文:

I have followed this tutorial: http://golang.org/doc/articles/wiki/final.go and have slightly modified it for my needs/wants. The problem is I would like to support HTML in the templates. I realize this is a security risk but it's not a concern at the moment.

The result of a page render:

&lt;h1&gt;this&lt;strong&gt;is&lt;/strong&gt;a test&lt;/h1&gt;

Let me explain a little bit of the code:

type Page struct {
    Title string
    Body  []byte
}

The data I would like to have HTML is stored in Page.Body. This is type []byte which means I can't (or can I?) run html/template.HTML(Page.Body) as that function expects a string.

I have this which pre-renders the templates:

var (
    templates = template.Must(template.ParseFiles(&quot;tmpl/edit.html&quot;, &quot;tmpl/view.html&quot;))
)

And the actual ExecuteTemplate looks like this:

err := templates.ExecuteTemplate(w, tmpl+&quot;.html&quot;, p)

Where w is w http.ResponseWriter, tmpl is tmpl string, and p is p *Page

Finally my &#39;view.html&#39; (template) looks like the following:

&lt;h1&gt;{{.Title}}&lt;/h1&gt;
&lt;p&gt;[&lt;a href=&quot;/edit/{{.Title}}&quot;&gt;edit&lt;/a&gt;]&lt;/p&gt;
&lt;div&gt;{{printf &quot;%s&quot; .Body}}&lt;/div&gt;

Things I have tried:

  • {{printf &quot;%s&quot; .Body | html}} doesn't do anything

  • I have included github.com/russross/blackfriday (Markdown processor) and have run p.Body = blackfriday.MarkdownCommon(p.Body) which correctly converts Markdown to HTML, but the HTML is still output as entities.

  • EDIT: I have attempted the following bit of code (I don't know why the format is messed up) and it still outputs the exact same.

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

Any guidance is greatly appreciated. If I'm being confusing please ask and I can modify my question.

答案1

得分: 78

将你的[]bytestring转换为template.HTML类型(在这里有文档记录)。

p.Body = template.HTML(s) // 其中s是一个字符串或[]byte

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

{{.Body}}

它将被打印而不进行转义。

编辑

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

type Page struct {
    Title string
    Body  template.HTML
}

然后对其进行赋值。

英文:

Convert your []byte or string to type template.HTML (documented here)

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

Then, in your template, just:

{{.Body}}

It will be printed without escaping.

EDIT

In order to be able to include HTML in you page's body you need to change the Page type declaration:

type Page struct {
    Title string
    Body  template.HTML
}

then assign to it.

答案2

得分: 22

请看一下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"))
英文:

Take a look at the template.HTML type. It can be used to encapsulate a known safe fragment of HTML (like the output from Markdown). The "html/template" package will not escape this this type.

type Page struct {
    Title string
    Body template.HTML
}

page := &amp;Page{
    Title: &quot;Example&quot;,
    Body:  template.HTML(blackfriday.MarkdownCommon([]byte(&quot;foo bar&quot;)),
}

I usually write my own func Markdown(text string) html.Template method that calls blackfriday with the appropriate config and does some type conversions. Another alternative might be also to register a "html" func in the template parser, that allows you to output any value without any escaping by doing something like {{html .MySafeStr}}. The code might look like:

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

答案3

得分: 20

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

func noescape(str string) template.HTML {
    return template.HTML(str)
}

var fn = template.FuncMap{
    "noescape": noescape,
}

然后在你的模板中使用:

{{ noescape $x.Body }}
英文:

I created a custom function for the template as follows:

func noescape(str string) template.HTML {
	return template.HTML(str)
}

var fn = template.FuncMap{
	&quot;noescape&quot;: noescape,
}

Then on your template:

{{ noescape $x.Body }}

答案4

得分: 3

这是一种不需要对现有结构进行任何更改,并且对模板只需要进行非常小的增量更改的方法:

将这些行代码进行更改:

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>

非常简单!

英文:

Here's an approach that doesn't require any changes to your existing structs, and a very minimal, additive change to your templates:

Change these lines:

var (
    templates = template.Must(template.ParseFiles(&quot;tmpl/edit.html&quot;, &quot;tmpl/view.html&quot;))
)

to this (include a funcmap with a function that will output un-escaped HTML):

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

And then just change your template HTML from this:

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

to this (use your new function):

&lt;div&gt;{{ .Body | safeHTML }}&lt;/div&gt;

Much easier!

答案5

得分: 1

我正在使用Beego和React.js,并花了几个小时来尝试运行JSX解析器。结果发现html/template会剥离掉注释,特别是js文档块 /** @jsx React.DOM */。

为了解决这个问题,我创建了一个特殊的方法来将注释作为JS代码进行类型转换,并在模板中调用它。

在你的控制器中创建一个方法(我使用的是Beego):

func jsxdoc()(out template.JS) {
    return template.JS(`/** @jsx React.DOM */`)
}

将该方法添加到函数映射中,以便在视图中使用:

beego.AddFuncMap("jsxdoc", jsxdoc)

在模板中:

<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>

希望对你有帮助!

英文:

I'm using Beego and React.js and fought for hours trying to get the JSX parser to run. Turns out html/template strips out comments especially the js doc block /** @jsx React.DOM */.

Got around it by creating a special method to Type the comment as JS and calling it from within the template.

// Create a method in your controller (I&#39;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(&quot;jsxdoc&quot;, jsxdoc)

// In template
&lt;script type=&quot;text/jsx&quot;&gt;
    {{ jsxdoc }}
    var CommentBox = React.createClass({
      render: function() {
        return (
          &lt;div class=&quot;commentBox&quot;&gt;
            Hello, world! I am a CommentBox.
          &lt;/div&gt;
        );
      }
    });
    React.renderComponent(
      &lt;CommentBox /&gt;,
      document.getElementById(&#39;content&#39;)
    );
&lt;/script&gt;

答案6

得分: 0

为了澄清并更简单地将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), })
英文:

For clarification and a much simpler way of passing HTML to template, see

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

Just create your HTML string via go and pass it into your template, e.g.:

Sout := &quot;&quot;
.
.

    Sout += fmt.Sprintf(`&lt;tr&gt;&lt;td&gt;%s&lt;td align=center&gt;%.2f&lt;td&gt;%s&lt;td&gt;%s&lt;td&gt;%s&lt;td&gt;%s&lt;td align=center&gt;%d&lt;td align=center&gt;%d
                    &lt;td align=center&gt;%d`, AccountID, amount, remissiondetails, created, begins, ends,
                    freePDFs, freeinformants, freeSDQs)

.
.
    render(w, &quot;templates/Waivers.html&quot;, map[string]interface{}{ &quot;Body&quot;:template.HTML(Sout), })

答案7

得分: 0

在我的情况下(我正在使用一个视图struct来填充一个Activity列表),我需要将属性Message string更改为Message template.HTML。然后,在设置属性值时,我可以调用activity.Message = template.HTML("The <b>HTML</b>")

英文:

In my case (where I am populating a view struct with a list of Activity), I had to change the property Message string to Message template.HTML. Then, when setting the property value I can call activity.Message = template.HTML(&quot;The &lt;b&gt;HTML&lt;/b&gt;&quot;).

答案8

得分: -1

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

str := string(page.Body)
英文:

Why not convert the []byte to a string? You can do it like this:

str := string(page.Body)

huangapple
  • 本文由 发表于 2013年8月12日 03:04:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/18175630.html
匿名

发表评论

匿名网友

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

确定