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}