1use std::sync::Arc;
5
6use crate::attrs::Attrs;
7use crate::fragment::Fragment;
8use crate::mark::Mark;
9use crate::schema::NodeSpec;
10
11#[derive(Debug)]
12pub(crate) struct NodeTypeInner {
13 pub(crate) id: usize,
14 pub(crate) name: String,
15 pub(crate) spec: NodeSpec,
16 pub(crate) groups: Vec<String>,
17 pub(crate) is_text: bool,
18 pub(crate) content_is_empty: bool,
20}
21
22#[derive(Debug, Clone)]
24pub struct NodeType(pub(crate) Arc<NodeTypeInner>);
25
26impl NodeType {
27 pub fn name(&self) -> &str {
29 &self.0.name
30 }
31
32 pub fn id(&self) -> usize {
34 self.0.id
35 }
36
37 pub fn spec(&self) -> &NodeSpec {
39 &self.0.spec
40 }
41
42 pub fn is_text(&self) -> bool {
44 self.0.is_text
45 }
46
47 pub fn is_inline(&self) -> bool {
49 self.0.is_text || self.0.spec.inline
50 }
51
52 pub fn is_block(&self) -> bool {
56 !self.is_inline()
57 }
58
59 pub fn is_leaf(&self) -> bool {
62 self.0.content_is_empty
63 }
64
65 pub fn is_atom(&self) -> bool {
68 self.0.spec.atom || self.is_leaf()
69 }
70
71 pub fn is_in_group(&self, group: &str) -> bool {
73 self.0.groups.iter().any(|g| g == group)
74 }
75}
76
77impl PartialEq for NodeType {
78 fn eq(&self, other: &Self) -> bool {
79 self.0.id == other.0.id
80 }
81}
82impl Eq for NodeType {}
83
84#[derive(Debug)]
85pub(crate) struct NodeInner {
86 pub(crate) type_: NodeType,
87 pub(crate) attrs: Attrs,
88 pub(crate) content: Fragment,
89 pub(crate) marks: Vec<Mark>,
90 pub(crate) text: Option<String>,
92}
93
94#[derive(Debug, Clone)]
102pub struct Node(pub(crate) Arc<NodeInner>);
103
104impl Node {
105 pub(crate) fn new_element(
106 type_: NodeType,
107 attrs: Attrs,
108 content: Fragment,
109 marks: Vec<Mark>,
110 ) -> Node {
111 Node(Arc::new(NodeInner {
112 type_,
113 attrs,
114 content,
115 marks,
116 text: None,
117 }))
118 }
119
120 pub(crate) fn new_text(type_: NodeType, text: String, marks: Vec<Mark>) -> Node {
121 Node(Arc::new(NodeInner {
122 type_,
123 attrs: Attrs::new(),
124 content: Fragment::empty(),
125 marks,
126 text: Some(text),
127 }))
128 }
129
130 pub fn node_type(&self) -> &NodeType {
132 &self.0.type_
133 }
134
135 pub fn attrs(&self) -> &Attrs {
137 &self.0.attrs
138 }
139
140 pub fn content(&self) -> &Fragment {
142 &self.0.content
143 }
144
145 pub fn marks(&self) -> &[Mark] {
147 &self.0.marks
148 }
149
150 pub fn text(&self) -> Option<&str> {
152 self.0.text.as_deref()
153 }
154
155 pub fn is_text(&self) -> bool {
157 self.0.text.is_some()
158 }
159
160 pub fn is_leaf(&self) -> bool {
162 self.0.type_.is_leaf()
163 }
164
165 pub fn is_inline(&self) -> bool {
167 self.0.type_.is_inline()
168 }
169
170 pub fn is_block(&self) -> bool {
172 self.0.type_.is_block()
173 }
174
175 pub fn child_count(&self) -> usize {
177 self.0.content.child_count()
178 }
179
180 pub fn child(&self, i: usize) -> &Node {
185 self.0.content.child(i)
186 }
187
188 pub fn node_size(&self) -> usize {
190 if let Some(t) = &self.0.text {
191 t.chars().count()
192 } else if self.0.type_.is_leaf() {
193 1
194 } else {
195 self.0.content.size() + 2
196 }
197 }
198
199 pub fn text_content(&self) -> String {
201 if let Some(t) = &self.0.text {
202 return t.clone();
203 }
204 let mut s = String::new();
205 for child in self.0.content.iter() {
206 s.push_str(&child.text_content());
207 }
208 s
209 }
210
211 pub fn with_marks(&self, marks: Vec<Mark>) -> Node {
213 let inner = &*self.0;
214 Node(Arc::new(NodeInner {
215 type_: inner.type_.clone(),
216 attrs: inner.attrs.clone(),
217 content: inner.content.clone(),
218 marks,
219 text: inner.text.clone(),
220 }))
221 }
222
223 pub(crate) fn copy_content(&self, content: Fragment) -> Node {
227 debug_assert!(self.0.text.is_none(), "copy_content on a text node");
228 let inner = &*self.0;
229 Node(Arc::new(NodeInner {
230 type_: inner.type_.clone(),
231 attrs: inner.attrs.clone(),
232 content,
233 marks: inner.marks.clone(),
234 text: None,
235 }))
236 }
237
238 pub(crate) fn with_text(&self, text: String) -> Node {
240 debug_assert!(self.0.text.is_some(), "with_text on a non-text node");
241 Node::new_text(self.0.type_.clone(), text, self.0.marks.clone())
242 }
243
244 pub(crate) fn same_markup(&self, other: &Node) -> bool {
247 self.0.type_ == other.0.type_
248 && self.0.attrs == other.0.attrs
249 && self.0.marks == other.0.marks
250 }
251
252 pub(crate) fn with_attrs(&self, attrs: Attrs) -> Node {
255 let inner = &*self.0;
256 Node(Arc::new(NodeInner {
257 type_: inner.type_.clone(),
258 attrs,
259 content: inner.content.clone(),
260 marks: inner.marks.clone(),
261 text: inner.text.clone(),
262 }))
263 }
264
265 pub fn node_at(&self, pos: usize) -> Option<Node> {
269 let mut node = self.clone();
270 let mut pos = pos;
271 loop {
272 let (index, offset) = node.0.content.find_index(pos);
273 let child = node.0.content.children().get(index)?.clone();
274 if offset == pos || child.is_text() {
275 return Some(child);
276 }
277 pos -= offset + 1;
278 node = child;
279 }
280 }
281
282 pub(crate) fn cut(&self, from: usize, to: usize) -> Node {
285 if let Some(t) = &self.0.text {
286 let chars: Vec<char> = t.chars().collect();
287 let to = to.min(chars.len());
288 if from == 0 && to == chars.len() {
289 return self.clone();
290 }
291 return self.with_text(chars[from..to].iter().collect());
292 }
293 if from == 0 && to == self.0.content.size() {
294 return self.clone();
295 }
296 self.copy_content(self.0.content.cut(from, to))
297 }
298}
299
300impl PartialEq for Node {
301 fn eq(&self, other: &Self) -> bool {
302 if Arc::ptr_eq(&self.0, &other.0) {
303 return true;
304 }
305 self.0.type_ == other.0.type_
306 && self.0.text == other.0.text
307 && self.0.attrs == other.0.attrs
308 && self.0.marks == other.0.marks
309 && self.0.content == other.0.content
310 }
311}
312impl Eq for Node {}