fix(dom): keep <head> content when setting documentElement.innerHTML
Setting innerHTML on the <html> element parses the fragment in its own context
(added in a2fd4d1), which runs html5ever's "before head" insertion mode and
synthesizes both <head> and <body> under the fragment root. The importer's
helper walked into the root <html> and, if it found a <body> child, returned
that body -- so import_children_from imported only the body's children and any
assigned <head> content (<title>, <meta>, <link>) was silently dropped.
A <body> child of the fragment root only appears in this <html>-context case;
every other element context leaves parsed content directly under the root and
already fell through to returning it. Rename find_body_or_root -> fragment_root
and return the root <html> element so both head and body children import.
Behavior for all non-<html> contexts is unchanged.
Fixes #556
This commit is contained in:
1 parent
f0541f40a4
commit
d0d8617ca6
3 files changed
+45
-9
No files matched your search
@@ -839,18 +839,22 @@ impl DomTree {
|
||||
self.append_child(parent_id, text_id);
|
||||
}
|
||||
|
||||
pub fn find_body_or_root(&self) -> NodeId {
|
||||
/// The node whose children are a parsed fragment's top-level nodes: the
|
||||
/// synthetic root `<html>` element html5ever wraps a fragment in, or the
|
||||
/// document if there is none. Importing this node's children reproduces the
|
||||
/// fragment as written.
|
||||
///
|
||||
/// This must NOT descend into a synthesized `<body>`. A `<body>` child of the
|
||||
/// root only appears when the fragment is parsed in the `<html>` context
|
||||
/// (documentElement.innerHTML), where html5ever's "before head" mode
|
||||
/// synthesizes both `<head>` and `<body>`; returning the body there dropped
|
||||
/// the head siblings. Every other element context leaves the parsed content
|
||||
/// directly under the root, so it is unaffected.
|
||||
pub fn fragment_root(&self) -> NodeId {
|
||||
let doc = self.document();
|
||||
for child in self.children(doc) {
|
||||
if let Some(n) = self.get_node(child) {
|
||||
if n.as_element().map(|name| name.local.as_ref() == "html").unwrap_or(false) {
|
||||
for html_child in self.children(child) {
|
||||
if let Some(hc) = self.get_node(html_child) {
|
||||
if hc.as_element().map(|name| name.local.as_ref() == "body").unwrap_or(false) {
|
||||
return html_child;
|
||||
}
|
||||
}
|
||||
}
|
||||
return child;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user