ferris/
core_rule.rs

1// Counts the number of crabs lurking around.
2
3use super::block_rule::BlockFerris;
4use super::inline_rule::InlineFerris;
5use markdown_that::parser::core::CoreRule;
6use markdown_that::{MarkdownThat, Node, NodeValue, Renderer};
7
8#[derive(Debug)]
9// This is a structure that represents your custom Node in AST,
10// it has one single argument - crab counter.
11pub struct FerrisCounter(usize);
12
13// This defines how your custom node should be rendered.
14impl NodeValue for FerrisCounter {
15    fn render(&self, node: &Node, fmt: &mut dyn Renderer) {
16        // `node.attrs` are custom attributes added by other plugins
17        // (for example, source mapping information)
18        let mut attrs = node.attrs.clone();
19
20        // add a custom class attribute
21        attrs.push(("class", "ferris-counter".into()));
22
23        fmt.cr(); // linebreak, multiples get merged
24        fmt.open("footer", &attrs);
25        #[allow(clippy::useless_format)] // for simplicity's sake
26        fmt.text(&match self.0 {
27            0 => format!("No crabs around here."),
28            1 => format!("There is a crab lurking in this document."),
29            _ => format!("There are {} crabs lurking in this document.", self.0),
30        });
31        fmt.close("footer");
32        fmt.cr();
33    }
34}
35
36// This is an extension for the markdown parser.
37struct FerrisCounterRule;
38
39impl CoreRule for FerrisCounterRule {
40    // This is a custom function that will be invoked once per document.
41    //
42    // It has `root` node of the AST as an argument and may modify its
43    // contents as you like.
44    //
45    fn run(root: &mut Node, _: &MarkdownThat) {
46        let mut counter = 0;
47
48        // walk through AST recursively and count the number of two
49        // custom nodes added by other two rules
50        root.walk(|node, _| {
51            if node.is::<InlineFerris>() || node.is::<BlockFerris>() {
52                counter += 1;
53            }
54        });
55
56        // append a counter to the root as a custom node
57        root.children.push(Node::new(FerrisCounter(counter)))
58    }
59}
60
61pub fn add(md: &mut MarkdownThat) {
62    // insert this rule into parser
63    md.add_rule::<FerrisCounterRule>();
64}