1use style::dom::TNode as _;
2
3use crate::{BaseDocument, Node};
4
5#[derive(Clone)]
6pub struct TreeTraverser<'a> {
8 doc: &'a BaseDocument,
9 stack: Vec<usize>,
10}
11
12impl<'a> TreeTraverser<'a> {
13 pub fn new(doc: &'a BaseDocument) -> Self {
15 Self::new_with_root(doc, 0)
16 }
17
18 pub fn new_with_root(doc: &'a BaseDocument, root: usize) -> Self {
20 let mut stack = Vec::with_capacity(32);
21 stack.push(root);
22 TreeTraverser { doc, stack }
23 }
24}
25impl Iterator for TreeTraverser<'_> {
26 type Item = usize;
27
28 fn next(&mut self) -> Option<Self::Item> {
29 let id = self.stack.pop()?;
30 let node = self.doc.get_node(id)?;
31 self.stack.extend(node.children.iter().rev());
32 Some(id)
33 }
34}
35
36#[derive(Clone)]
37pub struct AncestorTraverser<'a> {
39 doc: &'a BaseDocument,
40 current: usize,
41}
42impl<'a> AncestorTraverser<'a> {
43 pub fn new(doc: &'a BaseDocument, node_id: usize) -> Self {
45 AncestorTraverser {
46 doc,
47 current: node_id,
48 }
49 }
50}
51impl Iterator for AncestorTraverser<'_> {
52 type Item = usize;
53
54 fn next(&mut self) -> Option<Self::Item> {
55 let current_node = self.doc.get_node(self.current)?;
56 self.current = current_node.parent?;
57 Some(self.current)
58 }
59}
60
61impl BaseDocument {
62 pub fn node_chain(&self, node_id: usize) -> Vec<usize> {
64 let mut chain = Vec::with_capacity(16);
65 chain.push(node_id);
66 chain.extend(
67 AncestorTraverser::new(self, node_id).filter(|id| self.nodes[*id].is_element()),
68 );
69 chain
70 }
71
72 pub fn visit<F>(&self, mut visit: F)
73 where
74 F: FnMut(usize, &Node),
75 {
76 TreeTraverser::new(self).for_each(|node_id| visit(node_id, &self.nodes[node_id]));
77 }
78
79 pub fn non_anon_ancestor_if_anon(&self, mut node_id: usize) -> usize {
82 loop {
83 let node = &self.nodes[node_id];
84
85 if !node.is_anonymous() {
86 return node.id;
87 }
88
89 let Some(parent_id) = node.layout_parent.get() else {
90 panic!("Node does not exist or does not have a non-anonymous parent");
93 };
94
95 node_id = parent_id;
96 }
97 }
98
99 pub fn iter_children_mut(
100 &mut self,
101 node_id: usize,
102 mut cb: impl FnMut(usize, &mut BaseDocument),
103 ) {
104 let children = std::mem::take(&mut self.nodes[node_id].children);
105 for child_id in children.iter().cloned() {
106 cb(child_id, self);
107 }
108 self.nodes[node_id].children = children;
109 }
110
111 pub fn iter_subtree_mut(
112 &mut self,
113 node_id: usize,
114 mut cb: impl FnMut(usize, &mut BaseDocument),
115 ) {
116 cb(node_id, self);
117 iter_subtree_mut_inner(self, node_id, &mut cb);
118 fn iter_subtree_mut_inner(
119 doc: &mut BaseDocument,
120 node_id: usize,
121 cb: &mut impl FnMut(usize, &mut BaseDocument),
122 ) {
123 let children = std::mem::take(&mut doc.nodes[node_id].children);
124 for child_id in children.iter().cloned() {
125 cb(child_id, doc);
126 iter_subtree_mut_inner(doc, child_id, cb);
127 }
128 doc.nodes[node_id].children = children;
129 }
130 }
131
132 pub fn iter_children_and_pseudos_mut(
133 &mut self,
134 node_id: usize,
135 mut cb: impl FnMut(usize, &mut BaseDocument),
136 ) {
137 let before = self.nodes[node_id].before.take();
138 if let Some(before_node_id) = before {
139 cb(before_node_id, self)
140 }
141 self.nodes[node_id].before = before;
142
143 self.iter_children_mut(node_id, &mut cb);
144
145 let after = self.nodes[node_id].after.take();
146 if let Some(after_node_id) = after {
147 cb(after_node_id, self)
148 }
149 self.nodes[node_id].after = after;
150 }
151
152 pub fn next_node(&self, start: &Node, mut filter: impl FnMut(&Node) -> bool) -> Option<usize> {
153 let start_id = start.id;
154 let mut node = start;
155 let mut look_in_children = true;
156 loop {
157 let next = if look_in_children && !node.children.is_empty() {
159 let node_id = node.children[0];
160 &self.nodes[node_id]
161 }
162 else if let Some(parent) = node.parent_node() {
164 let self_idx = parent
165 .children
166 .iter()
167 .position(|id| *id == node.id)
168 .unwrap();
169 if let Some(sibling_id) = parent.children.get(self_idx + 1) {
171 look_in_children = true;
172 &self.nodes[*sibling_id]
173 }
174 else {
176 look_in_children = false;
177 node = parent;
178 continue;
179 }
180 }
181 else {
183 look_in_children = true;
184 self.root_node()
185 };
186
187 if filter(next) {
188 return Some(next.id);
189 } else if next.id == start_id {
190 return None;
191 }
192
193 node = next;
194 }
195 }
196
197 pub fn node_layout_ancestors(&self, node_id: usize) -> Vec<usize> {
198 let mut ancestors = Vec::with_capacity(12);
199 let mut maybe_id = Some(node_id);
200 while let Some(id) = maybe_id {
201 ancestors.push(id);
202 maybe_id = self.nodes[id].layout_parent.get();
203 }
204 ancestors.reverse();
205 ancestors
206 }
207
208 pub fn maybe_node_layout_ancestors(&self, node_id: Option<usize>) -> Vec<usize> {
209 node_id
210 .map(|id| self.node_layout_ancestors(id))
211 .unwrap_or_default()
212 }
213}