markdown_that/plugins/cmark/block/
code.rs1use crate::parser::block::{BlockRule, BlockState};
7use crate::{MarkdownThat, Node, NodeValue, Renderer};
8
9const CODE_INDENT: i32 = 4;
10
11#[derive(Debug)]
12pub struct CodeBlock {
13 pub content: String,
14}
15
16impl NodeValue for CodeBlock {
17 fn render(&self, node: &Node, fmt: &mut dyn Renderer) {
18 fmt.cr();
19 fmt.open("pre", &[]);
20 fmt.open("code", &node.attrs);
21 fmt.text(&self.content);
22 fmt.close("code");
23 fmt.close("pre");
24 fmt.cr();
25 }
26}
27
28pub fn add(md: &mut MarkdownThat) {
29 md.block.add_rule::<CodeScanner>();
30 md.max_indent = CODE_INDENT;
31}
32
33#[doc(hidden)]
34pub struct CodeScanner;
35impl BlockRule for CodeScanner {
36 fn check(_: &mut BlockState) -> Option<()> {
37 None
38 }
39
40 fn run(state: &mut BlockState) -> Option<(Node, usize)> {
41 if state.line_indent(state.line) < CODE_INDENT {
42 return None;
43 }
44
45 let mut next_line = state.line + 1;
46 let mut last = next_line;
47
48 while next_line < state.line_max {
49 if state.is_empty(next_line) {
50 next_line += 1;
51 continue;
52 }
53
54 if state.line_indent(next_line) >= CODE_INDENT {
55 next_line += 1;
56 last = next_line;
57 continue;
58 }
59
60 break;
61 }
62
63 let (mut content, _mapping) = state.get_lines(
64 state.line,
65 last,
66 CODE_INDENT as usize + state.blk_indent,
67 false,
68 );
69 content += "\n";
70
71 let node = Node::new(CodeBlock { content });
72 Some((node, last - state.line))
75 }
76}