1use blitz_traits::node_id::NodeId;
2use std::cmp::Ordering;
3
4use style::{dom::TNode as _, values::specified::box_::DisplayInside};
5
6use crate::{BaseDocument, Node};
7
8macro_rules! iter_children {
9 ($node_expr:expr, $cb:expr) => {{
10 let node = &mut $node_expr;
11 let children = core::mem::take(&mut node.children);
12 for child_id in children.iter().copied() {
13 $cb(child_id)
14 }
15 $node_expr.children = children;
16 }};
17}
18pub(crate) use iter_children;
19
20macro_rules! iter_children_and_pseudos {
21 ($node_expr:expr, $cb:expr) => {{
22 let node = &mut $node_expr;
24
25 let before = node.before();
27 let after = node.after();
28 let children = core::mem::take(&mut node.children);
29
30 if let Some(before) = before {
31 $cb(before)
32 }
33 for child_id in children.iter().copied() {
34 $cb(child_id)
35 }
36 if let Some(after) = after {
37 $cb(after)
38 }
39
40 $node_expr.children = children;
42 }};
43}
44pub(crate) use iter_children_and_pseudos;
45
46#[derive(Clone)]
47pub struct TreeTraverser<'a> {
49 doc: &'a BaseDocument,
50 stack: Vec<NodeId>,
51}
52
53impl<'a> TreeTraverser<'a> {
54 pub fn new(doc: &'a BaseDocument) -> Self {
56 Self::new_with_root(doc, doc.root_node().id)
57 }
58
59 pub fn new_with_root(doc: &'a BaseDocument, root: NodeId) -> Self {
61 let mut stack = Vec::with_capacity(32);
62 stack.push(root);
63 TreeTraverser { doc, stack }
64 }
65}
66impl Iterator for TreeTraverser<'_> {
67 type Item = NodeId;
68
69 fn next(&mut self) -> Option<Self::Item> {
70 let id = self.stack.pop()?;
71 let node = self.doc.get_node(id)?;
72 self.stack.extend(node.children.iter().rev());
73 Some(id)
74 }
75}
76
77#[derive(Clone)]
78pub struct AncestorTraverser<'a> {
80 doc: &'a BaseDocument,
81 current: NodeId,
82}
83impl<'a> AncestorTraverser<'a> {
84 pub fn new(doc: &'a BaseDocument, node_id: NodeId) -> Self {
86 AncestorTraverser {
87 doc,
88 current: node_id,
89 }
90 }
91}
92impl Iterator for AncestorTraverser<'_> {
93 type Item = NodeId;
94
95 fn next(&mut self) -> Option<Self::Item> {
96 let current_node = self.doc.get_node(self.current)?;
97 self.current = current_node.parent?;
98 Some(self.current)
99 }
100}
101
102impl Node {
103 #[allow(dead_code)]
104 pub(crate) fn should_traverse_layout_children(&mut self) -> bool {
105 let prefer_layout_children = match self.display_constructed_as().inside() {
106 DisplayInside::None => return false,
107 DisplayInside::Contents => false,
108 DisplayInside::Flow | DisplayInside::FlowRoot | DisplayInside::TableCell => {
109 self.element_data()
111 .is_none_or(|el| el.inline_layout_data.is_none())
112 }
113 DisplayInside::Flex | DisplayInside::Grid => true,
114 DisplayInside::Table => false,
115 DisplayInside::TableRowGroup => false,
116 DisplayInside::TableColumn => false,
117 DisplayInside::TableColumnGroup => false,
118 DisplayInside::TableHeaderGroup => false,
119 DisplayInside::TableFooterGroup => false,
120 DisplayInside::TableRow => false,
121 };
122 let has_layout_children = self.layout_children.get_mut().is_some();
123 prefer_layout_children & has_layout_children
124 }
125}
126
127impl BaseDocument {
128 pub fn node_chain(&self, node_id: NodeId) -> Vec<NodeId> {
130 let mut chain = Vec::with_capacity(16);
131 chain.push(node_id);
132 chain.extend(
133 AncestorTraverser::new(self, node_id).filter(|id| self.nodes[*id].is_element()),
134 );
135 chain
136 }
137
138 pub fn visit<F>(&self, mut visit: F)
139 where
140 F: FnMut(NodeId, &Node),
141 {
142 TreeTraverser::new(self).for_each(|node_id| visit(node_id, &self.nodes[node_id]));
143 }
144
145 pub fn non_anon_ancestor_if_anon(&self, mut node_id: NodeId) -> NodeId {
148 loop {
149 let node = &self.nodes[node_id];
150
151 if !node.is_anonymous() {
152 return node.id;
153 }
154
155 let Some(parent_id) = node.layout_parent.get() else {
156 panic!("Node does not exist or does not have a non-anonymous parent");
159 };
160
161 node_id = parent_id;
162 }
163 }
164
165 pub fn iter_children_mut(
166 &mut self,
167 node_id: NodeId,
168 mut cb: impl FnMut(NodeId, &mut BaseDocument),
169 ) {
170 let children = std::mem::take(&mut self.nodes[node_id].children);
171 for child_id in children.iter().cloned() {
172 cb(child_id, self);
173 }
174 self.nodes[node_id].children = children;
175 }
176
177 pub fn iter_subtree_mut(
178 &mut self,
179 node_id: NodeId,
180 mut cb: impl FnMut(NodeId, &mut BaseDocument),
181 ) {
182 cb(node_id, self);
183 iter_subtree_mut_inner(self, node_id, &mut cb);
184 fn iter_subtree_mut_inner(
185 doc: &mut BaseDocument,
186 node_id: NodeId,
187 cb: &mut impl FnMut(NodeId, &mut BaseDocument),
188 ) {
189 let children = std::mem::take(&mut doc.nodes[node_id].children);
190 for child_id in children.iter().cloned() {
191 cb(child_id, doc);
192 iter_subtree_mut_inner(doc, child_id, cb);
193 }
194 doc.nodes[node_id].children = children;
195 }
196 }
197
198 pub fn iter_children_and_pseudos_mut(
199 &mut self,
200 node_id: NodeId,
201 mut cb: impl FnMut(NodeId, &mut BaseDocument),
202 ) {
203 let before = self.nodes[node_id].before();
204 self.nodes[node_id].set_pe_by_index(1, None);
205 if let Some(before_node_id) = before {
206 cb(before_node_id, self)
207 }
208 self.nodes[node_id].set_pe_by_index(1, before);
209
210 self.iter_children_mut(node_id, &mut cb);
211
212 let after = self.nodes[node_id].after();
213 self.nodes[node_id].set_pe_by_index(0, None);
214 if let Some(after_node_id) = after {
215 cb(after_node_id, self)
216 }
217 self.nodes[node_id].set_pe_by_index(0, after);
218 }
219
220 pub fn next_node(&self, start: &Node, mut filter: impl FnMut(&Node) -> bool) -> Option<NodeId> {
221 let start_id = start.id;
222 let mut node = start;
223 let mut look_in_children = true;
224 loop {
225 let next = if look_in_children && !node.children.is_empty() {
227 let node_id = node.children[0];
228 &self.nodes[node_id]
229 }
230 else if let Some(parent) = node.parent_node() {
232 let self_idx = parent
233 .children
234 .iter()
235 .position(|id| *id == node.id)
236 .unwrap();
237 if let Some(sibling_id) = parent.children.get(self_idx + 1) {
239 look_in_children = true;
240 &self.nodes[*sibling_id]
241 }
242 else {
244 look_in_children = false;
245 node = parent;
246 continue;
247 }
248 }
249 else {
251 look_in_children = true;
252 self.root_node()
253 };
254
255 if filter(next) {
256 return Some(next.id);
257 } else if next.id == start_id {
258 return None;
259 }
260
261 node = next;
262 }
263 }
264
265 fn deepest_last_descendant<'a>(&'a self, mut node: &'a Node) -> &'a Node {
268 while let Some(last_child_id) = node.children.last() {
269 node = &self.nodes[*last_child_id];
270 }
271 node
272 }
273
274 pub fn prev_node(&self, start: &Node, mut filter: impl FnMut(&Node) -> bool) -> Option<NodeId> {
277 let start_id = start.id;
278 let mut node = start;
279 loop {
280 let prev = if let Some(parent) = node.parent_node() {
281 let self_idx = parent
282 .children
283 .iter()
284 .position(|id| *id == node.id)
285 .unwrap();
286 if self_idx > 0 {
289 self.deepest_last_descendant(&self.nodes[parent.children[self_idx - 1]])
290 } else {
291 parent
292 }
293 }
294 else {
296 self.deepest_last_descendant(self.root_node())
297 };
298
299 if filter(prev) {
300 return Some(prev.id);
301 } else if prev.id == start_id {
302 return None;
303 }
304
305 node = prev;
306 }
307 }
308
309 pub fn node_layout_ancestors(&self, node_id: NodeId) -> Vec<NodeId> {
310 let mut ancestors = Vec::with_capacity(12);
311 let mut maybe_id = Some(node_id);
312 while let Some(id) = maybe_id {
313 ancestors.push(id);
314 maybe_id = self.nodes[id].layout_parent.get();
315 }
316 ancestors.reverse();
317 ancestors
318 }
319
320 pub fn maybe_node_layout_ancestors(&self, node_id: Option<NodeId>) -> Vec<NodeId> {
321 node_id
322 .map(|id| self.node_layout_ancestors(id))
323 .unwrap_or_default()
324 }
325
326 pub fn compare_document_order(&self, node_a: NodeId, node_b: NodeId) -> Ordering {
331 if node_a == node_b {
332 return Ordering::Equal;
333 }
334
335 let chain_a = self.ancestor_chain_from_root(node_a);
337 let chain_b = self.ancestor_chain_from_root(node_b);
338
339 let mut common_depth = 0;
341 for (a, b) in chain_a.iter().zip(chain_b.iter()) {
342 if a != b {
343 break;
344 }
345 common_depth += 1;
346 }
347
348 if common_depth == chain_a.len() {
350 return Ordering::Less; }
352 if common_depth == chain_b.len() {
353 return Ordering::Greater; }
355
356 debug_assert!(
360 common_depth > 0,
361 "nodes must share a common ancestor (the root)"
362 );
363
364 let divergent_a = chain_a[common_depth];
366 let divergent_b = chain_b[common_depth];
367 let parent_id = chain_a[common_depth - 1];
368 let parent = &self.nodes[parent_id];
369
370 for &child_id in &parent.children {
371 if child_id == divergent_a {
372 return Ordering::Less;
373 }
374 if child_id == divergent_b {
375 return Ordering::Greater;
376 }
377 }
378
379 Ordering::Equal
381 }
382
383 fn ancestor_chain_from_root(&self, node_id: NodeId) -> Vec<NodeId> {
385 let mut ancestors = Vec::with_capacity(16);
386 let mut current = Some(node_id);
387 while let Some(id) = current {
388 ancestors.push(id);
389 current = self.nodes[id].parent;
390 }
391 ancestors.reverse();
392 ancestors
393 }
394
395 pub fn collect_inline_roots_in_range(
399 &self,
400 start_node: NodeId,
401 end_node: NodeId,
402 ) -> Vec<NodeId> {
403 let (start_anchor, start_anon) = self.resolve_for_traversal(start_node);
405 let (end_anchor, end_anon) = self.resolve_for_traversal(end_node);
406
407 if start_anon.is_some() && end_anon.is_some() && start_anchor == end_anchor {
409 return self.collect_anonymous_siblings(start_anchor, start_node, end_node);
410 }
411
412 let (first_anchor, first_anon, last_anchor, last_anon) = match self
414 .compare_document_order(start_anchor, end_anchor)
415 {
416 Ordering::Less | Ordering::Equal => (start_anchor, start_anon, end_anchor, end_anon),
417 Ordering::Greater => (end_anchor, end_anon, start_anchor, start_anon),
418 };
419
420 let mut result = Vec::new();
421 let mut found_first = false;
422
423 for node_id in TreeTraverser::new(self) {
425 if !found_first {
426 if node_id == first_anchor {
427 found_first = true;
428 if let Some(anon_id) = first_anon {
429 let stop_at = if first_anchor == last_anchor {
432 last_anon
434 } else {
435 Some(last_anchor)
437 };
438 self.collect_layout_children_inline_roots(
439 node_id,
440 Some(anon_id),
441 stop_at,
442 &mut result,
443 );
444 if result.last() == Some(&last_anchor)
446 || last_anon.is_some_and(|la| result.last() == Some(&la))
447 {
448 break;
449 }
450 continue;
451 }
452 }
453 }
454
455 if found_first {
456 if node_id == last_anchor {
457 if let Some(anon_id) = last_anon {
458 self.collect_layout_children_inline_roots(
460 node_id,
461 None,
462 Some(anon_id),
463 &mut result,
464 );
465 if !result.contains(&anon_id) {
467 result.push(anon_id);
468 }
469 } else {
470 let node = &self.nodes[node_id];
472 if node.flags.is_inline_root() && !result.contains(&node_id) {
473 result.push(node_id);
474 }
475 }
476 break;
477 }
478
479 let node = &self.nodes[node_id];
480 if node.flags.is_inline_root() && !result.contains(&node_id) {
481 result.push(node_id);
482 } else {
483 self.collect_layout_children_inline_roots(
486 node_id,
487 None,
488 Some(last_anchor),
489 &mut result,
490 );
491 }
492 }
493 }
494
495 result
496 }
497
498 fn resolve_for_traversal(&self, node_id: NodeId) -> (NodeId, Option<NodeId>) {
502 let node = &self.nodes[node_id];
503 if node.is_anonymous() {
504 (node.parent.unwrap_or(node_id), Some(node_id))
505 } else {
506 (node_id, None)
507 }
508 }
509
510 fn collect_anonymous_siblings(
513 &self,
514 parent_id: NodeId,
515 start: NodeId,
516 end: NodeId,
517 ) -> Vec<NodeId> {
518 let parent = &self.nodes[parent_id];
519 let layout_children = parent.layout_children.borrow();
520 let Some(children) = layout_children.as_ref() else {
521 return Vec::new();
522 };
523
524 let start_idx = children.iter().position(|&id| id == start);
525 let end_idx = children.iter().position(|&id| id == end);
526
527 let (first_idx, last_idx) = match (start_idx, end_idx) {
528 (Some(s), Some(e)) if s <= e => (s, e),
529 (Some(s), Some(e)) => (e, s),
530 _ => return Vec::new(),
531 };
532
533 let mut result = Vec::new();
534 for &child_id in &children[first_idx..=last_idx] {
535 let child = &self.nodes[child_id];
536 if child.flags.is_inline_root() {
537 result.push(child_id);
538 } else {
539 self.collect_all_inline_roots_in_subtree(child_id, &mut result);
541 }
542 }
543 result
544 }
545
546 fn collect_all_inline_roots_in_subtree(&self, node_id: NodeId, result: &mut Vec<NodeId>) {
548 let node = &self.nodes[node_id];
549 let layout_children = node.layout_children.borrow();
550 let Some(children) = layout_children.as_ref() else {
551 return;
552 };
553
554 for &child_id in children.iter() {
555 let child = &self.nodes[child_id];
556 if child.flags.is_inline_root() {
557 result.push(child_id);
558 } else {
559 self.collect_all_inline_roots_in_subtree(child_id, result);
561 }
562 }
563 }
564
565 fn collect_layout_children_inline_roots(
569 &self,
570 parent_id: NodeId,
571 from: Option<NodeId>,
572 until: Option<NodeId>,
573 result: &mut Vec<NodeId>,
574 ) {
575 let parent = &self.nodes[parent_id];
576 let layout_children = parent.layout_children.borrow();
577 let Some(children) = layout_children.as_ref() else {
578 return;
579 };
580
581 let mut collecting = from.is_none(); for &child_id in children.iter() {
583 if from == Some(child_id) {
584 collecting = true;
585 }
586 if collecting {
587 if let Some(until_id) = until {
589 if self.is_ancestor_of(child_id, until_id) {
590 break;
591 }
592 }
593 if until == Some(child_id) {
595 break;
596 }
597 let child = &self.nodes[child_id];
598 if child.flags.is_inline_root() {
599 result.push(child_id);
600 } else {
601 self.collect_all_inline_roots_in_subtree(child_id, result);
603 }
604 }
605 }
606 }
607
608 fn is_ancestor_of(&self, ancestor_id: NodeId, descendant_id: NodeId) -> bool {
610 let mut current = descendant_id;
611 while let Some(parent) = self.nodes[current].parent {
612 if parent == ancestor_id {
613 return true;
614 }
615 current = parent;
616 }
617 false
618 }
619}