markdown_it/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::ruler::Ruler;
12use crate::common::TypeKey;
13use crate::parser::extset::RootExtSet;
14use crate::parser::inline::InlineRoot;
15use crate::parser::node::NodeEmpty;
16use crate::{MarkdownIt, 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 { break; }
43
44 if state.line_indent(state.line) < 0 { break; }
47
48 if state.level >= state.md.max_nesting {
51 state.line = state.line_max;
52 break;
53 }
54
55 let mut ok = None;
62
63 for rule in self.ruler.iter() {
64 ok = rule.1(state);
65 if ok.is_some() {
66 break;
67 }
68 }
69
70 if let Some((mut node, len)) = ok {
71 state.line += len;
72 if !node.is::<NodeEmpty>() {
73 node.srcmap = state.get_map(state.line - len, state.line - 1);
74 state.node.children.push(node);
75 }
76 } else {
77 let mut content = state.get_line(state.line).to_owned();
81 content.push('\n');
82 let node = Node::new(InlineRoot::new(
83 content,
84 vec![(0, state.line_offsets[state.line].first_nonspace)],
85 ));
86 state.node.children.push(node);
87 state.line += 1;
88 }
89
90 state.tight = !has_empty_lines;
93
94 if state.is_empty(state.line - 1) {
96 has_empty_lines = true;
97 }
98
99 if state.line < state.line_max && state.is_empty(state.line) {
100 has_empty_lines = true;
101 state.line += 1;
102 }
103 }
104 });
105 }
106
107 pub fn parse(&self, src: &str, node: Node, md: &MarkdownIt, root_ext: &mut RootExtSet) -> Node {
110 let mut state = BlockState::new(src, md, root_ext, node);
111 self.tokenize(&mut state);
112 state.node
113 }
114
115 pub fn add_rule<T: BlockRule>(&mut self) -> RuleBuilder<RuleFns> {
116 let item = self.ruler.add(TypeKey::of::<T>(), (T::check, T::run));
117 RuleBuilder::new(item)
118 }
119
120 pub fn has_rule<T: BlockRule>(&mut self) -> bool {
121 self.ruler.contains(TypeKey::of::<T>())
122 }
123
124 pub fn remove_rule<T: BlockRule>(&mut self) {
125 self.ruler.remove(TypeKey::of::<T>());
126 }
127}