mdbook_hide/
lib.rs

1use log::info;
2use mdbook::book::Book;
3use mdbook::errors::Error;
4use mdbook::preprocess::{Preprocessor, PreprocessorContext};
5use mdbook::BookItem;
6use regex::Regex;
7
8pub struct HidePreprocessor {
9    hide: bool,
10    re: Regex,
11}
12
13const NAME: &str = "hide";
14
15impl HidePreprocessor {
16    pub fn new(ctx: &PreprocessorContext) -> HidePreprocessor {
17        let mut hide = false;
18        let re = Regex::new(r"<!--hidden-->").unwrap();
19
20        if let Some(cfg) = ctx.config.get_preprocessor(NAME) {
21            if cfg.contains_key("hide") {
22                hide = cfg.get("hide").unwrap().as_bool().unwrap();
23            }
24        }
25
26        HidePreprocessor { hide, re }
27    }
28
29    fn process_item(&self, item: BookItem) -> Option<BookItem> {
30        if let BookItem::Chapter(ref c) = item {
31            if self.re.is_match(&c.content) {
32                info!("removing chapter {}", c.name);
33                return None;
34            }
35
36            let mut new = c.clone();
37            new.sub_items.clear();
38
39            for i in c.sub_items.iter() {
40                let cloned_item = i.clone();
41
42                if let Some(cloned_item) = self.process_item(cloned_item) {
43                    new.sub_items.push(cloned_item)
44                }
45            }
46
47            return Some(BookItem::Chapter(new));
48        } else {
49            Some(item)
50        }
51    }
52}
53
54impl Default for HidePreprocessor {
55    fn default() -> Self {
56        HidePreprocessor {
57            hide: false,
58            re: Regex::new(r"").unwrap(),
59        }
60    }
61}
62
63impl Preprocessor for HidePreprocessor {
64    fn name(&self) -> &str {
65        "hide"
66    }
67
68    fn run(&self, _ctx: &PreprocessorContext, book: Book) -> Result<Book, Error> {
69        info!("Running mdbook-hide preprocessor");
70
71        if !self.hide {
72            return Ok(book);
73        }
74
75        let mut updated = Book::new();
76
77        for section in book.sections.iter() {
78            let cloned_section = section.clone();
79
80            if let Some(proccessed_item) = self.process_item(cloned_section) {
81                updated.push_item(proccessed_item);
82            }
83        }
84
85        Ok(updated)
86    }
87
88    fn supports_renderer(&self, renderer: &str) -> bool {
89        renderer != "not-supported"
90    }
91}