mdbook_renderer/lib.rs
1//! Library to assist implementing an mdbook renderer.
2//!
3//! This library is used to implement a
4//! [renderer](https://rust-lang.github.io/mdBook/for_developers/backends.html)
5//! for [mdBook](https://rust-lang.github.io/mdBook/). See the linked chapter
6//! for more information on how to implement a renderer.
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::collections::HashMap;
14use std::io::Read;
15use std::path::PathBuf;
16
17pub use mdbook_core::MDBOOK_VERSION;
18pub use mdbook_core::book;
19pub use mdbook_core::config;
20pub use mdbook_core::errors;
21
22/// An mdbook backend.
23///
24/// Types that implement the `Renderer` trait can be used with
25/// [`MDBook::with_renderer`] to programmatically add renderers.
26///
27/// [`MDBook::with_renderer`]: https://docs.rs/mdbook-driver/latest/mdbook_driver/struct.MDBook.html#method.with_renderer
28pub trait Renderer {
29 /// The `Renderer`'s name.
30 fn name(&self) -> &str;
31
32 /// Invoke the `Renderer`, passing in all the necessary information for
33 /// describing a book.
34 fn render(&self, ctx: &RenderContext) -> Result<()>;
35}
36
37/// The context provided to all renderers.
38#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
39#[non_exhaustive]
40pub struct RenderContext {
41 /// Which version of `mdbook` did this come from (as written in `mdbook`'s
42 /// `Cargo.toml`). Useful if you know the renderer is only compatible with
43 /// certain versions of `mdbook`.
44 pub version: String,
45 /// The book's root directory.
46 pub root: PathBuf,
47 /// A loaded representation of the book itself.
48 pub book: Book,
49 /// The loaded configuration file.
50 pub config: Config,
51 /// Where the renderer *must* put any build artefacts generated. To allow
52 /// renderers to cache intermediate results, this directory is not
53 /// guaranteed to be empty or even exist.
54 pub destination: PathBuf,
55 /// Internal mapping of chapter titles.
56 ///
57 /// This is used internally by mdbook to compute custom chapter titles.
58 /// This should not be used outside of mdbook's internals.
59 #[serde(skip)]
60 pub chapter_titles: HashMap<PathBuf, String>,
61}
62
63impl RenderContext {
64 /// Create a new `RenderContext`.
65 pub fn new<P, Q>(root: P, book: Book, config: Config, destination: Q) -> RenderContext
66 where
67 P: Into<PathBuf>,
68 Q: Into<PathBuf>,
69 {
70 RenderContext {
71 book,
72 config,
73 version: crate::MDBOOK_VERSION.to_string(),
74 root: root.into(),
75 destination: destination.into(),
76 chapter_titles: HashMap::new(),
77 }
78 }
79
80 /// Get the source directory's (absolute) path on disk.
81 pub fn source_dir(&self) -> PathBuf {
82 self.root.join(&self.config.book.src)
83 }
84
85 /// Load a `RenderContext` from its JSON representation.
86 pub fn from_json<R: Read>(reader: R) -> Result<RenderContext> {
87 serde_json::from_reader(reader).with_context(|| "Unable to deserialize the `RenderContext`")
88 }
89}