Replace the old book structure with the new one
This commit is contained in:
parent
170bf8b1eb
commit
d3ae2eda56
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
250
src/book/mod.rs
250
src/book/mod.rs
|
@ -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(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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(())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue