Move preprocess field location and add tests

This commit is contained in:
Jaime Valdemoros 2018-01-15 22:54:14 +00:00
parent 08027b86cc
commit b599956516
4 changed files with 90 additions and 15 deletions

View File

@ -88,7 +88,7 @@ impl MDBook {
let livereload = None; let livereload = None;
let renderers = determine_renderers(&config); let renderers = determine_renderers(&config);
let preprocessors = determine_preprocessors(&config); let preprocessors = determine_preprocessors(&config)?;
Ok(MDBook { Ok(MDBook {
root, root,
@ -334,25 +334,26 @@ fn determine_renderers(config: &Config) -> Vec<Box<Renderer>> {
} }
/// Look at the `MDBook` and try to figure out what preprocessors to run. /// Look at the `MDBook` and try to figure out what preprocessors to run.
fn determine_preprocessors(config: &Config) -> Vec<Box<Preprocessor>> { fn determine_preprocessors(config: &Config) -> Result<Vec<Box<Preprocessor>>> {
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<Box<Preprocessor>> = Vec::new(); let mut preprocessors: Vec<Box<Preprocessor>> = Vec::new();
if let Some(preprocess_array) = config.get("preprocess").and_then(|o| o.as_array()) { for key in preprocess_list {
for key in preprocess_array.iter() { if key == "links" {
match key.as_str() {
Some(key) if key == "links" => {
preprocessors.push(Box::new(LinkPreprocessor::new())) preprocessors.push(Box::new(LinkPreprocessor::new()))
} } else {
_ => {} bail!("{:?} is not a recognised preprocessor", key);
}
} }
} }
if preprocessors.is_empty() { Ok(preprocessors)
preprocessors.push(Box::new(LinkPreprocessor::new()))
}
preprocessors
} }
fn interpret_custom_renderer(key: &str, table: &Value) -> Box<Renderer> { fn interpret_custom_renderer(key: &str, table: &Value) -> Box<Renderer> {
@ -410,4 +411,65 @@ mod tests {
assert_eq!(got.len(), 1); assert_eq!(got.len(), 1);
assert_eq!(got[0].name(), "random"); 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());
}
} }

View File

@ -329,6 +329,9 @@ pub struct BuildConfig {
/// Should non-existent markdown files specified in `SETTINGS.md` be created /// Should non-existent markdown files specified in `SETTINGS.md` be created
/// if they don't exist? /// if they don't exist?
pub create_missing: bool, pub create_missing: bool,
/// Which preprocessors should be applied
pub preprocess: Option<Vec<String>>,
} }
impl Default for BuildConfig { impl Default for BuildConfig {
@ -336,6 +339,7 @@ impl Default for BuildConfig {
BuildConfig { BuildConfig {
build_dir: PathBuf::from("book"), build_dir: PathBuf::from("book"),
create_missing: true, create_missing: true,
preprocess: None,
} }
} }
} }
@ -422,6 +426,7 @@ mod tests {
[build] [build]
build-dir = "outputs" build-dir = "outputs"
create-missing = false create-missing = false
preprocess = ["first_preprocessor", "second_preprocessor"]
[output.html] [output.html]
theme = "./themedir" theme = "./themedir"
@ -449,6 +454,8 @@ mod tests {
let build_should_be = BuildConfig { let build_should_be = BuildConfig {
build_dir: PathBuf::from("outputs"), build_dir: PathBuf::from("outputs"),
create_missing: false, create_missing: false,
preprocess: Some(vec!["first_preprocessor".to_string(),
"second_preprocessor".to_string()]),
}; };
let playpen_should_be = Playpen { let playpen_should_be = Playpen {
editable: true, editable: true,
@ -550,6 +557,7 @@ mod tests {
let build_should_be = BuildConfig { let build_should_be = BuildConfig {
build_dir: PathBuf::from("my-book"), build_dir: PathBuf::from("my-book"),
create_missing: true, create_missing: true,
preprocess: None,
}; };
let html_should_be = HtmlConfig { let html_should_be = HtmlConfig {

View File

@ -19,6 +19,10 @@ impl LinkPreprocessor {
} }
impl Preprocessor for LinkPreprocessor { impl Preprocessor for LinkPreprocessor {
fn name(&self) -> &str {
"links"
}
fn run(&self, ctx: &PreprocessorContext, book: &mut Book) -> Result<()> { fn run(&self, ctx: &PreprocessorContext, book: &mut Book) -> Result<()> {
for section in &mut book.sections { for section in &mut book.sections {
match *section { match *section {

View File

@ -12,5 +12,6 @@ pub struct PreprocessorContext {
} }
pub trait Preprocessor { pub trait Preprocessor {
fn name(&self) -> &str;
fn run(&self, ctx: &PreprocessorContext, book: &mut Book) -> Result<()>; fn run(&self, ctx: &PreprocessorContext, book: &mut Book) -> Result<()>;
} }