rrekaF
rrekaF

Reputation: 31

How to make html templates recognize a string as html in go

I have a wiki web app from the go docs tutorial and want to add a few things. One of those things is a list of all wiki entries at the front page. I have a html template that looks like this:

<h1>This is the front page of the wiki</h1>

<p>here is the list of entries:</p>
<div>
    <ul>

        {{printf "%s" .Body}}
        
    </ul>
</div>

And here is the handler of the page

func frontHandler(w http.ResponseWriter, r *http.Request){
    entries := getEntries()
    p := &Page{Title: "FrontPage", Body:  []byte(entries)}

    renderTemplate(w, "front", p)

}

I've formatted the list of entries to work as a ul in html, it is a splice of strings joined into one to convert it to a splice of bytes, it is formatted like this:

<li><a href="/view/page1">page1</a></li>
<li><a href="/view/page2">page2</a></li>

and so on, so i would like to render it as html instead of plain text like it is now.

I've tried changing how i pass the body of the page from a splice of bytes to a string and it had the same outcome. I tried changing how i render the page to take a different struct made specifically for the front page as a workaround but it also had no effect. Here is how i render the template

func renderTemplate(w http.ResponseWriter, tmpl string, p *Page){
    err := templates.ExecuteTemplate(w, tmpl + ".html", p)
    if err != nil{
        http.Error(w, err.Error(), http.StatusInternalServerError)
    }
}

I've also tried a few different ways of showing it in the .html file instead of the {{printf "%s" .Body"}} and I've been unsuccessful.

Any help is much appreciated, also let me know if i should provide more info.

Upvotes: 0

Views: 2834

Answers (1)

Chaithanya
Chaithanya

Reputation: 41

You can use Typed strings

As per documentation:

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.

Example:

base.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div>
      <ul>
        {{range .}}{{.}}{{end}} <!-- Loop over the pipeline(.) -->
      </ul>
    </div>
  </body>
</html>

func frontHandler(w http.ResponseWriter, r *http.Request) {

    entry := []string{"<li><a href=\"/view/page1\">page1</a></li>", "<li><a href=\"/view/page2\">page2</a></li>"}
    tmpl, err := template.ParseFiles("base.html")
    if err != nil {
        log.Fatal("Unable to parse")
    }

    // template.HTML takes only one string, hence we loop over the entry slice 
    //and store the slice values in htmlvalues of `HTML` type
    var htmlvalues []template.HTML 

    for _, n := range entry {
        htmlEncapsulate := template.HTML(n)
        htmlvalues = append(htmlvalues, htmlEncapsulate)
    }
    tmpl.Execute(w, htmlvalues)

Upvotes: 2

Related Questions