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