///|
fn document_html_element(root : @dom.Node) -> @dom.Node? {
for child in root.children {
if child.kind == Element && child.name == "html" {
return Some(child)
}
}
None
}
///|
fn append_children_to(target : @dom.Node, children : Array[@dom.Node]) -> Unit {
for child in children {
target.append_child(child)
}
}
///|
fn append_body_node_contents(
body_node : @dom.Node,
source : @dom.Node,
body_children : Array[@dom.Node],
) -> Unit {
merge_missing_attrs(body_node, source)
let existing = source.children.copy()
source.children.clear()
for child in existing {
if child.kind == Element && child.name == "body" {
append_body_node_contents(body_node, child, body_children)
} else {
body_children.push(child)
}
}
}
///|
fn append_html_node_contents(
html_node : @dom.Node,
source : @dom.Node,
html_children : Array[@dom.Node],
) -> Unit {
merge_missing_attrs(html_node, source)
let existing = source.children.copy()
source.children.clear()
for child in existing {
if child.kind == Element && child.name == "html" {
append_html_node_contents(html_node, child, html_children)
} else {
html_children.push(child)
}
}
}
///|
fn absorb_root_html_siblings(root : @dom.Node, html : @dom.Node) -> Unit {
let original = root.children.copy()
root.children.clear()
let mut saw_html = false
for child in original {
if child.kind == Element && child.name == "html" {
if saw_html {
append_html_node_contents(html, child, html.children)
} else {
root.append_child(child)
saw_html = true
}
} else {
root.append_child(child)
}
}
}
///|
fn scaffold_existing_html_element(html : @dom.Node) -> Unit {
let raw_original = html.children.copy()
html.children.clear()
let original : Array[@dom.Node] = []
for child in raw_original {
if child.kind == Element && child.name == "html" {
append_html_node_contents(html, child, original)
} else {
original.push(child)
}
}
let mut head : @dom.Node? = None
let mut body : @dom.Node? = None
let mut frameset : @dom.Node? = None
let before_head_children : Array[@dom.Node] = []
let between_head_body_children : Array[@dom.Node] = []
let head_children : Array[@dom.Node] = []
let body_children : Array[@dom.Node] = []
let after_frameset_children : Array[@dom.Node] = []
let mut body_started = false
for child in original {
if child.kind == Comment &&
!body_started &&
head is None &&
head_children.is_empty() {
before_head_children.push(child)
} else if child.kind == Comment && !body_started && head is Some(_) {
between_head_body_children.push(child)
} else if child.kind == Element &&
child.name == "head" &&
head is None &&
!body_started {
head = Some(child)
} else if child.kind == Element && child.name == "body" && body is None {
body = Some(child)
body_started = true
append_body_node_contents(child, child, body_children)
} else if child.kind == Element && child.name == "body" {
append_body_node_contents(body.unwrap(), child, body_children)
body_started = true
} else if child.kind == Element &&
child.name == "frameset" &&
body is None &&
frameset is None &&
!body_started {
frameset = Some(child)
body_started = true
} else if frameset is Some(_) && body is None {
after_frameset_children.push(child)
} else if child.kind == Element && child.name == "head" {
let existing = child.children.copy()
for grandchild in existing {
body_children.push(grandchild)
}
body_started = true
} else if child.kind == Element &&
is_document_head_element_name(child.name) &&
!body_started {
head_children.push(child)
} else if child.kind == Comment && !body_started {
head_children.push(child)
} else if is_whitespace_text_node(child) && !body_started {
if head is Some(_) {
between_head_body_children.push(child)
} else if !head_children.is_empty() {
head_children.push(child)
}
} else if child.kind == Text && !body_started {
if head is None && !head_children.is_empty() {
let (leading, rest) = split_text_node_leading_ascii_whitespace(child)
match leading {
Some(node) => head_children.push(node)
None => ()
}
body_started = true
body_children.push(rest.unwrap())
} else if head is None {
body_started = true
body_children.push(
text_node_without_leading_ascii_whitespace(child).unwrap(),
)
} else {
body_started = true
body_children.push(child)
}
} else {
body_started = true
body_children.push(child)
}
}
let head_node = head.unwrap_or(@dom.element("head"))
append_children_to(html, before_head_children)
html.append_child(head_node)
append_children_to(head_node, head_children)
append_children_to(html, between_head_body_children)
match frameset {
Some(frameset_node) if body is None && body_children.is_empty() => {
html.append_child(frameset_node)
append_children_to(html, after_frameset_children)
}
_ => {
let body_node = body.unwrap_or(@dom.element("body"))
append_children_to(body_node, body_children)
html.append_child(body_node)
}
}
}