// 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::() || node.is::() { 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::(); }