Some clean-up + initial implementation of '--theme' flag for init. Still needs some work
This commit is contained in:
parent
909953d877
commit
835c61c7f3
|
@ -6,7 +6,7 @@ description = "create books from markdown files (like Gitbook)"
|
||||||
documentation = "http://azerupi.github.io/mdBook/index.html"
|
documentation = "http://azerupi.github.io/mdBook/index.html"
|
||||||
repository = "https://github.com/azerupi/mdBook"
|
repository = "https://github.com/azerupi/mdBook"
|
||||||
keywords = ["book", "gitbook", "rustbook", "markdown"]
|
keywords = ["book", "gitbook", "rustbook", "markdown"]
|
||||||
license = "MPL"
|
license = "MPL-2.0"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
exclude = [
|
exclude = [
|
||||||
"book-example/*",
|
"book-example/*",
|
||||||
|
|
|
@ -24,9 +24,9 @@ fn main() {
|
||||||
.after_help("For more information about a specific command, try `mdbook <command> --help`")
|
.after_help("For more information about a specific command, try `mdbook <command> --help`")
|
||||||
.subcommand(SubCommand::with_name("init")
|
.subcommand(SubCommand::with_name("init")
|
||||||
.about("Create boilerplate structure and files in the directory")
|
.about("Create boilerplate structure and files in the directory")
|
||||||
// the {n} denotes a newline which will properly aligned in all help
|
// the {n} denotes a newline which will properly aligned in all help messages
|
||||||
// messages
|
.arg_from_usage("[dir] 'A directory for your book{n}(Defaults to Current Directory when ommitted)'")
|
||||||
.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")
|
.subcommand(SubCommand::with_name("build")
|
||||||
.about("Build the book from the markdown files")
|
.about("Build the book from the markdown files")
|
||||||
.arg_from_usage("[dir] 'A directory for your book{n}(Defaults to Current Directory when ommitted)'"))
|
.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 {
|
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>> {
|
fn init(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);
|
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>> {
|
fn build(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.build()
|
try!(book.build());
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_book_dir(args: &ArgMatches) -> PathBuf {
|
fn get_book_dir(args: &ArgMatches) -> PathBuf {
|
||||||
|
|
|
@ -22,7 +22,7 @@ impl BookConfig {
|
||||||
author: String::new(),
|
author: String::new(),
|
||||||
dest: PathBuf::from("book"),
|
dest: PathBuf::from("book"),
|
||||||
src: PathBuf::from("src"),
|
src: PathBuf::from("src"),
|
||||||
indent_spaces: 4,
|
indent_spaces: 4, // indentation used for SUMMARY.md
|
||||||
multilingual: false,
|
multilingual: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,7 @@ impl BookConfig {
|
||||||
|
|
||||||
// If path is relative make it absolute from the parent directory of src
|
// If path is relative make it absolute from the parent directory of src
|
||||||
if dest.is_relative() {
|
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);
|
self.set_dest(dest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -68,7 +68,7 @@ impl BookConfig {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dest(&self) -> &Path {
|
pub fn get_dest(&self) -> &Path {
|
||||||
&self.dest
|
&self.dest
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ impl BookConfig {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn src(&self) -> &Path {
|
pub fn get_src(&self) -> &Path {
|
||||||
&self.src
|
&self.src
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ use std::error::Error;
|
||||||
use {BookConfig, BookItem};
|
use {BookConfig, BookItem};
|
||||||
use book::BookItems;
|
use book::BookItems;
|
||||||
use parse;
|
use parse;
|
||||||
|
use theme;
|
||||||
use renderer::Renderer;
|
use renderer::Renderer;
|
||||||
use renderer::HtmlHandlebars;
|
use renderer::HtmlHandlebars;
|
||||||
|
|
||||||
|
@ -96,8 +97,8 @@ impl MDBook {
|
||||||
|
|
||||||
debug!("[fn]: init");
|
debug!("[fn]: init");
|
||||||
|
|
||||||
let dest = self.config.dest();
|
let dest = self.config.get_dest();
|
||||||
let src = self.config.src();
|
let src = self.config.get_src();
|
||||||
|
|
||||||
// Hacky way to check if the directory exists... Until PathExt moves to stable
|
// Hacky way to check if the directory exists... Until PathExt moves to stable
|
||||||
match metadata(&dest) {
|
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.
|
/// 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 `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`
|
||||||
|
@ -220,11 +260,19 @@ impl MDBook {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_dest(&self) -> &Path {
|
||||||
|
self.config.get_dest()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_src(mut self, src: &Path) -> Self {
|
pub fn set_src(mut self, src: &Path) -> Self {
|
||||||
self.config.set_src(&self.root.join(src));
|
self.config.set_src(&self.root.join(src));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_src(&self) -> &Path {
|
||||||
|
self.config.get_src()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_title(mut self, title: &str) -> Self {
|
pub fn set_title(mut self, title: &str) -> Self {
|
||||||
self.config.title = title.to_owned();
|
self.config.title = title.to_owned();
|
||||||
self
|
self
|
||||||
|
@ -240,7 +288,7 @@ impl MDBook {
|
||||||
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() ...
|
||||||
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 {
|
for item in book_items {
|
||||||
self.content.push(item)
|
self.content.push(item)
|
||||||
|
|
|
@ -31,11 +31,11 @@ impl Renderer for HtmlHandlebars {
|
||||||
let mut handlebars = Handlebars::new();
|
let mut handlebars = Handlebars::new();
|
||||||
|
|
||||||
// Load theme
|
// Load theme
|
||||||
let theme = theme::Theme::new(&config.src());
|
let theme = theme::Theme::new(&config.get_src());
|
||||||
|
|
||||||
// Register template
|
// Register template
|
||||||
debug!("[*]: Register handlebars 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
|
// Register helpers
|
||||||
debug!("[*]: Register handlebars helpers");
|
debug!("[*]: Register handlebars helpers");
|
||||||
|
@ -47,7 +47,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");
|
||||||
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"))),
|
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() {
|
if item.path != PathBuf::new() {
|
||||||
|
|
||||||
let path = config.src().join(&item.path);
|
let path = config.get_src().join(&item.path);
|
||||||
|
|
||||||
debug!("[*]: Opening file: {:?}", path);
|
debug!("[*]: Opening file: {:?}", path);
|
||||||
let mut f = try!(File::open(&path));
|
let mut f = try!(File::open(&path));
|
||||||
|
@ -86,10 +86,10 @@ impl Renderer for HtmlHandlebars {
|
||||||
debug!("[*]: Render template");
|
debug!("[*]: Render template");
|
||||||
let rendered = try!(handlebars.render("index", &data));
|
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
|
// Write to file
|
||||||
let mut file = try!(utils::create_file(&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.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()));
|
try!(file.write_all(&rendered.into_bytes()));
|
||||||
|
|
||||||
|
@ -97,13 +97,13 @@ impl Renderer for HtmlHandlebars {
|
||||||
if index {
|
if index {
|
||||||
debug!("[*]: index.html");
|
debug!("[*]: index.html");
|
||||||
try!(fs::copy(
|
try!(fs::copy(
|
||||||
config.dest().join(&item.path.with_extension("html")),
|
config.get_dest().join(&item.path.with_extension("html")),
|
||||||
config.dest().join("index.html")
|
config.get_dest().join("index.html")
|
||||||
));
|
));
|
||||||
|
|
||||||
output!(
|
output!(
|
||||||
"[*] Creating index.html from {:?} ✓",
|
"[*] Creating index.html from {:?} ✓",
|
||||||
config.dest().join(&item.path.with_extension("html"))
|
config.get_dest().join(&item.path.with_extension("html"))
|
||||||
);
|
);
|
||||||
index = false;
|
index = false;
|
||||||
}
|
}
|
||||||
|
@ -114,17 +114,17 @@ impl Renderer for HtmlHandlebars {
|
||||||
|
|
||||||
debug!("[*] Copy static files");
|
debug!("[*] Copy static files");
|
||||||
// JavaScript
|
// 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));
|
try!(js_file.write_all(&theme.js));
|
||||||
|
|
||||||
// Css
|
// 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));
|
try!(css_file.write_all(&theme.css));
|
||||||
|
|
||||||
// syntax highlighting
|
// 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));
|
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));
|
try!(highlight_js.write_all(&theme.highlight_js));
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -2,14 +2,20 @@ use std::path::Path;
|
||||||
use std::fs::{File, metadata};
|
use std::fs::{File, metadata};
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
|
||||||
static INDEX: &'static str = include_str!("index.hbs");
|
pub static INDEX: &'static [u8] = include_bytes!("index.hbs");
|
||||||
static CSS: &'static [u8] = include_bytes!("book.css");
|
pub static CSS: &'static [u8] = include_bytes!("book.css");
|
||||||
static JS: &'static [u8] = include_bytes!("book.js");
|
pub static JS: &'static [u8] = include_bytes!("book.js");
|
||||||
static HIGHLIGHT_JS: &'static [u8] = include_bytes!("highlight.js");
|
pub static HIGHLIGHT_JS: &'static [u8] = include_bytes!("highlight.js");
|
||||||
static HIGHLIGHT_CSS: &'static [u8] = include_bytes!("highlight.css");
|
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 struct Theme {
|
||||||
pub index: String,
|
pub index: Vec<u8>,
|
||||||
pub css: Vec<u8>,
|
pub css: Vec<u8>,
|
||||||
pub js: Vec<u8>,
|
pub js: Vec<u8>,
|
||||||
pub highlight_css: Vec<u8>,
|
pub highlight_css: Vec<u8>,
|
||||||
|
@ -56,8 +62,8 @@ impl Theme {
|
||||||
// index.hbs
|
// index.hbs
|
||||||
match File::open(&src.join("index.hbs")) {
|
match File::open(&src.join("index.hbs")) {
|
||||||
Ok(mut f) => {
|
Ok(mut f) => {
|
||||||
theme.index = String::new(); // Reset the value, because read_to_string appends...
|
theme.index.clear(); // Reset the value, because read_to_string appends...
|
||||||
f.read_to_string(&mut theme.index).unwrap();
|
f.read_to_end(&mut theme.index).unwrap();
|
||||||
},
|
},
|
||||||
_ => {},
|
_ => {},
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue