diff --git a/src/bin/mdbook.rs b/src/bin/mdbook.rs index 8503c6a5..ec0f6b41 100644 --- a/src/bin/mdbook.rs +++ b/src/bin/mdbook.rs @@ -97,7 +97,7 @@ fn init(args: &ArgMatches) -> Result<(), Box> { // Skip this if `--force` is present if !args.is_present("force") { // Print warning - print!("\nCopying the default theme to {:?}", book.get_src()); + print!("\nCopying the default theme to {:?}", book.source()); println!("could potentially overwrite files already present in that directory."); print!("\nAre you sure you want to continue? (y/n) "); @@ -159,8 +159,8 @@ fn watch(args: &ArgMatches) -> Result<(), Box> { Ok(mut watcher) => { // Add the source directory to the watcher - if let Err(e) = watcher.watch(book.get_src()) { - println!("Error while watching {:?}:\n {:?}", book.get_src(), e); + if let Err(e) = watcher.watch(book.source()) { + println!("Error while watching {:?}:\n {:?}", book.source(), e); ::std::process::exit(0); }; diff --git a/src/book/bookconfig.rs b/src/book/bookconfig.rs deleted file mode 100644 index bae825cd..00000000 --- a/src/book/bookconfig.rs +++ /dev/null @@ -1,118 +0,0 @@ -extern crate rustc_serialize; -use self::rustc_serialize::json::Json; -use std::fs::File; -use std::io::Read; -use std::path::{Path, PathBuf}; - -#[derive(Debug, Clone)] -pub struct BookConfig { - pub title: String, - pub author: String, - pub description: String, - root: PathBuf, - dest: PathBuf, - src: PathBuf, - pub indent_spaces: i32, - multilingual: bool, -} - - -impl BookConfig { - pub fn new(root: &Path) -> Self { - BookConfig { - title: String::new(), - author: String::new(), - description: String::new(), - root: root.to_owned(), - dest: PathBuf::from("book"), - src: PathBuf::from("src"), - indent_spaces: 4, // indentation used for SUMMARY.md - multilingual: false, - } - } - - pub fn read_config(&mut self, root: &Path) -> &mut Self { - - debug!("[fn]: read_config"); - - // If the file does not exist, return early - let mut config_file = match File::open(root.join("book.json")) { - Ok(f) => f, - Err(_) => { - debug!("[*]: Failed to open {:?}", root.join("book.json")); - return self; - }, - }; - - debug!("[*]: Reading config"); - let mut data = String::new(); - - // Just return if an error occured. - // I would like to propagate the error, but I have to return `&self` - if let Err(_) = config_file.read_to_string(&mut data) { - return self; - } - - // Convert to JSON - if let Ok(config) = Json::from_str(&data) { - // Extract data - - debug!("[*]: Extracting data from config"); - // Title & author - if let Some(a) = config.find_path(&["title"]) { - self.title = a.to_string().replace("\"", "") - } - if let Some(a) = config.find_path(&["author"]) { - self.author = a.to_string().replace("\"", "") - } - if let Some(a) = config.find_path(&["description"]) { - self.description = a.to_string().replace("\"", "") - } - - // Destination - if let Some(a) = config.find_path(&["dest"]) { - let dest = PathBuf::from(&a.to_string().replace("\"", "")); - - // If path is relative make it absolute from the parent directory of src - match dest.is_relative() { - true => { - let dest = self.get_root().join(&dest).to_owned(); - self.set_dest(&dest); - }, - false => { - self.set_dest(&dest); - }, - } - } - } - - self - } - - pub fn get_root(&self) -> &Path { - &self.root - } - - pub fn set_root(&mut self, root: &Path) -> &mut Self { - self.root = root.to_owned(); - self - } - - pub fn get_dest(&self) -> &Path { - &self.dest - } - - pub fn set_dest(&mut self, dest: &Path) -> &mut Self { - self.dest = dest.to_owned(); - self - } - - pub fn get_src(&self) -> &Path { - &self.src - } - - pub fn set_src(&mut self, src: &Path) -> &mut Self { - self.src = src.to_owned(); - self - } -} diff --git a/src/book/mdbook.rs b/src/book/mdbook.rs index b8c9a95a..70cda9d2 100644 --- a/src/book/mdbook.rs +++ b/src/book/mdbook.rs @@ -6,13 +6,13 @@ use std::io::Write; use std::io::ErrorKind; use std::process::Command; -use {BookConfig, BookItem, theme, parse, utils}; +use {BookItem, Config, theme, parse}; use book::BookItems; use renderer::{Renderer, HtmlHandlebars}; pub struct MDBook { - config: BookConfig, + config: Config, pub content: Vec, renderer: Box, } @@ -23,20 +23,18 @@ impl MDBook { /// - The default source directory is set to `root/src` /// - The default output directory is set to `root/book` /// - /// They can both be changed by using [`set_src()`](#method.set_src) and [`set_dest()`](#method.set_dest) + /// They can both be changed by using [`set_source()`](#method.set_source) and [`set_dest()`](#method.set_dest) pub fn new(root: &Path) -> MDBook { - if !root.exists() || !root.is_dir() { - output!("{:?} No directory with that name", root); - } + let mut config = Config::new(); + + config.set_root(root) + .set_source(Path::new("src/")); MDBook { content: vec![], - config: BookConfig::new(root) - .set_src(&root.join("src")) - .set_dest(&root.join("book")) - .to_owned(), + config: config, renderer: Box::new(HtmlHandlebars::new()), } } @@ -94,19 +92,13 @@ impl MDBook { debug!("[fn]: init"); - if !self.config.get_root().exists() { - fs::create_dir_all(self.config.get_root()).unwrap(); - output!("{:?} created", self.config.get_root()); + if !self.config.root().exists() { + fs::create_dir_all(self.config.root()).unwrap(); + output!("{:?} created", self.config.root()); } { - let dest = self.config.get_dest(); - let src = self.config.get_src(); - - if !dest.exists() { - debug!("[*]: {:?} does not exist, trying to create directory", dest); - try!(fs::create_dir(&dest)); - } + let src = self.config.source(); if !src.exists() { debug!("[*]: {:?} does not exist, trying to create directory", src); @@ -140,7 +132,7 @@ impl MDBook { BookItem::Spacer => continue, BookItem::Chapter(_, ref ch) | BookItem::Affix(ref ch) => { if ch.path != PathBuf::new() { - let path = self.config.get_src().join(&ch.path); + let path = self.config.source().join(&ch.path); if !path.exists() { debug!("[*]: {:?} does not exist, trying to create file", path); @@ -198,8 +190,7 @@ impl MDBook { try!(self.init()); - // Clean output directory - try!(utils::fs::remove_dir_content(&self.config.get_dest())); + // TODO: Clean output directory for all renderers try!(self.renderer.render(&self)); @@ -214,7 +205,7 @@ impl MDBook { pub fn copy_theme(&self) -> Result<(), Box> { debug!("[fn]: copy_theme"); - let theme_dir = self.config.get_src().join("theme"); + let theme_dir = self.config.source().join("theme"); if !theme_dir.exists() { debug!("[*]: {:?} does not exist, trying to create directory", theme_dir); @@ -265,8 +256,12 @@ impl MDBook { /// of the current working directory by using a relative path instead of an absolute path. pub fn read_config(mut self) -> Self { - let root = self.config.get_root().to_owned(); - self.config.read_config(&root); + let root = self.config.root().to_owned(); + + if let Err(e) = self.config.read_config(&root) { + output!("Error: could not read config\n {:?}", e); + }; + self } @@ -304,7 +299,7 @@ impl MDBook { BookItem::Chapter(_, ref ch) => { if ch.path != PathBuf::new() { - let path = self.get_src().join(&ch.path); + let path = self.source().join(&ch.path); println!("[*]: Testing file: {:?}", path); @@ -328,73 +323,45 @@ impl MDBook { Ok(()) } - pub fn get_root(&self) -> &Path { - self.config.get_root() + pub fn config(&self) -> &Config { + &self.config } - pub fn set_dest(mut self, dest: &Path) -> Self { - - // Handle absolute and relative paths - match dest.is_absolute() { - true => { - self.config.set_dest(dest); - }, - false => { - let dest = self.config.get_root().join(dest).to_owned(); - self.config.set_dest(&dest); - }, - } - - self - } - - pub fn get_dest(&self) -> &Path { - self.config.get_dest() - } - - pub fn set_src(mut self, src: &Path) -> Self { + pub fn set_source(mut self, src: &Path) -> Self { // Handle absolute and relative paths match src.is_absolute() { true => { - self.config.set_src(src); + self.config.set_source(src); }, false => { - let src = self.config.get_root().join(src).to_owned(); - self.config.set_src(&src); + let src = self.config.root().join(src).to_owned(); + self.config.set_source(&src); }, } self } - pub fn get_src(&self) -> &Path { - self.config.get_src() + pub fn source(&self) -> &Path { + self.config.source() } pub fn set_title(mut self, title: &str) -> Self { - self.config.title = title.to_owned(); + self.config.set_title(title); self } pub fn get_title(&self) -> &str { - &self.config.title + self.config.title() } - pub fn set_author(mut self, author: &str) -> Self { - self.config.author = author.to_owned(); - self - } - - pub fn get_author(&self) -> &str { - &self.config.author - } pub fn set_description(mut self, description: &str) -> Self { self.config.description = description.to_owned(); self } - + pub fn get_description(&self) -> &str { &self.config.description } @@ -402,7 +369,7 @@ impl MDBook { // Construct book fn parse_summary(&mut self) -> Result<(), Box> { // When append becomes stable, use self.content.append() ... - self.content = try!(parse::construct_bookitems(&self.config.get_src().join("SUMMARY.md"))); + self.content = try!(parse::construct_bookitems(&self.config.source().join("SUMMARY.md"))); Ok(()) } } diff --git a/src/book/mod.rs b/src/book/mod.rs index 9821c374..9a50c279 100644 --- a/src/book/mod.rs +++ b/src/book/mod.rs @@ -1,7 +1,5 @@ pub mod mdbook; pub mod bookitem; -pub mod bookconfig; pub use self::bookitem::{BookItem, BookItems}; -pub use self::bookconfig::BookConfig; pub use self::mdbook::MDBook; diff --git a/src/config/mod.rs b/src/config/mod.rs index e0abff08..da754e1d 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -169,36 +169,81 @@ impl Config { Ok(()) } + // Title + pub fn set_title(&mut self, title: &str) -> &mut Self { + self.title = String::from(title); + self + } + pub fn title(&self) -> &str { &self.title } + + // Description + pub fn set_description(&mut self, description: &str) -> &mut Self { + self.description = String::from(description); + self + } + pub fn description(&self) -> &str { &self.description } + + // Authors + pub fn add_author(&mut self, author: Author) -> &mut Self { + self.authors.push(author); + self + } + pub fn authors(&self) -> &[Author] { &self.authors } + // Root + pub fn set_root(&mut self, root: &Path) -> &mut Self { + self.root = PathBuf::from(root); + self + } + + pub fn root(&self) -> &Path { + &self.root + } + + // Source + pub fn set_source(&mut self, source: &Path) -> &mut Self { + if source.is_relative() { + self.source = self.root.join(self.source.clone()); + } else { + self.source = PathBuf::from(source); + } + + self + } + pub fn source(&self) -> &Path { &self.source } pub fn outputs(&self) -> &[Output] { - &self.outputs + unimplemented!(); + // &self.outputs } pub fn language(&self) -> &Language { - &self.language + unimplemented!(); + // &self.language } pub fn translations(&self) -> &[Language] { - &self.translations + unimplemented!(); + // &self.translations } pub fn plugins(&self) -> &[Plugin] { - &self.plugins + unimplemented!(); + // &self.plugins } } diff --git a/src/lib.rs b/src/lib.rs index 90daa562..07b25800 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -80,5 +80,5 @@ pub mod utils; pub use book::MDBook; pub use book::BookItem; -pub use book::BookConfig; +pub use config::Config; pub use renderer::Renderer; diff --git a/src/renderer/html_handlebars/hbs_renderer.rs b/src/renderer/html_handlebars/hbs_renderer.rs index 9c5501e6..90065cfb 100644 --- a/src/renderer/html_handlebars/hbs_renderer.rs +++ b/src/renderer/html_handlebars/hbs_renderer.rs @@ -27,11 +27,16 @@ impl HtmlHandlebars { impl Renderer for HtmlHandlebars { fn render(&self, book: &MDBook) -> Result<(), Box> { + + // Temporary fix while refactoring + // FIXME: When the new renderers are done, use the destination set in the renderer + let dest = book.config().root().join("book/"); + debug!("[fn]: render"); let mut handlebars = Handlebars::new(); // Load theme - let theme = theme::Theme::new(book.get_src()); + let theme = theme::Theme::new(book.source()); // Register template debug!("[*]: Register handlebars template"); @@ -50,7 +55,7 @@ impl Renderer for HtmlHandlebars { // Check if dest directory exists debug!("[*]: Check if destination directory exists"); - if let Err(_) = fs::create_dir_all(book.get_dest()) { + if let Err(_) = fs::create_dir_all(dest.clone()) { return Err(Box::new(io::Error::new(io::ErrorKind::Other, "Unexpected error when constructing destination path"))); } @@ -63,7 +68,7 @@ impl Renderer for HtmlHandlebars { BookItem::Chapter(_, ref ch) | BookItem::Affix(ref ch) => { if ch.path != PathBuf::new() { - let path = book.get_src().join(&ch.path); + let path = book.source().join(&ch.path); debug!("[*]: Opening file: {:?}", path); let mut f = try!(File::open(&path)); @@ -108,10 +113,10 @@ impl Renderer for HtmlHandlebars { debug!("[*]: Create file {:?}", &book.get_dest().join(&ch.path).with_extension("html")); // Write to file - let mut file = try!(utils::fs::create_file(&book.get_dest() - .join(&ch.path) - .with_extension("html"))); - output!("[*] Creating {:?} ✓", &book.get_dest().join(&ch.path).with_extension("html")); + let mut file = try!(utils::fs::create_file(&dest.clone().join(&ch.path) + .with_extension("html"))); + + output!("[*] Creating {:?} ✓", dest.join(&ch.path).with_extension("html")); try!(file.write_all(&rendered.into_bytes())); @@ -119,9 +124,9 @@ impl Renderer for HtmlHandlebars { if index { debug!("[*]: index.html"); - let mut index_file = try!(File::create(book.get_dest().join("index.html"))); + let mut index_file = try!(File::create(dest.join("index.html"))); let mut content = String::new(); - let _source = try!(File::open(book.get_dest().join(&ch.path.with_extension("html")))) + let _source = try!(File::open(dest.join(&ch.path.with_extension("html")))) .read_to_string(&mut content); // This could cause a problem when someone displays code containing @@ -134,7 +139,7 @@ impl Renderer for HtmlHandlebars { try!(index_file.write_all(content.as_bytes())); output!("[*] Creating index.html from {:?} ✓", - book.get_dest().join(&ch.path.with_extension("html"))); + dest.join(&ch.path.with_extension("html"))); index = false; } } @@ -160,7 +165,7 @@ impl Renderer for HtmlHandlebars { // Rendere the handlebars template with the data debug!("[*]: Render template"); let rendered = try!(handlebars.render("index", &data)); - let mut file = try!(utils::fs::create_file(&book.get_dest().join("print").with_extension("html"))); + let mut file = try!(utils::fs::create_file(&dest.join("print").with_extension("html"))); try!(file.write_all(&rendered.into_bytes())); output!("[*] Creating print.html ✓"); @@ -168,7 +173,7 @@ impl Renderer for HtmlHandlebars { debug!("[*] Copy static files"); // JavaScript - let mut js_file = if let Ok(f) = File::create(book.get_dest().join("book.js")) { + let mut js_file = if let Ok(f) = File::create(dest.join("book.js")) { f } else { return Err(Box::new(io::Error::new(io::ErrorKind::Other, "Could not create book.js"))); @@ -176,7 +181,7 @@ impl Renderer for HtmlHandlebars { try!(js_file.write_all(&theme.js)); // Css - let mut css_file = if let Ok(f) = File::create(book.get_dest().join("book.css")) { + let mut css_file = if let Ok(f) = File::create(dest.join("book.css")) { f } else { return Err(Box::new(io::Error::new(io::ErrorKind::Other, "Could not create book.css"))); @@ -190,7 +195,7 @@ impl Renderer for HtmlHandlebars { try!(favicon_file.write_all(&theme.favicon)); // JQuery local fallback - let mut jquery = if let Ok(f) = File::create(book.get_dest().join("jquery.js")) { + let mut jquery = if let Ok(f) = File::create(dest.join("jquery.js")) { f } else { return Err(Box::new(io::Error::new(io::ErrorKind::Other, "Could not create jquery.js"))); @@ -198,21 +203,21 @@ impl Renderer for HtmlHandlebars { try!(jquery.write_all(&theme.jquery)); // syntax highlighting - let mut highlight_css = if let Ok(f) = File::create(book.get_dest().join("highlight.css")) { + let mut highlight_css = if let Ok(f) = File::create(dest.join("highlight.css")) { f } else { return Err(Box::new(io::Error::new(io::ErrorKind::Other, "Could not create highlight.css"))); }; try!(highlight_css.write_all(&theme.highlight_css)); - let mut tomorrow_night_css = if let Ok(f) = File::create(book.get_dest().join("tomorrow-night.css")) { + let mut tomorrow_night_css = if let Ok(f) = File::create(dest.join("tomorrow-night.css")) { f } else { return Err(Box::new(io::Error::new(io::ErrorKind::Other, "Could not create tomorrow-night.css"))); }; try!(tomorrow_night_css.write_all(&theme.tomorrow_night_css)); - let mut highlight_js = if let Ok(f) = File::create(book.get_dest().join("highlight.js")) { + let mut highlight_js = if let Ok(f) = File::create(dest.join("highlight.js")) { f } else { return Err(Box::new(io::Error::new(io::ErrorKind::Other, "Could not create highlight.js"))); @@ -220,14 +225,14 @@ impl Renderer for HtmlHandlebars { try!(highlight_js.write_all(&theme.highlight_js)); // Font Awesome local fallback - let mut font_awesome = if let Ok(f) = utils::fs::create_file(&book.get_dest() + let mut font_awesome = if let Ok(f) = utils::fs::create_file(&dest .join("_FontAwesome/css/font-awesome.css")) { f } else { return Err(Box::new(io::Error::new(io::ErrorKind::Other, "Could not create font-awesome.css"))); }; try!(font_awesome.write_all(theme::FONT_AWESOME)); - let mut font_awesome = if let Ok(f) = utils::fs::create_file(&book.get_dest() + let mut font_awesome = if let Ok(f) = utils::fs::create_file(&dest .join("_FontAwesome/fonts/fontawesome-we\ bfont.eot")) { f @@ -235,7 +240,7 @@ impl Renderer for HtmlHandlebars { return Err(Box::new(io::Error::new(io::ErrorKind::Other, "Could not create fontawesome-webfont.eot"))); }; try!(font_awesome.write_all(theme::FONT_AWESOME_EOT)); - let mut font_awesome = if let Ok(f) = utils::fs::create_file(&book.get_dest() + let mut font_awesome = if let Ok(f) = utils::fs::create_file(&dest .join("_FontAwesome/fonts/fontawesome-we\ bfont.svg")) { f @@ -243,7 +248,7 @@ impl Renderer for HtmlHandlebars { return Err(Box::new(io::Error::new(io::ErrorKind::Other, "Could not create fontawesome-webfont.svg"))); }; try!(font_awesome.write_all(theme::FONT_AWESOME_SVG)); - let mut font_awesome = if let Ok(f) = utils::fs::create_file(&book.get_dest() + let mut font_awesome = if let Ok(f) = utils::fs::create_file(&dest .join("_FontAwesome/fonts/fontawesome-we\ bfont.ttf")) { f @@ -251,7 +256,7 @@ impl Renderer for HtmlHandlebars { return Err(Box::new(io::Error::new(io::ErrorKind::Other, "Could not create fontawesome-webfont.ttf"))); }; try!(font_awesome.write_all(theme::FONT_AWESOME_TTF)); - let mut font_awesome = if let Ok(f) = utils::fs::create_file(&book.get_dest() + let mut font_awesome = if let Ok(f) = utils::fs::create_file(&dest .join("_FontAwesome/fonts/fontawesome-we\ bfont.woff")) { f @@ -259,7 +264,7 @@ impl Renderer for HtmlHandlebars { return Err(Box::new(io::Error::new(io::ErrorKind::Other, "Could not create fontawesome-webfont.woff"))); }; try!(font_awesome.write_all(theme::FONT_AWESOME_WOFF)); - let mut font_awesome = if let Ok(f) = utils::fs::create_file(&book.get_dest() + let mut font_awesome = if let Ok(f) = utils::fs::create_file(&dest .join("_FontAwesome/fonts/fontawesome-we\ bfont.woff2")) { f @@ -267,7 +272,7 @@ impl Renderer for HtmlHandlebars { return Err(Box::new(io::Error::new(io::ErrorKind::Other, "Could not create fontawesome-webfont.woff2"))); }; try!(font_awesome.write_all(theme::FONT_AWESOME_WOFF2)); - let mut font_awesome = if let Ok(f) = utils::fs::create_file(&book.get_dest() + let mut font_awesome = if let Ok(f) = utils::fs::create_file(&dest .join("_FontAwesome/fonts/FontAwesome.\ ttf")) { f @@ -277,7 +282,7 @@ impl Renderer for HtmlHandlebars { try!(font_awesome.write_all(theme::FONT_AWESOME_TTF)); // Copy all remaining files - try!(utils::fs::copy_files_except_ext(book.get_src(), book.get_dest(), true, &["md"])); + try!(utils::fs::copy_files_except_ext(book.source(), &dest, true, &["md"])); Ok(()) }