summaryrefslogtreecommitdiff
path: root/src/md/visitor/typesetting.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/md/visitor/typesetting.rs')
-rw-r--r--src/md/visitor/typesetting.rs85
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);
+ }
+ }
+ }
+ }
+}