HtmlConfig is no longer optional

`HtmlConfig` was both guaranteed to exist within `BookConfig`
and `expect`ed in few places.
This simplifies the API a little by representing the fact that
`HtmlConfig` is currently mandatory for proper mdBook binary operation.
This commit is contained in:
Michal Budzynski 2017-06-27 14:01:33 +02:00
parent 5a27207844
commit b1ca9cf5b5
11 changed files with 97 additions and 173 deletions

View File

@ -34,10 +34,8 @@ pub fn execute(args: &ArgMatches) -> Result<()> {
book.build()?; book.build()?;
if let Some(d) = book.get_destination() {
if args.is_present("open") { if args.is_present("open") {
open(d.join("index.html")); open(book.get_destination().join("index.html"));
}
} }
Ok(()) Ok(())

View File

@ -49,9 +49,7 @@ pub fn execute(args: &ArgMatches) -> Result<()> {
} }
// Because of `src/book/mdbook.rs#L37-L39`, `dest` will always start with `root` // Because of `src/book/mdbook.rs#L37-L39`, `dest` will always start with `root`
let is_dest_inside_root = book.get_destination() let is_dest_inside_root = book.get_destination().starts_with(book.get_root());
.map(|p| p.starts_with(book.get_root()))
.unwrap_or(false);
if !args.is_present("force") && is_dest_inside_root { if !args.is_present("force") && is_dest_inside_root {
println!("\nDo you want a .gitignore to be created? (y/n)"); println!("\nDo you want a .gitignore to be created? (y/n)");

View File

@ -40,11 +40,6 @@ pub fn execute(args: &ArgMatches) -> Result<()> {
None => book, None => book,
}; };
if let None = book.get_destination() {
println!("The HTML renderer is not set up, impossible to serve the files.");
std::process::exit(2);
}
if args.is_present("curly-quotes") { if args.is_present("curly-quotes") {
book = book.with_curly_quotes(true); book = book.with_curly_quotes(true);
} }
@ -79,8 +74,7 @@ pub fn execute(args: &ArgMatches) -> Result<()> {
book.build()?; book.build()?;
let mut chain = Chain::new(staticfile::Static::new(book.get_destination() let mut chain = Chain::new(staticfile::Static::new(book.get_destination()));
.expect("destination is present, checked before")));
chain.link_after(ErrorRecover); chain.link_after(ErrorRecover);
let _iron = Iron::new(chain).http(&*address).unwrap(); let _iron = Iron::new(chain).http(&*address).unwrap();

View File

@ -37,9 +37,7 @@ pub fn execute(args: &ArgMatches) -> Result<()> {
if args.is_present("open") { if args.is_present("open") {
book.build()?; book.build()?;
if let Some(d) = book.get_destination() { open(book.get_destination().join("index.html"));
open(d.join("index.html"));
}
} }
trigger_on_change(&mut book, |path, book| { trigger_on_change(&mut book, |path, book| {
@ -78,9 +76,7 @@ pub fn trigger_on_change<F>(book: &mut MDBook, closure: F) -> ()
}; };
// Add the theme directory to the watcher // Add the theme directory to the watcher
if let Some(t) = book.get_theme_path() { watcher.watch(book.get_theme_path(), Recursive).unwrap_or_default();
watcher.watch(t, Recursive).unwrap_or_default();
}
// Add the book.{json,toml} file to the watcher if it exists, because it's not // Add the book.{json,toml} file to the watcher if it exists, because it's not

View File

@ -138,11 +138,9 @@ impl MDBook {
{ {
if let Some(htmlconfig) = self.config.get_html_config() { if !self.get_destination().exists() {
if !htmlconfig.get_destination().exists() { debug!("[*]: {:?} does not exist, trying to create directory", self.get_destination());
debug!("[*]: {:?} does not exist, trying to create directory", htmlconfig.get_destination()); fs::create_dir_all(self.get_destination())?;
fs::create_dir_all(htmlconfig.get_destination())?;
}
} }
@ -203,11 +201,7 @@ impl MDBook {
pub fn create_gitignore(&self) { pub fn create_gitignore(&self) {
let gitignore = self.get_gitignore(); let gitignore = self.get_gitignore();
// If the HTML renderer is not set, return
if self.config.get_html_config().is_none() { return; }
let destination = self.config.get_html_config() let destination = self.config.get_html_config()
.expect("The HtmlConfig does exist, checked just before")
.get_destination(); .get_destination();
// Check that the gitignore does not extist and that the destination path begins with the root path // Check that the gitignore does not extist and that the destination path begins with the root path
@ -243,9 +237,7 @@ impl MDBook {
self.init()?; self.init()?;
// Clean output directory // Clean output directory
if let Some(htmlconfig) = self.config.get_html_config() { utils::fs::remove_dir_content(self.config.get_html_config().get_destination())?;
utils::fs::remove_dir_content(htmlconfig.get_destination())?;
}
self.renderer.render(self) self.renderer.render(self)
} }
@ -258,9 +250,7 @@ impl MDBook {
pub fn copy_theme(&self) -> Result<()> { pub fn copy_theme(&self) -> Result<()> {
debug!("[fn]: copy_theme"); debug!("[fn]: copy_theme");
if let Some(htmlconfig) = self.config.get_html_config() { let themedir = self.config.get_html_config().get_theme();
let themedir = htmlconfig.get_theme();
if !themedir.exists() { if !themedir.exists() {
debug!("[*]: {:?} does not exist, trying to create directory", themedir); debug!("[*]: {:?} does not exist, trying to create directory", themedir);
fs::create_dir(&themedir)?; fs::create_dir(&themedir)?;
@ -289,13 +279,12 @@ impl MDBook {
// highlight.js // highlight.js
let mut highlight_js = File::create(&themedir.join("highlight.js"))?; let mut highlight_js = File::create(&themedir.join("highlight.js"))?;
highlight_js.write_all(theme::HIGHLIGHT_JS)?; highlight_js.write_all(theme::HIGHLIGHT_JS)?;
}
Ok(()) Ok(())
} }
pub fn write_file<P: AsRef<Path>>(&self, filename: P, content: &[u8]) -> Result<()> { pub fn write_file<P: AsRef<Path>>(&self, filename: P, content: &[u8]) -> Result<()> {
let path = self.get_destination().ok_or_else(|| String::from("HtmlConfig not set, could not find a destination"))? let path = self.get_destination()
.join(filename); .join(filename);
utils::fs::create_file(&path)? utils::fs::create_file(&path)?
@ -392,22 +381,15 @@ impl MDBook {
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();
if let Some(htmlconfig) = self.config.get_mut_html_config() { self.config.get_mut_html_config()
htmlconfig.set_destination(&root, &destination.into()); .set_destination(&root, &destination.into());
} else {
error!("There is no HTML renderer set...");
}
self self
} }
pub fn get_destination(&self) -> Option<&Path> { pub fn get_destination(&self) -> &Path {
if let Some(htmlconfig) = self.config.get_html_config() { self.config.get_html_config()
return Some(htmlconfig.get_destination()); .get_destination()
}
None
} }
pub fn with_source<T: Into<PathBuf>>(mut self, source: T) -> Self { pub fn with_source<T: Into<PathBuf>>(mut self, source: T) -> Self {
@ -453,94 +435,61 @@ impl MDBook {
pub fn with_theme_path<T: Into<PathBuf>>(mut self, theme_path: T) -> Self { pub fn with_theme_path<T: Into<PathBuf>>(mut self, theme_path: T) -> Self {
let root = self.config.get_root().to_owned(); let root = self.config.get_root().to_owned();
if let Some(htmlconfig) = self.config.get_mut_html_config() { self.config.get_mut_html_config()
htmlconfig.set_theme(&root, &theme_path.into()); .set_theme(&root, &theme_path.into());
} else {
error!("There is no HTML renderer set...");
}
self self
} }
pub fn get_theme_path(&self) -> Option<&Path> { pub fn get_theme_path(&self) -> &Path {
if let Some(htmlconfig) = self.config.get_html_config() { self.config.get_html_config()
return Some(htmlconfig.get_theme()); .get_theme()
}
None
} }
pub fn with_curly_quotes(mut self, curly_quotes: bool) -> Self { pub fn with_curly_quotes(mut self, curly_quotes: bool) -> Self {
if let Some(htmlconfig) = self.config.get_mut_html_config() { self.config.get_mut_html_config()
htmlconfig.set_curly_quotes(curly_quotes); .set_curly_quotes(curly_quotes);
} else {
error!("There is no HTML renderer set...");
}
self self
} }
pub fn get_curly_quotes(&self) -> bool { pub fn get_curly_quotes(&self) -> bool {
if let Some(htmlconfig) = self.config.get_html_config() { self.config.get_html_config()
return htmlconfig.get_curly_quotes(); .get_curly_quotes()
}
false
} }
pub fn with_mathjax_support(mut self, mathjax_support: bool) -> Self { pub fn with_mathjax_support(mut self, mathjax_support: bool) -> Self {
if let Some(htmlconfig) = self.config.get_mut_html_config() { self.config.get_mut_html_config()
htmlconfig.set_mathjax_support(mathjax_support); .set_mathjax_support(mathjax_support);
} else {
error!("There is no HTML renderer set...");
}
self self
} }
pub fn get_mathjax_support(&self) -> bool { pub fn get_mathjax_support(&self) -> bool {
if let Some(htmlconfig) = self.config.get_html_config() { self.config.get_html_config()
return htmlconfig.get_mathjax_support(); .get_mathjax_support()
}
false
} }
pub fn get_google_analytics_id(&self) -> Option<String> { pub fn get_google_analytics_id(&self) -> Option<String> {
if let Some(htmlconfig) = self.config.get_html_config() { self.config.get_html_config()
return htmlconfig.get_google_analytics_id(); .get_google_analytics_id()
}
None
} }
pub fn has_additional_js(&self) -> bool { pub fn has_additional_js(&self) -> bool {
if let Some(htmlconfig) = self.config.get_html_config() { self.config.get_html_config()
return htmlconfig.has_additional_js(); .has_additional_js()
}
false
} }
pub fn get_additional_js(&self) -> &[PathBuf] { pub fn get_additional_js(&self) -> &[PathBuf] {
if let Some(htmlconfig) = self.config.get_html_config() { self.config.get_html_config()
return htmlconfig.get_additional_js(); .get_additional_js()
}
&[]
} }
pub fn has_additional_css(&self) -> bool { pub fn has_additional_css(&self) -> bool {
if let Some(htmlconfig) = self.config.get_html_config() { self.config.get_html_config()
return htmlconfig.has_additional_css(); .has_additional_css()
}
false
} }
pub fn get_additional_css(&self) -> &[PathBuf] { pub fn get_additional_css(&self) -> &[PathBuf] {
if let Some(htmlconfig) = self.config.get_html_config() { self.config.get_html_config()
return htmlconfig.get_additional_css(); .get_additional_css()
}
&[]
} }
// Construct book // Construct book

View File

@ -5,7 +5,7 @@ use super::tomlconfig::TomlConfig;
use super::jsonconfig::JsonConfig; use super::jsonconfig::JsonConfig;
/// Configuration struct containing all the configuration options available in mdBook. /// Configuration struct containing all the configuration options available in mdBook.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub struct BookConfig { pub struct BookConfig {
root: PathBuf, root: PathBuf,
source: PathBuf, source: PathBuf,
@ -17,7 +17,7 @@ pub struct BookConfig {
multilingual: bool, multilingual: bool,
indent_spaces: i32, indent_spaces: i32,
html_config: Option<HtmlConfig>, html_config: HtmlConfig,
} }
impl BookConfig { impl BookConfig {
@ -33,7 +33,7 @@ impl BookConfig {
/// ///
/// assert_eq!(config.get_root(), &root); /// assert_eq!(config.get_root(), &root);
/// assert_eq!(config.get_source(), PathBuf::from("directory/to/my/book/src")); /// assert_eq!(config.get_source(), PathBuf::from("directory/to/my/book/src"));
/// assert_eq!(config.get_html_config(), Some(&HtmlConfig::new(PathBuf::from("directory/to/my/book")))); /// assert_eq!(config.get_html_config(), &HtmlConfig::new(PathBuf::from("directory/to/my/book")));
/// ``` /// ```
pub fn new<T: Into<PathBuf>>(root: T) -> Self { pub fn new<T: Into<PathBuf>>(root: T) -> Self {
let root: PathBuf = root.into(); let root: PathBuf = root.into();
@ -50,7 +50,7 @@ impl BookConfig {
multilingual: false, multilingual: false,
indent_spaces: 4, indent_spaces: 4,
html_config: Some(htmlconfig), html_config: htmlconfig,
} }
} }
@ -109,9 +109,8 @@ impl BookConfig {
if let Some(tomlhtmlconfig) = tomlconfig.output.and_then(|o| o.html) { if let Some(tomlhtmlconfig) = tomlconfig.output.and_then(|o| o.html) {
let root = self.root.clone(); let root = self.root.clone();
if let Some(htmlconfig) = self.get_mut_html_config() { self.get_mut_html_config()
htmlconfig.fill_from_tomlconfig(root, tomlhtmlconfig); .fill_from_tomlconfig(root, tomlhtmlconfig);
}
} }
self self
@ -148,16 +147,14 @@ impl BookConfig {
if let Some(d) = jsonconfig.dest { if let Some(d) = jsonconfig.dest {
let root = self.get_root().to_owned(); let root = self.get_root().to_owned();
if let Some(htmlconfig) = self.get_mut_html_config() { self.get_mut_html_config()
htmlconfig.set_destination(&root, &d); .set_destination(&root, &d);
}
} }
if let Some(d) = jsonconfig.theme_path { if let Some(d) = jsonconfig.theme_path {
let root = self.get_root().to_owned(); let root = self.get_root().to_owned();
if let Some(htmlconfig) = self.get_mut_html_config() { self.get_mut_html_config()
htmlconfig.set_theme(&root, &d); .set_theme(&root, &d);
}
} }
self self
@ -217,16 +214,16 @@ impl BookConfig {
} }
pub fn set_html_config(&mut self, htmlconfig: HtmlConfig) -> &mut Self { pub fn set_html_config(&mut self, htmlconfig: HtmlConfig) -> &mut Self {
self.html_config = Some(htmlconfig); self.html_config = htmlconfig;
self self
} }
/// Returns the configuration for the HTML renderer or None of there isn't any /// Returns the configuration for the HTML renderer or None of there isn't any
pub fn get_html_config(&self) -> Option<&HtmlConfig> { pub fn get_html_config(&self) -> &HtmlConfig {
self.html_config.as_ref() &self.html_config
} }
pub fn get_mut_html_config(&mut self) -> Option<&mut HtmlConfig> { pub fn get_mut_html_config(&mut self) -> &mut HtmlConfig {
self.html_config.as_mut() &mut self.html_config
} }
} }

View File

@ -110,10 +110,6 @@ impl HtmlHandlebars {
info!( info!(
"[*] Creating index.html from {:?} ✓", "[*] Creating index.html from {:?} ✓",
book.get_destination() book.get_destination()
.expect(
"If the HTML renderer is called, one would assume the HtmlConfig is \
set... (4)",
)
.join(&ch.path.with_extension("html")) .join(&ch.path.with_extension("html"))
); );
@ -252,9 +248,7 @@ impl Renderer for HtmlHandlebars {
// Print version // Print version
let mut print_content = String::new(); let mut print_content = String::new();
let destination = book.get_destination().expect( let destination = book.get_destination();
"If the HTML renderer is called, one would assume the HtmlConfig is set... (2)",
);
debug!("[*]: Check if destination directory exists"); debug!("[*]: Check if destination directory exists");
if fs::create_dir_all(&destination).is_err() { if fs::create_dir_all(&destination).is_err() {

View File

@ -46,7 +46,7 @@ pub struct Theme {
} }
impl Theme { impl Theme {
pub fn new(src: Option<&Path>) -> Self { pub fn new(src: &Path) -> Self {
// Default theme // Default theme
let mut theme = Theme { let mut theme = Theme {
@ -64,12 +64,10 @@ impl Theme {
}; };
// Check if the given path exists // Check if the given path exists
if src.is_none() || !src.unwrap().exists() || !src.unwrap().is_dir() { if !src.exists() || !src.is_dir() {
return theme; return theme;
} }
let src = src.unwrap();
// Check for individual files if they exist // Check for individual files if they exist
// index.hbs // index.hbs

View File

@ -20,14 +20,14 @@ fn do_not_overwrite_unspecified_config_values() {
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().unwrap(), 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.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("bar")); assert_eq!(book.get_source(), dir.path().join("bar"));
assert_eq!(book.get_destination().unwrap(), 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
@ -40,7 +40,7 @@ fn do_not_overwrite_unspecified_config_values() {
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().unwrap(), 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);
} }

View File

@ -66,7 +66,7 @@ fn from_json_destination() {
let parsed = JsonConfig::from_json(json).expect("This should parse"); let parsed = JsonConfig::from_json(json).expect("This should parse");
let config = BookConfig::from_jsonconfig("root", parsed); let config = BookConfig::from_jsonconfig("root", parsed);
let htmlconfig = config.get_html_config().expect("There should be an HtmlConfig"); let htmlconfig = config.get_html_config();
assert_eq!(htmlconfig.get_destination(), PathBuf::from("root/htmlbook")); assert_eq!(htmlconfig.get_destination(), PathBuf::from("root/htmlbook"));
} }
@ -81,7 +81,7 @@ fn from_json_output_html_theme() {
let parsed = JsonConfig::from_json(json).expect("This should parse"); let parsed = JsonConfig::from_json(json).expect("This should parse");
let config = BookConfig::from_jsonconfig("root", parsed); let config = BookConfig::from_jsonconfig("root", parsed);
let htmlconfig = config.get_html_config().expect("There should be an HtmlConfig"); let htmlconfig = config.get_html_config();
assert_eq!(htmlconfig.get_theme(), &PathBuf::from("root/theme")); assert_eq!(htmlconfig.get_theme(), &PathBuf::from("root/theme"));
} }

View File

@ -68,7 +68,7 @@ fn from_toml_output_html_destination() {
let parsed = TomlConfig::from_toml(toml).expect("This should parse"); let parsed = TomlConfig::from_toml(toml).expect("This should parse");
let config = BookConfig::from_tomlconfig("root", parsed); let config = BookConfig::from_tomlconfig("root", parsed);
let htmlconfig = config.get_html_config().expect("There should be an HtmlConfig"); let htmlconfig = config.get_html_config();
assert_eq!(htmlconfig.get_destination(), PathBuf::from("root/htmlbook")); assert_eq!(htmlconfig.get_destination(), PathBuf::from("root/htmlbook"));
} }
@ -82,7 +82,7 @@ fn from_toml_output_html_theme() {
let parsed = TomlConfig::from_toml(toml).expect("This should parse"); let parsed = TomlConfig::from_toml(toml).expect("This should parse");
let config = BookConfig::from_tomlconfig("root", parsed); let config = BookConfig::from_tomlconfig("root", parsed);
let htmlconfig = config.get_html_config().expect("There should be an HtmlConfig"); let htmlconfig = config.get_html_config();
assert_eq!(htmlconfig.get_theme(), &PathBuf::from("root/theme")); assert_eq!(htmlconfig.get_theme(), &PathBuf::from("root/theme"));
} }
@ -96,7 +96,7 @@ fn from_toml_output_html_curly_quotes() {
let parsed = TomlConfig::from_toml(toml).expect("This should parse"); let parsed = TomlConfig::from_toml(toml).expect("This should parse");
let config = BookConfig::from_tomlconfig("root", parsed); let config = BookConfig::from_tomlconfig("root", parsed);
let htmlconfig = config.get_html_config().expect("There should be an HtmlConfig"); let htmlconfig = config.get_html_config();
assert_eq!(htmlconfig.get_curly_quotes(), true); assert_eq!(htmlconfig.get_curly_quotes(), true);
} }
@ -110,7 +110,7 @@ fn from_toml_output_html_mathjax_support() {
let parsed = TomlConfig::from_toml(toml).expect("This should parse"); let parsed = TomlConfig::from_toml(toml).expect("This should parse");
let config = BookConfig::from_tomlconfig("root", parsed); let config = BookConfig::from_tomlconfig("root", parsed);
let htmlconfig = config.get_html_config().expect("There should be an HtmlConfig"); let htmlconfig = config.get_html_config();
assert_eq!(htmlconfig.get_mathjax_support(), true); assert_eq!(htmlconfig.get_mathjax_support(), true);
} }
@ -124,7 +124,7 @@ fn from_toml_output_html_google_analytics() {
let parsed = TomlConfig::from_toml(toml).expect("This should parse"); let parsed = TomlConfig::from_toml(toml).expect("This should parse");
let config = BookConfig::from_tomlconfig("root", parsed); let config = BookConfig::from_tomlconfig("root", parsed);
let htmlconfig = config.get_html_config().expect("There should be an HtmlConfig"); let htmlconfig = config.get_html_config();
assert_eq!(htmlconfig.get_google_analytics_id().expect("the google-analytics key was provided"), String::from("123456")); assert_eq!(htmlconfig.get_google_analytics_id().expect("the google-analytics key was provided"), String::from("123456"));
} }
@ -138,7 +138,7 @@ fn from_toml_output_html_additional_stylesheet() {
let parsed = TomlConfig::from_toml(toml).expect("This should parse"); let parsed = TomlConfig::from_toml(toml).expect("This should parse");
let config = BookConfig::from_tomlconfig("root", parsed); let config = BookConfig::from_tomlconfig("root", parsed);
let htmlconfig = config.get_html_config().expect("There should be an HtmlConfig"); let htmlconfig = config.get_html_config();
assert_eq!(htmlconfig.get_additional_css(), &[PathBuf::from("root/custom.css"), PathBuf::from("root/two/custom.css")]); assert_eq!(htmlconfig.get_additional_css(), &[PathBuf::from("root/custom.css"), PathBuf::from("root/two/custom.css")]);
} }
@ -152,7 +152,7 @@ fn from_toml_output_html_additional_scripts() {
let parsed = TomlConfig::from_toml(toml).expect("This should parse"); let parsed = TomlConfig::from_toml(toml).expect("This should parse");
let config = BookConfig::from_tomlconfig("root", parsed); let config = BookConfig::from_tomlconfig("root", parsed);
let htmlconfig = config.get_html_config().expect("There should be an HtmlConfig"); let htmlconfig = config.get_html_config();
assert_eq!(htmlconfig.get_additional_js(), &[PathBuf::from("root/custom.js"), PathBuf::from("root/two/custom.js")]); assert_eq!(htmlconfig.get_additional_js(), &[PathBuf::from("root/custom.js"), PathBuf::from("root/two/custom.js")]);
} }