tiptap_rusty_parser/select.rs
1//! Selector helpers — convenience queries by type, mark, or attribute.
2//!
3//! Thin wrappers over the closure-based [`Node::find`] / [`Node::find_all`]
4//! primitives in [`crate::query`]. Handy when you don't want to write a closure,
5//! and a friendlier surface for future CLI / FFI layers (which can't pass Rust
6//! closures across the boundary).
7
8use crate::node::Node;
9use serde_json::Value;
10
11impl Node {
12 /// All descendants (incl. `self`) whose type equals `node_type`.
13 ///
14 /// ```
15 /// use tiptap_rusty_parser::Document;
16 /// let doc = Document::from_json_str(
17 /// r#"{"type":"doc","content":[{"type":"paragraph"},{"type":"paragraph"}]}"#,
18 /// ).unwrap();
19 /// assert_eq!(doc.by_type("paragraph").len(), 2);
20 /// ```
21 pub fn by_type(&self, node_type: &str) -> Vec<&Node> {
22 self.find_all(|n| n.node_type.as_deref() == Some(node_type))
23 }
24
25 /// First descendant (incl. `self`) whose type equals `node_type`, pre-order.
26 pub fn first_by_type(&self, node_type: &str) -> Option<&Node> {
27 self.find(|n| n.node_type.as_deref() == Some(node_type))
28 }
29
30 /// Mutable variant of [`Node::by_type`].
31 pub fn by_type_mut(&mut self, node_type: &str) -> Vec<&mut Node> {
32 let mut pred = |n: &Node| n.node_type.as_deref() == Some(node_type);
33 self.find_all_mut(&mut pred)
34 }
35
36 /// All descendants (incl. `self`) carrying a mark of `mark_type`.
37 ///
38 /// ```
39 /// use tiptap_rusty_parser::Document;
40 /// let doc = Document::from_json_str(
41 /// r#"{"type":"doc","content":[{"type":"text","text":"a","marks":[{"type":"bold"}]}]}"#,
42 /// ).unwrap();
43 /// assert_eq!(doc.by_mark("bold").len(), 1);
44 /// ```
45 pub fn by_mark(&self, mark_type: &str) -> Vec<&Node> {
46 self.find_all(|n| n.has_mark(mark_type))
47 }
48
49 /// All descendants (incl. `self`) whose attribute `key` equals `value`.
50 ///
51 /// ```
52 /// use tiptap_rusty_parser::Document;
53 /// let doc = Document::from_json_str(
54 /// r#"{"type":"doc","content":[{"type":"heading","attrs":{"level":1}}]}"#,
55 /// ).unwrap();
56 /// assert_eq!(doc.by_attr("level", 1).len(), 1);
57 /// ```
58 pub fn by_attr(&self, key: &str, value: impl Into<Value>) -> Vec<&Node> {
59 let value = value.into();
60 self.find_all(|n| n.attr(key) == Some(&value))
61 }
62}