换行符转换为<br/>

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

Newline to <br/>

问题

我正在尝试在我的Golang模板中将"\n"转换为"<br/>"。

type Page struct {
    HTTPMethod      string
    Template        string
    CharSet         string
    Slug            string
    MetaTitle       string
    MetaDescription string
    MetaKeywords    string
    Title           string
    Body            string
    Navigation      Links
    Detail          interface{}
}

for _, page := range pages.Pages {
    page := page
    router.HandleFunc(page.Slug, func(w http.ResponseWriter, r *http.Request) {
        err := tmpl.ExecuteTemplate(w, page.Template, page)// page of type Page
        if err != nil {
            http.Error(w, err.Error(), http.StatusInternalServerError)
        }
    })
}

模板如下:

{{define "index"}}{{template "header" . }}<h1>{{.Title}}</h1><div>{{.Body}}</div>{{template "footer"}}{{end}}

我尝试使用以下代码连接字符串:

page.Body = "Some text." +htmlBRTag+ "More text"

输出如下:

htmlBRTag := "&lt;br/&gt;" // -> &lt;br/&gt;
htmlBRTag = "<br/>" //-> <br/>

预期结果应该是:

page.Body = "Some text.<br/>More text"

有什么建议吗?

以下是可以直接运行的可复制代码:

package main

import (
    "fmt"
    "html/template"
    "log"
    "net/http"

    "github.com/gorilla/handlers"
    "github.com/gorilla/mux"
)

type Data struct {
    Field1 string
    Field2 string
    Field3 string
}

var tmpl *template.Template

func main() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Printf("Recovering from panic, error is: %v \n", r)
        }
    }()
    router := mux.NewRouter()

    port := ":8085"
    htmlBreak := "<br/>"
    data := Data{}
    data.Field1 = "Some text<br/>More text"
    data.Field2 = "Some text" + htmlBreak + "More text"
    data.Field3 = template.HTMLEscapeString(data.Field2)

    router.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        err := tmpl.ExecuteTemplate(w, "index", data)
        if err != nil {
            http.Error(w, err.Error(), http.StatusInternalServerError)
        }
    })

    var err error
    tmpl, err = template.ParseGlob("views/*")
    if err != nil {
        panic(err.Error())
    }

    router.PathPrefix("/").HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
        http.FileServer(http.Dir("./static/")).ServeHTTP(res, req)
    })

    fmt.Println("Server running on localhost" + port)

    err = http.ListenAndServe(port, handlers.CompressHandler(router))
    if err != nil {
        log.Fatal(err)
    }
}

在./views文件夹中有index.html、index.html和footer.html:

{{define "header"}}<!doctype html><html lang="en"><head><meta charset="utf-8"><title>Title</title></head><body>{{end}}

{{define "index"}}{{template "header" . }}
<div>F1: {{.Field1}}</div>
<div>F2: {{.Field2}}</div>
<div>F3: {{.Field3}}</div>
{{template "footer"}}{{end}}

{{define "footer"}}</body></html>{{end}}

当前输出为:

F1: Some text&lt;br/&gt;More text
F2: Some text&lt;br/&gt;More text
F3: Some text&amp;lt;br/&amp;gt;More text

预期结果是换行符:

Some text
More text

我尝试了以下代码:

htmlBRTag := "<br/>"
b = "Some text." +htmlBRTag+ "More text"
Page.Body = template.HTMLEscapeString(b)

模板中的文本变为:

Some text.&amp;lt;br/&amp;gt;More text
英文:

I am attempting to convert my "\n" to "&lt;br/&gt;" in my Golang templates.

type Page struct {
HTTPMethod      string
Template        string
CharSet         string
Slug            string
MetaTitle       string
MetaDescription string
MetaKeywords    string
Title           string
Body            string
Navigation      Links
Detail          interface{}
}
for _, page := range pages.Pages {
page := page
router.HandleFunc(page.Slug, func(w http.ResponseWriter, r *http.Request) {
err := tmpl.ExecuteTemplate(w, page.Template, page)// page of type Page
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
})
}

The template looks like:

{{define &quot;index&quot;}}{{template &quot;header&quot; . }}&lt;h1&gt;{{.Title}}&lt;/h1&gt;&lt;div&gt;{{.Body}}&lt;/div&gt;{{template &quot;footer&quot;}}{{end}}

I attempted to concatenate the string with:

page.Body = &quot;Some text.&quot; +htmlBRTag+ &quot;More text&quot;

Which outputs the following:

htmlBRTag := &quot;&amp;lt;br/&amp;gt;&quot; // -&gt; &amp;lt;br/&amp;gt;
htmlBRTag = &quot;&lt;br/&gt;&quot; //-&gt; &lt;br/&gt;

The expected outcome would be:

page.Body = &quot;Some text.&lt;br/&gt;More text&quot;

Any suggestions how to do this?

Below is replicable code that runs out of the box:

package main
import (
&quot;fmt&quot;
&quot;html/template&quot;
&quot;log&quot;
&quot;net/http&quot;
&quot;github.com/gorilla/handlers&quot;
&quot;github.com/gorilla/mux&quot;
)
type Data struct {
Field1 string
Field2 string
Field3 string
}
var tmpl *template.Template
func main() {
defer func() {
if r := recover(); r != nil {
fmt.Printf(&quot;Recovering from panic, error is: %v \n&quot;, r)
}
}()
router := mux.NewRouter()
port := &quot;:8085&quot;
htmlBreak := &quot;&lt;br/&gt;&quot;
data := Data{}
data.Field1 = &quot;Some text&lt;br/&gt;More text&quot;
data.Field2 = &quot;Some text&quot; + htmlBreak + &quot;More text&quot;
data.Field3 = template.HTMLEscapeString(data.Field2)
router.HandleFunc(&quot;/&quot;, func(w http.ResponseWriter, r *http.Request) {
err := tmpl.ExecuteTemplate(w, &quot;index&quot;, data)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
})
var err error
tmpl, err = template.ParseGlob(&quot;views/*&quot;)
if err != nil {
panic(err.Error())
}
router.PathPrefix(&quot;/&quot;).HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
http.FileServer(http.Dir(&quot;./static/&quot;)).ServeHTTP(res, req)
})
fmt.Println(&quot;Server running on localhost&quot; + port)
err = http.ListenAndServe(port, handlers.CompressHandler(router))
if err != nil {
log.Fatal(err)
}
}

And in the ./views folder I have index.html, index.html, footer.html

{{define &quot;header&quot;}}&lt;!doctype html&gt;&lt;html lang=&quot;en&quot;&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;{{end}}
{{define &quot;index&quot;}}{{template &quot;header&quot; . }}
&lt;div&gt;F1: {{.Field1}}&lt;/div&gt;
&lt;div&gt;F2: {{.Field2}}&lt;/div&gt;
&lt;div&gt;F3: {{.Field3}}&lt;/div&gt;
{{template &quot;footer&quot;}}{{end}}
{{define &quot;footer&quot;}}&lt;/body&gt;&lt;/html&gt;{{end}}

The current output is:

F1: Some text&lt;br/&gt;More text
F2: Some text&lt;br/&gt;More text
F3: Some text&amp;lt;br/&amp;gt;More text

The expected outcome is a line break like:

Some text
More text

I tried the following:

htmlBRTag := &quot;&lt;br/&gt;&quot;
b = &quot;Some text.&quot; +htmlBRTag+ &quot;More text&quot;
Page.Body = template.HTMLEscapeString(b)

The text in the template becomes:

Some text.&amp;lt;br/&amp;gt;More text

答案1

得分: 1

你可以考虑使用正则表达式来替换所有的换行符"\n"为"
"。

代码如下:

package main

import (
    "regexp"
    "fmt"
)

func main() {
    var re = regexp.MustCompile(`(?m)\n`)
    var substitution = "<br/>"

    var str = `here is some text
    that have 
    newline characters`

    fmt.Println(re.ReplaceAllString(str, substitution))
}

你可以在这里尝试使用正则表达式:https://regex101.com/codegen?language=golang

英文:

You may want to consider using a regex expression that simply replaces all of the \n's with &lt;br/&gt;

To do that, your code would look like this

package main
import (
&quot;regexp&quot;
&quot;fmt&quot;
)
func main() {
var re = regexp.MustCompile(`(?m)\n`)
var substitution = &quot;&lt;br/&gt;&quot;
var str = `here is some text
that have 
newline characters`
fmt.Println(re.ReplaceAllString(str, substitution))
}

you can play around with regex here: https://regex101.com/codegen?language=golang

答案2

得分: 1

感谢您添加示例代码,这样更容易理解您的问题。不过,您的示例代码仍然包含了很多不必要的代码,所以我将使用这个更简单的代码来回答(代码越简单越好)。

请注意,当前的输出实际上是:

<!doctype html><html lang="en"><head><meta charset="utf-8"><title>Title</title></head><body>
<div>F1: Some text&lt;br/&gt;More text</div>
<div>F2: Some text&lt;br/&gt;More text</div>
<div>F3: Some text&amp;lt;br/&amp;gt;More text</div>
</body></html>

您在问题中包含的输出似乎是浏览器显示的内容。浏览器解析接收到的HTML并将其显示出来 - 因此&lt;div&gt;F1: Some text&amp;lt;br/&amp;gt;More text&lt;/div&gt;在浏览器中显示为F1: Some text&lt;br/&gt;More text&lt;br/&gt;是显示的文本,而不是HTML元素&lt;br/&gt;)。

当浏览器处理HTML时,任何转义字符都会被取消转义(例如&amp;lt;变为&lt;)。使用转义字符的原因是防止浏览器将其解析为HTML元素(例如&lt;br&gt;)。如果您想要换行,输出中需要包含未转义的&lt;br/&gt;作为原始文本。

Go模板会自动转义传入的字符串中的一系列字符。这是出于安全考虑;否则,用户可能会提交一个带有&lt;script&gt;..&lt;/script&gt;的字符串,如果将其发送到另一个用户的浏览器中,可能会运行一个可能做坏事的脚本!

如果您确信传入的文本是干净的,那么可以使用template.HTML类型告诉模板引擎您信任这个字符串,例如data.Field4 = template.HTML("Some text 55" + htmlBreak + "More text")

以下是一个完整的示例(playground):

package main

import (
	"html/template"
	"io"
	"net/http"
	"net/http/httptest"
	"os"
)

type Data struct {
	Field1 string
	Field2 string
	Field3 string
	Field4 template.HTML
}

var tmpl *template.Template

func main() {
	htmlBreak := "<br/>"
	data := Data{}
	data.Field1 = "Some text<br/>More text"
	data.Field2 = "Some text" + htmlBreak + "More text"
	data.Field3 = template.HTMLEscapeString(data.Field2)
	data.Field4 = template.HTML("Some text 55" + htmlBreak + "More text")

	var err error
	tmpl, err := template.New("index").Parse(`{{define "header"}}<!doctype html><html lang="en"><head><meta charset="utf-8"><title>Title</title></head><body>{{end}}

{{define "index"}}{{template "header" . }}
<div>F1: {{.Field1}}</div>
<div>F2: {{.Field2}}</div>
<div>F3: {{.Field3}}</div>
<div>F3: {{.Field4}}</div>
{{template "footer"}}{{end}}

{{define "footer"}}</body></html>{{end}}
`)
	// tmpl, err = template.ParseGlob("views/*")
	if err != nil {
		panic(err.Error())
	}

	// Now run the template (normally done in a handler)
	w := httptest.NewRecorder()
	if err = tmpl.ExecuteTemplate(w, "index", data); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
	w.Flush()
	io.Copy(os.Stdout, w.Result().Body)
}

输出结果为:

<!doctype html><html lang="en"><head><meta charset="utf-8"><title>Title</title></head><body>
<div>F1: Some text&lt;br/&gt;More text</div>
<div>F2: Some text&lt;br/&gt;More text</div>
<div>F3: Some text&amp;lt;br/&amp;gt;More text</div>
<div>F3: Some text 55&lt;br/&gt;More text</div>
</body></html>

请注意新行中的&lt;br/&gt;,浏览器将其显示为换行符。

英文:

Thank you for adding the example code; this makes it much easier to understand your issue. However your example still includes a lot of unnecessary code so I'll answer using this (the simpler the code the better).

Note that this answer matches my comment but as you have included an example its easier to spell it out in a way that you are more likely to understand.

The current output is actually:

&lt;!doctype html&gt;&lt;html lang=&quot;en&quot;&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;F1: Some text&amp;lt;br/&amp;gt;More text&lt;/div&gt;
&lt;div&gt;F2: Some text&amp;lt;br/&amp;gt;More text&lt;/div&gt;
&lt;div&gt;F3: Some text&amp;amp;lt;br/&amp;amp;gt;More text&lt;/div&gt;
&lt;/body&gt;&lt;/html&gt;

The output that you have included in your question appears to be what the browser is displaying. The browser parses the HTML sent to it and displays it - so &lt;div&gt;F1: Some text&amp;lt;br/&amp;gt;More text&lt;/div&gt; becomes F1: Some text&lt;br/&gt;More text when viewed in a browser (the &lt;br/&gt; is text that is displayed; not the HTML element &lt;br/&gt;).

When the browser processes the HTML any escaped characters are unescaped (e.g. &amp;lt; becomes &lt;). The reason that escaped characters are used is to prevent the browser from parsing them as HTML elements (e.g. &lt;br&gt;). If you want a line break then the output needs to include &lt;br/&gt; as raw text (not escaped).

Go templates automatically escape a range of characters in strings passed in as parameters. This is done for security; otherwise a user might be able to submit a string with &lt;script&gt;..&lt;/script&gt; and if you send that to another users browser it may end up running a script that could do nasty things!

If you are SURE that the text you are passing in is clean then you can use the type template.HTML to tell the template engine that you trust this string e.g. data.Field4 = template.HTML(&quot;Some text 55&quot; + htmlBreak + &quot;More text&quot;).

Following is a full example (playground):

package main

import (
	&quot;html/template&quot;
	&quot;io&quot;
	&quot;net/http&quot;
	&quot;net/http/httptest&quot;
	&quot;os&quot;
)

type Data struct {
	Field1 string
	Field2 string
	Field3 string
	Field4 template.HTML
}

var tmpl *template.Template

func main() {
	htmlBreak := &quot;&lt;br/&gt;&quot;
	data := Data{}
	data.Field1 = &quot;Some text&lt;br/&gt;More text&quot;
	data.Field2 = &quot;Some text&quot; + htmlBreak + &quot;More text&quot;
	data.Field3 = template.HTMLEscapeString(data.Field2)
	data.Field4 = template.HTML(&quot;Some text 55&quot; + htmlBreak + &quot;More text&quot;)

	var err error
	tmpl, err := template.New(&quot;index&quot;).Parse(`{{define &quot;header&quot;}}&lt;!doctype html&gt;&lt;html lang=&quot;en&quot;&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;{{end}}

{{define &quot;index&quot;}}{{template &quot;header&quot; . }}
&lt;div&gt;F1: {{.Field1}}&lt;/div&gt;
&lt;div&gt;F2: {{.Field2}}&lt;/div&gt;
&lt;div&gt;F3: {{.Field3}}&lt;/div&gt;
&lt;div&gt;F3: {{.Field4}}&lt;/div&gt;
{{template &quot;footer&quot;}}{{end}}

{{define &quot;footer&quot;}}&lt;/body&gt;&lt;/html&gt;{{end}}
`)
	// tmpl, err = template.ParseGlob(&quot;views/*&quot;)
	if err != nil {
		panic(err.Error())
	}

	// Now run the template (normally done in a handler)
	w := httptest.NewRecorder()
	if err = tmpl.ExecuteTemplate(w, &quot;index&quot;, data); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
	w.Flush()
	io.Copy(os.Stdout, w.Result().Body)
}

The output is:

&lt;!doctype html&gt;&lt;html lang=&quot;en&quot;&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;F1: Some text&amp;lt;br/&amp;gt;More text&lt;/div&gt;
&lt;div&gt;F2: Some text&amp;lt;br/&amp;gt;More text&lt;/div&gt;
&lt;div&gt;F3: Some text&amp;amp;lt;br/&amp;amp;gt;More text&lt;/div&gt;
&lt;div&gt;F3: Some text 55&lt;br/&gt;More text&lt;/div&gt;
&lt;/body&gt;&lt;/html&gt;

Note the &lt;br/&gt; in the new line; the browser will display this as a break.

答案3

得分: 0

你的问题有点模糊,但我认为你可能正在寻找名为HTMLEscapeString(s)的函数。

HTMLEscapeString返回纯文本数据s的转义HTML等效字符串。

https://pkg.go.dev/html/template@go1.17.2#HTMLEscapeString

英文:

Your question is a little vague, but I believe you may be looking for the function named HTMLEscapeString(s).

HTMLEscapeString returns the escaped HTML equivalent of the plain text data s.

https://pkg.go.dev/html/template@go1.17.2#HTMLEscapeString

huangapple
  • 本文由 发表于 2021年11月4日 08:06:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/69833115.html
匿名

发表评论

匿名网友

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

确定