markdown_that/plugins/cmark/block/
paragraph.rs1use crate::parser::block::{BlockRule, BlockState};
7use crate::parser::inline::InlineRoot;
8use crate::{MarkdownThat, Node, NodeValue, Renderer};
9
10pub fn add(md: &mut MarkdownThat) {
11 md.block.add_rule::<ParagraphScanner>().after_all();
12}
13
14#[derive(Debug)]
15pub struct Paragraph;
16
17impl NodeValue for Paragraph {
18 fn render(&self, node: &Node, fmt: &mut dyn Renderer) {
19 fmt.cr();
20 fmt.open("p", &node.attrs);
21 fmt.contents(&node.children);
22 fmt.close("p");
23 fmt.cr();
24 }
25}
26
27#[doc(hidden)]
28pub struct ParagraphScanner;
29impl BlockRule for ParagraphScanner {
30 fn check(_: &mut BlockState) -> Option<()> {
31 None }
33
34 fn run(state: &mut BlockState) -> Option<(Node, usize)> {
35 let start_line = state.line;
36 let mut next_line = start_line;
37
38 'outer: loop {
40 next_line += 1;
41
42 if next_line >= state.line_max || state.is_empty(next_line) {
43 break;
44 }
45
46 if state.line_indent(next_line) >= state.md.max_indent {
49 continue;
50 }
51
52 if state.line_offsets[next_line].indent_nonspace < 0 {
54 continue;
55 }
56
57 let old_state_line = state.line;
59 state.line = next_line;
60 if state.test_rules_at_line() {
61 state.line = old_state_line;
62 break 'outer;
63 }
64 state.line = old_state_line;
65 }
66
67 let (content, mapping) = state.get_lines(start_line, next_line, state.blk_indent, false);
68
69 let mut node = Node::new(Paragraph);
70 node.children
71 .push(Node::new(InlineRoot::new(content, mapping)));
72 Some((node, next_line - start_line))
73 }
74}