///|
fn prune_empty_node_is_effectively_empty(
node : @dom.Node,
strip_whitespace : Bool,
) -> Bool {
if node.kind != Element {
return false
}
if node.ns == Some("html") && @ser.is_void_element(node.name) {
return false
}
for child in node.children {
match child.kind {
Text =>
if strip_whitespace {
if !child.data[:].trim().is_empty() {
return false
}
} else if child.data != "" {
return false
}
Comment | Doctype => ()
Element | Document | Fragment => return false
}
}
true
}
///|
fn apply_prune_empty_transform(
root : @dom.Node,
transform : TransformSpec,
limits : @sel.SelectorLimits,
) -> Unit raise @core.HtmlError {
apply_prune_empty_transforms(root, [transform], limits)
}
///|
fn apply_prune_empty_transforms(
root : @dom.Node,
transforms : Array[TransformSpec],
limits : @sel.SelectorLimits,
) -> Unit raise @core.HtmlError {
match root.kind {
Document | Fragment | Element =>
prune_empty_children(root, transforms, limits)
_ => ()
}
}
///|
fn prune_empty_children(
parent : @dom.Node,
transforms : Array[TransformSpec],
limits : @sel.SelectorLimits,
) -> Unit raise @core.HtmlError {
let mut index = 0
while index < parent.children.length() {
let child = parent.children[index]
match child.kind {
Document | Fragment => {
prune_empty_children(child, transforms, limits)
index += 1
}
Element => {
prune_empty_children(child, transforms, limits)
let mut removed = false
for transform in transforms {
if transform_matches_element(child, transform, limits) &&
prune_empty_node_is_effectively_empty(
child,
transform.strip_whitespace,
) {
transform_call_hook(child, transform)
transform_report(
transform,
"Pruned empty <" +
@syn.lower_ascii(child.name) +
"> (matched selector '" +
transform.selector +
"')",
Some(child),
)
@san.remove_child_at(parent, index)
removed = true
break
}
}
if removed {
()
} else {
index += 1
}
}
_ => index += 1
}
}
}