mdbook_preprocessor/lib.rs
1//! Library to assist implementing an mdbook preprocessor.
2//!
3//! This library is used to implement a
4//! [preprocessor](https://rust-lang.github.io/mdBook/for_developers/preprocessors.html)
5//! for [mdBook](https://rust-lang.github.io/mdBook/). See the linked chapter
6//! for more information on how to implement a preprocessor.
7
8use anyhow::Context;
9use mdbook_core::book::Book;
10use mdbook_core::config::Config;
11use mdbook_core::errors::Result;
12use serde::{Deserialize, Serialize};
13use std::cell::RefCell;
14use std::collections::HashMap;
15use std::io::Read;
16use std::path::PathBuf;
17
18pub use mdbook_core::MDBOOK_VERSION;
19pub use mdbook_core::book;
20pub use mdbook_core::config;
21pub use mdbook_core::errors;
22
23/// An operation which is run immediately after loading a book into memory and
24/// before it gets rendered.
25///
26/// Types that implement the `Preprocessor` trait can be used with
27/// [`MDBook::with_preprocessor`] to programmatically add preprocessors.
28///
29/// [`MDBook::with_preprocessor`]: https://docs.rs/mdbook-driver/latest/mdbook_driver/struct.MDBook.html#method.with_preprocessor
30pub trait Preprocessor {
31 /// Get the `Preprocessor`'s name.
32 fn name(&self) -> &str;
33
34 /// Run this `Preprocessor`, allowing it to update the book before it is
35 /// given to a renderer.
36 fn run(&self, ctx: &PreprocessorContext, book: Book) -> Result<Book>;
37
38 /// A hint to `MDBook` whether this preprocessor is compatible with a
39 /// particular renderer.
40 ///
41 /// By default, always returns `true`.
42 fn supports_renderer(&self, _renderer: &str) -> Result<bool> {
43 Ok(true)
44 }
45}
46
47/// Extra information for a `Preprocessor` to give them more context when
48/// processing a book.
49#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
50#[non_exhaustive]
51pub struct PreprocessorContext {
52 /// The location of the book directory on disk.
53 pub root: PathBuf,
54 /// The book configuration (`book.toml`).
55 pub config: Config,
56 /// The `Renderer` this preprocessor is being used with.
57 pub renderer: String,
58 /// The calling `mdbook` version.
59 pub mdbook_version: String,
60 /// Internal mapping of chapter titles.
61 ///
62 /// This is used internally by mdbook to compute custom chapter titles.
63 /// This should not be used outside of mdbook's internals.
64 #[serde(skip)]
65 pub chapter_titles: RefCell<HashMap<PathBuf, String>>,
66}
67
68impl PreprocessorContext {
69 /// Create a new `PreprocessorContext`.
70 pub fn new(root: PathBuf, config: Config, renderer: String) -> Self {
71 PreprocessorContext {
72 root,
73 config,
74 renderer,
75 mdbook_version: crate::MDBOOK_VERSION.to_string(),
76 chapter_titles: RefCell::new(HashMap::new()),
77 }
78 }
79}
80
81/// Parses the input given to a preprocessor.
82pub fn parse_input<R: Read>(reader: R) -> Result<(PreprocessorContext, Book)> {
83 serde_json::from_reader(reader).with_context(|| "Unable to parse the input")
84}