markdown_syntax/
leaves.rs1use alloc::string::String;
6use alloc::vec::Vec;
7
8use crate::ast::*;
9use crate::parse::Definitions;
10use crate::span::Span;
11
12pub(crate) struct LeafMut<'a> {
15 pub(crate) span: Option<Span>,
16 pub(crate) inlines: &'a mut Vec<Inline>,
17 pub(crate) source: &'a mut Option<String>,
18}
19
20pub(crate) fn visit(
23 blocks: &[Block],
24 path: &mut Vec<usize>,
25 visit_leaf: &mut impl FnMut(&[usize], Option<Span>, Option<&str>),
26) {
27 for (index, block) in blocks.iter().enumerate() {
28 path.push(index);
29 match block {
30 Block::Paragraph(node) => visit_leaf(path, node.meta.span, node.source.as_deref()),
31 Block::Heading(node) => visit_leaf(path, node.meta.span, node.source.as_deref()),
32 Block::LeafDirective(node) => {
33 visit_leaf(path, node.meta.span, node.label_source.as_deref())
34 }
35 Block::ContainerDirective(node) => {
36 visit_leaf(path, node.meta.span, node.label_source.as_deref());
37 visit(&node.children, path, visit_leaf);
38 }
39 Block::Table(node) => {
40 for (row, cells) in node.rows.iter().enumerate() {
41 for (cell, node) in cells.cells.iter().enumerate() {
42 path.extend([row, cell]);
43 visit_leaf(path, node.meta.span, node.source.as_deref());
44 path.truncate(path.len() - 2);
45 }
46 }
47 }
48 Block::BlockQuote(node) => visit(&node.children, path, visit_leaf),
49 Block::Alert(node) => visit(&node.children, path, visit_leaf),
50 Block::FootnoteDefinition(node) => visit(&node.children, path, visit_leaf),
51 Block::HtmlContainer(node) => match &node.content {
52 HtmlContainerContent::Blocks(children) => visit(children, path, visit_leaf),
53 HtmlContainerContent::Inlines(_) => {}
54 },
55 Block::List(node) => {
56 for (item, node) in node.children.iter().enumerate() {
57 path.push(item);
58 visit(&node.children, path, visit_leaf);
59 path.pop();
60 }
61 }
62 Block::ThematicBreak(_)
63 | Block::CodeBlock(_)
64 | Block::HtmlBlock(_)
65 | Block::Definition(_)
66 | Block::MathBlock(_)
67 | Block::Frontmatter(_)
68 | Block::BlankLine(_) => {}
69 }
70 path.pop();
71 }
72}
73
74pub(crate) fn visit_mut(blocks: &mut [Block], visit_leaf: &mut impl FnMut(LeafMut<'_>)) {
76 for block in blocks {
77 match block {
78 Block::Paragraph(node) => visit_leaf(LeafMut {
79 span: node.meta.span,
80 inlines: &mut node.children,
81 source: &mut node.source,
82 }),
83 Block::Heading(node) => visit_leaf(LeafMut {
84 span: node.meta.span,
85 inlines: &mut node.children,
86 source: &mut node.source,
87 }),
88 Block::LeafDirective(node) => visit_leaf(LeafMut {
89 span: node.meta.span,
90 inlines: &mut node.label,
91 source: &mut node.label_source,
92 }),
93 Block::ContainerDirective(node) => {
94 visit_leaf(LeafMut {
95 span: node.meta.span,
96 inlines: &mut node.label,
97 source: &mut node.label_source,
98 });
99 visit_mut(&mut node.children, visit_leaf);
100 }
101 Block::Table(node) => {
102 for cell in node.rows.iter_mut().flat_map(|row| &mut row.cells) {
103 visit_leaf(LeafMut {
104 span: cell.meta.span,
105 inlines: &mut cell.children,
106 source: &mut cell.source,
107 });
108 }
109 }
110 Block::BlockQuote(node) => visit_mut(&mut node.children, visit_leaf),
111 Block::Alert(node) => visit_mut(&mut node.children, visit_leaf),
112 Block::FootnoteDefinition(node) => visit_mut(&mut node.children, visit_leaf),
113 Block::HtmlContainer(node) => match &mut node.content {
114 HtmlContainerContent::Blocks(children) => visit_mut(children, visit_leaf),
115 HtmlContainerContent::Inlines(_) => {}
116 },
117 Block::List(node) => {
118 for item in &mut node.children {
119 visit_mut(&mut item.children, visit_leaf);
120 }
121 }
122 Block::ThematicBreak(_)
123 | Block::CodeBlock(_)
124 | Block::HtmlBlock(_)
125 | Block::Definition(_)
126 | Block::MathBlock(_)
127 | Block::Frontmatter(_)
128 | Block::BlankLine(_) => {}
129 }
130 }
131}
132
133pub(crate) fn any_kept(blocks: &[Block]) -> bool {
135 let mut kept = false;
136 visit(blocks, &mut Vec::new(), &mut |_, _, source| {
137 kept |= source.is_some()
138 });
139 kept
140}
141
142impl Document {
143 pub fn reread_kept_sources(&mut self) {
151 let definitions = Definitions::of(self);
152 visit_mut(&mut self.children, &mut |leaf| {
153 if let Some(text) = leaf.source.as_deref() {
154 *leaf.inlines = crate::parse::parse_inline_tree(text, &definitions).inlines;
155 }
156 });
157 }
158}