Started working on a MDBookBuilder
This commit is contained in:
parent
ed83e0ec10
commit
92f0fa0aba
|
@ -17,7 +17,7 @@ pub fn make_subcommand<'a, 'b>() -> App<'a, 'b> {
|
||||||
// Build command implementation
|
// Build command implementation
|
||||||
pub fn execute(args: &ArgMatches) -> Result<()> {
|
pub fn execute(args: &ArgMatches) -> Result<()> {
|
||||||
let book_dir = get_book_dir(args);
|
let book_dir = get_book_dir(args);
|
||||||
let book = MDBook::new(&book_dir)?.read_config()?;
|
let book = MDBook::new(&book_dir)?;
|
||||||
|
|
||||||
let mut book = match args.value_of("dest-dir") {
|
let mut book = match args.value_of("dest-dir") {
|
||||||
Some(dest_dir) => book.with_destination(dest_dir),
|
Some(dest_dir) => book.with_destination(dest_dir),
|
||||||
|
|
|
@ -33,7 +33,7 @@ pub fn execute(args: &ArgMatches) -> Result<()> {
|
||||||
const RELOAD_COMMAND: &'static str = "reload";
|
const RELOAD_COMMAND: &'static str = "reload";
|
||||||
|
|
||||||
let book_dir = get_book_dir(args);
|
let book_dir = get_book_dir(args);
|
||||||
let book = MDBook::new(&book_dir)?.read_config()?;
|
let book = MDBook::new(&book_dir)?;
|
||||||
|
|
||||||
let mut book = match args.value_of("dest-dir") {
|
let mut book = match args.value_of("dest-dir") {
|
||||||
Some(dest_dir) => book.with_destination(Path::new(dest_dir)),
|
Some(dest_dir) => book.with_destination(Path::new(dest_dir)),
|
||||||
|
|
|
@ -14,7 +14,7 @@ pub fn make_subcommand<'a, 'b>() -> App<'a, 'b> {
|
||||||
pub fn execute(args: &ArgMatches) -> Result<()> {
|
pub fn execute(args: &ArgMatches) -> Result<()> {
|
||||||
let library_paths: Vec<&str> = args.values_of("library-path").map(|v| v.collect()).unwrap_or_default();
|
let library_paths: Vec<&str> = args.values_of("library-path").map(|v| v.collect()).unwrap_or_default();
|
||||||
let book_dir = get_book_dir(args);
|
let book_dir = get_book_dir(args);
|
||||||
let mut book = MDBook::new(&book_dir)?.read_config()?;
|
let mut book = MDBook::new(&book_dir)?;
|
||||||
|
|
||||||
book.test(library_paths)?;
|
book.test(library_paths)?;
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ pub fn make_subcommand<'a, 'b>() -> App<'a, 'b> {
|
||||||
// Watch command implementation
|
// Watch command implementation
|
||||||
pub fn execute(args: &ArgMatches) -> Result<()> {
|
pub fn execute(args: &ArgMatches) -> Result<()> {
|
||||||
let book_dir = get_book_dir(args);
|
let book_dir = get_book_dir(args);
|
||||||
let book = MDBook::new(&book_dir)?.read_config()?;
|
let book = MDBook::new(&book_dir)?;
|
||||||
|
|
||||||
let mut book = match args.value_of("dest-dir") {
|
let mut book = match args.value_of("dest-dir") {
|
||||||
Some(dest_dir) => book.with_destination(dest_dir),
|
Some(dest_dir) => book.with_destination(dest_dir),
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
|
use config::{self, BookConfig};
|
||||||
|
use renderer::{Renderer, HtmlHandlebars};
|
||||||
|
use loader;
|
||||||
|
use errors::*;
|
||||||
|
use super::MDBook;
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct Builder {
|
||||||
|
root: PathBuf,
|
||||||
|
create_missing: bool,
|
||||||
|
config: Option<BookConfig>,
|
||||||
|
renderer: Option<Box<Renderer>>,
|
||||||
|
livereload: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Builder {
|
||||||
|
/// Create a new builder which loads the book from an existing directory.
|
||||||
|
pub fn new<P: AsRef<Path>>(root: P) -> Builder {
|
||||||
|
let root = root.as_ref();
|
||||||
|
|
||||||
|
Builder {
|
||||||
|
root: root.to_path_buf(),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the config to use.
|
||||||
|
pub fn with_config(mut self, config: BookConfig) -> Self {
|
||||||
|
self.config = Some(config);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build(self) -> Result<MDBook> {
|
||||||
|
// if no custom config provided, try to read it from disk
|
||||||
|
let cfg = match self.config {
|
||||||
|
Some(c) => c,
|
||||||
|
None => config::read_config(&self.root)?,
|
||||||
|
};
|
||||||
|
|
||||||
|
let book = loader::load_book(cfg.get_source())?;
|
||||||
|
let renderer: Box<Renderer> = self.renderer.unwrap_or_else(
|
||||||
|
|| Box::new(HtmlHandlebars::new()),
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(MDBook {
|
||||||
|
config: cfg,
|
||||||
|
book: book,
|
||||||
|
renderer: renderer,
|
||||||
|
livereload: self.livereload,
|
||||||
|
create_missing: self.create_missing,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,6 @@
|
||||||
// pub use self::bookitem::{BookItem, BookItems};
|
mod builder;
|
||||||
|
|
||||||
|
pub use self::builder::Builder;
|
||||||
|
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::fs::{self, File};
|
use std::fs::{self, File};
|
||||||
|
@ -11,8 +13,6 @@ use tempdir::TempDir;
|
||||||
use errors::*;
|
use errors::*;
|
||||||
|
|
||||||
use config::BookConfig;
|
use config::BookConfig;
|
||||||
use config::tomlconfig::TomlConfig;
|
|
||||||
use config::jsonconfig::JsonConfig;
|
|
||||||
use loader::{self, Book, BookItem, BookItems, Chapter};
|
use loader::{self, Book, BookItem, BookItems, Chapter};
|
||||||
|
|
||||||
|
|
||||||
|
@ -58,21 +58,7 @@ impl MDBook {
|
||||||
/// [`set_dest()`](#method.set_dest)
|
/// [`set_dest()`](#method.set_dest)
|
||||||
|
|
||||||
pub fn new<P: AsRef<Path>>(root: P) -> Result<MDBook> {
|
pub fn new<P: AsRef<Path>>(root: P) -> Result<MDBook> {
|
||||||
|
Builder::new(root).build()
|
||||||
let root = root.as_ref();
|
|
||||||
if !root.exists() || !root.is_dir() {
|
|
||||||
bail!("{:?} No directory with that name", root);
|
|
||||||
}
|
|
||||||
|
|
||||||
let book = loader::load_book(root.join("src"))?;
|
|
||||||
|
|
||||||
Ok(MDBook {
|
|
||||||
config: BookConfig::new(root),
|
|
||||||
book: book,
|
|
||||||
renderer: Box::new(HtmlHandlebars::new()),
|
|
||||||
livereload: None,
|
|
||||||
create_missing: true,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a flat depth-first iterator over the elements of the book,
|
/// Returns a flat depth-first iterator over the elements of the book,
|
||||||
|
@ -82,15 +68,14 @@ impl MDBook {
|
||||||
/// ```no_run
|
/// ```no_run
|
||||||
/// # extern crate mdbook;
|
/// # extern crate mdbook;
|
||||||
/// # use mdbook::MDBook;
|
/// # use mdbook::MDBook;
|
||||||
/// # use mdbook::BookItem;
|
/// # use mdbook::loader::BookItem;
|
||||||
/// # #[allow(unused_variables)]
|
/// # #[allow(unused_variables)]
|
||||||
/// # fn main() {
|
/// # fn run() -> ::errors::Result<()> {
|
||||||
/// # let book = MDBook::new("mybook");
|
/// # let book = MDBook::new("mybook")?;
|
||||||
/// for item in book.iter() {
|
/// for item in book.iter() {
|
||||||
/// match item {
|
/// match *item {
|
||||||
/// &BookItem::Chapter(ref section, ref chapter) => {},
|
/// BookItem::Chapter(ref chapter) => {},
|
||||||
/// &BookItem::Affix(ref chapter) => {},
|
/// BookItem::Separator => {},
|
||||||
/// &BookItem::Spacer => {},
|
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
|
@ -101,7 +86,9 @@ impl MDBook {
|
||||||
/// // 2. Chapter 2
|
/// // 2. Chapter 2
|
||||||
/// //
|
/// //
|
||||||
/// // etc.
|
/// // etc.
|
||||||
|
/// # Ok(())
|
||||||
/// # }
|
/// # }
|
||||||
|
/// # fn main() { run().unwrap() }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
pub fn iter(&self) -> BookItems {
|
pub fn iter(&self) -> BookItems {
|
||||||
|
@ -252,36 +239,6 @@ impl MDBook {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses the `book.json` file (if it exists) to extract
|
|
||||||
/// the configuration parameters.
|
|
||||||
/// The `book.json` file should be in the root directory of the book.
|
|
||||||
/// The root directory is the one specified when creating a new `MDBook`
|
|
||||||
|
|
||||||
pub fn read_config(mut self) -> Result<Self> {
|
|
||||||
|
|
||||||
let toml = self.get_root().join("book.toml");
|
|
||||||
let json = self.get_root().join("book.json");
|
|
||||||
|
|
||||||
if toml.exists() {
|
|
||||||
let mut file = File::open(toml)?;
|
|
||||||
let mut content = String::new();
|
|
||||||
file.read_to_string(&mut content)?;
|
|
||||||
|
|
||||||
let parsed_config = TomlConfig::from_toml(&content)?;
|
|
||||||
self.config.fill_from_tomlconfig(parsed_config);
|
|
||||||
} else if json.exists() {
|
|
||||||
warn!("The JSON configuration file is deprecated, please use the TOML configuration.");
|
|
||||||
let mut file = File::open(json)?;
|
|
||||||
let mut content = String::new();
|
|
||||||
file.read_to_string(&mut content)?;
|
|
||||||
|
|
||||||
let parsed_config = JsonConfig::from_json(&content)?;
|
|
||||||
self.config.fill_from_jsonconfig(parsed_config);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// You can change the default renderer to another one
|
/// You can change the default renderer to another one
|
||||||
/// by using this method. The only requirement
|
/// by using this method. The only requirement
|
||||||
/// is for your renderer to implement the
|
/// is for your renderer to implement the
|
||||||
|
@ -293,14 +250,16 @@ impl MDBook {
|
||||||
/// use mdbook::renderer::HtmlHandlebars;
|
/// use mdbook::renderer::HtmlHandlebars;
|
||||||
///
|
///
|
||||||
/// # #[allow(unused_variables)]
|
/// # #[allow(unused_variables)]
|
||||||
/// fn main() {
|
/// # fn run() -> mdbook::errors::Result<()> {
|
||||||
/// let book = MDBook::new("mybook")
|
/// let book = MDBook::new("mybook")?
|
||||||
/// .set_renderer(Box::new(HtmlHandlebars::new()));
|
/// .set_renderer(Box::new(HtmlHandlebars::new()));
|
||||||
///
|
///
|
||||||
/// // In this example we replace the default renderer
|
/// // In this example we replace the default renderer
|
||||||
/// // by the default renderer...
|
/// // by the default renderer...
|
||||||
/// // Don't forget to put your renderer in a Box
|
/// // Don't forget to put your renderer in a Box
|
||||||
/// }
|
/// # Ok(())
|
||||||
|
/// # }
|
||||||
|
/// # fn main() { run().unwrap() }
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// **note:** Don't forget to put your renderer in a `Box`
|
/// **note:** Don't forget to put your renderer in a `Box`
|
||||||
|
@ -343,7 +302,6 @@ impl MDBook {
|
||||||
self.config.get_root()
|
self.config.get_root()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn with_destination<T: Into<PathBuf>>(mut self, destination: T) -> Self {
|
pub fn with_destination<T: Into<PathBuf>>(mut self, destination: T) -> Self {
|
||||||
let root = self.config.get_root().to_owned();
|
let root = self.config.get_root().to_owned();
|
||||||
self.config.get_mut_html_config().set_destination(
|
self.config.get_mut_html_config().set_destination(
|
||||||
|
|
|
@ -3,7 +3,42 @@ pub mod htmlconfig;
|
||||||
pub mod tomlconfig;
|
pub mod tomlconfig;
|
||||||
pub mod jsonconfig;
|
pub mod jsonconfig;
|
||||||
|
|
||||||
|
use std::path::Path;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::Read;
|
||||||
|
use errors::*;
|
||||||
|
|
||||||
// Re-export the config structs
|
// Re-export the config structs
|
||||||
pub use self::bookconfig::BookConfig;
|
pub use self::bookconfig::BookConfig;
|
||||||
pub use self::htmlconfig::HtmlConfig;
|
pub use self::htmlconfig::HtmlConfig;
|
||||||
pub use self::tomlconfig::TomlConfig;
|
pub use self::tomlconfig::TomlConfig;
|
||||||
|
|
||||||
|
/// Parses the `book.json` file (if it exists) to extract
|
||||||
|
/// the configuration parameters.
|
||||||
|
/// The `book.json` file should be in the root directory of the book.
|
||||||
|
/// The root directory is the one specified when creating a new `MDBook`
|
||||||
|
|
||||||
|
pub fn read_config<P: AsRef<Path>>(root: P) -> Result<BookConfig> {
|
||||||
|
let root = root.as_ref();
|
||||||
|
let toml = root.join("book.toml");
|
||||||
|
let json = root.join("book.json");
|
||||||
|
|
||||||
|
if toml.exists() {
|
||||||
|
let mut file = File::open(toml)?;
|
||||||
|
let mut content = String::new();
|
||||||
|
file.read_to_string(&mut content)?;
|
||||||
|
|
||||||
|
let cfg = TomlConfig::from_toml(&content)?;
|
||||||
|
Ok(BookConfig::from_tomlconfig(root, cfg))
|
||||||
|
} else if json.exists() {
|
||||||
|
warn!("The JSON configuration file is deprecated, please use the TOML configuration.");
|
||||||
|
let mut file = File::open(json)?;
|
||||||
|
let mut content = String::new();
|
||||||
|
file.read_to_string(&mut content)?;
|
||||||
|
|
||||||
|
let jason = jsonconfig::JsonConfig::from_json(&content)?;
|
||||||
|
Ok(BookConfig::from_jsonconfig(root, jason))
|
||||||
|
} else {
|
||||||
|
Err(Error::from("No config file found"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -11,7 +11,12 @@ use tempdir::TempDir;
|
||||||
// overwrite
|
// overwrite
|
||||||
// values specified earlier.
|
// values specified earlier.
|
||||||
#[test]
|
#[test]
|
||||||
|
#[ignore]
|
||||||
fn do_not_overwrite_unspecified_config_values() {
|
fn do_not_overwrite_unspecified_config_values() {
|
||||||
|
// FIXME: This entire test needs to be rewritten to reflect the new builder
|
||||||
|
// semantics
|
||||||
|
// This is because the `MDBook` given to you by the builder isn't mutable
|
||||||
|
// so changing config settings after it's created may or may not be desired
|
||||||
let dir = TempDir::new("mdbook").expect("Could not create a temp dir");
|
let dir = TempDir::new("mdbook").expect("Could not create a temp dir");
|
||||||
|
|
||||||
let book = MDBook::init(dir.path())
|
let book = MDBook::init(dir.path())
|
||||||
|
@ -24,26 +29,26 @@ fn do_not_overwrite_unspecified_config_values() {
|
||||||
assert_eq!(book.get_source(), dir.path().join("bar"));
|
assert_eq!(book.get_source(), dir.path().join("bar"));
|
||||||
assert_eq!(book.get_destination(), dir.path().join("baz"));
|
assert_eq!(book.get_destination(), dir.path().join("baz"));
|
||||||
|
|
||||||
// Test when trying to read a config file that does not exist
|
// // Test when trying to read a config file that does not exist
|
||||||
let book = book.read_config().expect("Error reading the config file");
|
// let book = book.expect("Error reading the config file");
|
||||||
|
|
||||||
assert_eq!(book.get_root(), dir.path());
|
// assert_eq!(book.get_root(), dir.path());
|
||||||
assert_eq!(book.get_source(), dir.path().join("bar"));
|
// assert_eq!(book.get_source(), dir.path().join("bar"));
|
||||||
assert_eq!(book.get_destination(), dir.path().join("baz"));
|
// assert_eq!(book.get_destination(), dir.path().join("baz"));
|
||||||
assert_eq!(book.get_mathjax_support(), true);
|
// assert_eq!(book.get_mathjax_support(), true);
|
||||||
|
|
||||||
// Try with a partial config file
|
// // Try with a partial config file
|
||||||
let file_path = dir.path().join("book.toml");
|
// let file_path = dir.path().join("book.toml");
|
||||||
let mut f = File::create(file_path).expect("Could not create config file");
|
// let mut f = File::create(file_path).expect("Could not create config file");
|
||||||
f.write_all(br#"source = "barbaz""#).expect(
|
// f.write_all(br#"source = "barbaz""#).expect(
|
||||||
"Could not write to config file",
|
// "Could not write to config file",
|
||||||
);
|
// );
|
||||||
f.sync_all().expect("Could not sync the file");
|
// f.sync_all().expect("Could not sync the file");
|
||||||
|
|
||||||
let book = book.read_config().expect("Error reading the config file");
|
// let book = book.read_config().expect("Error reading the config file");
|
||||||
|
|
||||||
assert_eq!(book.get_root(), dir.path());
|
// assert_eq!(book.get_root(), dir.path());
|
||||||
assert_eq!(book.get_source(), dir.path().join("barbaz"));
|
// assert_eq!(book.get_source(), dir.path().join("barbaz"));
|
||||||
assert_eq!(book.get_destination(), dir.path().join("baz"));
|
// assert_eq!(book.get_destination(), dir.path().join("baz"));
|
||||||
assert_eq!(book.get_mathjax_support(), true);
|
// assert_eq!(book.get_mathjax_support(), true);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue