在GAE上使用Go的html/template时,如何显示由html/template生成的换行符?

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

Displaying line breaks produced by html/template in Go on GAE

问题

我的应用程序是用Go语言编写的。应用程序的一个页面从HTML文本区域接收用户数据,并将其保存为字符串数据到Google App Engine的数据存储中。然后,在应用程序的另一个页面中,需要以用户在HTML文本区域中输入的格式显示数据,或者至少保留用户在输入数据时按下回车键时的换行符。

我尝试使用<pre>标签来显示用户在文本区域中输入的保留换行符,这个方法效果很好。然而,我发现在使用<pre>标签时,在字符串的开头插入了一个双制表符\t\t,我可以使用JavaScript去掉这个双制表符。

我想保留用户在文本区域中输入的换行符的方法是使用JavaScript的replace函数将所有的\r\n\n\r替换为<br>,但是这个方法没有成功。似乎Go语言没有将换行符输出到HTML源代码中。出于安全原因,我正在使用"html/template",但我没有预料到它会完全删除其输出中的\r\n字符。对于字符串开头的奇怪双制表符\t\t,有什么建议吗?

英文:

My application is written in Go. A page of the application receives user data from an HTML text area which is saved to Google App Engine datastore as string data. Then, on another page of the application, it requires to display the data in the format that the user typed into the HTML text area or at least preserve the line breaks as the user hit enter key while typing the data into the HTML text field.

I tried to use <pre> tag to display the preserved line breaks that user typed into the text field which worked fine. However, I found that there is a double tab

> \t\t

inserted at the beginning of the string when using the <pre> tag which I could remove the double tab by using Javascript.

My idea to keep the line breaks that users type into the text field is to use javascript replace function to replace all \r\n, \n and \rto <br>, however, it didn't work out. It seems like Go doesn't output the line breaks into the html source code. I am using "html/template" for safety reason but I didn't expect it to remove the \r\n characters from its output entirely. And is there any suggestion on the strange double tab \t\t at the beginning to the string?

答案1

得分: 4

在Go语言中,可以将换行符转换为<br>,而不是在JavaScript中进行转换。以下是相应的Go代码:

package main

import (
	"html/template"
	"log"
	"os"
	"strings"
)

func main() {
	const tpl = `
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>{{.Title}}</title>
	</head>
	<body>
		<div>{{nl2br .Text}}</div>
	</body>
</html>`

	check := func(err error) {
		if err != nil {
			log.Fatal(err)
		}
	}

	funcs := template.FuncMap{
		"nl2br": func(text string) template.HTML {
			return template.HTML(strings.Replace(template.HTMLEscapeString(text), "\n", "<br>", -1))
		},
	}

	t, err := template.New("webpage").Funcs(funcs).Parse(tpl)
	check(err)

	data := struct {
		Title string
		Text  string
	}{
		Title: "My page",
		Text:  "\t\tLine 1\r\nLine2\r\n",
	}

	err = t.Execute(os.Stdout, data)
	check(err)
}

你可以在这里运行这段代码:http://play.golang.org/p/jJXMZxtYcv

英文:

Instead of changing the newlines to &lt;br&gt; in javascript, do it in Go: http://play.golang.org/p/jJXMZxtYcv

package main

import (
	&quot;html/template&quot;
	&quot;log&quot;
	&quot;os&quot;
	&quot;strings&quot;
)

func main() {
	const tpl = `
&lt;!DOCTYPE html&gt;
&lt;html&gt;
	&lt;head&gt;
		&lt;meta charset=&quot;UTF-8&quot;&gt;
		&lt;title&gt;{{.Title}}&lt;/title&gt;
	&lt;/head&gt;
	&lt;body&gt;
		&lt;div&gt;{{nl2br .Text}}&lt;/div&gt;
	&lt;/body&gt;
&lt;/html&gt;`

	check := func(err error) {
		if err != nil {
			log.Fatal(err)
		}
	}

	funcs := template.FuncMap{
		&quot;nl2br&quot;: func(text string) template.HTML {
			return template.HTML(strings.Replace(template.HTMLEscapeString(text), &quot;\n&quot;, &quot;&lt;br&gt;&quot;, -1))
		},
	}

	t, err := template.New(&quot;webpage&quot;).Funcs(funcs).Parse(tpl)
	check(err)

	data := struct {
		Title string
		Text  string
	}{
		Title: &quot;My page&quot;,
		Text:  &quot;\t\tLine 1\r\nLine2\r\n&quot;,
	}

	err = t.Execute(os.Stdout, data)
	check(err)
}

答案2

得分: 4

你可以通过CSS格式化来解决这个问题,具体来说是使用white-space属性:

white-space属性指定如何处理元素内的空白字符。

CSS语法:

white-space: normal|nowrap|pre|pre-line|pre-wrap|initial|inherit;

pre值的作用类似于将其包装在HTML的<pre>标签中,这也会呈现出双制表符。

使用pre-line值可以解决你的问题:

pre-line会将连续的空白字符合并为一个空白字符。在需要时文本会换行,并在换行处断开。

因此,行会保留,但多个空白字符会合并为一个。优点是你不需要转换原始文本,浏览器会应用适当的格式化。代码仍然安全,不会受到HTML注入攻击的影响。

完整示例:

func main() {
    t := template.Must(template.New("").Parse(src))
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        t.Execute(w, text)
    })
    panic(http.ListenAndServe("localhost:8080", nil))
}

const src = `<html><body>Entered text:
<div style="white-space:pre-line">{{.}}</div>
</body></html>`

const text = "        1st line\n2nd line\r\n3rdline"

你最初的双制表符\t\t

请注意,你最初的双制表符\t\t不是由浏览器或表单提交生成的(也不是由Datastore生成的,如果你将其存储在那里),而很可能是你在模板中使用了2个制表符的缩进的结果。模板的缩进也会写入输出,所以你应该在模板中正确关闭<textarea>而不带换行符。由于你没有发布你的模板和代码,我无法更多地帮助你找出为什么会有最初的双制表符,但你应该找到根本原因,而不是处理症状。

英文:

You can simply solve you issue with CSS formatting, namely the white-space property:

> The white-space property specifies how white-space inside an element is handled.
>
> CSS Syntax:
>
> white-space: normal|nowrap|pre|pre-line|pre-wrap|initial|inherit;

The pre value acts as if it would be wrapped in an HTML &lt;pre&gt; tag, which would also render the double tabs.

Using the pre-line value works for you:

> pre-line Sequences of whitespace will collapse into a single whitespace. Text will wrap when necessary, and on line breaks

So lines are preserved, but multiple whitespaces are collapsed into a single one. Advantage is that you don't need to transform your original text, the browser will apply the proper formatting. Code remains safe against HTML injection attacks.

Complete example:

func main() {
    t := template.Must(template.New(&quot;&quot;).Parse(src))
    http.HandleFunc(&quot;/&quot;, func(w http.ResponseWriter, r *http.Request) {
        t.Execute(w, text)
    })
    panic(http.ListenAndServe(&quot;localhost:8080&quot;, nil))
}

const src = `&lt;html&gt;&lt;body&gt;Entered text:
&lt;div style=&quot;white-space:pre-line&quot;&gt;{{.}}&lt;/div&gt;
&lt;/body&gt;&lt;/html&gt;`

const text = &quot;\t\t1st line\n2nd line\r\n3rdline&quot;

Your initial double tabs \t\t

Note that your initial double tabs \t\t are not generated by browsers or form submits (nor the Datastore if you store it there) but are most likely the result of you using a template where you have an indentation of 2 tabs. Indentation of templates is also written to output, so you should properly close your &lt;textarea&gt; without newlines in the template. Since you didn't post your template and code, I can't be more help on finding out why you have initial double tabs, but you should find the root cause and not treat the symptoms.

huangapple
  • 本文由 发表于 2016年3月20日 21:34:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/36114389.html
匿名

发表评论

匿名网友

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

确定