mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-02-04 06:23:45 +00:00
Merge pull request #1410 from lightpanda-io/insertAdjacentHtml
Fix insertAdjacentHtml
This commit is contained in:
@@ -41,4 +41,53 @@
|
||||
testing.expectEqual("DIV", newElement.tagName);
|
||||
testing.expectEqual("after begin", newElement.innerText);
|
||||
testing.expectEqual("afterbegin", newElement.className);
|
||||
|
||||
const fuzzWrapper = document.createElement("div");
|
||||
fuzzWrapper.id = "fuzz-wrapper";
|
||||
document.body.appendChild(fuzzWrapper);
|
||||
|
||||
const fuzzCases = [
|
||||
// These cases have no <body> element (or empty body), so nothing is inserted
|
||||
{ name: "empty string", html: "", expectElements: 0 },
|
||||
{ name: "comment only", html: "<!-- comment -->", expectElements: 0 },
|
||||
{ name: "doctype only", html: "<!DOCTYPE html>", expectElements: 0 },
|
||||
{ name: "full empty doc", html: "<!DOCTYPE html><html><head></head><body></body></html>", expectElements: 0 },
|
||||
|
||||
{ name: "whitespace only", html: " ", expectElements: 0 },
|
||||
{ name: "newlines only", html: "\n\n\n", expectElements: 0 },
|
||||
{ name: "just text", html: "plain text", expectElements: 0 },
|
||||
// Head-only elements: Extracted from <head> container
|
||||
{ name: "empty meta", html: "<meta>", expectElements: 1 },
|
||||
{ name: "empty title", html: "<title></title>", expectElements: 1 },
|
||||
{ name: "empty head", html: "<head></head>", expectElements: 0 }, // Container with no children
|
||||
{ name: "empty body", html: "<body></body>", expectElements: 0 }, // Container with no children
|
||||
{ name: "empty html", html: "<html></html>", expectElements: 0 }, // Container with no children
|
||||
{ name: "meta only", html: "<meta charset='utf-8'>", expectElements: 1 },
|
||||
{ name: "title only", html: "<title>Test</title>", expectElements: 1 },
|
||||
{ name: "link only", html: "<link rel='stylesheet' href='test.css'>", expectElements: 1 },
|
||||
{ name: "meta and title", html: "<meta charset='utf-8'><title>Test</title>", expectElements: 2 },
|
||||
{ name: "script only", html: "<script>console.log('hi')<\/script>", expectElements: 1 },
|
||||
{ name: "style only", html: "<style>body { color: red; }<\/style>", expectElements: 1 },
|
||||
{ name: "unclosed div", html: "<div>content", expectElements: 1 },
|
||||
{ name: "unclosed span", html: "<span>text", expectElements: 1 },
|
||||
{ name: "invalid tag", html: "<notarealtag>content</notarealtag>", expectElements: 1 },
|
||||
{ name: "malformed", html: "<<div>>test<</div>>", expectElements: 1 }, // Parser handles it
|
||||
{ name: "just closing tag", html: "</div>", expectElements: 0 },
|
||||
{ name: "nested empty", html: "<div><div></div></div>", expectElements: 1 },
|
||||
{ name: "multiple top-level", html: "<span>1</span><span>2</span><span>3</span>", expectElements: 3 },
|
||||
{ name: "mixed text and elements", html: "Text before<b>bold</b>Text after", expectElements: 1 },
|
||||
{ name: "deeply nested", html: "<div><div><div><span>deep</span></div></div></div>", expectElements: 1 },
|
||||
];
|
||||
|
||||
fuzzCases.forEach((tc, idx) => {
|
||||
fuzzWrapper.innerHTML = "";
|
||||
fuzzWrapper.insertAdjacentHTML("beforeend", tc.html);
|
||||
if (tc.expectElements !== fuzzWrapper.childElementCount) {
|
||||
console.warn(`Fuzz idx: ${idx}`);
|
||||
testing.expectEqual(tc.expectElements, fuzzWrapper.childElementCount);
|
||||
}
|
||||
});
|
||||
|
||||
// Clean up
|
||||
document.body.removeChild(fuzzWrapper);
|
||||
</script>
|
||||
|
||||
@@ -290,23 +290,24 @@ pub fn insertAdjacentHTML(
|
||||
return error.Invalid;
|
||||
}
|
||||
|
||||
// We always get it wrapped like so:
|
||||
// <html><head></head><body>{ ... }</body></html>
|
||||
// None of the following can be null.
|
||||
const maybe_html_node = doc_node.firstChild();
|
||||
lp.assert(maybe_html_node != null, "Html.insertAdjacentHTML null html", .{});
|
||||
const html_node = maybe_html_node orelse return;
|
||||
|
||||
const maybe_body_node = html_node.lastChild();
|
||||
lp.assert(maybe_body_node != null, "Html.insertAdjacentHTML null bodys", .{});
|
||||
const body = maybe_body_node orelse return;
|
||||
// The parser wraps content in a document structure:
|
||||
// - Typical: <html><head>...</head><body>...</body></html>
|
||||
// - Head-only: <html><head><meta></head></html> (no body)
|
||||
// - Empty/comments: May have no <html> element at all
|
||||
const html_node = doc_node.firstChild() orelse return;
|
||||
|
||||
const target_node, const prev_node = try self.asElement().asNode().findAdjacentNodes(position);
|
||||
|
||||
var iter = body.childrenIterator();
|
||||
// Iterate through all children of <html> (typically <head> and/or <body>)
|
||||
// and insert their children (not the containers themselves) into the target.
|
||||
// This handles both body content AND head-only elements like <meta>, <title>, etc.
|
||||
var html_children = html_node.childrenIterator();
|
||||
while (html_children.next()) |container| {
|
||||
var iter = container.childrenIterator();
|
||||
while (iter.next()) |child_node| {
|
||||
_ = try target_node.insertBefore(child_node, prev_node, page);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn click(self: *HtmlElement, page: *Page) !void {
|
||||
|
||||
Reference in New Issue
Block a user