Confused about embedding HTML in markdown

If I set unsafe=true in the config and then I put some embedded HTML in the markdown for a page and display the content with a simple:

{{ .Content }}

somewhere on the page, the embedded HTML is correctly parsed and displayed, as expected. Any markdown syntax in the content for creating links, lists, or styling also works as expected.

But if I first pass the .Content to the findRE function and extract some of the content according to some regex and then display what I get back from findRE, neither embedded HTML tags nor markdown are parsed correctly - the tags and markdown syntax are just displayed instead of interpreted:

        {{ $snippetarray := findRE "START(.|\n)*?END" .Content }}
        {{ $snippet := index $snippetarray 0 }}
        {{ $snippet }}

and the content looks like:

something not interesting here
<a href="/">A link</a>
Should be a header
Some <b>bolded text</b>
more uninteresting stuff

what gets displayed is:
START<a href="/">A link</a>Should be a header==================Some <b>bolded text</b>END

instead of the styled text with the markdown syntax and HTML tags interpreted as you’d expect.

Why does this happen? And is there a workaround so that content that passes through findRE can still have any embedded markdown and HTML be interpreted as expected?


{{ $snippetarray := findRE "START(.|\n)*?END" .Content }}
{{ $snippet := index $snippetarray 0 }}
{{ $snippet }}


{{ $snippetarray := findRE "START(.|\n)*?END" .Content }}
{{ $snippet := index $snippetarray 0 }}
{{ $snippet | safeHTML }}

Thanks @jmooring, that does indeed solve the problem!

However, I’m still confused as to why I don’t have to do that, pipe the text through safeHTML, in the case of:

{{ .Content }}

Is Hugo doing something behind the scenes here, recognizing that you’re displaying the markdown content and automagically running it through safeHTML? If so, is this (and any other similar bits of magic) documented somewhere?

With this in config.toml

unsafe = true

you have instructed goldmark (the markdown parser) to “render raw HTML or potentially dangerous links… as written.” Reference:

That means that this markdown:


will be rendered as:


instead of:

<!-- raw HTML omitted -->

Your $snippet code in the template is executed after goldmark has done its work, and what you are seeing is contextual autoescaping performed by go’s html/template package. Piping $snippet through safeHTML prevents contextual autoescaping.

Finally, there’s no magic here—it’s just software.