Skip to main content

mdbook_plotly/preprocessor/
bookdata.rs

1use super::config::SUPPORTED_MDBOOK_VERSION;
2use crate::fatal;
3use crate::preprocessor::config::PreprocessorConfig;
4use log::{error, warn};
5use mdbook_preprocessor::{
6    PreprocessorContext,
7    book::{Book, BookItem, Chapter},
8};
9#[cfg(feature = "sync")]
10use rayon::prelude::*;
11
12pub struct BookData {
13    ctx: PreprocessorContext,
14    book: Book,
15    config: PreprocessorConfig,
16}
17
18impl BookData {
19    fn new(ctx: PreprocessorContext, book: Book, config: PreprocessorConfig) -> Self {
20        Self { ctx, book, config }
21    }
22
23    pub fn version(&self) -> &str {
24        &self.ctx.mdbook_version
25    }
26
27    pub fn is_compatible_version(&self) -> bool {
28        self.version() == SUPPORTED_MDBOOK_VERSION
29    }
30
31    pub fn emit_compatibility_warning(&self) {
32        if !self.is_compatible_version() {
33            warn!(
34                "This preprocessor was developed for mdbook v{}, but found v{}. May not work as expected.",
35                SUPPORTED_MDBOOK_VERSION,
36                self.version()
37            );
38        }
39    }
40
41    /// NOTE: This interface returns a cloned internal `PreprocessorConfig`.
42    pub fn get_config(&self) -> PreprocessorConfig {
43        self.config.clone()
44    }
45
46    /// NOTE: This interface returns a cloned internal `PathBuf`.
47    pub fn get_book_path(&self) -> std::path::PathBuf {
48        self.ctx.root.clone()
49    }
50
51    #[allow(unused)]
52    pub fn for_each_chapter_mut<F>(&mut self, mut f: F)
53    where
54        F: FnMut(&mut Chapter),
55    {
56        fn walk<F: FnMut(&mut Chapter)>(items: &mut [BookItem], f: &mut F) {
57            for item in items.iter_mut() {
58                if let BookItem::Chapter(ch) = item {
59                    f(ch);
60                    walk(&mut ch.sub_items, f);
61                }
62            }
63        }
64        walk(&mut self.book.items, &mut f);
65    }
66
67    #[cfg(feature = "sync")]
68    pub fn for_each_chapter_par<F>(&mut self, f: F)
69    where
70        F: Fn(&mut Chapter) + Sync + Send,
71    {
72        fn walk_par<F: Fn(&mut Chapter) + Sync + Send>(items: &mut [BookItem], f: &F) {
73            items.par_iter_mut().for_each(|item| {
74                if let BookItem::Chapter(ch) = item {
75                    f(ch);
76                    walk_par(&mut ch.sub_items, f);
77                }
78            });
79        }
80        walk_par(&mut self.book.items, &f);
81    }
82
83    pub fn into_book(self) -> Book {
84        self.book
85    }
86}
87
88pub fn get_book_data() -> BookData {
89    let (ctx, book) = match mdbook_preprocessor::parse_input(std::io::stdin()) {
90        Ok(parsed) => parsed,
91        Err(e) => fatal!("Input parsing failed.\nInterError: {:#?}", e),
92    };
93
94    let config = match ctx.config.get::<PreprocessorConfig>("preprocessor.plotly") {
95        Ok(Some(cfg)) => cfg,
96        Ok(None) => {
97            warn!("Custom config not found; using default configuration.");
98            PreprocessorConfig::default()
99        }
100        Err(e) => {
101            error!(
102                "Illegal config format for 'preprocessor.mdbook-plotly': {}",
103                e.root_cause()
104            );
105            PreprocessorConfig::default()
106        }
107    };
108
109    BookData::new(ctx, book, config)
110}