Skip to main content

tiptap_rusty_parser/
builder.rs

1//! Ergonomic constructors / builders for nodes.
2
3use crate::node::{Mark, Node};
4use serde_json::{Map, Value};
5
6impl Node {
7    /// Start an element node of `node_type` (no content/marks/attrs yet).
8    ///
9    /// ```
10    /// use tiptap_rusty_parser::Node;
11    /// let p = Node::element("paragraph")
12    ///     .with_attr("textAlign", "center")
13    ///     .with_text("hello");
14    /// assert_eq!(p.child_count(), 1);
15    /// ```
16    #[inline]
17    pub fn element(node_type: impl Into<String>) -> Node {
18        Node {
19            node_type: Some(node_type.into()),
20            ..Default::default()
21        }
22    }
23
24    /// A `text` node with the given string.
25    #[inline]
26    pub fn text(text: impl Into<String>) -> Node {
27        Node {
28            node_type: Some("text".into()),
29            text: Some(text.into()),
30            ..Default::default()
31        }
32    }
33
34    /// A `text` node with `text` and the given marks.
35    pub fn text_with_marks(text: impl Into<String>, marks: impl IntoIterator<Item = Mark>) -> Node {
36        Node {
37            node_type: Some("text".into()),
38            text: Some(text.into()),
39            marks: Some(marks.into_iter().collect()),
40            ..Default::default()
41        }
42    }
43
44    // ---- builder-style chaining ----------------------------------------
45
46    /// Builder: set one attr (consuming).
47    pub fn with_attr(mut self, key: impl Into<String>, value: impl Into<Value>) -> Self {
48        self.attrs
49            .get_or_insert_with(Map::new)
50            .insert(key.into(), value.into());
51        self
52    }
53
54    /// Builder: add a child (consuming).
55    pub fn with_child(mut self, node: Node) -> Self {
56        self.push_child(node);
57        self
58    }
59
60    /// Builder: add several children (consuming).
61    pub fn with_children(mut self, nodes: impl IntoIterator<Item = Node>) -> Self {
62        self.children_mut().extend(nodes);
63        self
64    }
65
66    /// Builder: add a `text` child (consuming).
67    pub fn with_text(self, text: impl Into<String>) -> Self {
68        self.with_child(Node::text(text))
69    }
70
71    /// Builder: add a mark (consuming).
72    pub fn with_mark(mut self, mark: Mark) -> Self {
73        self.marks.get_or_insert_with(Vec::new).push(mark);
74        self
75    }
76}
77
78/// Build a `doc` root node from its children.
79///
80/// ```
81/// use tiptap_rusty_parser::{doc, Node};
82/// let d = doc([Node::element("paragraph").with_text("hi")]);
83/// assert_eq!(d.node_type.as_deref(), Some("doc"));
84/// ```
85pub fn doc(children: impl IntoIterator<Item = Node>) -> Node {
86    Node {
87        node_type: Some("doc".into()),
88        content: Some(children.into_iter().collect()),
89        ..Default::default()
90    }
91}