Some clean-up + initial implementation of '--theme' flag for init. Still needs some work

This commit is contained in:
Mathieu David 2015-08-11 16:13:41 +02:00
parent 909953d877
commit 835c61c7f3
6 changed files with 115 additions and 36 deletions

View File

@ -6,7 +6,7 @@ description = "create books from markdown files (like Gitbook)"
documentation = "http://azerupi.github.io/mdBook/index.html"
repository = "https://github.com/azerupi/mdBook"
keywords = ["book", "gitbook", "rustbook", "markdown"]
license = "MPL"
license = "MPL-2.0"
readme = "README.md"
exclude = [
"book-example/*",

View File

@ -24,9 +24,9 @@ fn main() {
.after_help("For more information about a specific command, try `mdbook <command> --help`")
.subcommand(SubCommand::with_name("init")
.about("Create boilerplate structure and files in the directory")
// the {n} denotes a newline which will properly aligned in all help
// messages
.arg_from_usage("[dir] 'A directory for your book{n}(Defaults to Current Directory when ommitted)'"))
// the {n} denotes a newline which will properly aligned in all help messages
.arg_from_usage("[dir] 'A directory for your book{n}(Defaults to Current Directory when ommitted)'")
.arg_from_usage("--theme 'Copies the default theme into your source folder'"))
.subcommand(SubCommand::with_name("build")
.about("Build the book from the markdown files")
.arg_from_usage("[dir] 'A directory for your book{n}(Defaults to Current Directory when ommitted)'"))
@ -43,22 +43,47 @@ fn main() {
};
if let Err(e) = res {
writeln!(&mut io::stderr(), "Error: {}", e).ok();
writeln!(&mut io::stderr(), "An error occured:\n{}", e).ok();
}
}
fn init(args: &ArgMatches) -> Result<(), Box<Error>> {
let book_dir = get_book_dir(args);
let book = MDBook::new(&book_dir);
book.init()
// Call the function that does the initialization
try!(book.init());
// If flag `--theme` is present, copy theme to src
if args.is_present("theme") {
// Print warning
print!("\nCopying the default theme to {:?}", book.get_src());
println!("could potentially overwrite files already present in that directory.");
print!("\nAre you sure you want to continue? (y/n) ");
// Read answer from user
// Joke while I don't read user response, has to be deleted when merged into master !!!
println!("\n\nI am doing it anyways... (at the moment)");
// Call the function that copies the theme
try!(book.copy_theme());
println!("");
}
Ok(())
}
fn build(args: &ArgMatches) -> Result<(), Box<Error>> {
let book_dir = get_book_dir(args);
let mut book = MDBook::new(&book_dir).read_config();
book.build()
try!(book.build());
Ok(())
}
fn get_book_dir(args: &ArgMatches) -> PathBuf {

View File

@ -22,7 +22,7 @@ impl BookConfig {
author: String::new(),
dest: PathBuf::from("book"),
src: PathBuf::from("src"),
indent_spaces: 4,
indent_spaces: 4, // indentation used for SUMMARY.md
multilingual: false,
}
}
@ -60,7 +60,7 @@ impl BookConfig {
// If path is relative make it absolute from the parent directory of src
if dest.is_relative() {
let dest = &self.src().parent().unwrap().join(&dest);
let dest = &self.get_src().parent().unwrap().join(&dest);
self.set_dest(dest);
}
}
@ -68,7 +68,7 @@ impl BookConfig {
self
}
pub fn dest(&self) -> &Path {
pub fn get_dest(&self) -> &Path {
&self.dest
}
@ -77,7 +77,7 @@ impl BookConfig {
self
}
pub fn src(&self) -> &Path {
pub fn get_src(&self) -> &Path {
&self.src
}

View File

@ -6,6 +6,7 @@ use std::error::Error;
use {BookConfig, BookItem};
use book::BookItems;
use parse;
use theme;
use renderer::Renderer;
use renderer::HtmlHandlebars;
@ -96,8 +97,8 @@ impl MDBook {
debug!("[fn]: init");
let dest = self.config.dest();
let src = self.config.src();
let dest = self.config.get_dest();
let src = self.config.get_src();
// Hacky way to check if the directory exists... Until PathExt moves to stable
match metadata(&dest) {
@ -169,6 +170,45 @@ impl MDBook {
}
pub fn copy_theme(&self) -> Result<(), Box<Error>> {
debug!("[fn]: copy_theme");
let theme_dir = self.config.get_src().join("theme");
// Hacky way to check if the directory exists... Until PathExt moves to stable
match metadata(&theme_dir) {
Err(_) => {
// There is a very high chance that the error is due to the fact that
// the directory / file does not exist
debug!("[*]: {:?} does not exist, trying to create directory", theme_dir);
fs::create_dir(&theme_dir).unwrap();
},
Ok(_) => { /* If there is no error, the directory / file does exist */ }
}
// index.hbs
let mut index = try!(File::create(&theme_dir.join("index.hbs")));
try!(index.write_all(theme::INDEX));
// book.css
let mut css = try!(File::create(&theme_dir.join("book.css")));
try!(css.write_all(theme::CSS));
// book.js
let mut js = try!(File::create(&theme_dir.join("book.js")));
try!(js.write_all(theme::JS));
// highlight.css
let mut highlight_css = try!(File::create(&theme_dir.join("highlight.css")));
try!(highlight_css.write_all(theme::HIGHLIGHT_CSS));
// highlight.js
let mut highlight_js = try!(File::create(&theme_dir.join("highlight.js")));
try!(highlight_js.write_all(theme::HIGHLIGHT_JS));
Ok(())
}
/// 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`
@ -220,11 +260,19 @@ impl MDBook {
self
}
pub fn get_dest(&self) -> &Path {
self.config.get_dest()
}
pub fn set_src(mut self, src: &Path) -> Self {
self.config.set_src(&self.root.join(src));
self
}
pub fn get_src(&self) -> &Path {
self.config.get_src()
}
pub fn set_title(mut self, title: &str) -> Self {
self.config.title = title.to_owned();
self
@ -240,7 +288,7 @@ impl MDBook {
fn parse_summary(&mut self) -> Result<(), Box<Error>> {
// When append becomes stable, use self.content.append() ...
let book_items = try!(parse::construct_bookitems(&self.config.src().join("SUMMARY.md")));
let book_items = try!(parse::construct_bookitems(&self.config.get_src().join("SUMMARY.md")));
for item in book_items {
self.content.push(item)

View File

@ -31,11 +31,11 @@ impl Renderer for HtmlHandlebars {
let mut handlebars = Handlebars::new();
// Load theme
let theme = theme::Theme::new(&config.src());
let theme = theme::Theme::new(&config.get_src());
// Register template
debug!("[*]: Register handlebars template");
try!(handlebars.register_template_string("index", theme.index.to_owned()));
try!(handlebars.register_template_string("index", try!(String::from_utf8(theme.index))));
// Register helpers
debug!("[*]: Register handlebars helpers");
@ -47,7 +47,7 @@ impl Renderer for HtmlHandlebars {
// Check if dest directory exists
debug!("[*]: Check if destination directory exists");
match utils::create_path(config.dest()) {
match utils::create_path(config.get_dest()) {
Err(_) => return Err(Box::new(io::Error::new(io::ErrorKind::Other, "Unexcpected error when constructing destination path"))),
_ => {},
};
@ -58,7 +58,7 @@ impl Renderer for HtmlHandlebars {
if item.path != PathBuf::new() {
let path = config.src().join(&item.path);
let path = config.get_src().join(&item.path);
debug!("[*]: Opening file: {:?}", path);
let mut f = try!(File::open(&path));
@ -86,10 +86,10 @@ impl Renderer for HtmlHandlebars {
debug!("[*]: Render template");
let rendered = try!(handlebars.render("index", &data));
debug!("[*]: Create file {:?}", &config.dest().join(&item.path).with_extension("html"));
debug!("[*]: Create file {:?}", &config.get_dest().join(&item.path).with_extension("html"));
// Write to file
let mut file = try!(utils::create_file(&config.dest().join(&item.path).with_extension("html")));
output!("[*] Creating {:?} ✓", &config.dest().join(&item.path).with_extension("html"));
let mut file = try!(utils::create_file(&config.get_dest().join(&item.path).with_extension("html")));
output!("[*] Creating {:?} ✓", &config.get_dest().join(&item.path).with_extension("html"));
try!(file.write_all(&rendered.into_bytes()));
@ -97,13 +97,13 @@ impl Renderer for HtmlHandlebars {
if index {
debug!("[*]: index.html");
try!(fs::copy(
config.dest().join(&item.path.with_extension("html")),
config.dest().join("index.html")
config.get_dest().join(&item.path.with_extension("html")),
config.get_dest().join("index.html")
));
output!(
"[*] Creating index.html from {:?} ✓",
config.dest().join(&item.path.with_extension("html"))
config.get_dest().join(&item.path.with_extension("html"))
);
index = false;
}
@ -114,17 +114,17 @@ impl Renderer for HtmlHandlebars {
debug!("[*] Copy static files");
// JavaScript
let mut js_file = try!(File::create(config.dest().join("book.js")));
let mut js_file = try!(File::create(config.get_dest().join("book.js")));
try!(js_file.write_all(&theme.js));
// Css
let mut css_file = try!(File::create(config.dest().join("book.css")));
let mut css_file = try!(File::create(config.get_dest().join("book.css")));
try!(css_file.write_all(&theme.css));
// syntax highlighting
let mut highlight_css = try!(File::create(config.dest().join("highlight.css")));
let mut highlight_css = try!(File::create(config.get_dest().join("highlight.css")));
try!(highlight_css.write_all(&theme.highlight_css));
let mut highlight_js = try!(File::create(config.dest().join("highlight.js")));
let mut highlight_js = try!(File::create(config.get_dest().join("highlight.js")));
try!(highlight_js.write_all(&theme.highlight_js));
Ok(())

View File

@ -2,14 +2,20 @@ use std::path::Path;
use std::fs::{File, metadata};
use std::io::Read;
static INDEX: &'static str = include_str!("index.hbs");
static CSS: &'static [u8] = include_bytes!("book.css");
static JS: &'static [u8] = include_bytes!("book.js");
static HIGHLIGHT_JS: &'static [u8] = include_bytes!("highlight.js");
static HIGHLIGHT_CSS: &'static [u8] = include_bytes!("highlight.css");
pub static INDEX: &'static [u8] = include_bytes!("index.hbs");
pub static CSS: &'static [u8] = include_bytes!("book.css");
pub static JS: &'static [u8] = include_bytes!("book.js");
pub static HIGHLIGHT_JS: &'static [u8] = include_bytes!("highlight.js");
pub static HIGHLIGHT_CSS: &'static [u8] = include_bytes!("highlight.css");
/// The `Theme` struct should be used instead of the static variables because the `new()` method
/// will look if the user has a theme directory in his source folder and use the users theme instead
/// of the default.
///
/// You should exceptionnaly use the static variables only if you need the default theme even if the
/// user has specified another theme.
pub struct Theme {
pub index: String,
pub index: Vec<u8>,
pub css: Vec<u8>,
pub js: Vec<u8>,
pub highlight_css: Vec<u8>,
@ -56,8 +62,8 @@ impl Theme {
// index.hbs
match File::open(&src.join("index.hbs")) {
Ok(mut f) => {
theme.index = String::new(); // Reset the value, because read_to_string appends...
f.read_to_string(&mut theme.index).unwrap();
theme.index.clear(); // Reset the value, because read_to_string appends...
f.read_to_end(&mut theme.index).unwrap();
},
_ => {},
}