mdbook_trunk/
preprocessor.rs

1use std::{env, str};
2
3use anyhow::Result;
4use cargo::{GlobalContext, core::Workspace, util::important_paths::find_root_manifest_for_wd};
5use mdbook::{
6    BookItem,
7    book::Book,
8    preprocess::{Preprocessor, PreprocessorContext},
9};
10
11use crate::{parser::definition::parse_definitions, trunk::trunk};
12
13pub struct TrunkPreprocessor;
14
15impl TrunkPreprocessor {
16    pub fn new() -> Self {
17        Self
18    }
19}
20
21impl Default for TrunkPreprocessor {
22    fn default() -> Self {
23        Self::new()
24    }
25}
26
27impl Preprocessor for TrunkPreprocessor {
28    fn name(&self) -> &str {
29        "trunk"
30    }
31
32    fn run(&self, _ctx: &PreprocessorContext, book: Book) -> Result<Book> {
33        let mut book = book.clone();
34
35        let gctx = GlobalContext::default()?;
36        let workspace = Workspace::new(&find_root_manifest_for_wd(&env::current_dir()?)?, &gctx)?;
37
38        process_items(&workspace, &mut book.sections)?;
39
40        Ok(book)
41    }
42
43    fn supports_renderer(&self, _renderer: &str) -> bool {
44        true
45    }
46}
47
48fn process_items(workspace: &Workspace, items: &mut Vec<BookItem>) -> Result<()> {
49    for section in items {
50        if let BookItem::Chapter(chapter) = section {
51            let blocks = parse_definitions(chapter)?;
52
53            let mut offset: usize = 0;
54
55            for (span, config) in blocks {
56                let replacement = trunk(workspace, &config)?;
57
58                chapter
59                    .content
60                    .replace_range((span.start + offset)..(span.end + offset), &replacement);
61
62                offset += replacement.len() - span.len();
63            }
64
65            process_items(workspace, &mut chapter.sub_items)?;
66        }
67    }
68
69    Ok(())
70}