9

I'm building go web application. I found some anomaly on the rendered html page. All of my html comments <!-- --> are suddenly not being rendered. My guess it's because the go version I used (just updated to higher version), because it was fine before I updated it.

This is my code:

<!-- prepare the breadcrumbs -->
<ul class="breadcrumb" data-bind="foreach: viewModel.breadcrumbs">
    <!-- ko if: ($index() + 1) < len(viewModel.breadcrumbs()) -->
    <li>
        <a data-bind="attr: { href: href }">
            <i class="fa fa-home"></i> 
            <span data-bind="text: title"></span>
        </a>
    </li>
    <!-- /ko -->

    <!-- ko if: ($index() + 1) == len(viewModel.breadcrumbs()) -->
    <li class="active" data-bind="text: title"></li>
    <!-- /ko -->
</ul>

And this is the rendered page source:

enter image description here

Because of this issue, many of my KnockoutJS codes which are written using containerless control flow syntax goes crazy, it doesn't work at all.

What should I do to solve this? Thanks in advance

icza
  • 389,944
  • 63
  • 907
  • 827
novalagung
  • 10,905
  • 4
  • 58
  • 82

2 Answers2

18

There is a special type in the html/template package: template.HTML. Values of this type in the template are not escaped when the template is rendered.

So you may "mark" your HTML comments as template.HTML and so they will not be escaped or omitted during executing your template.

One way to do this is to register a custom function for your template, a function which can be called from your template which takes a string argument and returns it as template.HTML. You can "pass" all the HTML comments to this function, and as a result, your HTML comments will be retained in the output.

See this example:

func main() {
    t := template.Must(template.New("").Funcs(template.FuncMap{
        "safe": func(s string) template.HTML { return template.HTML(s) },
    }).Parse(src))
    t.Execute(os.Stdout, nil)
}

const src = `<html><body>
{{safe "<!-- This is a comment -->"}}
<div>Some <b>HTML</b> content</div>
</body></html>`

Output (try it on the Go Playground):

<html><body>
<!-- This is a comment -->
<div>Some <b>HTML</b> content</div>
</body></html>

So basically after registering our safe() function, transform all your HTML comments to a template action calling this safe() function and passing your original HTML comment.

Convert this:

<!-- Some HTML comment -->

To this:

{{safe "<!-- Some HTML comment -->"}}

Or alternatively (whichever you like):

{{"<!-- Some HTML comment -->" | safe}}

And you're good to go.

Note: If your HTML comment contains quotation marks ('"'), you can / have to escape it like this:

{{safe "<!-- Some \"HTML\" comment -->"}}

Note #2: Be aware that you shouldn't use conditional HTML comments as that may break the context sensitive escaping of html/template package. For details read this.

icza
  • 389,944
  • 63
  • 907
  • 827
-1

You can use text/template instead of html/template and do all escaping manually using built-in functions such as html and js (https://golang.org/pkg/text/template/#hdr-Functions). Be aware that this is very error prone though.

kostya
  • 9,221
  • 1
  • 29
  • 36
  • I believe this has nothing to do with `mux`, you should change your handlers to use `text/template` package instead of `html/template`. – kostya Dec 18 '15 at 07:41
  • Downvoted: this is not so much "error prone" as *a major security risk* if you in any way use the template for what it's designed to do: inserting untrusted (or, at least, unescaped) data in the middle of a page – kbolino Aug 10 '22 at 21:05