///|
fn collapse_transform_html_space(value : StringView) -> String {
let out = StringBuilder::new(size_hint=value.length())
let mut in_ws = false
for ch in value {
if is_html_whitespace_char(ch) {
if !in_ws {
out.write_char(' ')
in_ws = true
}
} else {
out.write_char(ch)
in_ws = false
}
}
out.to_string()
}
///|
fn apply_collapse_whitespace_transform(
root : @dom.Node,
skip_tags : Set[String],
transform : TransformSpec,
) -> Unit {
match root.kind {
Document | Fragment =>
collapse_whitespace_children(root, skip_tags, false, transform)
Element =>
collapse_whitespace_children(
root,
skip_tags,
skip_tags.contains(@syn.lower_ascii(root.name)),
transform,
)
_ => ()
}
}
///|
fn collapse_whitespace_children(
parent : @dom.Node,
skip_tags : Set[String],
skip : Bool,
transform : TransformSpec,
) -> Unit {
let mut index = 0
while index < parent.children.length() {
let child = parent.children[index]
match child.kind {
Text if !skip && child.data != "" => {
let collapsed = collapse_transform_html_space(child.data)
if collapsed != child.data {
transform_call_hook(child, transform)
transform_report(
transform,
"Collapsed whitespace in text node",
Some(child),
)
let replacement = @dom.text(collapsed)
replacement.parent = Some(parent)
parent.children[index] = replacement
if child.parent is Some(current_parent) &&
physical_equal(current_parent, parent) {
child.parent = None
}
}
}
Document | Fragment =>
collapse_whitespace_children(child, skip_tags, skip, transform)
Element => {
let child_skip = skip ||
skip_tags.contains(@syn.lower_ascii(child.name))
collapse_whitespace_children(child, skip_tags, child_skip, transform)
}
_ => ()
}
index += 1
}
}