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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
|
use std::{collections::HashMap, path::Path};
use log::trace;
use pandoc_ast::MutVisitor;
// If a link points to `./a/b/c.ext`, and a file in the output directory `pdbook/./a/b/c.html`
// exists, rewrite that link.
pub struct RelativizeUrls<'a> {
pub config: &'a crate::config::Config,
pub extension: &'a str,
pub build_dir: &'a Path,
pub source_dir: &'a Path,
}
impl<'a> pandoc_ast::MutVisitor for RelativizeUrls<'a> {
fn walk_inline(&mut self, inline: &mut pandoc_ast::Inline) {
let link = match inline {
pandoc_ast::Inline::Link(_, _, target) => &mut target.0,
_ => return,
};
if link.starts_with('#') || link.contains("://") {
return;
}
let link_path = self.source_dir.join(&link);
if link_path.is_absolute() {
return;
}
let mut output_path = self.build_dir.join(&link_path);
if !output_path.set_extension(self.extension) {
return;
}
trace!("Checking output_path: {:?}", output_path);
// TODO: warn when referencing a "markdown or other" file not specified in the summary
if output_path.exists() {
// TODO: relativize from URL root
trace!("Relativizing link '{}'", link_path.display());
*link = Path::new(link)
.with_extension(&self.extension)
.to_str()
.expect("Path constructed from UTF-8 valid strings in not UTF-8 valid")
.to_string();
trace!("-> into '{}'", link);
}
}
}
// Applied just to the summary
pub struct RelativizeSummary {
level: usize,
}
impl pandoc_ast::MutVisitor for RelativizeSummary {
fn walk_inline(&mut self, inline: &mut pandoc_ast::Inline) {
if self.level == 0 {
return;
}
let link = match inline {
pandoc_ast::Inline::Link(_, _, target) => &mut target.0,
_ => return,
};
// Assume link is to a managed file
for _ in 0..self.level {
link.insert_str(0, "../");
}
}
}
pub fn relativize_summary(summary: &pandoc_ast::Pandoc, level: usize) -> pandoc_ast::Pandoc {
use std::sync::RwLock;
lazy_static::lazy_static! {
static ref CACHE: RwLock<HashMap<usize, pandoc_ast::Pandoc>> = RwLock::new(HashMap::new());
}
CACHE
.write()
.expect("Relativized summary cache poison")
.entry(level)
.or_insert_with(|| {
let mut summary = summary.clone();
RelativizeSummary { level }.walk_pandoc(&mut summary);
summary
})
.clone()
}
pub struct InsertSummary<'a> {
pub summary: &'a pandoc_ast::Pandoc,
pub level: usize,
}
impl<'a> pandoc_ast::MutVisitor for InsertSummary<'a> {
fn walk_pandoc(&mut self, pandoc: &mut pandoc_ast::Pandoc) {
let summary = relativize_summary(self.summary, self.level);
pandoc.blocks.insert(
0,
pandoc_ast::Block::Div(
(String::new(), vec!["summary".to_string()], vec![]),
summary.blocks,
),
);
}
}
|