#![allow(dead_code)]
use std::rc::Rc;
use super::sink::{Handle, NodeData, RcDom};
pub trait DomVisitor {
fn visit_document(&mut self, _node: &Handle) {}
fn visit_doctype(&mut self, _node: &Handle) {}
fn visit_text(&mut self, _node: &Handle) {}
fn visit_comment(&mut self, _node: &Handle) {}
fn visit_element_start(&mut self, _node: &Handle, _name: &str) {}
fn visit_element_end(&mut self, _node: &Handle, _name: &str) {}
}
pub fn walk_dom<V: DomVisitor>(dom: &RcDom, visitor: &mut V) {
walk_node(&dom.document, visitor);
}
pub fn walk_node<V: DomVisitor>(node: &Handle, visitor: &mut V) {
match &node.data {
NodeData::Document => {
visitor.visit_document(node);
for child in node.children.borrow().iter() {
walk_node(child, visitor);
}
}
NodeData::Doctype => {
visitor.visit_doctype(node);
}
NodeData::Text { .. } => {
visitor.visit_text(node);
}
NodeData::Comment => {
visitor.visit_comment(node);
}
NodeData::Element { name, .. } => {
visitor.visit_element_start(node, name);
for child in node.children.borrow().iter() {
walk_node(child, visitor);
}
visitor.visit_element_end(node, name);
}
}
}
pub struct ElementCollector<F> {
pub elements: Vec<Handle>,
predicate: F,
}
impl<F> ElementCollector<F>
where
F: FnMut(&str) -> bool,
{
pub fn new(predicate: F) -> Self {
ElementCollector { elements: Vec::new(), predicate }
}
}
impl<F> DomVisitor for ElementCollector<F>
where
F: FnMut(&str) -> bool,
{
fn visit_element_start(&mut self, node: &Handle, name: &str) {
if (self.predicate)(name) {
self.elements.push(Rc::clone(node));
}
}
}