Skip to main content

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}