Merge pull request #1642 from lightpanda-io/html-noscript-no-escape
Some checks failed
e2e-test / zig build release (push) Has been cancelled
e2e-test / demo-scripts (push) Has been cancelled
e2e-test / cdp-and-hyperfine-bench (push) Has been cancelled
e2e-test / perf-fmt (push) Has been cancelled
e2e-test / browser fetch (push) Has been cancelled
zig-test / zig test using v8 in debug mode (push) Has been cancelled
zig-test / zig test (push) Has been cancelled
zig-test / perf-fmt (push) Has been cancelled
nightly build / build-linux-x86_64 (push) Has been cancelled
nightly build / build-linux-aarch64 (push) Has been cancelled
nightly build / build-macos-aarch64 (push) Has been cancelled
nightly build / build-macos-x86_64 (push) Has been cancelled
wpt / web platform tests json output (push) Has been cancelled
wpt / perf-fmt (push) Has been cancelled
e2e-integration-test / zig build release (push) Has been cancelled
e2e-integration-test / demo-integration-scripts (push) Has been cancelled

don't escape noscript content on html dump
This commit is contained in:
Karl Seguin
2026-02-25 07:31:26 +08:00
committed by GitHub
2 changed files with 30 additions and 0 deletions

View File

@@ -294,6 +294,12 @@ fn shouldEscapeText(node_: ?*Node) bool {
if (node.is(Node.Element.Html.Script) != null) { if (node.is(Node.Element.Html.Script) != null) {
return false; return false;
} }
// When scripting is enabled, <noscript> is a raw text element per the HTML spec
// (https://html.spec.whatwg.org/multipage/parsing.html#serialising-html-fragments).
// Its text content must not be HTML-escaped during serialization.
if (node.is(Node.Element.Html.Generic)) |generic| {
if (generic._tag == .noscript) return false;
}
return true; return true;
} }
fn writeEscapedText(text: []const u8, writer: *std.Io.Writer) !void { fn writeEscapedText(text: []const u8, writer: *std.Io.Writer) !void {

View File

@@ -0,0 +1,24 @@
<!DOCTYPE html>
<script src="../testing.js"></script>
<!-- When scripting is enabled the HTML parser treats <noscript> as a raw text
element: its entire content is stored as a single text node containing the
raw markup. Serializing it back (outerHTML / innerHTML) must output that
markup as-is without HTML-escaping the angle brackets. -->
<noscript id="ns1"><h1>Hello</h1><p>World</p></noscript>
<noscript id="ns2"><div id="bsky_post_summary"><h3>Post</h3><p id="bsky_display_name">Henri Helvetica</p></div></noscript>
<script id="noscript-outerHTML">
const ns1 = document.getElementById('ns1');
testing.expectEqual('<noscript id="ns1"><h1>Hello</h1><p>World</p></noscript>', ns1.outerHTML);
</script>
<script id="noscript-innerHTML">
const ns2 = document.getElementById('ns2');
testing.expectEqual('<div id="bsky_post_summary"><h3>Post</h3><p id="bsky_display_name">Henri Helvetica</p></div>', ns2.innerHTML);
</script>
<script id="noscript-textContent">
// The raw text node content must be the literal HTML markup (not parsed DOM)
testing.expectEqual('<h1>Hello</h1><p>World</p>', ns1.firstChild.nodeValue);
</script>