markdown_it/plugins/cmark/block/
heading.rs1use crate::parser::block::{BlockRule, BlockState};
7use crate::parser::inline::InlineRoot;
8use crate::{MarkdownIt, Node, NodeValue, Renderer};
9
10#[derive(Debug)]
11pub struct ATXHeading {
12 pub level: u8,
13}
14
15impl NodeValue for ATXHeading {
16 fn render(&self, node: &Node, fmt: &mut dyn Renderer) {
17 static TAG : [&str; 6] = [ "h1", "h2", "h3", "h4", "h5", "h6" ];
18 debug_assert!(self.level >= 1 && self.level <= 6);
19
20 fmt.cr();
21 fmt.open(TAG[self.level as usize - 1], &node.attrs);
22 fmt.contents(&node.children);
23 fmt.close(TAG[self.level as usize - 1]);
24 fmt.cr();
25 }
26}
27
28pub fn add(md: &mut MarkdownIt) {
29 md.block.add_rule::<HeadingScanner>();
30}
31
32#[doc(hidden)]
33pub struct HeadingScanner;
34impl BlockRule for HeadingScanner {
35 fn run(state: &mut BlockState) -> Option<(Node, usize)> {
36
37 if state.line_indent(state.line) >= state.md.max_indent { return None; }
38
39 let line = state.get_line(state.line);
40 let Some('#') = line.chars().next() else { return None; };
41
42 let text_pos;
43
44 let mut level = 0u8;
46 let mut chars = line.char_indices();
47 loop {
48 match chars.next() {
49 Some((_, '#')) => {
50 level += 1;
51 if level > 6 { return None; }
52 }
53 Some((x, ' ' | '\t')) => {
54 text_pos = x;
55 break;
56 }
57 None => {
58 text_pos = level as usize;
59 break;
60 }
61 Some(_) => return None,
62 }
63 }
64
65 let mut chars_back = chars.rev().peekable();
68 while let Some((_, ' ' | '\t')) = chars_back.peek() { chars_back.next(); }
69 while let Some((_, '#')) = chars_back.peek() { chars_back.next(); }
70
71 let text_max = match chars_back.next() {
72 Some((last_pos, ' ' | '\t')) => last_pos + 1,
74 Some(_) => line.len(),
76 None => text_pos,
78 };
79
80 let content = line[text_pos..text_max].to_owned();
81 let mapping = vec![(0, state.line_offsets[state.line].first_nonspace + text_pos)];
82
83 let mut node = Node::new(ATXHeading { level });
84 node.children.push(Node::new(InlineRoot::new(content, mapping)));
85 Some((node, 1))
86 }
87}