0

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.

2
  • 2
    Declare Page.Body field as type template.HTML. Set field using p := &Page{Title: "FrontPage", Body: template.HTML(entries)} Commented Jul 29, 2022 at 14:35
  • pkg.go.dev/html/template#hdr-Typed_Strings Commented Jul 29, 2022 at 17:03

1 Answer 1

2

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)
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.