Replace the old book structure with the new one

This commit is contained in:
Mathieu David 2017-05-18 23:52:38 +02:00
parent 170bf8b1eb
commit d3ae2eda56
6 changed files with 238 additions and 159 deletions

View File

@ -129,7 +129,7 @@ fn init(args: &ArgMatches) -> Result<(), Box<Error>> {
// Skip this if `--force` is present // Skip this if `--force` is present
if !args.is_present("force") { if !args.is_present("force") {
// Print warning // Print warning
print!("\nCopying the default theme to {:?}", book.get_src()); print!("\nCopying the default theme to {:?}", book.get_source());
println!("could potentially overwrite files already present in that directory."); println!("could potentially overwrite files already present in that directory.");
print!("\nAre you sure you want to continue? (y/n) "); print!("\nAre you sure you want to continue? (y/n) ");
@ -148,7 +148,9 @@ fn init(args: &ArgMatches) -> Result<(), Box<Error>> {
} }
// 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_dest().starts_with(book.get_root()); let is_dest_inside_root = book.get_destination()
.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)");
@ -168,10 +170,10 @@ fn init(args: &ArgMatches) -> Result<(), Box<Error>> {
// Build command implementation // Build command implementation
fn build(args: &ArgMatches) -> Result<(), Box<Error>> { fn build(args: &ArgMatches) -> Result<(), Box<Error>> {
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).read_config()?;
let mut book = match args.value_of("dest-dir") { let mut book = match args.value_of("dest-dir") {
Some(dest_dir) => book.set_dest(Path::new(dest_dir)), Some(dest_dir) => book.with_destination(Path::new(dest_dir)),
None => book, None => book,
}; };
@ -181,8 +183,10 @@ fn build(args: &ArgMatches) -> Result<(), Box<Error>> {
book.build()?; book.build()?;
if args.is_present("open") { if let Some(d) = book.get_destination() {
open(book.get_dest().join("index.html")); if args.is_present("open") {
open(d.join("index.html"));
}
} }
Ok(()) Ok(())
@ -193,16 +197,18 @@ fn build(args: &ArgMatches) -> Result<(), Box<Error>> {
#[cfg(feature = "watch")] #[cfg(feature = "watch")]
fn watch(args: &ArgMatches) -> Result<(), Box<Error>> { fn watch(args: &ArgMatches) -> Result<(), Box<Error>> {
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).read_config()?;
let mut book = match args.value_of("dest-dir") { let mut book = match args.value_of("dest-dir") {
Some(dest_dir) => book.set_dest(Path::new(dest_dir)), Some(dest_dir) => book.with_destination(Path::new(dest_dir)),
None => book, None => book,
}; };
if args.is_present("open") { if args.is_present("open") {
book.build()?; book.build()?;
open(book.get_dest().join("index.html")); if let Some(d) = book.get_destination() {
open(d.join("index.html"));
}
} }
trigger_on_change(&mut book, |path, book| { trigger_on_change(&mut book, |path, book| {
@ -223,13 +229,18 @@ fn serve(args: &ArgMatches) -> Result<(), Box<Error>> {
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).read_config()?;
let mut book = match args.value_of("dest-dir") { let mut book = match args.value_of("dest-dir") {
Some(dest_dir) => book.set_dest(Path::new(dest_dir)), Some(dest_dir) => book.with_destination(Path::new(dest_dir)),
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);
}
let port = args.value_of("port").unwrap_or("3000"); let port = args.value_of("port").unwrap_or("3000");
let ws_port = args.value_of("websocket-port").unwrap_or("3001"); let ws_port = args.value_of("websocket-port").unwrap_or("3001");
let interface = args.value_of("interface").unwrap_or("localhost"); let interface = args.value_of("interface").unwrap_or("localhost");
@ -260,7 +271,7 @@ fn serve(args: &ArgMatches) -> Result<(), Box<Error>> {
book.build()?; book.build()?;
let staticfile = staticfile::Static::new(book.get_dest()); let staticfile = staticfile::Static::new(book.get_destination().expect("destination is present, checked before"));
let iron = iron::Iron::new(staticfile); let iron = iron::Iron::new(staticfile);
let _iron = iron.http(&*address).unwrap(); let _iron = iron.http(&*address).unwrap();
@ -292,7 +303,7 @@ fn serve(args: &ArgMatches) -> Result<(), Box<Error>> {
fn test(args: &ArgMatches) -> Result<(), Box<Error>> { fn test(args: &ArgMatches) -> Result<(), Box<Error>> {
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).read_config()?;
book.test()?; book.test()?;
@ -341,8 +352,8 @@ fn trigger_on_change<F>(book: &mut MDBook, closure: F) -> ()
}; };
// Add the source directory to the watcher // Add the source directory to the watcher
if let Err(e) = watcher.watch(book.get_src(), Recursive) { if let Err(e) = watcher.watch(book.get_source(), Recursive) {
println!("Error while watching {:?}:\n {:?}", book.get_src(), e); println!("Error while watching {:?}:\n {:?}", book.get_source(), e);
::std::process::exit(0); ::std::process::exit(0);
}; };

View File

@ -4,29 +4,24 @@ pub mod bookconfig;
pub mod bookconfig_test; pub mod bookconfig_test;
pub use self::bookitem::{BookItem, BookItems}; pub use self::bookitem::{BookItem, BookItems};
pub use self::bookconfig::BookConfig;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::fs::{self, File}; use std::fs::{self, File};
use std::error::Error; use std::error::Error;
use std::io; use std::io;
use std::io::Write; use std::io::{Read, Write};
use std::io::ErrorKind; use std::io::ErrorKind;
use std::process::Command; use std::process::Command;
use {theme, parse, utils}; use {theme, parse, utils};
use renderer::{Renderer, HtmlHandlebars}; use renderer::{Renderer, HtmlHandlebars};
use config::{BookConfig, HtmlConfig};
use config::tomlconfig::TomlConfig;
pub struct MDBook { pub struct MDBook {
root: PathBuf, config: BookConfig,
dest: PathBuf,
src: PathBuf,
theme_path: PathBuf,
pub title: String,
pub author: String,
pub description: String,
pub content: Vec<BookItem>, pub content: Vec<BookItem>,
renderer: Box<Renderer>, renderer: Box<Renderer>,
@ -50,7 +45,7 @@ impl MDBook {
/// # use mdbook::MDBook; /// # use mdbook::MDBook;
/// # use std::path::Path; /// # use std::path::Path;
/// # fn main() { /// # fn main() {
/// let book = MDBook::new(Path::new("root_dir")); /// let book = MDBook::new("root_dir");
/// # } /// # }
/// ``` /// ```
/// ///
@ -75,14 +70,7 @@ impl MDBook {
} }
MDBook { MDBook {
root: root.to_owned(), config: BookConfig::new(root),
dest: root.join("book"),
src: root.join("src"),
theme_path: root.join("theme"),
title: String::new(),
author: String::new(),
description: String::new(),
content: vec![], content: vec![],
renderer: Box::new(HtmlHandlebars::new()), renderer: Box::new(HtmlHandlebars::new()),
@ -149,31 +137,33 @@ impl MDBook {
debug!("[fn]: init"); debug!("[fn]: init");
if !self.root.exists() { if !self.config.get_root().exists() {
fs::create_dir_all(&self.root).unwrap(); fs::create_dir_all(&self.config.get_root()).unwrap();
info!("{:?} created", &self.root); info!("{:?} created", &self.config.get_root());
} }
{ {
if !self.dest.exists() { if let Some(htmlconfig) = self.config.get_html_config() {
debug!("[*]: {:?} does not exist, trying to create directory", self.dest); if !htmlconfig.get_destination().exists() {
fs::create_dir_all(&self.dest)?; debug!("[*]: {:?} does not exist, trying to create directory", htmlconfig.get_destination());
fs::create_dir_all(htmlconfig.get_destination())?;
}
} }
if !self.src.exists() {
debug!("[*]: {:?} does not exist, trying to create directory", self.src); if !self.config.get_source().exists() {
fs::create_dir_all(&self.src)?; debug!("[*]: {:?} does not exist, trying to create directory", self.config.get_source());
fs::create_dir_all(self.config.get_source())?;
} }
let summary = self.src.join("SUMMARY.md"); let summary = self.config.get_source().join("SUMMARY.md");
if !summary.exists() { if !summary.exists() {
// Summary does not exist, create it // Summary does not exist, create it
debug!("[*]: {:?} does not exist, trying to create SUMMARY.md", &summary);
debug!("[*]: {:?} does not exist, trying to create SUMMARY.md", self.src.join("SUMMARY.md")); let mut f = File::create(&summary)?;
let mut f = File::create(&self.src.join("SUMMARY.md"))?;
debug!("[*]: Writing to SUMMARY.md"); debug!("[*]: Writing to SUMMARY.md");
@ -195,7 +185,7 @@ impl MDBook {
BookItem::Affix(ref ch) => ch, BookItem::Affix(ref ch) => ch,
}; };
if !ch.path.as_os_str().is_empty() { if !ch.path.as_os_str().is_empty() {
let path = self.src.join(&ch.path); let path = self.config.get_source().join(&ch.path);
if !path.exists() { if !path.exists() {
if !self.create_missing { if !self.create_missing {
@ -219,22 +209,23 @@ impl MDBook {
pub fn create_gitignore(&self) { pub fn create_gitignore(&self) {
let gitignore = self.get_gitignore(); let gitignore = self.get_gitignore();
if !gitignore.exists() { // If the HTML renderer is not set, return
// Gitignore does not exist, create it if self.config.get_html_config().is_none() { return; }
// Because of `src/book/mdbook.rs#L37-L39`, let destination = self.config.get_html_config()
// `dest` will always start with `root`. .expect("The HtmlConfig does exist, checked just before")
// If it is not, `strip_prefix` will return an Error. .get_destination();
if !self.get_dest().starts_with(&self.root) {
return;
}
let relative = self.get_dest() // Check that the gitignore does not extist and that the destination path begins with the root path
.strip_prefix(&self.root) // We assume tha if it does begin with the root path it is contained within. This assumption
.expect("Destination is not relative to root."); // will not hold true for paths containing double dots to go back up e.g. `root/../destination`
let relative = relative if !gitignore.exists() && destination.starts_with(self.config.get_root()) {
let relative = destination
.strip_prefix(self.config.get_root())
.expect("Could not strip the root prefix, path is not relative to root")
.to_str() .to_str()
.expect("Path could not be yielded into a string slice."); .expect("Could not convert to &str");
debug!("[*]: {:?} does not exist, trying to create .gitignore", gitignore); debug!("[*]: {:?} does not exist, trying to create .gitignore", gitignore);
@ -258,7 +249,9 @@ impl MDBook {
self.init()?; self.init()?;
// Clean output directory // Clean output directory
utils::fs::remove_dir_content(&self.dest)?; if let Some(htmlconfig) = self.config.get_html_config() {
utils::fs::remove_dir_content(htmlconfig.get_destination())?;
}
self.renderer.render(&self)?; self.renderer.render(&self)?;
@ -267,51 +260,56 @@ impl MDBook {
pub fn get_gitignore(&self) -> PathBuf { pub fn get_gitignore(&self) -> PathBuf {
self.root.join(".gitignore") self.config.get_root().join(".gitignore")
} }
pub fn copy_theme(&self) -> Result<(), Box<Error>> { pub fn copy_theme(&self) -> Result<(), Box<Error>> {
debug!("[fn]: copy_theme"); debug!("[fn]: copy_theme");
let theme_dir = self.src.join("theme"); if let Some(themedir) = self.config.get_html_config().and_then(HtmlConfig::get_theme) {
if !theme_dir.exists() { if !themedir.exists() {
debug!("[*]: {:?} does not exist, trying to create directory", theme_dir); debug!("[*]: {:?} does not exist, trying to create directory", themedir);
fs::create_dir(&theme_dir)?; fs::create_dir(&themedir)?;
}
// index.hbs
let mut index = File::create(&themedir.join("index.hbs"))?;
index.write_all(theme::INDEX)?;
// book.css
let mut css = File::create(&themedir.join("book.css"))?;
css.write_all(theme::CSS)?;
// favicon.png
let mut favicon = File::create(&themedir.join("favicon.png"))?;
favicon.write_all(theme::FAVICON)?;
// book.js
let mut js = File::create(&themedir.join("book.js"))?;
js.write_all(theme::JS)?;
// highlight.css
let mut highlight_css = File::create(&themedir.join("highlight.css"))?;
highlight_css.write_all(theme::HIGHLIGHT_CSS)?;
// highlight.js
let mut highlight_js = File::create(&themedir.join("highlight.js"))?;
highlight_js.write_all(theme::HIGHLIGHT_JS)?;
} }
// index.hbs
let mut index = File::create(&theme_dir.join("index.hbs"))?;
index.write_all(theme::INDEX)?;
// book.css
let mut css = File::create(&theme_dir.join("book.css"))?;
css.write_all(theme::CSS)?;
// favicon.png
let mut favicon = File::create(&theme_dir.join("favicon.png"))?;
favicon.write_all(theme::FAVICON)?;
// book.js
let mut js = File::create(&theme_dir.join("book.js"))?;
js.write_all(theme::JS)?;
// highlight.css
let mut highlight_css = File::create(&theme_dir.join("highlight.css"))?;
highlight_css.write_all(theme::HIGHLIGHT_CSS)?;
// highlight.js
let mut highlight_js = File::create(&theme_dir.join("highlight.js"))?;
highlight_js.write_all(theme::HIGHLIGHT_JS)?;
Ok(()) Ok(())
} }
pub fn write_file<P: AsRef<Path>>(&self, filename: P, content: &[u8]) -> Result<(), Box<Error>> { pub fn write_file<P: AsRef<Path>>(&self, filename: P, content: &[u8]) -> Result<(), Box<Error>> {
let path = self.get_dest().join(filename); let path = self.get_destination()
.ok_or(String::from("HtmlConfig not set, could not find a destination"))?
.join(filename);
utils::fs::create_file(&path) utils::fs::create_file(&path)
.and_then(|mut file| file.write_all(content)) .and_then(|mut file| file.write_all(content))
.map_err(|e| io::Error::new(io::ErrorKind::Other, format!("Could not create {}: {}", path.display(), e)))?; .map_err(|e| io::Error::new(io::ErrorKind::Other, format!("Could not create {}: {}", path.display(), e)))?;
Ok(()) Ok(())
} }
@ -320,21 +318,23 @@ impl MDBook {
/// The `book.json` file should be in the root directory of the book. /// 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` /// The root directory is the one specified when creating a new `MDBook`
pub fn read_config(mut self) -> Self { pub fn read_config(mut self) -> Result<Self, Box<Error>> {
let config = BookConfig::new(&self.root) let toml = self.get_root().join("book.toml");
.read_config(&self.root) let json = self.get_root().join("book.json");
.to_owned();
self.title = config.title; if toml.exists() {
self.description = config.description; let mut file = File::open(toml)?;
self.author = config.author; let mut content = String::new();
file.read_to_string(&mut content)?;
self.dest = config.dest; let parsed_config = TomlConfig::from_toml(&content)?;
self.src = config.src; self.config.fill_from_tomlconfig(parsed_config);
self.theme_path = config.theme_path; } else if json.exists() {
unimplemented!();
}
self Ok(self)
} }
/// You can change the default renderer to another one /// You can change the default renderer to another one
@ -374,7 +374,7 @@ impl MDBook {
if let BookItem::Chapter(_, ref ch) = *item { if let BookItem::Chapter(_, ref ch) = *item {
if ch.path != PathBuf::new() { if ch.path != PathBuf::new() {
let path = self.get_src().join(&ch.path); let path = self.get_source().join(&ch.path);
println!("[*]: Testing file: {:?}", path); println!("[*]: Testing file: {:?}", path);
@ -395,52 +395,49 @@ impl MDBook {
} }
pub fn get_root(&self) -> &Path { pub fn get_root(&self) -> &Path {
&self.root self.config.get_root()
} }
pub fn set_dest(mut self, dest: &Path) -> Self {
// Handle absolute and relative paths pub fn with_destination<T: Into<PathBuf>>(mut self, destination: T) -> Self {
if dest.is_absolute() { let root = self.config.get_root().to_owned();
self.dest = dest.to_owned(); if let Some(htmlconfig) = self.config.get_mut_html_config() {
htmlconfig.set_destination(&root, &destination.into());
} else { } else {
let dest = self.root.join(dest).to_owned(); error!("There is no HTML renderer set...");
self.dest = dest;
} }
self self
} }
pub fn get_dest(&self) -> &Path {
&self.dest
}
pub fn set_src(mut self, src: &Path) -> Self { pub fn get_destination(&self) -> Option<&Path> {
if let Some(htmlconfig) = self.config.get_html_config() {
// Handle absolute and relative paths return Some(htmlconfig.get_destination());
if src.is_absolute() {
self.src = src.to_owned();
} else {
let src = self.root.join(src).to_owned();
self.src = src;
} }
None
}
pub fn with_source<T: Into<PathBuf>>(mut self, source: T) -> Self {
self.config.set_source(source);
self self
} }
pub fn get_src(&self) -> &Path { pub fn get_source(&self) -> &Path {
&self.src self.config.get_source()
} }
pub fn set_title(mut self, title: &str) -> Self { pub fn with_title<T: Into<String>>(mut self, title: T) -> Self {
self.title = title.to_owned(); self.config.set_title(title);
self self
} }
pub fn get_title(&self) -> &str { pub fn get_title(&self) -> &str {
&self.title self.config.get_title()
} }
/*
pub fn set_author(mut self, author: &str) -> Self { pub fn set_author(mut self, author: &str) -> Self {
self.author = author.to_owned(); self.author = author.to_owned();
self self
@ -449,14 +446,14 @@ impl MDBook {
pub fn get_author(&self) -> &str { pub fn get_author(&self) -> &str {
&self.author &self.author
} }
*/
pub fn set_description(mut self, description: &str) -> Self { pub fn with_description<T: Into<String>>(mut self, description: T) -> Self {
self.description = description.to_owned(); self.config.set_description(description);
self self
} }
pub fn get_description(&self) -> &str { pub fn get_description(&self) -> &str {
&self.description self.config.get_description()
} }
pub fn set_livereload(&mut self, livereload: String) -> &mut Self { pub fn set_livereload(&mut self, livereload: String) -> &mut Self {
@ -473,23 +470,28 @@ impl MDBook {
self.livereload.as_ref() self.livereload.as_ref()
} }
pub fn set_theme_path(mut self, theme_path: &Path) -> Self { pub fn with_theme_path<T: Into<PathBuf>>(mut self, theme_path: T) -> Self {
self.theme_path = if theme_path.is_absolute() { let root = self.config.get_root().to_owned();
theme_path.to_owned() if let Some(htmlconfig) = self.config.get_mut_html_config() {
htmlconfig.set_theme(&root, &theme_path.into());
} else { } else {
self.root.join(theme_path).to_owned() error!("There is no HTML renderer set...");
}; }
self self
} }
pub fn get_theme_path(&self) -> &Path { pub fn get_theme_path(&self) -> Option<&PathBuf> {
&self.theme_path if let Some(htmlconfig) = self.config.get_html_config() {
return htmlconfig.get_theme();
}
None
} }
// Construct book // Construct book
fn parse_summary(&mut self) -> Result<(), Box<Error>> { fn parse_summary(&mut self) -> Result<(), Box<Error>> {
// When append becomes stable, use self.content.append() ... // When append becomes stable, use self.content.append() ...
self.content = parse::construct_bookitems(&self.src.join("SUMMARY.md"))?; self.content = parse::construct_bookitems(&self.get_source().join("SUMMARY.md"))?;
Ok(()) Ok(())
} }
} }

View File

@ -102,14 +102,45 @@ 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 source = config.get_source().to_owned();
let mut htmlconfig = config.get_mut_html_config().expect("We just created a new config and it creates a default HtmlConfig"); let mut htmlconfig = config.get_mut_html_config().expect("We just created a new config and it creates a default HtmlConfig");
htmlconfig.fill_from_tomlconfig(&root, &source, tomlhtmlconfig); htmlconfig.fill_from_tomlconfig(&root, tomlhtmlconfig);
} }
config config
} }
pub fn fill_from_tomlconfig(&mut self, tomlconfig: TomlConfig) -> &mut Self {
if let Some(s) = tomlconfig.source {
self.set_source(s);
}
if let Some(t) = tomlconfig.title {
self.set_title(t);
}
if let Some(d) = tomlconfig.description {
self.set_description(d);
}
if let Some(a) = tomlconfig.authors {
self.set_authors(a);
}
if let Some(a) = tomlconfig.author {
self.set_authors(vec![a]);
}
if let Some(tomlhtmlconfig) = tomlconfig.output.and_then(|o| o.html) {
let root = self.root.clone();
if let Some(htmlconfig) = self.get_mut_html_config() {
htmlconfig.fill_from_tomlconfig(root, tomlhtmlconfig);
}
}
self
}
pub fn set_root<T: Into<PathBuf>>(&mut self, root: T) -> &mut Self { pub fn set_root<T: Into<PathBuf>>(&mut self, root: T) -> &mut Self {
self.root = root.into(); self.root = root.into();
self self

View File

@ -29,10 +29,12 @@ impl HtmlConfig {
} }
} }
pub fn fill_from_tomlconfig<T: Into<PathBuf>>(&mut self, root: T, source: T, tomlconfig: TomlHtmlConfig) -> &mut Self { pub fn fill_from_tomlconfig<T: Into<PathBuf>>(&mut self, root: T, tomlconfig: TomlHtmlConfig) -> &mut Self {
let root = root.into();
if let Some(d) = tomlconfig.destination { if let Some(d) = tomlconfig.destination {
if d.is_relative() { if d.is_relative() {
self.destination = root.into().join(d); self.destination = root.join(d);
} else { } else {
self.destination = d; self.destination = d;
} }
@ -40,7 +42,7 @@ impl HtmlConfig {
if let Some(t) = tomlconfig.theme { if let Some(t) = tomlconfig.theme {
if t.is_relative() { if t.is_relative() {
self.theme = Some(source.into().join(t)); self.theme = Some(root.join(t));
} else { } else {
self.theme = Some(t); self.theme = Some(t);
} }
@ -53,6 +55,17 @@ impl HtmlConfig {
self self
} }
pub fn set_destination<T: Into<PathBuf>>(&mut self, root: T, destination: T) -> &mut Self {
let d = destination.into();
if d.is_relative() {
self.destination = root.into().join(d);
} else {
self.destination = d;
}
self
}
pub fn get_destination(&self) -> &Path { pub fn get_destination(&self) -> &Path {
&self.destination &self.destination
} }
@ -61,4 +74,15 @@ impl HtmlConfig {
pub fn get_theme(&self) -> Option<&PathBuf> { pub fn get_theme(&self) -> Option<&PathBuf> {
self.theme.as_ref() self.theme.as_ref()
} }
pub fn set_theme<T: Into<PathBuf>>(&mut self, root: T, theme: T) -> &mut Self {
let d = theme.into();
if d.is_relative() {
self.theme = Some(root.into().join(d));
} else {
self.theme = Some(d);
}
self
}
} }

View File

@ -89,5 +89,4 @@ pub mod utils;
pub use book::MDBook; pub use book::MDBook;
pub use book::BookItem; pub use book::BookItem;
pub use book::BookConfig;
pub use renderer::Renderer; pub use renderer::Renderer;

View File

@ -33,7 +33,7 @@ impl Renderer for HtmlHandlebars {
let mut handlebars = Handlebars::new(); let mut handlebars = Handlebars::new();
// Load theme // Load theme
let theme = theme::Theme::new(book.get_theme_path()); let theme = theme::Theme::new(book.get_theme_path().expect("If the HTML renderer is called, one would assume the HtmlConfig is set..."));
// Register template // Register template
debug!("[*]: Register handlebars template"); debug!("[*]: Register handlebars template");
@ -53,7 +53,7 @@ impl Renderer for HtmlHandlebars {
// Check if dest directory exists // Check if dest directory exists
debug!("[*]: Check if destination directory exists"); debug!("[*]: Check if destination directory exists");
if fs::create_dir_all(book.get_dest()).is_err() { if fs::create_dir_all(book.get_destination().expect("If the HTML renderer is called, one would assume the HtmlConfig is set...")).is_err() {
return Err(Box::new(io::Error::new(io::ErrorKind::Other, return Err(Box::new(io::Error::new(io::ErrorKind::Other,
"Unexpected error when constructing destination path"))); "Unexpected error when constructing destination path")));
} }
@ -67,7 +67,7 @@ impl Renderer for HtmlHandlebars {
BookItem::Affix(ref ch) => { BookItem::Affix(ref ch) => {
if ch.path != PathBuf::new() { if ch.path != PathBuf::new() {
let path = book.get_src().join(&ch.path); let path = book.get_source().join(&ch.path);
debug!("[*]: Opening file: {:?}", path); debug!("[*]: Opening file: {:?}", path);
let mut f = File::open(&path)?; let mut f = File::open(&path)?;
@ -116,8 +116,12 @@ impl Renderer for HtmlHandlebars {
debug!("[*]: index.html"); debug!("[*]: index.html");
let mut content = String::new(); let mut content = String::new();
let _source = File::open(book.get_dest().join(&ch.path.with_extension("html")))?
.read_to_string(&mut content); let _source = File::open(
book.get_destination()
.expect("If the HTML renderer is called, one would assume the HtmlConfig is set...")
.join(&ch.path.with_extension("html"))
)?.read_to_string(&mut content);
// This could cause a problem when someone displays // This could cause a problem when someone displays
// code containing <base href=...> // code containing <base href=...>
@ -131,7 +135,10 @@ impl Renderer for HtmlHandlebars {
book.write_file("index.html", content.as_bytes())?; book.write_file("index.html", content.as_bytes())?;
info!("[*] Creating index.html from {:?} ✓", info!("[*] Creating index.html from {:?} ✓",
book.get_dest().join(&ch.path.with_extension("html"))); book.get_destination()
.expect("If the HTML renderer is called, one would assume the HtmlConfig is set...")
.join(&ch.path.with_extension("html"))
);
index = false; index = false;
} }
} }
@ -181,7 +188,12 @@ impl Renderer for HtmlHandlebars {
book.write_file("_FontAwesome/fonts/FontAwesome.ttf", theme::FONT_AWESOME_TTF)?; book.write_file("_FontAwesome/fonts/FontAwesome.ttf", theme::FONT_AWESOME_TTF)?;
// Copy all remaining files // Copy all remaining files
utils::fs::copy_files_except_ext(book.get_src(), book.get_dest(), true, &["md"])?; utils::fs::copy_files_except_ext(
book.get_source(),
book.get_destination()
.expect("If the HTML renderer is called, one would assume the HtmlConfig is set..."), true, &["md"]
)?;
Ok(()) Ok(())
} }