diff options
Diffstat (limited to 'src/md/visitor/typesetting.rs')
-rw-r--r-- | src/md/visitor/typesetting.rs | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/src/md/visitor/typesetting.rs b/src/md/visitor/typesetting.rs new file mode 100644 index 0000000..2405c03 --- /dev/null +++ b/src/md/visitor/typesetting.rs @@ -0,0 +1,85 @@ +use crate::md::panhelper; +use crate::md::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<Block>) { + 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") || is_class(attr, "example") { + *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<Inline>) { + 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); + } + } + } + } +} |