From b5999565167b4aae1e56d1f65dbf50675e5762bd Mon Sep 17 00:00:00 2001 From: Jaime Valdemoros Date: Mon, 15 Jan 2018 22:54:14 +0000 Subject: [PATCH] Move preprocess field location and add tests --- src/book/mod.rs | 92 ++++++++++++++++++++++++++++++++++------- src/config.rs | 8 ++++ src/preprocess/links.rs | 4 ++ src/preprocess/mod.rs | 1 + 4 files changed, 90 insertions(+), 15 deletions(-) diff --git a/src/book/mod.rs b/src/book/mod.rs index 613b3306..8a9ddd01 100644 --- a/src/book/mod.rs +++ b/src/book/mod.rs @@ -88,7 +88,7 @@ impl MDBook { let livereload = None; let renderers = determine_renderers(&config); - let preprocessors = determine_preprocessors(&config); + let preprocessors = determine_preprocessors(&config)?; Ok(MDBook { root, @@ -334,25 +334,26 @@ fn determine_renderers(config: &Config) -> Vec> { } /// Look at the `MDBook` and try to figure out what preprocessors to run. -fn determine_preprocessors(config: &Config) -> Vec> { +fn determine_preprocessors(config: &Config) -> Result>> { + + let preprocess_list = match config.build.preprocess { + Some(ref p) => p, + // If no preprocessor field is set, default to the LinkPreprocessor. This allows you + // to disable the LinkPreprocessor by setting "preprocess" to an empty list. + None => return Ok(vec![Box::new(LinkPreprocessor::new())]) + }; + let mut preprocessors: Vec> = Vec::new(); - if let Some(preprocess_array) = config.get("preprocess").and_then(|o| o.as_array()) { - for key in preprocess_array.iter() { - match key.as_str() { - Some(key) if key == "links" => { - preprocessors.push(Box::new(LinkPreprocessor::new())) - } - _ => {} - } + for key in preprocess_list { + if key == "links" { + preprocessors.push(Box::new(LinkPreprocessor::new())) + } else { + bail!("{:?} is not a recognised preprocessor", key); } } - if preprocessors.is_empty() { - preprocessors.push(Box::new(LinkPreprocessor::new())) - } - - preprocessors + Ok(preprocessors) } fn interpret_custom_renderer(key: &str, table: &Value) -> Box { @@ -410,4 +411,65 @@ mod tests { assert_eq!(got.len(), 1); assert_eq!(got[0].name(), "random"); } + + #[test] + fn config_defaults_to_link_preprocessor_if_not_set() { + let cfg = Config::default(); + + // make sure we haven't got anything in the `output` table + assert!(cfg.build.preprocess.is_none()); + + let got = determine_preprocessors(&cfg); + + assert!(got.is_ok()); + assert_eq!(got.as_ref().unwrap().len(), 1); + assert_eq!(got.as_ref().unwrap()[0].name(), "links"); + } + + #[test] + fn config_doesnt_default_if_empty() { + let cfg_str: &'static str = r#" + [book] + title = "Some Book" + + [build] + build-dir = "outputs" + create-missing = false + preprocess = [] + "#; + + + let cfg = Config::from_str(cfg_str).unwrap(); + + // make sure we have something in the `output` table + assert!(cfg.build.preprocess.is_some()); + + let got = determine_preprocessors(&cfg); + + assert!(got.is_ok()); + assert!(got.unwrap().is_empty()); + } + + #[test] + fn config_complains_if_unimplemented_preprocessor() { + let cfg_str: &'static str = r#" + [book] + title = "Some Book" + + [build] + build-dir = "outputs" + create-missing = false + preprocess = ["random"] + "#; + + + let cfg = Config::from_str(cfg_str).unwrap(); + + // make sure we have something in the `output` table + assert!(cfg.build.preprocess.is_some()); + + let got = determine_preprocessors(&cfg); + + assert!(got.is_err()); + } } diff --git a/src/config.rs b/src/config.rs index 24c3f96e..e74f1917 100644 --- a/src/config.rs +++ b/src/config.rs @@ -329,6 +329,9 @@ pub struct BuildConfig { /// Should non-existent markdown files specified in `SETTINGS.md` be created /// if they don't exist? pub create_missing: bool, + /// Which preprocessors should be applied + pub preprocess: Option>, + } impl Default for BuildConfig { @@ -336,6 +339,7 @@ impl Default for BuildConfig { BuildConfig { build_dir: PathBuf::from("book"), create_missing: true, + preprocess: None, } } } @@ -422,6 +426,7 @@ mod tests { [build] build-dir = "outputs" create-missing = false + preprocess = ["first_preprocessor", "second_preprocessor"] [output.html] theme = "./themedir" @@ -449,6 +454,8 @@ mod tests { let build_should_be = BuildConfig { build_dir: PathBuf::from("outputs"), create_missing: false, + preprocess: Some(vec!["first_preprocessor".to_string(), + "second_preprocessor".to_string()]), }; let playpen_should_be = Playpen { editable: true, @@ -550,6 +557,7 @@ mod tests { let build_should_be = BuildConfig { build_dir: PathBuf::from("my-book"), create_missing: true, + preprocess: None, }; let html_should_be = HtmlConfig { diff --git a/src/preprocess/links.rs b/src/preprocess/links.rs index cbbd71f6..72bc6c8f 100644 --- a/src/preprocess/links.rs +++ b/src/preprocess/links.rs @@ -19,6 +19,10 @@ impl LinkPreprocessor { } impl Preprocessor for LinkPreprocessor { + fn name(&self) -> &str { + "links" + } + fn run(&self, ctx: &PreprocessorContext, book: &mut Book) -> Result<()> { for section in &mut book.sections { match *section { diff --git a/src/preprocess/mod.rs b/src/preprocess/mod.rs index 727fad1e..c31080a1 100644 --- a/src/preprocess/mod.rs +++ b/src/preprocess/mod.rs @@ -12,5 +12,6 @@ pub struct PreprocessorContext { } pub trait Preprocessor { + fn name(&self) -> &str; fn run(&self, ctx: &PreprocessorContext, book: &mut Book) -> Result<()>; } \ No newline at end of file