1use crate::stream::{Event, EventKind, StreamError, Text};
6use crate::{
7 stream::{Tag, TagKind},
8 NodeSyntax,
9};
10use alloc::{collections::BTreeMap, string::String, vec::Vec};
11use core::{num::NonZeroUsize, ops::Range};
12
13#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
15#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
16pub struct NodeId(NonZeroUsize);
17
18impl NodeId {
19 fn new(index: usize) -> Self {
20 Self(NonZeroUsize::new(index + 1).expect("an arena index cannot reach usize::MAX"))
21 }
22 fn index(self) -> usize {
23 self.0.get() - 1
24 }
25}
26
27#[derive(Clone, Debug)]
29#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
30pub struct Node {
31 pub kind: EventKind<'static>,
33 pub span: Range<usize>,
35 parent: Option<NodeId>,
36 first_child: Option<NodeId>,
37 next_sibling: Option<NodeId>,
38}
39
40impl Node {
41 pub fn parent(&self) -> Option<NodeId> {
43 self.parent
44 }
45 pub fn first_child(&self) -> Option<NodeId> {
47 self.first_child
48 }
49 pub fn next_sibling(&self) -> Option<NodeId> {
51 self.next_sibling
52 }
53}
54
55#[derive(Clone, Copy, Debug, PartialEq, Eq)]
57pub enum BuildProgress {
58 Pending,
60 Complete,
62}
63
64#[derive(Debug, Default)]
66pub struct AstBuilder {
67 nodes: Vec<Node>,
68 open: Vec<NodeId>,
69 last_child: Option<NodeId>,
71 complete: bool,
72 failed: bool,
73}
74
75impl AstBuilder {
76 pub fn new() -> Self {
78 Self::default()
79 }
80
81 pub fn with_capacity(nodes: usize, depth: usize) -> Self {
83 Self {
84 nodes: Vec::with_capacity(nodes),
85 open: Vec::with_capacity(depth),
86 ..Self::default()
87 }
88 }
89
90 pub fn consume<'a>(
96 &mut self,
97 events: &mut impl Iterator<Item = Result<Event<'a>, StreamError>>,
98 budget: usize,
99 ) -> Result<BuildProgress, StreamError> {
100 if self.failed {
101 return Err(StreamError::Unbalanced);
102 }
103 if self.complete {
104 return Ok(BuildProgress::Complete);
105 }
106 for _ in 0..budget {
107 let event = match events.next() {
108 Some(Ok(event)) => event,
109 Some(Err(error)) => {
110 self.failed = true;
111 return Err(error);
112 }
113 None => {
114 if !self.open.is_empty() || self.nodes.is_empty() {
115 self.failed = true;
116 return Err(StreamError::Unbalanced);
117 }
118 self.complete = true;
119 return Ok(BuildProgress::Complete);
120 }
121 };
122 if let Err(error) = self.append(event) {
123 self.failed = true;
124 return Err(error);
125 }
126 }
127 Ok(BuildProgress::Pending)
128 }
129
130 fn append(&mut self, event: Event<'_>) -> Result<(), StreamError> {
131 event.validate(None)?;
132 let event = Event {
133 kind: event.kind.map_text(Text::owned),
134 span: event.span,
135 };
136 if let EventKind::End(kind) = event.kind {
137 let id = self.open.pop().ok_or(StreamError::Unbalanced)?;
138 let node = &mut self.nodes[id.index()];
139 if !matches!(&node.kind, EventKind::Start(tag) if tag.kind() == kind) {
140 return Err(StreamError::Unbalanced);
141 }
142 if event.span.end < node.span.end {
143 return Err(StreamError::InvalidRange);
144 }
145 node.span.end = event.span.end;
146 self.last_child = Some(id);
147 return Ok(());
148 }
149 if self.open.is_empty() {
150 if !self.nodes.is_empty()
151 || !matches!(&event.kind, EventKind::Start(tag) if tag.kind() == crate::stream::TagKind::Document)
152 {
153 return Err(StreamError::Unbalanced);
154 }
155 } else if matches!(&event.kind, EventKind::Start(tag) if tag.kind() == crate::stream::TagKind::Document)
156 {
157 return Err(StreamError::Unbalanced);
158 }
159 if let EventKind::Start(tag) = &event.kind {
160 if matches!(tag.kind(), crate::stream::TagKind::Heading | crate::stream::TagKind::FootnoteDefinition) && self.open.iter().any(|id| {
161 matches!(&self.nodes[id.index()].kind, EventKind::Start(parent) if !parent.kind().allows_descendant(tag.kind()))
162 }) {
163 return Err(StreamError::Unbalanced);
164 }
165 }
166 let id = NodeId::new(self.nodes.len());
167 let parent = self.open.last().copied();
168 let start = matches!(event.kind, EventKind::Start(_));
169 self.nodes.push(Node {
170 kind: event.kind,
171 span: event.span,
172 parent,
173 first_child: None,
174 next_sibling: None,
175 });
176 if let Some(parent) = parent {
177 if let Some(previous) = self.last_child {
178 self.nodes[previous.index()].next_sibling = Some(id);
179 } else {
180 self.nodes[parent.index()].first_child = Some(id);
181 }
182 }
183 self.last_child = if start { None } else { Some(id) };
184 if start {
185 self.open.push(id);
186 }
187 Ok(())
188 }
189
190 pub fn finish<S: AsRef<str>>(self, source: S) -> Result<Document<S>, StreamError> {
195 if self.failed || !self.complete {
196 return Err(StreamError::Unbalanced);
197 }
198 let document = Document {
199 source,
200 nodes: self.nodes,
201 syntax: BTreeMap::new(),
202 };
203 for event in document.events() {
205 event
206 .expect("arena traversal cannot fail")
207 .validate(Some(document.source()))?;
208 }
209 Ok(document)
210 }
211
212 pub fn len(&self) -> usize {
214 self.nodes.len()
215 }
216 pub fn is_empty(&self) -> bool {
218 self.nodes.is_empty()
219 }
220}
221
222#[derive(Clone, Debug)]
224#[cfg_attr(feature = "serde", derive(serde::Serialize))]
225pub struct Document<S = String> {
226 source: S,
227 nodes: Vec<Node>,
228 syntax: BTreeMap<NodeId, Option<NodeSyntax<'static>>>,
229}
230
231impl<S: AsRef<str>> Document<S> {
232 pub fn parse(source: S, options: &crate::ParseOptions) -> Result<Self, StreamError> {
237 let mut builder = AstBuilder::new();
238 {
239 let mut events = crate::EventParser::new(source.as_ref(), options);
240 if builder.consume(&mut events, usize::MAX).is_err() {
241 unreachable!("the built-in Markdown producer yields a balanced semantic stream");
242 }
243 }
244 builder.finish(source)
245 }
246
247 pub fn source(&self) -> &str {
249 self.source.as_ref()
250 }
251 pub fn nodes(&self) -> &[Node] {
253 &self.nodes
254 }
255 pub fn root(&self) -> NodeId {
257 NodeId::new(0)
258 }
259 pub fn node(&self, id: NodeId) -> Option<&Node> {
261 self.nodes.get(id.index())
262 }
263
264 pub fn set_kind(&mut self, id: NodeId, kind: EventKind<'static>) -> Result<(), StreamError> {
270 kind.validate(Some(self.source()))?;
271 let node = self
272 .nodes
273 .get(id.index())
274 .ok_or(StreamError::InvalidRange)?;
275 let document = matches!(&kind, EventKind::Start(Tag::Document(_)));
276 if matches!(&kind, EventKind::End(_))
277 || document != (id == self.root())
278 || (node.first_child.is_some() && !matches!(&kind, EventKind::Start(_)))
279 {
280 return Err(StreamError::Unbalanced);
281 }
282 if let EventKind::Start(tag) = &kind {
283 self.check_capture(node.parent, tag.kind())?;
284 if self.descendants(id).skip(1).any(|child| matches!(&self.nodes[child.index()].kind, EventKind::Start(child_tag) if !tag.kind().allows_descendant(child_tag.kind()))) {
285 return Err(StreamError::Unbalanced);
286 }
287 }
288 self.nodes[id.index()].kind = kind;
289 self.syntax.insert(id, None);
290 self.refresh_context(id);
291 self.refresh_item(self.nodes[id.index()].parent);
292 Ok(())
293 }
294
295 pub fn text_mut(&mut self, id: NodeId) -> Result<&mut String, StreamError> {
300 let body = if matches!(self.node(id), Some(Node {kind:EventKind::Opaque {value:Text::Source(range),..},span,..}) if range==span)
302 {
303 self.frontmatter_value(id).map(String::from)
304 } else {
305 None
306 };
307 let node = self
308 .nodes
309 .get_mut(id.index())
310 .ok_or(StreamError::InvalidRange)?;
311 let (EventKind::Text(text)
312 | EventKind::SoftBreak(text)
313 | EventKind::Math(text)
314 | EventKind::Code { value: text, .. }
315 | EventKind::CodeBlock { value: text, .. }
316 | EventKind::Html { value: text, .. }
317 | EventKind::Opaque { value: text, .. }) = &mut node.kind
318 else {
319 return Err(StreamError::InvalidRange);
320 };
321 if let Some(body) = body {
322 *text = Text::from(body);
323 }
324 text.to_mut(self.source.as_ref())
325 }
326
327 pub fn events(&self) -> DocumentEvents<'_, S> {
329 DocumentEvents {
330 document: self,
331 current: Some(self.root()),
332 root: self.root(),
333 closing: false,
334 }
335 }
336}
337
338pub struct DocumentEvents<'a, S> {
340 document: &'a Document<S>,
341 current: Option<NodeId>,
342 root: NodeId,
343 closing: bool,
344}
345
346fn borrow_kind<'a>(kind: &'a EventKind<'_>) -> EventKind<'a> {
348 match kind {
349 EventKind::Start(tag) => {
350 let tag = match tag {
351 crate::stream::Tag::Link { destination, title } => crate::stream::Tag::Link {
352 destination: destination.borrowed(),
353 title: title.as_ref().map(Text::borrowed),
354 },
355 crate::stream::Tag::Image { destination, title } => crate::stream::Tag::Image {
356 destination: destination.borrowed(),
357 title: title.as_ref().map(Text::borrowed),
358 },
359 crate::stream::Tag::FootnoteDefinition(value) => {
360 crate::stream::Tag::FootnoteDefinition(value.borrowed())
361 }
362 _ => tag.clone(),
363 };
364 EventKind::Start(tag)
365 }
366 EventKind::Text(value) => EventKind::Text(value.borrowed()),
367 EventKind::SoftBreak(value) => EventKind::SoftBreak(value.borrowed()),
368 EventKind::Separator { value, conditional } => EventKind::Separator {
369 value: value.borrowed(),
370 conditional: *conditional,
371 },
372 EventKind::Code { value, language } => EventKind::Code {
373 value: value.borrowed(),
374 language: language.as_ref().map(Text::borrowed),
375 },
376 EventKind::CodeBlock {
377 value,
378 language,
379 fence,
380 math,
381 unclosed,
382 } => EventKind::CodeBlock {
383 value: value.borrowed(),
384 language: language.as_ref().map(Text::borrowed),
385 fence: *fence,
386 math: *math,
387 unclosed: *unclosed,
388 },
389 EventKind::Math(value) => EventKind::Math(value.borrowed()),
390 EventKind::Html { value, block } => EventKind::Html {
391 value: value.borrowed(),
392 block: *block,
393 },
394 EventKind::Definition {
395 label,
396 destination,
397 title,
398 } => EventKind::Definition {
399 label: label.borrowed(),
400 destination: destination.borrowed(),
401 title: title.as_ref().map(Text::borrowed),
402 },
403 EventKind::Opaque { value, block } => EventKind::Opaque {
404 value: value.borrowed(),
405 block: *block,
406 },
407 EventKind::FootnoteReference(value) => EventKind::FootnoteReference(value.borrowed()),
408 _ => kind.clone(),
409 }
410}
411
412impl<'a, S: AsRef<str>> Iterator for DocumentEvents<'a, S> {
413 type Item = Result<Event<'a>, StreamError>;
414 fn next(&mut self) -> Option<Self::Item> {
415 let id = self.current?;
416 let node = &self.document.nodes[id.index()];
417 let event = if self.closing {
418 match &node.kind {
419 EventKind::Start(tag) => Event {
420 kind: EventKind::End(tag.kind()),
421 span: node.span.end..node.span.end,
422 },
423 _ => unreachable!("only container nodes are closed"),
424 }
425 } else {
426 Event {
427 kind: borrow_kind(&node.kind),
428 span: node.span.clone(),
429 }
430 };
431 if !self.closing && matches!(node.kind, EventKind::Start(_)) {
432 if let Some(child) = node.first_child {
433 self.current = Some(child);
434 } else {
435 self.closing = true;
436 }
437 } else if id == self.root {
438 self.current = None;
439 } else if let Some(sibling) = node.next_sibling {
440 self.current = Some(sibling);
441 self.closing = false;
442 } else {
443 self.current = node.parent;
444 self.closing = true;
445 }
446 Some(Ok(event))
447 }
448}
449
450#[derive(Clone)]
452pub struct Children<'a> {
453 nodes: &'a [Node],
454 current: Option<NodeId>,
455}
456impl Iterator for Children<'_> {
457 type Item = NodeId;
458 fn next(&mut self) -> Option<NodeId> {
459 let id = self.current?;
460 self.current = self.nodes[id.index()].next_sibling;
461 Some(id)
462 }
463}
464
465#[derive(Clone)]
467pub struct Descendants<'a> {
468 nodes: &'a [Node],
469 root: NodeId,
470 current: Option<NodeId>,
471}
472impl Iterator for Descendants<'_> {
473 type Item = NodeId;
474 fn next(&mut self) -> Option<NodeId> {
475 let id = self.current?;
476 self.current = next_descendant(self.nodes, self.root, id);
477 Some(id)
478 }
479}
480
481fn next_descendant(nodes: &[Node], root: NodeId, id: NodeId) -> Option<NodeId> {
483 if let Some(child) = nodes[id.index()].first_child {
484 return Some(child);
485 }
486 let mut at = id;
487 loop {
488 if at == root {
489 return None;
490 }
491 let node = &nodes[at.index()];
492 if let Some(next) = node.next_sibling {
493 return Some(next);
494 }
495 at = node
496 .parent
497 .expect("a descendant has a parent before its subtree root");
498 }
499}
500
501impl<S: AsRef<str>> Document<S> {
502 pub fn children(&self, id: NodeId) -> Children<'_> {
504 Children {
505 nodes: &self.nodes,
506 current: self.node(id).and_then(Node::first_child),
507 }
508 }
509 pub fn descendants(&self, id: NodeId) -> Descendants<'_> {
511 Descendants {
512 nodes: &self.nodes,
513 root: id,
514 current: self.node(id).map(|_| id),
515 }
516 }
517 pub fn subtree_events(&self, id: NodeId) -> DocumentEvents<'_, S> {
519 DocumentEvents {
520 document: self,
521 current: self.node(id).map(|_| id),
522 root: id,
523 closing: false,
524 }
525 }
526 pub fn text_content(&self, id: NodeId) -> String {
528 self.collect_text::<false>(id)
529 }
530 fn collect_text<const HEADING: bool>(&self, id: NodeId) -> String {
531 let mut text = String::new();
532 for child in self.descendants(id) {
533 crate::headings::append_text::<HEADING>(
534 &self.nodes[child.index()].kind,
535 self.source(),
536 &mut text,
537 );
538 }
539 text
540 }
541 pub fn headings(&self, options: &crate::HeadingOptions) -> Vec<crate::HeadingEntry> {
543 let mut anchors = crate::headings::AnchorGenerator::default();
544 let mut entries = Vec::new();
545 for id in self.descendants(self.root()) {
546 if let EventKind::Start(Tag::Heading(level)) = self.nodes[id.index()].kind {
547 let mut text = self.collect_text::<true>(id);
548 text.truncate(crate::util::line_ending::trim_terminal_ending(&text).len());
549 let anchor = anchors.anchor_for(&text);
550 if (options.min_level..=options.max_level).contains(&level) {
551 entries.push(crate::HeadingEntry {
552 node: id,
553 level,
554 text,
555 anchor,
556 });
557 }
558 }
559 }
560 entries
561 }
562 pub fn syntax(&self, id: NodeId) -> Option<NodeSyntax<'_>> {
564 let node = self.node(id)?;
565 if let Some(value) = self.syntax.get(&id) {
566 return value.as_ref().map(NodeSyntax::borrowed);
567 }
568 if matches!(node.kind, EventKind::Start(Tag::Item { .. })) {
569 let mut previous: Option<NodeId> = None;
570 for child in self
571 .children(id)
572 .filter(|id| !matches!(self.nodes[id.index()].kind, EventKind::Separator { .. }))
573 {
574 if let Some(previous) = previous {
575 let end = self.nodes[previous.index()].span.end;
576 let start = self.nodes[child.index()].span.start;
577 if let Some(gap) = self.source().get(end..start) {
578 let ended = self
579 .source()
580 .as_bytes()
581 .get(end.wrapping_sub(1))
582 .is_some_and(|byte| matches!(byte, b'\r' | b'\n'));
583 if crate::util::line_ending::line_endings(gap)
584 .nth(usize::from(!ended))
585 .is_some()
586 {
587 return Some(NodeSyntax::ListItem { spread: true });
588 }
589 }
590 }
591 previous = Some(child);
592 }
593 return Some(NodeSyntax::ListItem { spread: false });
594 }
595 crate::node_syntax::infer(self.source(), node.span.clone(), &node.kind)
596 }
597 pub fn set_syntax(
602 &mut self,
603 id: NodeId,
604 syntax: Option<NodeSyntax<'static>>,
605 ) -> Result<(), StreamError> {
606 let node = self.node(id).ok_or(StreamError::InvalidRange)?;
607 if syntax
608 .as_ref()
609 .is_some_and(|value| !value.valid_for(&node.kind, self.source()))
610 {
611 return Err(StreamError::InvalidRange);
612 }
613 self.syntax.insert(id, syntax);
614 Ok(())
615 }
616 pub fn frontmatter_value(&self, id: NodeId) -> Option<&str> {
618 let node = self.node(id)?;
619 let EventKind::Opaque { value: text, .. } = &node.kind else {
620 return None;
621 };
622 if !matches!(self.syntax(id), Some(NodeSyntax::Frontmatter { .. })) {
623 return None;
624 }
625 let value = text
626 .resolve(self.source())
627 .expect("document text is validated");
628 if let Text::Source(range) = text {
629 if *range == node.span {
630 if let Some((_, _, _, body)) = crate::node_syntax::frontmatter(value) {
631 return value.get(body);
632 }
633 }
634 }
635 Some(value)
636 }
637 pub fn render_html(
642 &self,
643 options: &crate::CompileOptions,
644 output: &mut impl core::fmt::Write,
645 ) -> Result<(), StreamError> {
646 crate::render_events(self.source(), self.events(), options, output)
647 }
648 pub fn render_node(
653 &self,
654 id: NodeId,
655 options: &crate::CompileOptions,
656 output: &mut impl core::fmt::Write,
657 ) -> Result<(), StreamError> {
658 if self.node(id).is_none() {
659 return Err(StreamError::InvalidRange);
660 }
661 if id == self.root() {
662 return self.render_html(options, output);
663 }
664 let start = Event {
665 kind: EventKind::Start(Tag::Document(None)),
666 span: 0..0,
667 };
668 let end = Event {
669 kind: EventKind::End(TagKind::Document),
670 span: self.source().len()..self.source().len(),
671 };
672 crate::render_events(
673 self.source(),
674 core::iter::once(Ok(start))
675 .chain(self.subtree_events(id))
676 .chain(core::iter::once(Ok(end))),
677 options,
678 output,
679 )
680 }
681 fn tight_paragraph(&self, id: NodeId) -> bool {
682 if !matches!(
683 self.nodes[id.index()].kind,
684 EventKind::Start(Tag::Paragraph { .. })
685 ) {
686 return false;
687 }
688 let Some(parent) = self.nodes[id.index()].parent else {
689 return false;
690 };
691 if !matches!(
692 self.nodes[parent.index()].kind,
693 EventKind::Start(Tag::Item { .. })
694 ) {
695 return false;
696 }
697 self.nodes[parent.index()].parent.is_some_and(|list| {
698 matches!(
699 self.nodes[list.index()].kind,
700 EventKind::Start(Tag::List { tight: true, .. })
701 )
702 })
703 }
704 fn refresh_item(&mut self, id: Option<NodeId>) {
705 let Some(id) = id else {
706 return;
707 };
708 if !matches!(
709 self.nodes[id.index()].kind,
710 EventKind::Start(Tag::Item { .. })
711 ) {
712 return;
713 }
714 let last = self
715 .children(id)
716 .filter(|child| {
717 !matches!(
718 self.nodes[child.index()].kind,
719 EventKind::Separator { .. }
720 | EventKind::Definition { .. }
721 | EventKind::Opaque { .. }
722 | EventKind::Start(Tag::FootnoteDefinition(_))
723 )
724 })
725 .last();
726 let block_end = last.is_some_and(|last| !self.tight_paragraph(last));
727 self.nodes[id.index()].kind = EventKind::Start(Tag::Item { block_end });
728 }
729 fn refresh_context(&mut self, root: NodeId) {
731 let mut current = Some(root);
732 while let Some(id) = current {
733 current = next_descendant(&self.nodes, root, id);
734 if matches!(
735 self.nodes[id.index()].kind,
736 EventKind::Start(Tag::Paragraph { .. })
737 ) {
738 self.nodes[id.index()].kind = EventKind::Start(Tag::Paragraph {
739 tight: self.tight_paragraph(id),
740 });
741 }
742 self.refresh_item(Some(id));
743 }
744 }
745 fn check_capture(&self, mut parent: Option<NodeId>, kind: TagKind) -> Result<(), StreamError> {
746 while let Some(id) = parent {
747 let node = &self.nodes[id.index()];
748 if matches!(&node.kind,EventKind::Start(tag) if !tag.kind().allows_descendant(kind)) {
749 return Err(StreamError::Unbalanced);
750 }
751 parent = node.parent;
752 }
753 Ok(())
754 }
755 pub fn append_child(
760 &mut self,
761 parent: NodeId,
762 kind: EventKind<'static>,
763 ) -> Result<NodeId, StreamError> {
764 kind.validate(Some(self.source()))?;
765 if !matches!(
766 self.node(parent).map(|node| &node.kind),
767 Some(EventKind::Start(_))
768 ) {
769 return Err(StreamError::Unbalanced);
770 }
771 match &kind {
772 EventKind::End(_) | EventKind::Start(Tag::Document(_)) => {
773 return Err(StreamError::Unbalanced)
774 }
775 EventKind::Start(tag) => self.check_capture(Some(parent), tag.kind())?,
776 _ => {}
777 }
778 let previous = self.children(parent).last();
779 let id = self.insert_child(parent, kind, previous, None);
780 self.refresh_context(id);
781 self.refresh_item(Some(parent));
782 Ok(id)
783 }
784 fn link_child(
786 &mut self,
787 parent: NodeId,
788 id: NodeId,
789 previous: Option<NodeId>,
790 next: Option<NodeId>,
791 ) {
792 self.nodes[id.index()].parent = Some(parent);
793 self.nodes[id.index()].next_sibling = next;
794 if let Some(previous) = previous {
795 self.nodes[previous.index()].next_sibling = Some(id);
796 } else {
797 self.nodes[parent.index()].first_child = Some(id);
798 }
799 }
800 fn insert_child(
801 &mut self,
802 parent: NodeId,
803 kind: EventKind<'static>,
804 previous: Option<NodeId>,
805 next: Option<NodeId>,
806 ) -> NodeId {
807 let id = NodeId::new(self.nodes.len());
808 self.nodes.push(Node {
809 kind,
810 span: 0..0,
811 parent: None,
812 first_child: None,
813 next_sibling: None,
814 });
815 self.link_child(parent, id, previous, next);
816 id
817 }
818 pub fn detach(&mut self, id: NodeId) -> Result<(), StreamError> {
823 if id == self.root() {
824 return Err(StreamError::Unbalanced);
825 }
826 let node = self.node(id).ok_or(StreamError::InvalidRange)?;
827 let Some(parent) = node.parent else {
828 return Ok(());
829 };
830 self.unlink_child(id, parent);
831 self.refresh_context(id);
832 self.refresh_item(Some(parent));
833 Ok(())
834 }
835 fn unlink_child(&mut self, id: NodeId, parent: NodeId) {
836 let next = self.nodes[id.index()].next_sibling;
837 if self.nodes[parent.index()].first_child == Some(id) {
838 self.nodes[parent.index()].first_child = next;
839 } else {
840 let previous = self
841 .children(parent)
842 .find(|child| self.nodes[child.index()].next_sibling == Some(id))
843 .expect("an attached node occurs in its parent's child chain");
844 self.nodes[previous.index()].next_sibling = next;
845 }
846 self.nodes[id.index()].parent = None;
847 self.nodes[id.index()].next_sibling = None;
848 }
849 pub fn attach(
854 &mut self,
855 parent: NodeId,
856 id: NodeId,
857 before: Option<NodeId>,
858 ) -> Result<(), StreamError> {
859 if id == self.root()
860 || !matches!(
861 self.node(parent).map(|node| &node.kind),
862 Some(EventKind::Start(_))
863 )
864 {
865 return Err(StreamError::Unbalanced);
866 }
867 self.node(id).ok_or(StreamError::InvalidRange)?;
868 if before.is_some_and(|before| {
869 self.node(before)
870 .map_or(true, |node| node.parent != Some(parent))
871 }) {
872 return Err(StreamError::InvalidRange);
873 }
874 let mut ancestor = Some(parent);
875 while let Some(current) = ancestor {
876 if current == id {
877 return Err(StreamError::Unbalanced);
878 }
879 ancestor = self.nodes[current.index()].parent;
880 }
881 for child in self.descendants(id) {
882 if let EventKind::Start(tag) = &self.nodes[child.index()].kind {
883 self.check_capture(Some(parent), tag.kind())?;
884 }
885 }
886 if before == Some(id) {
887 return Ok(());
888 }
889 let former_parent = self.nodes[id.index()].parent;
890 if let Some(parent) = former_parent {
891 self.unlink_child(id, parent);
892 }
893 let previous = self
894 .children(parent)
895 .take_while(|child| Some(*child) != before)
896 .last();
897 self.link_child(parent, id, previous, before);
898 self.refresh_context(id);
899 if former_parent != Some(parent) {
900 self.refresh_item(former_parent);
901 }
902 self.refresh_item(Some(parent));
903 Ok(())
904 }
905 pub fn extract_children(&mut self, parent: NodeId) -> Result<Vec<NodeId>, StreamError> {
910 self.node(parent).ok_or(StreamError::InvalidRange)?;
911 let children: Vec<_> = self.children(parent).collect();
912 self.nodes[parent.index()].first_child = None;
913 for &id in &children {
914 self.nodes[id.index()].parent = None;
915 self.nodes[id.index()].next_sibling = None;
916 self.refresh_context(id);
917 }
918 self.refresh_item(Some(parent));
919 Ok(children)
920 }
921 pub fn replace_heading_section<T: AsRef<str>>(
928 &mut self,
929 parent: NodeId,
930 heading_index: usize,
931 replacement: &Document<T>,
932 replace_heading: bool,
933 remove_subsections: bool,
934 ) -> Result<bool, StreamError> {
935 self.node(parent).ok_or(StreamError::InvalidRange)?;
936 let mut children = self.children(parent);
937 let mut previous = children.by_ref().take(heading_index).last();
938 let Some(heading) = children.next() else {
939 return Ok(false);
940 };
941 let EventKind::Start(Tag::Heading(level)) = self.nodes[heading.index()].kind else {
942 return Ok(false);
943 };
944 let first = if replace_heading {
945 Some(heading)
946 } else {
947 self.nodes[heading.index()].next_sibling
948 };
949 let mut end = self.nodes[heading.index()].next_sibling;
950 while let Some(id) = end {
951 if matches!(self.nodes[id.index()].kind,EventKind::Start(Tag::Heading(next)) if !remove_subsections || next<=level)
952 {
953 break;
954 }
955 end = self.nodes[id.index()].next_sibling;
956 }
957 if !replace_heading {
959 previous = Some(heading);
960 }
961 if first != end {
963 if let Some(previous) = previous {
964 self.nodes[previous.index()].next_sibling = end;
965 } else {
966 self.nodes[parent.index()].first_child = end;
967 }
968 let mut at = first;
969 while at != end {
970 let id = at.expect("the section ends in the selected sibling chain");
971 at = self.nodes[id.index()].next_sibling;
972 self.nodes[id.index()].parent = None;
973 self.nodes[id.index()].next_sibling = None;
974 self.refresh_context(id);
975 }
976 self.refresh_item(Some(parent));
977 }
978 for child in replacement.children(replacement.root()) {
979 previous = Some(self.copy_subtree(replacement, child, parent, previous, end));
980 }
981 Ok(true)
982 }
983 fn copy_subtree<T: AsRef<str>>(
984 &mut self,
985 source: &Document<T>,
986 root: NodeId,
987 mut parent: NodeId,
988 mut previous: Option<NodeId>,
989 before: Option<NodeId>,
990 ) -> NodeId {
991 let copied_root = NodeId::new(self.nodes.len());
992 let mut original_parent = source.nodes[root.index()].parent;
993 for original in source.descendants(root) {
994 let node = &source.nodes[original.index()];
995 while original_parent != node.parent {
997 previous = Some(parent);
998 parent = self.nodes[parent.index()]
999 .parent
1000 .expect("a copied descendant has a copied parent");
1001 original_parent = source.nodes[original_parent
1002 .expect("subtree traversal stays below its original parent")
1003 .index()]
1004 .parent;
1005 }
1006 let body = source.frontmatter_value(original);
1007 let kind = borrow_kind(&node.kind).map_text(|value| {
1008 body.map_or_else(
1009 || value.materialized(source.source()),
1010 |body| Text::from(String::from(body)),
1011 )
1012 });
1013 let next = if original == root { before } else { None };
1014 let id = self.insert_child(parent, kind, previous, next);
1015 if let Some(syntax) = source
1016 .syntax(original)
1017 .and_then(|syntax| syntax.copied(source.source()))
1018 {
1019 self.set_syntax(id, Some(syntax))
1020 .expect("materialized syntax describes the copied node kind");
1021 }
1022 if node.first_child.is_some() {
1023 original_parent = Some(original);
1024 parent = id;
1025 previous = None;
1026 } else {
1027 previous = Some(id);
1028 }
1029 }
1030 self.refresh_context(copied_root);
1031 self.refresh_item(self.nodes[copied_root.index()].parent);
1032 copied_root
1033 }
1034}
1035
1036#[cfg(feature = "serde")]
1037impl<'de> serde::Deserialize<'de> for Document<String> {
1038 fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
1039 #[derive(serde::Deserialize)]
1040 struct Stored {
1041 source: String,
1042 nodes: Vec<Node>,
1043 #[serde(default)]
1044 syntax: BTreeMap<NodeId, Option<NodeSyntax<'static>>>,
1045 }
1046 let stored = Stored::deserialize(deserializer)?;
1047 let document = Self {
1048 source: stored.source,
1049 nodes: stored.nodes,
1050 syntax: stored.syntax,
1051 };
1052 document
1053 .validate_storage()
1054 .map_err(serde::de::Error::custom)?;
1055 Ok(document)
1056 }
1057}
1058
1059#[cfg(feature = "serde")]
1060impl<S: AsRef<str>> Document<S> {
1061 fn validate_storage(&self) -> Result<(), StreamError> {
1063 if !matches!(
1064 self.nodes.first().map(|node| &node.kind),
1065 Some(EventKind::Start(Tag::Document(_)))
1066 ) {
1067 return Err(StreamError::Unbalanced);
1068 }
1069 if self.nodes[0].parent.is_some() || self.nodes[0].next_sibling.is_some() {
1070 return Err(StreamError::Unbalanced);
1071 }
1072 let mut seen = alloc::vec![false;self.nodes.len()];
1073 let mut pending = Vec::new();
1074 for (index, node) in self.nodes.iter().enumerate() {
1075 if node.parent.is_none() {
1076 if node.next_sibling.is_some() {
1077 return Err(StreamError::Unbalanced);
1078 }
1079 pending.push((NodeId::new(index), None, false));
1080 }
1081 }
1082 while let Some((id, parent, capture)) = pending.pop() {
1083 let node = self.node(id).ok_or(StreamError::InvalidRange)?;
1084 if seen[id.index()] || node.parent != parent {
1085 return Err(StreamError::Unbalanced);
1086 }
1087 seen[id.index()] = true;
1088 Event {
1089 kind: borrow_kind(&node.kind),
1090 span: node.span.clone(),
1091 }
1092 .validate(Some(self.source()))?;
1093 let container = matches!(node.kind, EventKind::Start(_));
1094 if matches!(node.kind, EventKind::End(_))
1095 || (node.first_child.is_some() && !container)
1096 || matches!(node.kind, EventKind::Start(Tag::Document(_))) != (id == self.root())
1097 {
1098 return Err(StreamError::Unbalanced);
1099 }
1100 if capture
1101 && matches!(
1102 node.kind,
1103 EventKind::Start(Tag::Heading(_) | Tag::FootnoteDefinition(_))
1104 )
1105 {
1106 return Err(StreamError::Unbalanced);
1107 }
1108 if let Some(next) = node.next_sibling {
1109 pending.push((next, parent, capture));
1110 }
1111 if let Some(child) = node.first_child {
1112 let capture = capture
1113 || matches!(
1114 node.kind,
1115 EventKind::Start(Tag::Heading(_) | Tag::Image { .. })
1116 );
1117 pending.push((child, Some(id), capture));
1118 }
1119 }
1120 if seen.iter().any(|visited| !*visited) {
1121 return Err(StreamError::Unbalanced);
1122 }
1123 for (&id, value) in &self.syntax {
1124 let node = self.node(id).ok_or(StreamError::InvalidRange)?;
1125 if value
1126 .as_ref()
1127 .is_some_and(|value| !value.valid_for(&node.kind, self.source()))
1128 {
1129 return Err(StreamError::InvalidRange);
1130 }
1131 }
1132 Ok(())
1133 }
1134}