Add a create-missing option to book.toml.

This commit is contained in:
Chris Spiegel 2017-11-29 20:02:58 -08:00
parent 1aa9c92ac1
commit 93874edebf
4 changed files with 59 additions and 7 deletions

View File

@ -10,6 +10,9 @@ title = "Example book"
author = "John Doe" author = "John Doe"
description = "The example book covers examples." description = "The example book covers examples."
[build]
create-missing = false
[output.html] [output.html]
destination = "my-example-book" destination = "my-example-book"
additional-css = ["custom.css"] additional-css = ["custom.css"]
@ -45,6 +48,20 @@ src = "my-src" # the source files will be found in `root/my-src` instead of `ro
build-dir = "build" build-dir = "build"
``` ```
### Build options
This controls the build process of your book.
- **create-missing:** By default, any missing files specified in `SUMMARY.md`
will be created when the book is built. If this is `false` then the build
process will instead exit with an error if any files do not exist.
**book.toml**
```toml
[build]
create-missing = false
```
### HTML renderer options ### HTML renderer options
The HTML renderer has a couple of options as well. All the options for the The HTML renderer has a couple of options as well. All the options for the
renderer need to be specified under the TOML table `[output.html]`. renderer need to be specified under the TOML table `[output.html]`.
@ -134,4 +151,4 @@ if let Some(baz) = book_config.get_deserialized::<Vec<bool>>("output.random.baz"
} }
// start the rendering process // start the rendering process
``` ```

View File

@ -14,7 +14,7 @@ pub fn make_subcommand<'a, 'b>() -> App<'a, 'b> {
book{n}(Defaults to ./book when omitted)'", book{n}(Defaults to ./book when omitted)'",
) )
.arg_from_usage( .arg_from_usage(
"--no-create 'Will not create non-existent files linked from SUMMARY.md'", "--no-create 'Will not create non-existent files linked from SUMMARY.md (deprecated: use book.toml instead)'",
) )
.arg_from_usage( .arg_from_usage(
"[dir] 'A directory for your book{n}(Defaults to Current Directory \ "[dir] 'A directory for your book{n}(Defaults to Current Directory \
@ -32,7 +32,7 @@ pub fn execute(args: &ArgMatches) -> Result<()> {
} }
if args.is_present("no-create") { if args.is_present("no-create") {
book.create_missing = false; book.create_missing = Some(false);
} }
book.build()?; book.build()?;

View File

@ -25,8 +25,10 @@ pub struct MDBook {
pub livereload: Option<String>, pub livereload: Option<String>,
/// Should `mdbook build` create files referenced from SUMMARY.md if they /// Should `mdbook build` create files referenced from SUMMARY.md if they
/// don't exist /// don't exist? If `None`, use the setting specified in `book.toml`,
pub create_missing: bool, /// otherwise use this.
/// This is for backward compatibility only.
pub create_missing: Option<bool>,
} }
impl MDBook { impl MDBook {
@ -71,7 +73,7 @@ impl MDBook {
renderer: Box::new(HtmlHandlebars::new()), renderer: Box::new(HtmlHandlebars::new()),
livereload: None, livereload: None,
create_missing: true, create_missing: None,
} }
} }
@ -179,7 +181,9 @@ impl MDBook {
let path = self.get_source().join(&ch.path); let path = self.get_source().join(&ch.path);
if !path.exists() { if !path.exists() {
if !self.create_missing { let create_missing = self.create_missing.unwrap_or(self.config.build.create_missing);
if !create_missing {
return Err( return Err(
format!("'{}' referenced from SUMMARY.md does not exist.", path.to_string_lossy()).into(), format!("'{}' referenced from SUMMARY.md does not exist.", path.to_string_lossy()).into(),
); );

View File

@ -12,6 +12,7 @@ use errors::*;
pub struct Config { pub struct Config {
/// Metadata about the book. /// Metadata about the book.
pub book: BookConfig, pub book: BookConfig,
pub build: BuildConfig,
rest: Table, rest: Table,
} }
@ -171,8 +172,14 @@ impl<'de> Deserialize<'de> for Config {
let book: BookConfig = table.remove("book") let book: BookConfig = table.remove("book")
.and_then(|value| value.try_into().ok()) .and_then(|value| value.try_into().ok())
.unwrap_or_default(); .unwrap_or_default();
let build: BuildConfig = table.remove("build")
.and_then(|value| value.try_into().ok())
.unwrap_or_default();
Ok(Config { Ok(Config {
book: book, book: book,
build: build,
rest: table, rest: table,
}) })
} }
@ -217,6 +224,23 @@ impl Default for BookConfig {
} }
} }
/// Configuration for the build procedure.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(default, rename_all = "kebab-case")]
pub struct BuildConfig {
/// Should non-existent markdown files specified in `SETTINGS.md` be created
/// if they don't exist?
pub create_missing: bool,
}
impl Default for BuildConfig {
fn default() -> BuildConfig {
BuildConfig {
create_missing: true,
}
}
}
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)] #[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
#[serde(default, rename_all = "kebab-case")] #[serde(default, rename_all = "kebab-case")]
pub struct HtmlConfig { pub struct HtmlConfig {
@ -250,6 +274,9 @@ mod tests {
src = "source" src = "source"
build-dir = "outputs" build-dir = "outputs"
[build]
create-missing = false
[output.html] [output.html]
theme = "./themedir" theme = "./themedir"
curly-quotes = true curly-quotes = true
@ -274,6 +301,9 @@ mod tests {
build_dir: PathBuf::from("outputs"), build_dir: PathBuf::from("outputs"),
..Default::default() ..Default::default()
}; };
let build_should_be = BuildConfig {
create_missing: false,
};
let playpen_should_be = Playpen { let playpen_should_be = Playpen {
editable: true, editable: true,
editor: PathBuf::from("ace"), editor: PathBuf::from("ace"),
@ -290,6 +320,7 @@ mod tests {
let got = Config::from_str(src).unwrap(); let got = Config::from_str(src).unwrap();
assert_eq!(got.book, book_should_be); assert_eq!(got.book, book_should_be);
assert_eq!(got.build, build_should_be);
assert_eq!(got.html_config().unwrap(), html_should_be); assert_eq!(got.html_config().unwrap(), html_should_be);
} }