use crate::panhelper; use crate::typeset; use crate::{Bindings, Style, Warnings}; use pandoc_ast::{Block, Inline, MutVisitor}; /// Visitor for the pandoc AST. /// /// This includes rendering stuff which we find as we go pub struct TypesettingVisitor<'a> { style: Style, bindings: &'a Bindings, warnings: Warnings, } impl<'a> TypesettingVisitor<'a> { pub fn new(style: Style, bindings: &'a Bindings) -> Self { TypesettingVisitor { style, bindings, warnings: Warnings::default(), } } pub fn warnings(self) -> Warnings { self.warnings } } // Visit interesting parts of the Pandoc abstract syntax tree. The // document top level is a vector of blocks and we visit that and // replace any fenced code block with the scenario tag with a typeset // paragraph. Also, replace fenced code blocks with known diagram // markup with the rendered SVG image. impl<'a> MutVisitor for TypesettingVisitor<'a> { fn visit_vec_block(&mut self, vec_block: &mut Vec) { use panhelper::is_class; for block in vec_block { match block { Block::CodeBlock(attr, s) => { if is_class(attr, "scenario") { *block = typeset::scenario_snippet(self.bindings, s, &mut self.warnings) } else if is_class(attr, "file") { *block = typeset::file_block(attr, s) } else if is_class(attr, "dot") { *block = typeset::dot_to_block(s, &mut self.warnings) } else if is_class(attr, "plantuml") { *block = typeset::plantuml_to_block(s, &mut self.warnings) } else if is_class(attr, "roadmap") { *block = typeset::roadmap_to_block(s, &mut self.warnings) } else if is_class(attr, "pikchr") { let other_classes: Vec<_> = attr .1 .iter() .map(String::as_str) .filter(|s| *s != "pikchr") .collect(); let class = if other_classes.is_empty() { None } else { Some(other_classes.join(" ")) }; let class = class.as_deref(); *block = typeset::pikchr_to_block(s, class, &mut self.warnings) } } _ => { self.visit_block(block); } } } } fn visit_vec_inline(&mut self, vec_inline: &mut Vec) { for inline in vec_inline { match inline { Inline::Link(attr, vec, target) if self.style.links_as_notes() => { *inline = typeset::link_as_note(attr.clone(), vec.to_vec(), target.clone()); } _ => { self.visit_inline(inline); } } } } }