///|
fn apply_decide_transform(
root : @dom.Node,
transform : TransformSpec,
limits : @sel.SelectorLimits,
) -> Unit raise @core.HtmlError {
match root.kind {
Document | Fragment | Element =>
decide_transform_children(root, transform, limits)
_ => ()
}
}
///|
fn decide_transform_all_nodes(transform : TransformSpec) -> Bool {
transform.selector[:].trim() == "*"
}
///|
fn decide_action_label(action : DecideAction) -> String {
match action {
Keep => "keep"
Drop => "drop"
Unwrap => "unwrap"
Empty => "empty"
Escape => "escape"
}
}
///|
fn decide_node_label(node : @dom.Node) -> String {
if node.name.has_prefix("#") || node.name == "!doctype" {
node.name
} else {
@syn.lower_ascii(node.name)
}
}
///|
fn decide_transform_matches_node(
node : @dom.Node,
transform : TransformSpec,
all_nodes : Bool,
limits : @sel.SelectorLimits,
) -> Bool raise @core.HtmlError {
if all_nodes {
true
} else {
node.kind == Element && transform_matches_element(node, transform, limits)
}
}
///|
fn decide_transform_action(
node : @dom.Node,
transform : TransformSpec,
) -> DecideAction {
match transform.decide_callback {
Some(callback) => {
let action = (callback.callback)(node)
if action != Keep {
transform_call_hook(node, transform)
transform_report(
transform,
"Decide -> " +
decide_action_label(action) +
" '" +
decide_node_label(node) +
"' (matched selector '" +
transform.selector +
"')",
Some(node),
)
}
action
}
None => Keep
}
}
///|
fn decide_escape_child_at(parent : @dom.Node, index : Int) -> Unit {
match parent.children[index].kind {
Element => ignore(escape_transform_child_at(parent, index))
Document | Fragment => ignore(@san.unwrap_child_at(parent, index))
Text | Comment | Doctype => @san.remove_child_at(parent, index)
}
}
///|
fn decide_transform_children(
parent : @dom.Node,
transform : TransformSpec,
limits : @sel.SelectorLimits,
) -> Unit raise @core.HtmlError {
let all_nodes = decide_transform_all_nodes(transform)
let mut index = 0
while index < parent.children.length() {
let child = parent.children[index]
if decide_transform_matches_node(child, transform, all_nodes, limits) {
match decide_transform_action(child, transform) {
Keep => {
match child.kind {
Document | Fragment | Element =>
decide_transform_children(child, transform, limits)
_ => ()
}
index += 1
}
Empty => {
ignore(empty_transform_node(child))
index += 1
}
Drop => @san.remove_child_at(parent, index)
Unwrap => ignore(@san.unwrap_child_at(parent, index))
Escape => decide_escape_child_at(parent, index)
}
} else {
match child.kind {
Document | Fragment | Element =>
decide_transform_children(child, transform, limits)
_ => ()
}
index += 1
}
}
}