Code following blank line in script tag is wrapped in <p> tag

Searched around here, but couldn’t find this problem.

Markdown in tmp.md:

<div></div>
<script>
function f(x) {

return x;
}
</script>

Config (unsafe rendering is enabled):

[markup.goldmark.renderer]
unsafe = true

Commands (minify is enabled):

❯ hugo version
hugo v0.163.3+extended+withdeploy darwin/arm64 BuildDate=2026-06-18T16:18:24Z VendorInfo=Homebrew

❯ hugo --baseURL https://example.com --minify

Output:

Start building sites … 
hugo v0.163.3+extended+withdeploy darwin/arm64 BuildDate=2026-06-18T16:18:24Z VendorInfo=Homebrew

Total in 1006 ms
ERROR error building site: render: [en v1.0.0 guest] failed to render pages: failed to process "/tmp/index.html": "/var/folders/bx/qk0phsxd265fqj512dnnpg080000gp/T/hugo-transform-error1046853356:393:9": unexpected < in expression on line 393 and column 9
    3: <p>return x;
       ^

If you delete the div, it works:

<script>
function f(x) {

return x;
}
</script>

If you put a blank line after the div, it works:

<div></div>

<script>
function f(x) {

return x;
}
</script>

If you delete the blank line after the function keyword, it works:

<div></div>
<script>
function f(x) {
return x;
}
</script>

Oddly, before doing any of those things (using the original code), the syntax highlighting for the JS is screwed up in the Helix text editor, rendering the JS as plain white text (perhaps as plaintext?). After doing any of those things, the syntax highlighting for the JS starts working.

The error only happens when --minify is used.

I’m scratching my head trying to understand what’s going on here. ChatGPT wasn’t helpful. At first I thought the issue was the JS being indented 4 spaces, but the error still happens without indentation.

This (HTML inside) Markdown code used to work with Hugo. I’m not sure when it stopped working.

no solution just some findings:

i played some versions down to 0.110.0 and they all behave like that.. three years… I guess that ship has sailed long ago

the test case can be stripped down to:

<hr/>
<!--  a blank line -->
<script>

</script>

if there’s no blank line between the tags you may not use blank lines in the script

The root cause is the markdown processing which generates invalid HTML and is reproducible in both goldmark playground and commonmark.js demo.

  • JS minification fails with a syntax error because of the <p> tag inside
  • Browser error if nobody magically removes the <p> tags inside the script
# This works              # this Fails
<hr/>                     <hr/>
                          <script>
<script>
                          </script>
</script>

# HTML                    # HTML
<hr/>                     <hr/>
<script>                  <script>
                          <p></script></p>
</script>

# minified                # failing
<hr><script></script>     unexpected < in expression

From the Ast view I think it’s a parsing issue wrongly splitting the HTML tags

Good AST - Two HTMLBlock
Document {
    Pos: 0
    HTMLBlock {
        Pos: 0
        RawText: "<hr/>
"
        HasBlankPreviousLines: true
    }
    HTMLBlock {
        Pos: 7
        RawText: "<script>

"
        Closure: "</script>
"
        HasBlankPreviousLines: true
    }
}
Bad AST - HTMLBlock and Paragraph
Document {
    Pos: 0
    HTMLBlock {
        Pos: 0
        RawText: "<hr/>
<script>
"
        HasBlankPreviousLines: true
    }
    Paragraph {
        Pos: 16
        RawText: "</script>"
        HasBlankPreviousLines: true
        RawHTML {
            Pos: 16
            RawText: </script>
        }
    }
}```

Mixing HTML with Markdown is hard.

Avoiding indentation is pretty easy to remember, but understanding the effects of blank lines (or their absence) requires a thorough reading of the spec. Or in my case, re-reading it every time something like this comes up.

If I’m reading the spec correctly, you are getting the expected result.

  1. The opening <div> starts an HTML block per rule #6.

  2. The HTML block ends when it encounters the first blank line, also per rule #6. That means that the block is this:

    <div></div>
    <script>
    function f(x) {
    
  3. Now we are no longer within an HTML block, so the remainder, including the closing </script> tag, is treated as a paragraph.

Adding a blank line after the closing </div> will create two HTML blocks, the second one beginning with <script> and ending with </script> per rule #1.

totally agreed! :100:

my parsing “expectations” vs the real spec.

I’ll burn that deep in my brain :wink:

Thanks @jmooring, that seems to be the answer. I didn’t realize the parser tried to parse Markdown within HTML. I thought it just switched to parsing as HTML until the matching end tag, and then switched back to Markdown. It’s an easy fix to put every open/close tag in column 1 on its own line, which avoids the issue.