1use style::{dom::TNode as _, values::specified::box_::DisplayInside};
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 Node {
62 #[allow(dead_code)]
63 pub(crate) fn should_traverse_layout_children(&mut self) -> bool {
64 let prefer_layout_children = match self.display_constructed_as.inside() {
65 DisplayInside::None => return false,
66 DisplayInside::Contents => false,
67 DisplayInside::Flow | DisplayInside::FlowRoot | DisplayInside::TableCell => {
68 self.element_data()
70 .is_none_or(|el| el.inline_layout_data.is_none())
71 }
72 DisplayInside::Flex | DisplayInside::Grid => true,
73 DisplayInside::Table => false,
74 DisplayInside::TableRowGroup => false,
75 DisplayInside::TableColumn => false,
76 DisplayInside::TableColumnGroup => false,
77 DisplayInside::TableHeaderGroup => false,
78 DisplayInside::TableFooterGroup => false,
79 DisplayInside::TableRow => false,
80 };
81 let has_layout_children = self.layout_children.get_mut().is_some();
82 prefer_layout_children & has_layout_children
83 }
84}
85
86impl BaseDocument {
87 pub fn node_chain(&self, node_id: usize) -> Vec<usize> {
89 let mut chain = Vec::with_capacity(16);
90 chain.push(node_id);
91 chain.extend(
92 AncestorTraverser::new(self, node_id).filter(|id| self.nodes[*id].is_element()),
93 );
94 chain
95 }
96
97 pub fn visit<F>(&self, mut visit: F)
98 where
99 F: FnMut(usize, &Node),
100 {
101 TreeTraverser::new(self).for_each(|node_id| visit(node_id, &self.nodes[node_id]));
102 }
103
104 pub fn non_anon_ancestor_if_anon(&self, mut node_id: usize) -> usize {
107 loop {
108 let node = &self.nodes[node_id];
109
110 if !node.is_anonymous() {
111 return node.id;
112 }
113
114 let Some(parent_id) = node.layout_parent.get() else {
115 panic!("Node does not exist or does not have a non-anonymous parent");
118 };
119
120 node_id = parent_id;
121 }
122 }
123
124 pub fn iter_children_mut(
125 &mut self,
126 node_id: usize,
127 mut cb: impl FnMut(usize, &mut BaseDocument),
128 ) {
129 let children = std::mem::take(&mut self.nodes[node_id].children);
130 for child_id in children.iter().cloned() {
131 cb(child_id, self);
132 }
133 self.nodes[node_id].children = children;
134 }
135
136 pub fn iter_subtree_mut(
137 &mut self,
138 node_id: usize,
139 mut cb: impl FnMut(usize, &mut BaseDocument),
140 ) {
141 cb(node_id, self);
142 iter_subtree_mut_inner(self, node_id, &mut cb);
143 fn iter_subtree_mut_inner(
144 doc: &mut BaseDocument,
145 node_id: usize,
146 cb: &mut impl FnMut(usize, &mut BaseDocument),
147 ) {
148 let children = std::mem::take(&mut doc.nodes[node_id].children);
149 for child_id in children.iter().cloned() {
150 cb(child_id, doc);
151 iter_subtree_mut_inner(doc, child_id, cb);
152 }
153 doc.nodes[node_id].children = children;
154 }
155 }
156
157 pub fn iter_children_and_pseudos_mut(
158 &mut self,
159 node_id: usize,
160 mut cb: impl FnMut(usize, &mut BaseDocument),
161 ) {
162 let before = self.nodes[node_id].before.take();
163 if let Some(before_node_id) = before {
164 cb(before_node_id, self)
165 }
166 self.nodes[node_id].before = before;
167
168 self.iter_children_mut(node_id, &mut cb);
169
170 let after = self.nodes[node_id].after.take();
171 if let Some(after_node_id) = after {
172 cb(after_node_id, self)
173 }
174 self.nodes[node_id].after = after;
175 }
176
177 pub fn next_node(&self, start: &Node, mut filter: impl FnMut(&Node) -> bool) -> Option<usize> {
178 let start_id = start.id;
179 let mut node = start;
180 let mut look_in_children = true;
181 loop {
182 let next = if look_in_children && !node.children.is_empty() {
184 let node_id = node.children[0];
185 &self.nodes[node_id]
186 }
187 else if let Some(parent) = node.parent_node() {
189 let self_idx = parent
190 .children
191 .iter()
192 .position(|id| *id == node.id)
193 .unwrap();
194 if let Some(sibling_id) = parent.children.get(self_idx + 1) {
196 look_in_children = true;
197 &self.nodes[*sibling_id]
198 }
199 else {
201 look_in_children = false;
202 node = parent;
203 continue;
204 }
205 }
206 else {
208 look_in_children = true;
209 self.root_node()
210 };
211
212 if filter(next) {
213 return Some(next.id);
214 } else if next.id == start_id {
215 return None;
216 }
217
218 node = next;
219 }
220 }
221
222 pub fn node_layout_ancestors(&self, node_id: usize) -> Vec<usize> {
223 let mut ancestors = Vec::with_capacity(12);
224 let mut maybe_id = Some(node_id);
225 while let Some(id) = maybe_id {
226 ancestors.push(id);
227 maybe_id = self.nodes[id].layout_parent.get();
228 }
229 ancestors.reverse();
230 ancestors
231 }
232
233 pub fn maybe_node_layout_ancestors(&self, node_id: Option<usize>) -> Vec<usize> {
234 node_id
235 .map(|id| self.node_layout_ancestors(id))
236 .unwrap_or_default()
237 }
238}