pub struct Document { /* private fields */ }Expand description
An owned Tiptap document (its root node, usually type: "doc").
Derefs to the root Node, so all query/mutation methods are available
directly on a Document.
Implementations§
Source§impl Document
impl Document
Sourcepub fn from_json_str(s: &str) -> Result<Self>
pub fn from_json_str(s: &str) -> Result<Self>
Parse from a JSON string.
use tiptap_rusty_parser::Document;
let d = Document::from_json_str(r#"{"type":"doc","content":[]}"#).unwrap();
assert_eq!(d.node_type.as_deref(), Some("doc"));Sourcepub fn from_value(value: Value) -> Result<Self>
pub fn from_value(value: Value) -> Result<Self>
Parse from a serde_json::Value.
Sourcepub fn from_reader(reader: impl Read) -> Result<Self>
pub fn from_reader(reader: impl Read) -> Result<Self>
Parse from any reader.
Sourcepub fn to_json_str(&self) -> Result<String>
pub fn to_json_str(&self) -> Result<String>
Serialize to a compact JSON string.
Sourcepub fn to_string_pretty(&self) -> Result<String>
pub fn to_string_pretty(&self) -> Result<String>
Serialize to a pretty JSON string.
Sourcepub fn diff(&self, other: &Document) -> Vec<Change>
pub fn diff(&self, other: &Document) -> Vec<Change>
Structural diff from this document to other. See Node::diff.
Sourcepub fn apply(&mut self, changes: &[Change]) -> Result<(), ApplyError>
pub fn apply(&mut self, changes: &[Change]) -> Result<(), ApplyError>
Apply a Change list in place. See crate::apply.
Sourcepub fn invert(&self, changes: &[Change]) -> Result<Vec<Change>, ApplyError>
pub fn invert(&self, changes: &[Change]) -> Result<Vec<Change>, ApplyError>
Invert a Change list relative to this document. See crate::invert.
Sourcepub fn normalize(&mut self)
pub fn normalize(&mut self)
Normalize the document tree in place. See Node::normalize.
Sourcepub fn normalize_with(&mut self, opts: &NormalizeOptions)
pub fn normalize_with(&mut self, opts: &NormalizeOptions)
Normalize with custom options. See Node::normalize_with.
Sourcepub fn to_html(&self) -> String
pub fn to_html(&self) -> String
Render to an HTML string. See Node::to_html.
Sourcepub fn to_html_with(&self, opts: &HtmlOptions) -> String
pub fn to_html_with(&self, opts: &HtmlOptions) -> String
Render to HTML with custom options. See Node::to_html_with.
Methods from Deref<Target = Node>§
Sourcepub fn set_block_type(
&mut self,
path: &[usize],
new_type: impl Into<String>,
attrs: Option<Map<String, Value>>,
) -> Result<(), BlockError>
pub fn set_block_type( &mut self, path: &[usize], new_type: impl Into<String>, attrs: Option<Map<String, Value>>, ) -> Result<(), BlockError>
Change the type (and attrs) of the block at path in place, keeping its
content — unlike a wholesale Change::Replace.
attrs = None clears attrs. The root (&[]) may be retyped.
Sourcepub fn split_block(
&mut self,
path: &[usize],
at: usize,
depth: usize,
) -> Result<(), BlockError>
pub fn split_block( &mut self, path: &[usize], at: usize, depth: usize, ) -> Result<(), BlockError>
Split the block at path at child-boundary index at into two siblings:
the left keeps children [..at], a new right sibling takes [at..]
(same type/attrs/marks/extra). depth also splits that many ancestors
(ProseMirror-style), clamped at the root.
Sourcepub fn split_block_at(
&mut self,
path: &[usize],
pos: Position,
depth: usize,
) -> Result<(), BlockError>
pub fn split_block_at( &mut self, path: &[usize], pos: Position, depth: usize, ) -> Result<(), BlockError>
Split the block at path at an inline Position (materializing a
mid-text boundary first), then split like Node::split_block.
Sourcepub fn join_blocks(
&mut self,
parent: &[usize],
index: usize,
) -> Result<(), BlockError>
pub fn join_blocks( &mut self, parent: &[usize], index: usize, ) -> Result<(), BlockError>
Merge the block at parent[index] into its previous sibling
parent[index-1] (appending its content, re-merging inline text at the
seam). The previous sibling’s type/attrs win on a mismatch.
Sourcepub fn wrap(
&mut self,
path: &[usize],
wrapper_type: impl Into<String>,
attrs: Option<Map<String, Value>>,
) -> Result<(), BlockError>
pub fn wrap( &mut self, path: &[usize], wrapper_type: impl Into<String>, attrs: Option<Map<String, Value>>, ) -> Result<(), BlockError>
Wrap the single block at path in a new parent of wrapper_type.
Sourcepub fn wrap_range(
&mut self,
range: &BlockRange,
wrapper_type: impl Into<String>,
attrs: Option<Map<String, Value>>,
) -> Result<(), BlockError>
pub fn wrap_range( &mut self, range: &BlockRange, wrapper_type: impl Into<String>, attrs: Option<Map<String, Value>>, ) -> Result<(), BlockError>
Wrap a contiguous run of sibling blocks (one level) in a new parent of
wrapper_type. Nested structures (e.g. bulletList > listItem) are
composed by the caller.
Sourcepub fn lift(&mut self, path: &[usize]) -> Result<(), BlockError>
pub fn lift(&mut self, path: &[usize]) -> Result<(), BlockError>
Lift the block at path out of its parent into its grandparent,
splitting the parent around it so preceding/following siblings are kept
(a sole-child parent simply collapses to the lifted node).
Sourcepub fn apply(&mut self, changes: &[Change]) -> Result<(), ApplyError>
pub fn apply(&mut self, changes: &[Change]) -> Result<(), ApplyError>
Apply changes to self in order. See apply.
Sourcepub fn invert(&self, changes: &[Change]) -> Result<Vec<Change>, ApplyError>
pub fn invert(&self, changes: &[Change]) -> Result<Vec<Change>, ApplyError>
Invert changes relative to self (the pre-image). See invert.
Sourcepub fn to_html(&self) -> String
pub fn to_html(&self) -> String
Render this node (and its subtree) to an HTML string with default options.
Sourcepub fn to_html_with(&self, opts: &HtmlOptions) -> String
pub fn to_html_with(&self, opts: &HtmlOptions) -> String
Render to HTML with custom HtmlOptions.
Sourcepub fn get_mark(&self, mark_type: &str) -> Option<&Mark>
pub fn get_mark(&self, mark_type: &str) -> Option<&Mark>
Reference to the first mark of mark_type.
Sourcepub fn add_mark(&mut self, mark: Mark) -> bool
pub fn add_mark(&mut self, mark: Mark) -> bool
Add mark if no mark of that type exists yet. Returns true if added.
Sourcepub fn remove_mark(&mut self, mark_type: &str) -> usize
pub fn remove_mark(&mut self, mark_type: &str) -> usize
Remove every mark of mark_type. Returns count removed.
Sourcepub fn toggle_mark(&mut self, mark: Mark) -> bool
pub fn toggle_mark(&mut self, mark: Mark) -> bool
Toggle a mark: remove if present, else add. Returns true if now present.
Sourcepub fn set_mark_attr(
&mut self,
mark_type: &str,
key: impl Into<String>,
value: impl Into<Value>,
) -> bool
pub fn set_mark_attr( &mut self, mark_type: &str, key: impl Into<String>, value: impl Into<Value>, ) -> bool
Set an attr on the (first) mark of mark_type. Returns false if absent.
Sourcepub fn clear_marks(&mut self)
pub fn clear_marks(&mut self)
Drop all marks.
Sourcepub fn attrs_mut(&mut self) -> &mut Map<String, Value>
pub fn attrs_mut(&mut self) -> &mut Map<String, Value>
Mutable access to the attrs map, creating it if absent.
Sourcepub fn set_attr(
&mut self,
key: impl Into<String>,
value: impl Into<Value>,
) -> Option<Value>
pub fn set_attr( &mut self, key: impl Into<String>, value: impl Into<Value>, ) -> Option<Value>
Set attr key, returning the previous value if any.
Sourcepub fn remove_attr(&mut self, key: &str) -> Option<Value>
pub fn remove_attr(&mut self, key: &str) -> Option<Value>
Remove attr key, returning its value if present.
Sourcepub fn child_count(&self) -> usize
pub fn child_count(&self) -> usize
Number of direct children.
Sourcepub fn children_mut(&mut self) -> &mut Vec<Node>
pub fn children_mut(&mut self) -> &mut Vec<Node>
Mutable access to children, creating the vec if absent.
Sourcepub fn push_child(&mut self, node: Node)
pub fn push_child(&mut self, node: Node)
Append a child.
Sourcepub fn insert_child(&mut self, i: usize, node: Node)
pub fn insert_child(&mut self, i: usize, node: Node)
Insert a child at i (clamped to len).
Sourcepub fn remove_child(&mut self, i: usize) -> Option<Node>
pub fn remove_child(&mut self, i: usize) -> Option<Node>
Remove and return the child at i.
Sourcepub fn replace_child(&mut self, i: usize, node: Node) -> Option<Node>
pub fn replace_child(&mut self, i: usize, node: Node) -> Option<Node>
Replace the child at i, returning the old node.
Sourcepub fn clear_children(&mut self)
pub fn clear_children(&mut self)
Remove all children.
Sourcepub fn retain_children(&mut self, pred: impl FnMut(&Node) -> bool)
pub fn retain_children(&mut self, pred: impl FnMut(&Node) -> bool)
Retain only children matching pred.
Sourcepub fn replace_all(
&mut self,
pred: impl FnMut(&Node) -> bool,
f: impl FnMut(&mut Node),
) -> usize
pub fn replace_all( &mut self, pred: impl FnMut(&Node) -> bool, f: impl FnMut(&mut Node), ) -> usize
Apply f to every node (incl. self) matching pred. Returns count.
Sourcepub fn normalize(&mut self)
pub fn normalize(&mut self)
Normalize this subtree in place with default NormalizeOptions.
Sourcepub fn normalize_with(&mut self, opts: &NormalizeOptions)
pub fn normalize_with(&mut self, opts: &NormalizeOptions)
Normalize this subtree in place with custom NormalizeOptions.
Sourcepub fn node_at(&self, path: &[usize]) -> Option<&Node>
pub fn node_at(&self, path: &[usize]) -> Option<&Node>
Node at path (relative to self), or None if any index is missing.
use tiptap_rusty_parser::Document;
let doc = Document::from_json_str(
r#"{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"hi"}]}]}"#,
).unwrap();
assert_eq!(doc.node_at(&[0, 0]).unwrap().get_text(), Some("hi"));
assert!(doc.node_at(&[5]).is_none());Sourcepub fn node_at_mut(&mut self, path: &[usize]) -> Option<&mut Node>
pub fn node_at_mut(&mut self, path: &[usize]) -> Option<&mut Node>
Mutable variant of Node::node_at.
Sourcepub fn path_to(&self, pred: impl FnMut(&Node) -> bool) -> Option<Vec<usize>>
pub fn path_to(&self, pred: impl FnMut(&Node) -> bool) -> Option<Vec<usize>>
Path to the first node (incl. self) matching pred, pre-order.
Returns Some(vec![]) when self matches.
use tiptap_rusty_parser::Document;
let doc = Document::from_json_str(
r#"{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"hi"}]}]}"#,
).unwrap();
let p = doc.path_to(|n| n.node_type.as_deref() == Some("text")).unwrap();
assert_eq!(p, vec![0, 0]);
assert_eq!(doc.node_at(&p).unwrap().get_text(), Some("hi"));Sourcepub fn paths_to(&self, pred: impl FnMut(&Node) -> bool) -> Vec<Vec<usize>>
pub fn paths_to(&self, pred: impl FnMut(&Node) -> bool) -> Vec<Vec<usize>>
Paths to every node (incl. self) matching pred, pre-order.
Sourcepub fn node_size(&self) -> usize
pub fn node_size(&self) -> usize
ProseMirror node size with the default LeafPolicy.
Sourcepub fn node_size_with(&self, policy: &LeafPolicy) -> usize
pub fn node_size_with(&self, policy: &LeafPolicy) -> usize
ProseMirror node size under policy.
Sourcepub fn content_size(&self) -> usize
pub fn content_size(&self) -> usize
Sum of child sizes (the count of inner positions) with the default policy.
Sourcepub fn content_size_with(&self, policy: &LeafPolicy) -> usize
pub fn content_size_with(&self, policy: &LeafPolicy) -> usize
Sum of child sizes under policy.
Sourcepub fn is_leaf(&self) -> bool
pub fn is_leaf(&self) -> bool
Whether this node is a ProseMirror leaf under the default policy.
Sourcepub fn is_leaf_with(&self, policy: &LeafPolicy) -> bool
pub fn is_leaf_with(&self, policy: &LeafPolicy) -> bool
Whether this node is a ProseMirror leaf under policy (non-text, and its
type is in the leaf set).
Sourcepub fn resolve(&self, pos: usize) -> Result<ResolvedPos, PosError>
pub fn resolve(&self, pos: usize) -> Result<ResolvedPos, PosError>
Resolve a flat position with the default LeafPolicy.
Sourcepub fn resolve_with(
&self,
pos: usize,
policy: &LeafPolicy,
) -> Result<ResolvedPos, PosError>
pub fn resolve_with( &self, pos: usize, policy: &LeafPolicy, ) -> Result<ResolvedPos, PosError>
Resolve a flat position into a ResolvedPos under policy.
Sourcepub fn pos_before(&self, path: &[usize]) -> Result<usize, PosError>
pub fn pos_before(&self, path: &[usize]) -> Result<usize, PosError>
Flat position of the boundary just before the node at path (default policy).
Sourcepub fn pos_before_with(
&self,
path: &[usize],
policy: &LeafPolicy,
) -> Result<usize, PosError>
pub fn pos_before_with( &self, path: &[usize], policy: &LeafPolicy, ) -> Result<usize, PosError>
Flat position of the boundary just before the node at path under policy.
Sourcepub fn pos_after(&self, path: &[usize]) -> Result<usize, PosError>
pub fn pos_after(&self, path: &[usize]) -> Result<usize, PosError>
Flat position just after the node at path (default policy).
Sourcepub fn pos_after_with(
&self,
path: &[usize],
policy: &LeafPolicy,
) -> Result<usize, PosError>
pub fn pos_after_with( &self, path: &[usize], policy: &LeafPolicy, ) -> Result<usize, PosError>
Flat position just after the node at path under policy.
Sourcepub fn pos_in_text(
&self,
text_path: &[usize],
offset: usize,
) -> Result<usize, PosError>
pub fn pos_in_text( &self, text_path: &[usize], offset: usize, ) -> Result<usize, PosError>
Flat position at scalar offset inside the text node at text_path.
Errors if text_path is not a text node or offset exceeds its length.
Sourcepub fn pos_to_inline(
&self,
pos: usize,
) -> Result<(Vec<usize>, Position), PosError>
pub fn pos_to_inline( &self, pos: usize, ) -> Result<(Vec<usize>, Position), PosError>
Map a flat position to the (block path, inline Position) pair used by
the inline range-editing API (Node::insert_text etc.), with the
default policy. The block path is the resolved container.
Sourcepub fn inline_to_pos(
&self,
block_path: &[usize],
inline: Position,
) -> Result<usize, PosError>
pub fn inline_to_pos( &self, block_path: &[usize], inline: Position, ) -> Result<usize, PosError>
Inverse of Node::pos_to_inline: the flat position for a block-local
inline Position (default policy).
Sourcepub fn walk(&self, f: &mut impl FnMut(&Node))
pub fn walk(&self, f: &mut impl FnMut(&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);Sourcepub fn walk_mut(&mut self, f: &mut impl FnMut(&mut Node))
pub fn walk_mut(&mut self, f: &mut impl FnMut(&mut Node))
Mutable pre-order visit of self and every descendant.
Sourcepub fn find(&self, pred: impl FnMut(&Node) -> bool) -> Option<&Node>
pub fn find(&self, pred: impl FnMut(&Node) -> bool) -> Option<&Node>
First node (incl. self) matching pred, pre-order.
Sourcepub fn find_mut(&mut self, pred: impl FnMut(&Node) -> bool) -> Option<&mut Node>
pub fn find_mut(&mut self, pred: impl FnMut(&Node) -> bool) -> Option<&mut Node>
Mutable variant of Node::find.
Sourcepub fn find_all(&self, pred: impl FnMut(&Node) -> bool) -> Vec<&Node>
pub fn find_all(&self, pred: impl FnMut(&Node) -> bool) -> Vec<&Node>
All nodes (incl. self) matching pred, pre-order.
Sourcepub fn find_all_mut(
&mut self,
pred: &mut impl FnMut(&Node) -> bool,
) -> Vec<&mut Node>
pub fn find_all_mut( &mut self, pred: &mut impl FnMut(&Node) -> bool, ) -> Vec<&mut Node>
Mutable variant of Node::find_all. Collects matching &mut Node.
Sourcepub fn descendants(&self) -> Descendants<'_> ⓘ
pub fn descendants(&self) -> Descendants<'_> ⓘ
Lazy pre-order iterator over self and all descendants.
Sourcepub fn insert_text(
&mut self,
pos: Position,
text: &str,
marks: Option<&[Mark]>,
) -> Result<(), RangeError>
pub fn insert_text( &mut self, pos: Position, text: &str, marks: Option<&[Mark]>, ) -> Result<(), RangeError>
Insert text (with optional marks) at pos in this block’s inline
content, splitting the target text node if needed and merging with
adjacent equal-mark text afterwards.
Sourcepub fn delete_range(&mut self, range: Range) -> Result<(), RangeError>
pub fn delete_range(&mut self, range: Range) -> Result<(), RangeError>
Delete everything in range, splitting text nodes at the boundaries and
removing fully-covered inline nodes. A collapsed range is a no-op.
Sourcepub fn replace_range(
&mut self,
range: Range,
text: &str,
marks: Option<&[Mark]>,
) -> Result<(), RangeError>
pub fn replace_range( &mut self, range: Range, text: &str, marks: Option<&[Mark]>, ) -> Result<(), RangeError>
Replace range with text (carrying optional marks).
Sourcepub fn add_mark_range(
&mut self,
range: Range,
mark: Mark,
) -> Result<(), RangeError>
pub fn add_mark_range( &mut self, range: Range, mark: Mark, ) -> Result<(), RangeError>
Add mark to every text node covered by range (splitting at the
boundaries first), then re-merge equal-mark neighbours.
Sourcepub fn remove_mark_range(
&mut self,
range: Range,
mark_type: &str,
) -> Result<(), RangeError>
pub fn remove_mark_range( &mut self, range: Range, mark_type: &str, ) -> Result<(), RangeError>
Remove every mark of mark_type from text nodes covered by range.
Sourcepub fn toggle_mark_range(
&mut self,
range: Range,
mark: Mark,
) -> Result<(), RangeError>
pub fn toggle_mark_range( &mut self, range: Range, mark: Mark, ) -> Result<(), RangeError>
Toggle mark over range: if every covered text node already has a
mark of that type, remove it from all; otherwise add it to all. Mirrors
the ProseMirror toggle semantics, range-scoped.
Sourcepub fn validate(&self, schema: &Schema) -> Vec<Violation>
pub fn validate(&self, schema: &Schema) -> Vec<Violation>
Validate against schema, collecting every Violation. An empty
result means the document is valid.
use tiptap_rusty_parser::{Document, Schema, NodeSpec};
let schema = Schema::new()
.node("doc", NodeSpec::new().content(["paragraph"]))
.node("paragraph", NodeSpec::new())
.node("heading", NodeSpec::new());
let doc = Document::from_json_str(
r#"{"type":"doc","content":[{"type":"heading"}]}"#,
).unwrap();
let v = doc.validate(&schema);
assert_eq!(v.len(), 1); // heading is a known type, but not allowed as a child of docSourcepub fn is_valid(&self, schema: &Schema) -> bool
pub fn is_valid(&self, schema: &Schema) -> bool
True if the document has no schema violations.
use tiptap_rusty_parser::{Document, Schema, NodeSpec};
let schema = Schema::new().node("doc", NodeSpec::new());
let doc = Document::from_json_str(r#"{"type":"doc"}"#).unwrap();
assert!(doc.is_valid(&schema));Sourcepub fn by_type(&self, node_type: &str) -> Vec<&Node>
pub fn by_type(&self, node_type: &str) -> Vec<&Node>
All descendants (incl. self) whose type equals node_type.
use tiptap_rusty_parser::Document;
let doc = Document::from_json_str(
r#"{"type":"doc","content":[{"type":"paragraph"},{"type":"paragraph"}]}"#,
).unwrap();
assert_eq!(doc.by_type("paragraph").len(), 2);Sourcepub fn first_by_type(&self, node_type: &str) -> Option<&Node>
pub fn first_by_type(&self, node_type: &str) -> Option<&Node>
First descendant (incl. self) whose type equals node_type, pre-order.
Sourcepub fn by_type_mut(&mut self, node_type: &str) -> Vec<&mut Node>
pub fn by_type_mut(&mut self, node_type: &str) -> Vec<&mut Node>
Mutable variant of Node::by_type.
Sourcepub fn by_mark(&self, mark_type: &str) -> Vec<&Node>
pub fn by_mark(&self, mark_type: &str) -> Vec<&Node>
All descendants (incl. self) carrying a mark of mark_type.
use tiptap_rusty_parser::Document;
let doc = Document::from_json_str(
r#"{"type":"doc","content":[{"type":"text","text":"a","marks":[{"type":"bold"}]}]}"#,
).unwrap();
assert_eq!(doc.by_mark("bold").len(), 1);Sourcepub fn by_attr(&self, key: &str, value: impl Into<Value>) -> Vec<&Node>
pub fn by_attr(&self, key: &str, value: impl Into<Value>) -> Vec<&Node>
All descendants (incl. self) whose attribute key equals value.
use tiptap_rusty_parser::Document;
let doc = Document::from_json_str(
r#"{"type":"doc","content":[{"type":"heading","attrs":{"level":1}}]}"#,
).unwrap();
assert_eq!(doc.by_attr("level", 1).len(), 1);Sourcepub fn text_content(&self) -> String
pub fn text_content(&self) -> String
Concatenate all descendant text, with no separators.
Matches ProseMirror’s node.textContent.
use tiptap_rusty_parser::Document;
let doc = Document::from_json_str(
r#"{"type":"doc","content":[
{"type":"paragraph","content":[{"type":"text","text":"Hello "},{"type":"text","text":"world"}]}
]}"#,
).unwrap();
assert_eq!(doc.text_content(), "Hello world");Sourcepub fn text_content_with_separator(&self, sep: &str) -> String
pub fn text_content_with_separator(&self, sep: &str) -> String
Concatenate descendant text, inserting sep between adjacent block-level
siblings (a node is “block-level” if it has content and is not a text
node). Text within a block stays contiguous.
use tiptap_rusty_parser::Document;
let doc = Document::from_json_str(
r#"{"type":"doc","content":[
{"type":"paragraph","content":[{"type":"text","text":"Hello"}]},
{"type":"paragraph","content":[{"type":"text","text":"world"}]}
]}"#,
).unwrap();
assert_eq!(doc.text_content_with_separator("\n\n"), "Hello\n\nworld");Sourcepub fn char_count(&self) -> usize
pub fn char_count(&self) -> usize
Total number of Unicode scalar values across all descendant text.
Sourcepub fn word_count(&self) -> usize
pub fn word_count(&self) -> usize
Number of words across all text, via Unicode word segmentation.
Blocks are separated by a space first, so words don’t merge across block boundaries. Correct for CJK and other complex scripts.
use tiptap_rusty_parser::Document;
let doc = Document::from_json_str(
r#"{"type":"doc","content":[
{"type":"paragraph","content":[{"type":"text","text":"Hello"}]},
{"type":"paragraph","content":[{"type":"text","text":"brave world"}]}
]}"#,
).unwrap();
assert_eq!(doc.word_count(), 3);