markdown_that/parser/block/
mod.rs1mod state;
3pub use state::*;
4
5mod rule;
6pub use rule::*;
7
8#[doc(hidden)]
9pub mod builtin;
10
11use crate::common::TypeKey;
12use crate::common::ruler::Ruler;
13use crate::parser::extset::RootExtSet;
14use crate::parser::inline::InlineRoot;
15use crate::parser::node::NodeEmpty;
16use crate::{MarkdownThat, Node};
17
18type RuleFns = (
19 fn(&mut BlockState) -> Option<()>,
20 fn(&mut BlockState) -> Option<(Node, usize)>,
21);
22
23#[derive(Debug, Default)]
24pub struct BlockParser {
26 ruler: Ruler<TypeKey, RuleFns>,
27}
28
29impl BlockParser {
30 pub fn new() -> Self {
31 Self::default()
32 }
33
34 pub fn tokenize(&self, state: &mut BlockState) {
37 stacker::maybe_grow(64 * 1024, 1024 * 1024, || {
38 let mut has_empty_lines = false;
39
40 while state.line < state.line_max {
41 state.line = state.skip_empty_lines(state.line);
42 if state.line >= state.line_max {
43 break;
44 }
45
46 if state.line_indent(state.line) < 0 {
49 break;
50 }
51
52 if state.level >= state.md.max_nesting {
55 state.line = state.line_max;
56 break;
57 }
58
59 let mut ok = None;
66
67 for rule in self.ruler.iter() {
68 ok = rule.1(state);
69 if ok.is_some() {
70 break;
71 }
72 }
73
74 if let Some((mut node, len)) = ok {
75 state.line += len;
76 if !node.is::<NodeEmpty>() {
77 node.srcmap = state.get_map(state.line - len, state.line - 1);
78 state.node.children.push(node);
79 }
80 } else {
81 let mut content = state.get_line(state.line).to_owned();
85 content.push('\n');
86 let node = Node::new(InlineRoot::new(
87 content,
88 vec![(0, state.line_offsets[state.line].first_nonspace)],
89 ));
90 state.node.children.push(node);
91 state.line += 1;
92 }
93
94 state.tight = !has_empty_lines;
97
98 if state.is_empty(state.line - 1) {
100 has_empty_lines = true;
101 }
102
103 if state.line < state.line_max && state.is_empty(state.line) {
104 has_empty_lines = true;
105 state.line += 1;
106 }
107 }
108 });
109 }
110
111 pub fn parse(
114 &self,
115 src: &str,
116 node: Node,
117 md: &MarkdownThat,
118 root_ext: &mut RootExtSet,
119 ) -> Node {
120 let mut state = BlockState::new(src, md, root_ext, node);
121 self.tokenize(&mut state);
122 state.node
123 }
124
125 pub fn add_rule<T: BlockRule>(&mut self) -> RuleBuilder<RuleFns> {
126 let item = self.ruler.add(TypeKey::of::<T>(), (T::check, T::run));
127 RuleBuilder::new(item)
128 }
129
130 pub fn has_rule<T: BlockRule>(&mut self) -> bool {
131 self.ruler.contains(TypeKey::of::<T>())
132 }
133
134 pub fn remove_rule<T: BlockRule>(&mut self) {
135 self.ruler.remove(TypeKey::of::<T>());
136 }
137}