markdown_it/parser/inline/builtin/
inline_parser.rs

1use crate::parser::block::builtin::BlockParserRule;
2use crate::parser::core::{CoreRule, Root};
3use crate::parser::extset::{InlineRootExtSet, RootExtSet};
4use crate::{MarkdownIt, Node, NodeValue};
5
6#[derive(Debug)]
7/// Temporary node which gets replaced with inline nodes when
8/// [InlineParser](crate::parser::inline::InlineParser) is called.
9pub struct InlineRoot {
10    pub content: String,
11    pub mapping: Vec<(usize, usize)>,
12    pub ext: InlineRootExtSet,
13}
14
15impl InlineRoot {
16    pub fn new(content: String, mapping: Vec<(usize, usize)>) -> Self {
17        Self { content, mapping, ext: InlineRootExtSet::new() }
18    }
19}
20
21// this token is supposed to be replaced by one or many actual tokens by inline rule
22impl NodeValue for InlineRoot {}
23
24pub fn add(md: &mut MarkdownIt) {
25    md.add_rule::<InlineParserRule>()
26        .after::<BlockParserRule>()
27        .before_all();
28}
29
30pub struct InlineParserRule;
31impl CoreRule for InlineParserRule {
32    fn run(root: &mut Node, md: &MarkdownIt) {
33        fn walk_recursive(node: &mut Node, md: &MarkdownIt, root_ext: &mut RootExtSet) {
34            let mut idx = 0;
35            while idx < node.children.len() {
36                let child = &mut node.children[idx];
37                if let Some(data) = child.cast_mut::<InlineRoot>() {
38                    let content = std::mem::take(&mut data.content);
39                    let mapping = std::mem::take(&mut data.mapping);
40                    let mut inline_ext = std::mem::take(&mut data.ext);
41
42                    let mut root = std::mem::take(child);
43                    root.ext = std::mem::take(&mut node.ext);
44                    root.children = Vec::new();
45                    root = md.inline.parse(content, mapping, root, md, root_ext, &mut inline_ext);
46
47                    let len = root.children.len();
48                    node.children.splice(idx..=idx, std::mem::take(&mut root.children));
49                    node.ext = std::mem::take(&mut root.ext);
50                    idx += len;
51                } else {
52                    stacker::maybe_grow(64*1024, 1024*1024, || {
53                        walk_recursive(child, md, root_ext);
54                    });
55                    idx += 1;
56                }
57            }
58        }
59
60        let data = root.cast_mut::<Root>().unwrap();
61        let mut root_ext = std::mem::take(&mut data.ext);
62
63        // this is invalid if input only contains reference;
64        // so if user disables block parser, he must insert smth like this instead
65        /*if root.children.is_empty() {
66            // block parser disabled, parse as if input was one big inline block
67            let data = root.cast_mut::<Root>().unwrap();
68            let node = Node::new(InlineRoot {
69                content: data.content.clone(),
70                mapping: vec![(0, 0)],
71            });
72            root.children.push(node);
73        }*/
74
75        walk_recursive(root, md, &mut root_ext);
76
77        let data = root.cast_mut::<Root>().unwrap();
78        data.ext = root_ext;
79    }
80}