如何在Golang模板中使用动态HTML标签?

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

How to use dynamic HTML tags in golang template?

问题

我正在尝试使用动态标签(默认为h2)来渲染一个标题。

<{{ or .Settings.headlineTag "h2" }}> 
  {{ .Content.headline }}
</ {{ or .Settings.headlineTag "h2" }}>

不幸的是,输出结果被转义了:

<h2>
  Headline
</ h2>

我该如何使其按预期工作?

英文:

I am trying to render a headline with a dynamic tag (fallback should be h2).

<{{ or .Settings.headlineTag "h2" }}> 
  {{ .Content.headline }}
</ {{ or .Settings.headlineTag "h2" }}>

Unfortunately the output is escaped:

<h2>
  Headline
</ h2>

How can I make this work as expected?

答案1

得分: 1

https://pkg.go.dev/html/template#hdr-Typed_Strings:

> 默认情况下,该包假设所有的管道都产生纯文本字符串。它添加了必要的转义管道阶段,以正确且安全地嵌入该纯文本字符串到适当的上下文中。
>
> 当数据值不是纯文本时,您可以通过标记其类型来确保它不会过度转义。
>
> 来自content.go的HTML、JS、URL和其他类型可以携带安全内容,免于转义。

以下是一个创建函数以组合标签并返回template.HTML的示例:

package main

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

func main() {
	data := []struct {
		Tag     string
		Content string
	}{
		{
			Tag:     "h1",
			Content: "How to use dynamic <HTML> tags in golang template?",
		},
		{
			Content: `.Settings.headlineTag "h2"`,
		},
	}

	const tpl = `
{{ range . }}
  {{ tag .Tag "h2" .Content }}
{{ end }}
`

	t, err := template.New("webpage").
		Funcs(template.FuncMap{
			"tag": func(tag, fallback, content string) template.HTML {
				name := tag
				if name == "" {
					name = fallback
				}

				v := fmt.Sprintf("<%s>%s</%s>", name, template.HTMLEscapeString(content), name)
				return template.HTML(v)
			},
		}).
		Parse(tpl)
	if err != nil {
		panic(err)
	}

	err = t.Execute(os.Stdout, data)
	if err != nil {
		panic(err)
	}
}

输出:

<h1>How to use dynamic &lt;HTML&gt; tags in golang template?</h1>

<h2>.Settings.headlineTag &amp;#34;h2&amp;#34;</h2>
英文:

https://pkg.go.dev/html/template#hdr-Typed_Strings:

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

Here is an example that creates a function to compose the tag and return a template.HTML:

package main

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

func main() {
	data := []struct {
		Tag     string
		Content string
	}{
		{
			Tag:     &quot;h1&quot;,
			Content: &quot;How to use dynamic &lt;HTML&gt; tags in golang template?&quot;,
		},
		{
			Content: `.Settings.headlineTag &quot;h2&quot;`,
		},
	}

	const tpl = `
{{ range . }}
  {{ tag .Tag &quot;h2&quot; .Content }}
{{ end }}
`

	t, err := template.New(&quot;webpage&quot;).
		Funcs(template.FuncMap{
			&quot;tag&quot;: func(tag, fallback, content string) template.HTML {
				name := tag
				if name == &quot;&quot; {
					name = fallback
				}

				v := fmt.Sprintf(&quot;&lt;%s&gt;%s&lt;/%s&gt;&quot;, name, template.HTMLEscapeString(content), name)
				return template.HTML(v)
			},
		}).
		Parse(tpl)
	if err != nil {
		panic(err)
	}

	err = t.Execute(os.Stdout, data)
	if err != nil {
		panic(err)
	}
}

Output:

&lt;h1&gt;How to use dynamic &amp;lt;HTML&amp;gt; tags in golang template?&lt;/h1&gt;

&lt;h2&gt;.Settings.headlineTag &amp;#34;h2&amp;#34;&lt;/h2&gt;

huangapple
  • 本文由 发表于 2023年4月5日 18:14:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/75938194.html
匿名

发表评论

匿名网友

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

确定