1use crate::node::Node;
30use crate::normalize::{normalize_children, NormalizeOptions};
31use crate::range::{ensure_boundary, Position, RangeError};
32use serde_json::{Map, Value};
33use std::fmt;
34
35#[derive(Debug, Clone, PartialEq, Eq)]
37pub struct BlockRange {
38 pub parent: Vec<usize>,
40 pub start: usize,
42 pub end: usize,
44}
45
46impl BlockRange {
47 pub fn new(parent: Vec<usize>, start: usize, end: usize) -> Self {
49 Self { parent, start, end }
50 }
51
52 pub fn single(path: &[usize]) -> Self {
55 match path.split_last() {
56 Some((&i, parent)) => Self::new(parent.to_vec(), i, i + 1),
57 None => Self::new(Vec::new(), 0, 0),
58 }
59 }
60
61 pub fn len(&self) -> usize {
63 self.end.saturating_sub(self.start)
64 }
65
66 pub fn is_empty(&self) -> bool {
68 self.end <= self.start
69 }
70}
71
72#[derive(Debug, Clone, PartialEq, Eq)]
74pub enum BlockError {
75 PathNotFound {
77 path: Vec<usize>,
79 },
80 IndexOutOfRange {
82 parent: Vec<usize>,
84 index: usize,
86 },
87 NoParent,
89 NoPreviousSibling {
91 path: Vec<usize>,
93 },
94 InvalidRange {
96 parent: Vec<usize>,
98 start: usize,
100 end: usize,
102 },
103 Range(RangeError),
105}
106
107impl From<RangeError> for BlockError {
108 fn from(e: RangeError) -> Self {
109 BlockError::Range(e)
110 }
111}
112
113impl fmt::Display for BlockError {
114 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
115 match self {
116 BlockError::PathNotFound { path } => write!(f, "block: no node at path {path:?}"),
117 BlockError::IndexOutOfRange { parent, index } => {
118 write!(f, "block: index {index} out of range under {parent:?}")
119 }
120 BlockError::NoParent => write!(f, "block: operation requires a parent node"),
121 BlockError::NoPreviousSibling { path } => {
122 write!(f, "block: no previous sibling to join at {path:?}")
123 }
124 BlockError::InvalidRange { parent, start, end } => {
125 write!(f, "block: invalid range [{start},{end}) under {parent:?}")
126 }
127 BlockError::Range(e) => write!(f, "block: {e}"),
128 }
129 }
130}
131
132impl std::error::Error for BlockError {}
133
134fn with_content(meta: &Node, content: Vec<Node>) -> Node {
136 Node {
137 node_type: meta.node_type.clone(),
138 attrs: meta.attrs.clone(),
139 marks: meta.marks.clone(),
140 extra: meta.extra.clone(),
141 content: Some(content),
142 text: None,
143 }
144}
145
146impl Node {
147 pub fn set_block_type(
151 &mut self,
152 path: &[usize],
153 new_type: impl Into<String>,
154 attrs: Option<Map<String, Value>>,
155 ) -> Result<(), BlockError> {
156 let node = self.at_block(path)?;
157 node.node_type = Some(new_type.into());
158 node.attrs = attrs;
159 Ok(())
160 }
161
162 pub fn split_block(
167 &mut self,
168 path: &[usize],
169 at: usize,
170 depth: usize,
171 ) -> Result<(), BlockError> {
172 if path.is_empty() {
173 return Err(BlockError::NoParent);
174 }
175 let block = self.node_at(path).ok_or_else(|| BlockError::PathNotFound {
176 path: path.to_vec(),
177 })?;
178 let len = block.children().len();
179 if at > len {
180 return Err(BlockError::IndexOutOfRange {
181 parent: path.to_vec(),
182 index: at,
183 });
184 }
185
186 let block_mut = self.node_at_mut(path).unwrap();
188 let right_children = block_mut.children_mut().split_off(at);
189 normalize_children(block_mut.children_mut(), &NormalizeOptions::default());
190 let mut new_node = with_content(block_mut, right_children);
191 normalize_children(
192 new_node.content.as_mut().unwrap(),
193 &NormalizeOptions::default(),
194 );
195
196 let mut cur = path.to_vec();
199 for _ in 0..depth {
200 if cur.len() < 2 {
201 break; }
203 let pidx = *cur.last().unwrap();
204 let ppath = &cur[..cur.len() - 1];
205 let parent = self.node_at_mut(ppath).unwrap();
206 let following = parent.children_mut().split_off(pidx + 1);
207 let mut content = Vec::with_capacity(following.len() + 1);
208 content.push(new_node);
209 content.extend(following);
210 new_node = with_content(parent, content);
211 cur.truncate(cur.len() - 1);
212 }
213
214 let insert_idx = *cur.last().unwrap() + 1;
216 let host = self.node_at_mut(&cur[..cur.len() - 1]).unwrap();
217 host.insert_child(insert_idx, new_node);
218 Ok(())
219 }
220
221 pub fn split_block_at(
224 &mut self,
225 path: &[usize],
226 pos: Position,
227 depth: usize,
228 ) -> Result<(), BlockError> {
229 if path.is_empty() {
232 return Err(BlockError::NoParent);
233 }
234 let at = {
235 let block = self
236 .node_at_mut(path)
237 .ok_or_else(|| BlockError::PathNotFound {
238 path: path.to_vec(),
239 })?;
240 ensure_boundary(block.children_mut(), pos)?
241 };
242 self.split_block(path, at, depth)
243 }
244
245 pub fn join_blocks(&mut self, parent: &[usize], index: usize) -> Result<(), BlockError> {
249 if index == 0 {
250 let mut path = parent.to_vec();
251 path.push(0);
252 return Err(BlockError::NoPreviousSibling { path });
253 }
254 let parent_node = self
255 .node_at_mut(parent)
256 .ok_or_else(|| BlockError::PathNotFound {
257 path: parent.to_vec(),
258 })?;
259 let children = match parent_node.content.as_mut() {
260 Some(c) if index < c.len() => c,
261 _ => {
262 return Err(BlockError::IndexOutOfRange {
263 parent: parent.to_vec(),
264 index,
265 })
266 }
267 };
268 let right = children.remove(index);
269 if let Some(rc) = right.content {
270 if !rc.is_empty() {
271 let left = &mut children[index - 1];
272 left.children_mut().extend(rc);
273 normalize_children(left.children_mut(), &NormalizeOptions::default());
274 }
275 }
276 Ok(())
277 }
278
279 pub fn wrap(
281 &mut self,
282 path: &[usize],
283 wrapper_type: impl Into<String>,
284 attrs: Option<Map<String, Value>>,
285 ) -> Result<(), BlockError> {
286 self.wrap_range(&BlockRange::single(path), wrapper_type, attrs)
287 }
288
289 pub fn wrap_range(
293 &mut self,
294 range: &BlockRange,
295 wrapper_type: impl Into<String>,
296 attrs: Option<Map<String, Value>>,
297 ) -> Result<(), BlockError> {
298 let parent = self
299 .node_at_mut(&range.parent)
300 .ok_or_else(|| BlockError::PathNotFound {
301 path: range.parent.clone(),
302 })?;
303 let children = parent.children_mut();
304 if range.start > range.end || range.end > children.len() {
305 return Err(BlockError::InvalidRange {
306 parent: range.parent.clone(),
307 start: range.start,
308 end: range.end,
309 });
310 }
311 let run: Vec<Node> = children
312 .splice(range.start..range.end, std::iter::empty())
313 .collect();
314 let wrapper = Node {
315 node_type: Some(wrapper_type.into()),
316 attrs,
317 content: Some(run),
318 ..Node::default()
319 };
320 children.insert(range.start, wrapper);
321 Ok(())
322 }
323
324 pub fn lift(&mut self, path: &[usize]) -> Result<(), BlockError> {
328 let n = path.len();
329 if n < 2 {
330 return Err(BlockError::NoParent);
331 }
332 self.node_at(path).ok_or_else(|| BlockError::PathNotFound {
333 path: path.to_vec(),
334 })?;
335 let child_idx = path[n - 1];
336 let parent_idx = path[n - 2];
337
338 let parent = self.node_at_mut(&path[..n - 1]).unwrap();
340 let mut tail = parent.children_mut().split_off(child_idx);
341 let moved = tail.remove(0);
342 let right_children = tail;
343 let left_children = std::mem::take(parent.content.as_mut().unwrap());
344
345 let mut insert: Vec<Node> = Vec::with_capacity(3);
347 if !left_children.is_empty() {
348 insert.push(with_content(parent, left_children));
349 }
350 insert.push(moved);
351 if !right_children.is_empty() {
352 insert.push(with_content(parent, right_children));
353 }
354
355 let gp = self.node_at_mut(&path[..n - 2]).unwrap();
357 gp.children_mut().splice(parent_idx..parent_idx + 1, insert);
358 Ok(())
359 }
360
361 fn at_block(&mut self, path: &[usize]) -> Result<&mut Node, BlockError> {
363 self.node_at_mut(path)
364 .ok_or_else(|| BlockError::PathNotFound {
365 path: path.to_vec(),
366 })
367 }
368}