fix some <pre> edge cases unescaping entities inside <pre><code> tags whitespace handling
2 files changed, 41 insertions(+), 8 deletions(-)
changed files
M format.go → format.go
@@ -123,7 +123,7 @@ func printNode(w io.Writer, n *html.Node, pre bool, level int) (err error) { switch n.Type { case html.TextNode: if pre { - if _, err = fmt.Fprint(w, n.Data); err != nil { + if _, err = fmt.Fprint(w, html.EscapeString(n.Data)); err != nil { return } return nil@@ -171,8 +171,8 @@ } } } case html.ElementNode: - if n.PrevSibling == nil || - (n.PrevSibling.Type != html.TextNode || unicode.IsSpace(getLastRune(n.PrevSibling.Data))) { + if !pre && (n.PrevSibling == nil || + (n.PrevSibling.Type != html.TextNode || unicode.IsSpace(getLastRune(n.PrevSibling.Data)))) { if err = printIndent(w, level); err != nil { return }@@ -189,16 +189,16 @@ } if _, err = fmt.Fprint(w, ">"); err != nil { return } - if !hasSingleTextChild(n) { + if !pre && !hasSingleTextChild(n) { if _, err = fmt.Fprint(w, "\n"); err != nil { return } } if !isVoidElement(n) { - if err = printChildren(w, n, n.Data == "pre", level+1); err != nil { + if err = printChildren(w, n, pre || n.Data == "pre", level+1); err != nil { return } - if isSpecialContentElement(n) || !hasSingleTextChild(n) { + if !pre && (isSpecialContentElement(n) || !hasSingleTextChild(n)) { if err = printIndent(w, level); err != nil { return }@@ -207,9 +207,9 @@ if _, err = fmt.Fprintf(w, "</%s>", n.Data); err != nil { return } - if n.NextSibling == nil || + if !pre && (n.NextSibling == nil || (n.NextSibling.Type == html.ElementNode) || - (n.NextSibling.Type == html.TextNode && !unicode.IsPunct(getFirstRune(n.NextSibling.Data))) { + (n.NextSibling.Type == html.TextNode && !unicode.IsPunct(getFirstRune(n.NextSibling.Data)))) { if _, err = fmt.Fprint(w, "\n"); err != nil { return }
M format_test.go → format_test.go
@@ -102,6 +102,39 @@ <time>19:00</time>–<time>20:00</time> </div> `, }, + { + name: "HTML entities in pre/code blocks are preserved", + input: `<pre><code><tab></code></pre>`, + expected: `<pre> +<code><tab></code></pre> +`, + }, + { + name: "multiple HTML entities in pre blocks are preserved", + input: `<pre><html> & "quotes"</pre>`, + expected: `<pre><html> & "quotes"</pre> +`, + }, + { + name: "HTML entities in nested code within pre are preserved", + input: `<pre>Some text <code><tag></code> more text</pre>`, + expected: `<pre> +Some text <code><tag></code> more text</pre> +`, + }, + { + name: "ampersands in pre blocks are preserved", + input: `<pre>npm install && npm test</pre>`, + expected: `<pre>npm install && npm test</pre> +`, + }, + { + name: "complex HTML entities in code blocks are preserved", + input: `<pre><code>const html = "<div class="test">Hello & goodbye</div>";</code></pre>`, + expected: `<pre> +<code>const html = "<div class="test">Hello & goodbye</div>";</code></pre> +`, + }, } for _, test := range tests {