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
use mdbook::book::{
Book,
BookItem,
};
use mdbook::errors::Error;
use mdbook::preprocess::*;
use regex::{
Captures,
Regex,
};
pub struct SvgbobPreprocessor;
impl Preprocessor for SvgbobPreprocessor {
fn name(&self) -> &str {
"svgbob"
}
fn run(&self, ctx: &PreprocessorContext, book: &mut Book) -> Result<(), Error> {
process(&mut book.sections)
}
}
fn process<'a, I>(items: I) -> Result<(), Error>
where
I: IntoIterator<Item = &'a mut BookItem> + 'a,
{
let re = Regex::new(r"```(?:svg)?bob\n([\S\s]+?)\n```").unwrap();
for item in items {
if let BookItem::Chapter(ref mut chapter) = item {
let res = re.replace_all(&chapter.content, |captures: &Captures| {
let bob_source = captures.get(1).unwrap().as_str();
format!("{}", svgbob::to_svg(bob_source)).replace("\n", " ")
});
chapter.content = res.to_string();
process(&mut chapter.sub_items);
}
}
Ok(())
}
pub struct TOCPreprocessor;
impl Preprocessor for TOCPreprocessor {
fn name(&self) -> &str {
"toc"
}
fn run(&self, ctx: &PreprocessorContext, book: &mut Book) -> Result<(), Error> {
for section in &mut book.sections {
if let BookItem::Chapter(ref mut chapter) = section {
if !chapter.sub_items.is_empty() {
let toc: Vec<String> = chapter
.sub_items
.iter()
.filter_map(|sub_item| {
if let BookItem::Chapter(ref chapter) = sub_item {
Some(format!(
"1. [{}]({})",
chapter.name,
chapter.path.to_string_lossy()
))
} else {
None
}
})
.collect();
chapter.content = chapter
.content
.replace("{{#toc}}", &format!("\n\n{}\n\n", toc.join("\n")));
}
}
}
Ok(())
}
}