Clean up build configuration.

This rolls all "create missing" handling into BuildConfig, and moves the
build-dir option from the "book" table to the "build" table. Some
documentation cleanup surrounding the build table is also updated.
This commit is contained in:
Chris Spiegel 2017-11-30 07:26:30 -08:00
parent 93874edebf
commit b0b09bad3f
8 changed files with 33 additions and 33 deletions

View File

@ -11,10 +11,10 @@ author = "John Doe"
description = "The example book covers examples." description = "The example book covers examples."
[build] [build]
build-dir = "my-example-book"
create-missing = false create-missing = false
[output.html] [output.html]
destination = "my-example-book"
additional-css = ["custom.css"] additional-css = ["custom.css"]
``` ```
@ -35,8 +35,6 @@ This is general information about your book.
- **src:** By default, the source directory is found in the directory named - **src:** By default, the source directory is found in the directory named
`src` directly under the root folder. But this is configurable with the `src` `src` directly under the root folder. But this is configurable with the `src`
key in the configuration file. key in the configuration file.
- **build-dir:** The directory to put the rendered book in. By default this is
`book/` in the book's root directory.
**book.toml** **book.toml**
```toml ```toml
@ -45,20 +43,23 @@ title = "Example book"
authors = ["John Doe", "Jane Doe"] authors = ["John Doe", "Jane Doe"]
description = "The example book covers examples." description = "The example book covers examples."
src = "my-src" # the source files will be found in `root/my-src` instead of `root/src` src = "my-src" # the source files will be found in `root/my-src` instead of `root/src`
build-dir = "build"
``` ```
### Build options ### Build options
This controls the build process of your book. This controls the build process of your book.
- **build-dir:** The directory to put the rendered book in. By default this is
`book/` in the book's root directory.
- **create-missing:** By default, any missing files specified in `SUMMARY.md` - **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 will be created when the book is built (i.e. `create-missing = true`). If this
process will instead exit with an error if any files do not exist. is `false` then the build process will instead exit with an error if any files
do not exist.
**book.toml** **book.toml**
```toml ```toml
[build] [build]
build-dir = "build"
create-missing = false create-missing = false
``` ```

View File

@ -28,11 +28,12 @@ pub fn execute(args: &ArgMatches) -> Result<()> {
let mut book = MDBook::new(&book_dir).read_config()?; let mut book = MDBook::new(&book_dir).read_config()?;
if let Some(dest_dir) = args.value_of("dest-dir") { if let Some(dest_dir) = args.value_of("dest-dir") {
book.config.book.build_dir = PathBuf::from(dest_dir); book.config.build.build_dir = PathBuf::from(dest_dir);
} }
// This flag is deprecated in favor of being set via `book.toml`.
if args.is_present("no-create") { if args.is_present("no-create") {
book.create_missing = Some(false); book.config.build.create_missing = false;
} }
book.build()?; book.build()?;

View File

@ -52,7 +52,7 @@ pub fn execute(args: &ArgMatches) -> Result<()> {
let mut book = MDBook::new(&book_dir).read_config()?; let mut book = MDBook::new(&book_dir).read_config()?;
if let Some(dest_dir) = args.value_of("dest-dir") { if let Some(dest_dir) = args.value_of("dest-dir") {
book.config.book.build_dir = PathBuf::from(dest_dir); book.config.build.build_dir = PathBuf::from(dest_dir);
} }
let port = args.value_of("port").unwrap_or("3000"); let port = args.value_of("port").unwrap_or("3000");

View File

@ -30,7 +30,7 @@ pub fn execute(args: &ArgMatches) -> Result<()> {
let mut book = MDBook::new(&book_dir).read_config()?; let mut book = MDBook::new(&book_dir).read_config()?;
if let Some(dest_dir) = args.value_of("dest-dir") { if let Some(dest_dir) = args.value_of("dest-dir") {
book.config.book.build_dir = PathBuf::from(dest_dir); book.config.build.build_dir = PathBuf::from(dest_dir);
} }
if args.is_present("open") { if args.is_present("open") {

View File

@ -23,12 +23,6 @@ pub struct MDBook {
renderer: Box<Renderer>, renderer: Box<Renderer>,
pub livereload: Option<String>, pub livereload: Option<String>,
/// Should `mdbook build` create files referenced from SUMMARY.md if they
/// don't exist? If `None`, use the setting specified in `book.toml`,
/// otherwise use this.
/// This is for backward compatibility only.
pub create_missing: Option<bool>,
} }
impl MDBook { impl MDBook {
@ -73,7 +67,6 @@ impl MDBook {
renderer: Box::new(HtmlHandlebars::new()), renderer: Box::new(HtmlHandlebars::new()),
livereload: None, livereload: None,
create_missing: None,
} }
} }
@ -181,9 +174,7 @@ impl MDBook {
let path = self.get_source().join(&ch.path); let path = self.get_source().join(&ch.path);
if !path.exists() { if !path.exists() {
let create_missing = self.create_missing.unwrap_or(self.config.build.create_missing); if !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(),
); );
@ -388,7 +379,7 @@ impl MDBook {
} }
pub fn get_destination(&self) -> PathBuf { pub fn get_destination(&self) -> PathBuf {
self.root.join(&self.config.book.build_dir) self.root.join(&self.config.build.build_dir)
} }
pub fn get_source(&self) -> PathBuf { pub fn get_source(&self) -> PathBuf {

View File

@ -92,7 +92,7 @@ impl Config {
get_and_insert!(table, "description" => cfg.book.description); get_and_insert!(table, "description" => cfg.book.description);
// This complicated chain of and_then's is so we can move // This complicated chain of and_then's is so we can move
// "output.html.destination" to "book.build_dir" and parse it into a // "output.html.destination" to "build.build_dir" and parse it into a
// PathBuf. // PathBuf.
let destination: Option<PathBuf> = table.get_mut("output") let destination: Option<PathBuf> = table.get_mut("output")
.and_then(|output| output.as_table_mut()) .and_then(|output| output.as_table_mut())
@ -102,7 +102,7 @@ impl Config {
.and_then(|dest| dest.try_into().ok()); .and_then(|dest| dest.try_into().ok());
if let Some(dest) = destination { if let Some(dest) = destination {
cfg.book.build_dir = dest; cfg.build.build_dir = dest;
} }
cfg.rest = table; cfg.rest = table;
@ -164,7 +164,9 @@ impl<'de> Deserialize<'de> for Config {
warn!("We'll parse it for now, but you should probably convert to the new format."); warn!("We'll parse it for now, but you should probably convert to the new format.");
warn!("See the mdbook documentation for more details, although as a rule of thumb"); warn!("See the mdbook documentation for more details, although as a rule of thumb");
warn!("just move all top level configuration entries like `title`, `author` and"); warn!("just move all top level configuration entries like `title`, `author` and");
warn!("`description` under a table called `[book]` and it should all work."); warn!("`description` under a table called `[book]`, move the `destination` entry");
warn!("from `[output.html]`, renamed to `build-dir`, under a table called");
warn!("`[build]`, and it should all work.");
warn!("Documentation: http://rust-lang-nursery.github.io/mdBook/format/config.html"); warn!("Documentation: http://rust-lang-nursery.github.io/mdBook/format/config.html");
return Ok(Config::from_legacy(table)); return Ok(Config::from_legacy(table));
} }
@ -205,8 +207,6 @@ pub struct BookConfig {
pub description: Option<String>, pub description: Option<String>,
/// Location of the book source relative to the book's root directory. /// Location of the book source relative to the book's root directory.
pub src: PathBuf, pub src: PathBuf,
/// Where to put built artefacts relative to the book's root directory.
pub build_dir: PathBuf,
/// Does this book support more than one language? /// Does this book support more than one language?
pub multilingual: bool, pub multilingual: bool,
} }
@ -218,7 +218,6 @@ impl Default for BookConfig {
authors: Vec::new(), authors: Vec::new(),
description: None, description: None,
src: PathBuf::from("src"), src: PathBuf::from("src"),
build_dir: PathBuf::from("book"),
multilingual: false, multilingual: false,
} }
} }
@ -228,6 +227,8 @@ impl Default for BookConfig {
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(default, rename_all = "kebab-case")] #[serde(default, rename_all = "kebab-case")]
pub struct BuildConfig { pub struct BuildConfig {
/// Where to put built artefacts relative to the book's root directory.
pub build_dir: PathBuf,
/// 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,
@ -236,6 +237,7 @@ pub struct BuildConfig {
impl Default for BuildConfig { impl Default for BuildConfig {
fn default() -> BuildConfig { fn default() -> BuildConfig {
BuildConfig { BuildConfig {
build_dir: PathBuf::from("book"),
create_missing: true, create_missing: true,
} }
} }
@ -272,9 +274,9 @@ mod tests {
description = "A completely useless book" description = "A completely useless book"
multilingual = true multilingual = true
src = "source" src = "source"
build-dir = "outputs"
[build] [build]
build-dir = "outputs"
create-missing = false create-missing = false
[output.html] [output.html]
@ -298,10 +300,10 @@ mod tests {
description: Some(String::from("A completely useless book")), description: Some(String::from("A completely useless book")),
multilingual: true, multilingual: true,
src: PathBuf::from("source"), src: PathBuf::from("source"),
build_dir: PathBuf::from("outputs"),
..Default::default() ..Default::default()
}; };
let build_should_be = BuildConfig { let build_should_be = BuildConfig {
build_dir: PathBuf::from("outputs"),
create_missing: false, create_missing: false,
}; };
let playpen_should_be = Playpen { let playpen_should_be = Playpen {
@ -397,11 +399,15 @@ mod tests {
"Create book from markdown files. Like Gitbook but implemented in Rust", "Create book from markdown files. Like Gitbook but implemented in Rust",
)), )),
authors: vec![String::from("Mathieu David")], authors: vec![String::from("Mathieu David")],
build_dir: PathBuf::from("my-book"),
src: PathBuf::from("./source"), src: PathBuf::from("./source"),
..Default::default() ..Default::default()
}; };
let build_should_be = BuildConfig {
build_dir: PathBuf::from("my-book"),
create_missing: true,
};
let html_should_be = HtmlConfig { let html_should_be = HtmlConfig {
theme: Some(PathBuf::from("my-theme")), theme: Some(PathBuf::from("my-theme")),
curly_quotes: true, curly_quotes: true,
@ -413,6 +419,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);
} }
} }

View File

@ -28,7 +28,7 @@
//! //!
//! // tweak the book configuration a bit //! // tweak the book configuration a bit
//! md.config.book.src = PathBuf::from("source"); //! md.config.book.src = PathBuf::from("source");
//! md.config.book.build_dir = PathBuf::from("book"); //! md.config.build.build_dir = PathBuf::from("book");
//! //!
//! // Render the book //! // Render the book
//! md.build().unwrap(); //! md.build().unwrap();

View File

@ -42,7 +42,7 @@ fn run_mdbook_init_with_custom_book_and_src_locations() {
let mut md = MDBook::new(temp.path()); let mut md = MDBook::new(temp.path());
md.config.book.src = PathBuf::from("in"); md.config.book.src = PathBuf::from("in");
md.config.book.build_dir = PathBuf::from("out"); md.config.build.build_dir = PathBuf::from("out");
md.init().unwrap(); md.init().unwrap();