mdbook_bibtex/
lib.rs

1use anyhow::{Result, anyhow};
2use itertools::Itertools;
3use mdbook_preprocessor::{Preprocessor, PreprocessorContext, book::Book};
4
5use config::{BibliographyLocation, Config};
6
7mod bib;
8mod config;
9#[cfg(test)]
10mod tests;
11
12pub struct BibtexPreprocessor;
13
14impl Preprocessor for BibtexPreprocessor {
15    fn name(&self) -> &str {
16        "bibtex-preprocessor"
17    }
18
19    fn run(&self, ctx: &PreprocessorContext, mut book: Book) -> Result<Book> {
20        let config: Config = (&ctx.config).try_into()?;
21
22        match config.biblio_location {
23            BibliographyLocation::Footnotes | BibliographyLocation::Chapter => {
24                let mut errs = vec![];
25                book.for_each_chapter_mut(|chapter| {
26                    let mut f = || -> Result<()> {
27                        let mut pass = bib::BibPass::new(&config)?;
28                        pass.collect_citations(chapter)?;
29                        let pass = pass.render()?;
30                        pass.replace_citations(chapter);
31                        pass.add_chapter_bib(chapter);
32                        Ok(())
33                    };
34
35                    if let Err(e) = f() {
36                        errs.push(e);
37                    }
38                });
39                if !errs.is_empty() {
40                    Err(anyhow!(errs.into_iter().map(|e| e.to_string()).join("\n")))?;
41                }
42            }
43            BibliographyLocation::Global => {
44                let mut pass = bib::BibPass::new(&config)?;
45
46                let mut errs = vec![];
47                book.chapters().for_each(|chapter| {
48                    if let Err(e) = pass.collect_citations(chapter) {
49                        errs.push(e);
50                    }
51                });
52                if !errs.is_empty() {
53                    Err(anyhow!(errs.into_iter().map(|e| e.to_string()).join("\n")))?;
54                }
55
56                let pass = pass.render()?;
57                book.for_each_chapter_mut(|chapter| {
58                    pass.replace_citations(chapter);
59                });
60                pass.add_global_bib(&mut book);
61            }
62        }
63
64        Ok(book)
65    }
66
67    fn supports_renderer(&self, renderer: &str) -> Result<bool> {
68        Ok(renderer != "not-supported")
69    }
70}