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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
|
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 graph 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") {
*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);
}
}
}
}
}
|