markdown_that/parser/
main.rs

1use crate::Node;
2use crate::common::TypeKey;
3use crate::common::ruler::Ruler;
4use crate::common::sourcemap::SourcePos;
5use crate::parser::block::{self, BlockParser};
6use crate::parser::core::{Root, *};
7use crate::parser::extset::MarkdownThatExtSet;
8use crate::parser::inline::{self, InlineParser};
9use crate::parser::linkfmt::{LinkFormatter, MDLinkFormatter};
10
11type RuleFn = fn(&mut Node, &MarkdownThat);
12
13#[derive(Debug)]
14/// Main parser struct, created once and reused for parsing multiple documents.
15pub struct MarkdownThat {
16    /// Block-level tokenizer.
17    pub block: BlockParser,
18
19    /// Inline-level tokenizer.
20    pub inline: InlineParser,
21
22    /// Link validator and formatter.
23    pub link_formatter: Box<dyn LinkFormatter>,
24
25    /// Storage for custom data used in plugins.
26    pub ext: MarkdownThatExtSet,
27
28    /// Maximum depth of the generated AST, exists to prevent recursion
29    /// (if markdown source reaches this depth, deeply nested structures
30    /// will be parsed as plain text).
31    /// TODO: doesn't work
32    #[doc(hidden)]
33    pub max_nesting: u32,
34
35    /// Maximum allowed indentation for syntax blocks
36    /// default i32::MAX, indented code blocks will set this to 4
37    pub max_indent: i32,
38
39    ruler: Ruler<TypeKey, RuleFn>,
40}
41
42impl MarkdownThat {
43    pub fn new() -> Self {
44        Self::default()
45    }
46
47    pub fn parse(&self, src: &str) -> Node {
48        let mut node = Node::new(Root::new(src.to_owned()));
49        node.srcmap = Some(SourcePos::new(0, src.len()));
50
51        for rule in self.ruler.iter() {
52            rule(&mut node, self);
53            debug_assert!(
54                node.is::<Root>(),
55                "root node of the AST must always be Root"
56            );
57        }
58        node
59    }
60
61    pub fn add_rule<T: CoreRule>(&mut self) -> RuleBuilder<RuleFn> {
62        let item = self.ruler.add(TypeKey::of::<T>(), T::run);
63        RuleBuilder::new(item)
64    }
65
66    pub fn has_rule<T: CoreRule>(&mut self) -> bool {
67        self.ruler.contains(TypeKey::of::<T>())
68    }
69
70    pub fn remove_rule<T: CoreRule>(&mut self) {
71        self.ruler.remove(TypeKey::of::<T>());
72    }
73}
74
75impl Default for MarkdownThat {
76    fn default() -> Self {
77        let mut md = Self {
78            block: BlockParser::new(),
79            inline: InlineParser::new(),
80            link_formatter: Box::new(MDLinkFormatter::new()),
81            ext: MarkdownThatExtSet::new(),
82            max_nesting: 100,
83            ruler: Ruler::new(),
84            max_indent: i32::MAX,
85        };
86
87        block::builtin::add(&mut md);
88        inline::builtin::add(&mut md);
89
90        md
91    }
92}