I am attempting to convert my “n
” to “<br/>
” 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 "index"}}{{template "header" . }}<h1>{{.Title}}</h1><div>{{.Body}}</div>{{template "footer"}}{{end}}
I attempted to concatenate the string with:
page.Body = "Some text." +htmlBRTag+ "More text"
Which outputs the following:
htmlBRTag := "<br/>" // -> <br/> htmlBRTag = "<br/>" //-> <br/>
The expected outcome would be:
page.Body = "Some text.<br/>More text"
Any suggestions how to do this?
Below is replicable code that runs out of the box:
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) } }
And in the ./views folder I have 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}}
The current output is:
F1: Some text<br/>More text F2: Some text<br/>More text F3: Some text<br/>More text
The expected outcome is a line break like:
Some text More text
I tried the following:
htmlBRTag := "<br/>" b = "Some text." +htmlBRTag+ "More text" Page.Body = template.HTMLEscapeString(b)
The text in the template becomes:
Some text.<br/>More text
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
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:
<!doctype html><html lang="en"><head><meta charset="utf-8"><title>Title</title></head><body> <div>F1: Some text<br/>More text</div> <div>F2: Some text<br/>More text</div> <div>F3: Some text&lt;br/&gt;More text</div> </body></html>
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 <div>F1: Some text<br/>More text</div>
becomes F1: Some text<br/>More text
when viewed in a browser (the <br/>
is text that is displayed; not the HTML element <br/>
).
When the browser processes the HTML any escaped characters are unescaped (e.g. <
becomes <
). The reason that escaped characters are used is to prevent the browser from parsing them as HTML elements (e.g. <br>
). If you want a line break then the output needs to include <br/>
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 <script>..</script>
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("Some text 55" + htmlBreak + "More text")
.
Following is a full example (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)
}
The output is:
<!doctype html><html lang="en"><head><meta charset="utf-8"><title>Title</title></head><body> <div>F1: Some text<br/>More text</div> <div>F2: Some text<br/>More text</div> <div>F3: Some text&lt;br/&gt;More text</div> <div>F3: Some text 55<br/>More text</div> </body></html>
Note the <br/>
in the new line; the browser will display this as a break.
Method 2
You may want to consider using a regex expression that simply replaces all of the n’s with <br/>
To do that, your code would look like this
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)) }
you can play around with regex here: https://regex101.com/codegen?language=golang
Method 3
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/[email protected]#HTMLEscapeString
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0