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