Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Go template.ExecuteTemplate include html

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:

<h1>this<strong>is</strong>a test</h1> 

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("tmpl/edit.html", "tmpl/view.html")) ) 

And the actual ExecuteTemplate looks like this:

err := templates.ExecuteTemplate(w, tmpl+".html", p) 

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

Finally my 'view.html' (template) looks like the following:

<h1>{{.Title}}</h1> <p>[<a href="/edit/{{.Title}}">edit</a>]</p> <div>{{printf "%s" .Body}}</div> 

Things I have tried:

  • {{printf "%s" .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.

like image 799
Peter Avatar asked Aug 11 '13 19:08

Peter


2 Answers

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.

like image 121
thwd Avatar answered Sep 29 '22 16:09

thwd


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 := &Page{     Title: "Example",     Body:  template.HTML(blackfriday.MarkdownCommon([]byte("foo bar")), } 

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("").Funcs(template.FuncMap{     "html": func(value interface{}) template.HTML {         return template.HTML(fmt.Sprint(value))     }, }).ParseFiles("file1.html", "file2.html")) 
like image 21
tux21b Avatar answered Sep 29 '22 18:09

tux21b