1use mdbook::BookItem;
2use mdbook::book::Book;
3use mdbook::errors::Error;
4use mdbook::preprocess::{Preprocessor, PreprocessorContext};
5use regex::Regex;
6use std::path::Path;
7use std::path::PathBuf;
8
9#[derive(Default)]
10pub struct SelfPathPreprocessor;
11
12impl SelfPathPreprocessor {
13 pub fn new() -> SelfPathPreprocessor {
14 SelfPathPreprocessor
15 }
16}
17
18impl Preprocessor for SelfPathPreprocessor {
19 fn name(&self) -> &str {
20 "selfpath"
21 }
22
23 fn run(&self, ctx: &PreprocessorContext, mut book: Book) -> Result<Book, Error> {
24 let include_ext = ctx
26 .config
27 .get_preprocessor(self.name())
28 .and_then(|table| table.get("include-file-ext"))
29 .and_then(|val| val.as_bool())
30 .unwrap_or(true);
31
32 let src_dir_name = &ctx.config.book.src;
34
35 let selfpath_re = Regex::new(r"\{\{\s*selfpath\s*\}\}").unwrap();
37
38 book.for_each_mut(|item: &mut BookItem| {
40 if let BookItem::Chapter(chapter) = item {
41 if let Some(ref source_path) = chapter.source_path {
43 let mut rel_path = PathBuf::new();
44 if src_dir_name.as_path() != Path::new(".") {
46 rel_path.push(&src_dir_name)
47 }
48 rel_path.push(source_path);
49 if !include_ext {
50 rel_path.set_extension("");
52 }
53 let rel_path_str = rel_path.to_string_lossy().replace('\\', "/");
55 chapter.content = selfpath_re.replace_all(&chapter.content, rel_path_str.as_str()).to_string();
57 }
58 }
59 });
60 Ok(book)
61 }
62
63 fn supports_renderer(&self, _renderer: &str) -> bool {
64 true
67 }
68}