1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
//! Traversal and querying via predicate closures.
//!
//! All traversal is depth-first pre-order (a node is visited before its
//! children). Iterators are stack-based (no recursion) to stay cheap and avoid
//! blowing the call stack on deep documents.
use crate::node::Node;
impl Node {
/// Visit `self` and every descendant, pre-order.
///
/// ```
/// use tiptap_rusty_parser::Document;
/// let doc = Document::from_json_str(r#"{"type":"doc","content":[{"type":"paragraph"}]}"#).unwrap();
/// let mut n = 0;
/// doc.root().walk(&mut |_| n += 1);
/// assert_eq!(n, 2);
/// ```
pub fn walk(&self, f: &mut impl FnMut(&Node)) {
f(self);
if let Some(children) = &self.content {
for child in children {
child.walk(f);
}
}
}
/// Mutable pre-order visit of `self` and every descendant.
pub fn walk_mut(&mut self, f: &mut impl FnMut(&mut Node)) {
f(self);
if let Some(children) = &mut self.content {
for child in children {
child.walk_mut(f);
}
}
}
/// First node (incl. `self`) matching `pred`, pre-order.
pub fn find(&self, mut pred: impl FnMut(&Node) -> bool) -> Option<&Node> {
self.descendants().find(|n| pred(n))
}
/// Mutable variant of [`Node::find`].
pub fn find_mut(&mut self, mut pred: impl FnMut(&Node) -> bool) -> Option<&mut Node> {
if pred(self) {
return Some(self);
}
let children = self.content.as_mut()?;
for child in children {
if let Some(found) = child.find_mut(&mut pred) {
return Some(found);
}
}
None
}
/// All nodes (incl. `self`) matching `pred`, pre-order.
pub fn find_all(&self, mut pred: impl FnMut(&Node) -> bool) -> Vec<&Node> {
self.descendants().filter(|n| pred(n)).collect()
}
/// Mutable variant of [`Node::find_all`]. Collects matching `&mut Node`.
pub fn find_all_mut(&mut self, pred: &mut impl FnMut(&Node) -> bool) -> Vec<&mut Node> {
let mut out = Vec::new();
self.collect_mut(pred, &mut out);
out
}
fn collect_mut<'a>(
&'a mut self,
pred: &mut impl FnMut(&Node) -> bool,
out: &mut Vec<&'a mut Node>,
) {
let matched = pred(self);
// Split borrow: push self, then recurse into children.
let children_ptr = self.content.as_mut().map(|c| c as *mut Vec<Node>);
if matched {
out.push(self);
}
// SAFETY: `content` is disjoint from the `&mut Node` pushed above
// (different field), and we never alias the same node twice.
if let Some(ptr) = children_ptr {
let children = unsafe { &mut *ptr };
for child in children {
child.collect_mut(pred, out);
}
}
}
/// Lazy pre-order iterator over `self` and all descendants.
#[inline]
pub fn descendants(&self) -> Descendants<'_> {
Descendants { stack: vec![self] }
}
}
/// Pre-order descendant iterator. See [`Node::descendants`].
pub struct Descendants<'a> {
stack: Vec<&'a Node>,
}
impl<'a> Iterator for Descendants<'a> {
type Item = &'a Node;
fn next(&mut self) -> Option<&'a Node> {
let node = self.stack.pop()?;
if let Some(children) = &node.content {
// Push in reverse so children pop in document order.
self.stack.extend(children.iter().rev());
}
Some(node)
}
}