mirror of
https://github.com/rust-lang/mdBook
synced 2024-12-13 22:32:35 +00:00
7aaa84853d
This test code will show preprocessor developers what the input data looks like and how to test the preprocessing results.
158 lines
4.9 KiB
Rust
158 lines
4.9 KiB
Rust
use crate::nop_lib::Nop;
|
|
use clap::{App, Arg, ArgMatches};
|
|
use mdbook::book::Book;
|
|
use mdbook::errors::Error;
|
|
use mdbook::preprocess::{CmdPreprocessor, Preprocessor, PreprocessorContext};
|
|
use semver::{Version, VersionReq};
|
|
use std::io;
|
|
use std::process;
|
|
|
|
pub fn make_app() -> App<'static> {
|
|
App::new("nop-preprocessor")
|
|
.about("A mdbook preprocessor which does precisely nothing")
|
|
.subcommand(
|
|
App::new("supports")
|
|
.arg(Arg::new("renderer").required(true))
|
|
.about("Check whether a renderer is supported by this preprocessor"),
|
|
)
|
|
}
|
|
|
|
fn main() {
|
|
let matches = make_app().get_matches();
|
|
|
|
// Users will want to construct their own preprocessor here
|
|
let preprocessor = Nop::new();
|
|
|
|
if let Some(sub_args) = matches.subcommand_matches("supports") {
|
|
handle_supports(&preprocessor, sub_args);
|
|
} else if let Err(e) = handle_preprocessing(&preprocessor) {
|
|
eprintln!("{}", e);
|
|
process::exit(1);
|
|
}
|
|
}
|
|
|
|
fn handle_preprocessing(pre: &dyn Preprocessor) -> Result<(), Error> {
|
|
let (ctx, book) = CmdPreprocessor::parse_input(io::stdin())?;
|
|
|
|
let book_version = Version::parse(&ctx.mdbook_version)?;
|
|
let version_req = VersionReq::parse(mdbook::MDBOOK_VERSION)?;
|
|
|
|
if !version_req.matches(&book_version) {
|
|
eprintln!(
|
|
"Warning: The {} plugin was built against version {} of mdbook, \
|
|
but we're being called from version {}",
|
|
pre.name(),
|
|
mdbook::MDBOOK_VERSION,
|
|
ctx.mdbook_version
|
|
);
|
|
}
|
|
|
|
let processed_book = pre.run(&ctx, book)?;
|
|
serde_json::to_writer(io::stdout(), &processed_book)?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn handle_supports(pre: &dyn Preprocessor, sub_args: &ArgMatches) -> ! {
|
|
let renderer = sub_args.value_of("renderer").expect("Required argument");
|
|
let supported = pre.supports_renderer(renderer);
|
|
|
|
// Signal whether the renderer is supported by exiting with 1 or 0.
|
|
if supported {
|
|
process::exit(0);
|
|
} else {
|
|
process::exit(1);
|
|
}
|
|
}
|
|
|
|
/// The actual implementation of the `Nop` preprocessor. This would usually go
|
|
/// in your main `lib.rs` file.
|
|
mod nop_lib {
|
|
use super::*;
|
|
|
|
/// A no-op preprocessor.
|
|
pub struct Nop;
|
|
|
|
impl Nop {
|
|
pub fn new() -> Nop {
|
|
Nop
|
|
}
|
|
}
|
|
|
|
impl Preprocessor for Nop {
|
|
fn name(&self) -> &str {
|
|
"nop-preprocessor"
|
|
}
|
|
|
|
fn run(&self, ctx: &PreprocessorContext, book: Book) -> Result<Book, Error> {
|
|
// In testing we want to tell the preprocessor to blow up by setting a
|
|
// particular config value
|
|
if let Some(nop_cfg) = ctx.config.get_preprocessor(self.name()) {
|
|
if nop_cfg.contains_key("blow-up") {
|
|
anyhow::bail!("Boom!!1!");
|
|
}
|
|
}
|
|
|
|
// we *are* a no-op preprocessor after all
|
|
Ok(book)
|
|
}
|
|
|
|
fn supports_renderer(&self, renderer: &str) -> bool {
|
|
renderer != "not-supported"
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod test {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn nop_preprocessor_run() {
|
|
let input_json = r##"[
|
|
{
|
|
"root": "/path/to/book",
|
|
"config": {
|
|
"book": {
|
|
"authors": ["AUTHOR"],
|
|
"language": "en",
|
|
"multilingual": false,
|
|
"src": "src",
|
|
"title": "TITLE"
|
|
},
|
|
"preprocessor": {
|
|
"nop": {}
|
|
}
|
|
},
|
|
"renderer": "html",
|
|
"mdbook_version": "0.4.21"
|
|
},
|
|
{
|
|
"sections": [
|
|
{
|
|
"Chapter": {
|
|
"name": "Chapter 1",
|
|
"content": "# Chapter 1\n",
|
|
"number": [1],
|
|
"sub_items": [],
|
|
"path": "chapter_1.md",
|
|
"source_path": "chapter_1.md",
|
|
"parent_names": []
|
|
}
|
|
}
|
|
],
|
|
"__non_exhaustive": null
|
|
}
|
|
]"##;
|
|
let input_json = input_json.as_bytes();
|
|
|
|
let (ctx, book) = mdbook::preprocess::CmdPreprocessor::parse_input(input_json).unwrap();
|
|
let expected_book = book.clone();
|
|
let result = Nop::new().run(&ctx, book);
|
|
assert!(result.is_ok());
|
|
|
|
// The nop-preprocessor should not have made any changes to the book content.
|
|
let actual_book = result.unwrap();
|
|
assert_eq!(actual_book, expected_book);
|
|
}
|
|
}
|
|
}
|