Incorporated Budziq's feedback
This commit is contained in:
parent
98a8ce934b
commit
f8cec4cef3
|
@ -44,7 +44,7 @@ ws = { version = "0.7", optional = true}
|
||||||
error-chain = "0.11"
|
error-chain = "0.11"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
pretty_assertions = "0.2.1"
|
pretty_assertions = "0.2"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["output", "watch", "serve"]
|
default = ["output", "watch", "serve"]
|
||||||
|
|
|
@ -24,9 +24,7 @@ pub fn execute(args: &ArgMatches) -> Result<()> {
|
||||||
None => book,
|
None => book,
|
||||||
};
|
};
|
||||||
|
|
||||||
if args.is_present("create") {
|
book.create_missing = args.is_present("create");
|
||||||
book.create_missing = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if args.is_present("curly-quotes") {
|
if args.is_present("curly-quotes") {
|
||||||
book = book.with_curly_quotes(true);
|
book = book.with_curly_quotes(true);
|
||||||
|
|
|
@ -13,7 +13,7 @@ use std::process::Command;
|
||||||
use tempdir::TempDir;
|
use tempdir::TempDir;
|
||||||
|
|
||||||
use {theme, utils};
|
use {theme, utils};
|
||||||
use renderer::{Renderer, HtmlHandlebars};
|
use renderer::{HtmlHandlebars, Renderer};
|
||||||
use preprocess;
|
use preprocess;
|
||||||
use errors::*;
|
use errors::*;
|
||||||
|
|
||||||
|
@ -23,6 +23,9 @@ use config::htmlconfig::HtmlConfig;
|
||||||
use config::jsonconfig::JsonConfig;
|
use config::jsonconfig::JsonConfig;
|
||||||
|
|
||||||
|
|
||||||
|
const STUB_SUMMARY_CONTENTS: &'static str = "# Summary\n\n- [Chapter 1](./chapter_1.md)]";
|
||||||
|
const STUB_CHAPTER_1: &'static str = "# Chapter 1\n";
|
||||||
|
|
||||||
/// A helper for managing the `Book`, its configuration, and the rendering
|
/// A helper for managing the `Book`, its configuration, and the rendering
|
||||||
/// process.
|
/// process.
|
||||||
pub struct MDBook {
|
pub struct MDBook {
|
||||||
|
@ -67,7 +70,6 @@ impl MDBook {
|
||||||
/// [`set_dest()`](#method.set_dest)
|
/// [`set_dest()`](#method.set_dest)
|
||||||
|
|
||||||
pub fn new<P: Into<PathBuf>>(root: P) -> MDBook {
|
pub fn new<P: Into<PathBuf>>(root: P) -> MDBook {
|
||||||
|
|
||||||
let root = root.into();
|
let root = root.into();
|
||||||
if !root.exists() || !root.is_dir() {
|
if !root.exists() || !root.is_dir() {
|
||||||
warn!("{:?} No directory with that name", root);
|
warn!("{:?} No directory with that name", root);
|
||||||
|
@ -114,7 +116,9 @@ impl MDBook {
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
pub fn iter(&self) -> BookItems {
|
pub fn iter(&self) -> BookItems {
|
||||||
self.content.as_ref().expect("Trying to iterate over a book before it is loaded. This is a bug")
|
self.content
|
||||||
|
.as_ref()
|
||||||
|
.expect("Trying to iterate over a book before it is loaded. This is a bug")
|
||||||
.iter()
|
.iter()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,12 +136,22 @@ impl MDBook {
|
||||||
/// It uses the paths given as source and output directories
|
/// It uses the paths given as source and output directories
|
||||||
/// and adds a `SUMMARY.md` and a
|
/// and adds a `SUMMARY.md` and a
|
||||||
/// `chapter_1.md` to the source directory.
|
/// `chapter_1.md` to the source directory.
|
||||||
|
|
||||||
pub fn init(&mut self) -> Result<()> {
|
pub fn init(&mut self) -> Result<()> {
|
||||||
|
|
||||||
debug!("[fn]: init");
|
debug!("[fn]: init");
|
||||||
|
|
||||||
{
|
self.create_book_directories()?;
|
||||||
|
self.create_stub_files()?;
|
||||||
|
|
||||||
|
self.parse_summary()
|
||||||
|
.chain_err(|| "Couldn't parse the SUMMARY.md file")?;
|
||||||
|
|
||||||
|
debug!("[*]: init done");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_book_directories(&self) -> Result<()> {
|
||||||
|
debug!("[*] Creating directories");
|
||||||
|
|
||||||
let root = self.config.get_root();
|
let root = self.config.get_root();
|
||||||
let dest = self.get_destination();
|
let dest = self.get_destination();
|
||||||
let src = self.config.get_source();
|
let src = self.config.get_source();
|
||||||
|
@ -151,16 +165,19 @@ impl MDBook {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_stub_files(&self) -> Result<()> {
|
||||||
|
debug!("[*] Creating stub files");
|
||||||
|
|
||||||
|
let src = self.config.get_source();
|
||||||
let summary = src.join("SUMMARY.md");
|
let summary = src.join("SUMMARY.md");
|
||||||
|
|
||||||
if !summary.exists() {
|
if !summary.exists() {
|
||||||
debug!("[*]: Creating SUMMARY.md");
|
debug!("[*]: Creating SUMMARY.md");
|
||||||
|
|
||||||
let mut f = File::create(&summary)?;
|
let mut f = File::create(&summary)?;
|
||||||
|
writeln!(f, "{}", STUB_SUMMARY_CONTENTS)?;
|
||||||
writeln!(f, "# Summary")?;
|
|
||||||
writeln!(f)?;
|
|
||||||
writeln!(f, "- [Chapter 1](./chapter_1.md)")?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let ch_1 = src.join("chapter_1.md");
|
let ch_1 = src.join("chapter_1.md");
|
||||||
|
@ -168,28 +185,24 @@ impl MDBook {
|
||||||
debug!("[*] Creating {}", ch_1.display());
|
debug!("[*] Creating {}", ch_1.display());
|
||||||
|
|
||||||
let mut f = File::create(&ch_1)?;
|
let mut f = File::create(&ch_1)?;
|
||||||
writeln!(f, "# Chapter 1")?;
|
writeln!(f, "{}", STUB_CHAPTER_1)?;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse SUMMARY.md and load the newly created files into memory
|
|
||||||
self.parse_summary().chain_err(|| "Couldn't parse the SUMMARY.md file")?;
|
|
||||||
|
|
||||||
debug!("[*]: init done");
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_gitignore(&self) {
|
pub fn create_gitignore(&self) {
|
||||||
let gitignore = self.get_gitignore();
|
let gitignore = self.get_gitignore();
|
||||||
|
|
||||||
let destination = self.config.get_html_config()
|
let destination = self.config.get_html_config().get_destination();
|
||||||
.get_destination();
|
|
||||||
|
|
||||||
// Check that the gitignore does not extist and that the destination path begins with the root path
|
// Check that the gitignore does not exist and that the destination path
|
||||||
// We assume tha if it does begin with the root path it is contained within. This assumption
|
// begins with the root path
|
||||||
// will not hold true for paths containing double dots to go back up e.g. `root/../destination`
|
// We assume tha if it does begin with the root path it is contained within.
|
||||||
|
// This assumption
|
||||||
|
// will not hold true for paths containing double dots to go back up e.g.
|
||||||
|
// `root/../destination`
|
||||||
if !gitignore.exists() && destination.starts_with(self.config.get_root()) {
|
if !gitignore.exists() && destination.starts_with(self.config.get_root()) {
|
||||||
|
|
||||||
let relative = destination
|
let relative = destination
|
||||||
.strip_prefix(self.config.get_root())
|
.strip_prefix(self.config.get_root())
|
||||||
.expect("Could not strip the root prefix, path is not relative to root")
|
.expect("Could not strip the root prefix, path is not relative to root")
|
||||||
|
@ -223,7 +236,6 @@ impl MDBook {
|
||||||
self.renderer.render(self)
|
self.renderer.render(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn get_gitignore(&self) -> PathBuf {
|
pub fn get_gitignore(&self) -> PathBuf {
|
||||||
self.config.get_root().join(".gitignore")
|
self.config.get_root().join(".gitignore")
|
||||||
}
|
}
|
||||||
|
@ -265,8 +277,7 @@ impl MDBook {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_file<P: AsRef<Path>>(&self, filename: P, content: &[u8]) -> Result<()> {
|
pub fn write_file<P: AsRef<Path>>(&self, filename: P, content: &[u8]) -> Result<()> {
|
||||||
let path = self.get_destination()
|
let path = self.get_destination().join(filename);
|
||||||
.join(filename);
|
|
||||||
|
|
||||||
utils::fs::create_file(&path)?
|
utils::fs::create_file(&path)?
|
||||||
.write_all(content)
|
.write_all(content)
|
||||||
|
@ -279,7 +290,6 @@ impl MDBook {
|
||||||
/// 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) -> Result<Self> {
|
pub fn read_config(mut self) -> Result<Self> {
|
||||||
|
|
||||||
let toml = self.get_root().join("book.toml");
|
let toml = self.get_root().join("book.toml");
|
||||||
let json = self.get_root().join("book.json");
|
let json = self.get_root().join("book.json");
|
||||||
|
|
||||||
|
@ -335,31 +345,33 @@ impl MDBook {
|
||||||
pub fn test(&mut self, library_paths: Vec<&str>) -> Result<()> {
|
pub fn test(&mut self, library_paths: Vec<&str>) -> Result<()> {
|
||||||
// read in the chapters
|
// read in the chapters
|
||||||
self.parse_summary().chain_err(|| "Couldn't parse summary")?;
|
self.parse_summary().chain_err(|| "Couldn't parse summary")?;
|
||||||
let library_args: Vec<&str> = (0..library_paths.len()).map(|_| "-L")
|
let library_args: Vec<&str> = (0..library_paths.len())
|
||||||
|
.map(|_| "-L")
|
||||||
.zip(library_paths.into_iter())
|
.zip(library_paths.into_iter())
|
||||||
.flat_map(|x| vec![x.0, x.1])
|
.flat_map(|x| vec![x.0, x.1])
|
||||||
.collect();
|
.collect();
|
||||||
let temp_dir = TempDir::new("mdbook")?;
|
let temp_dir = TempDir::new("mdbook")?;
|
||||||
for item in self.iter() {
|
for item in self.iter() {
|
||||||
|
|
||||||
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_source().join(&ch.path);
|
let path = self.get_source().join(&ch.path);
|
||||||
let base = path.parent().ok_or_else(
|
let base = path.parent()
|
||||||
|| String::from("Invalid bookitem path!"),
|
.ok_or_else(|| String::from("Invalid bookitem path!"))?;
|
||||||
)?;
|
|
||||||
let content = utils::fs::file_to_string(&path)?;
|
let content = utils::fs::file_to_string(&path)?;
|
||||||
// Parse and expand links
|
// Parse and expand links
|
||||||
let content = preprocess::links::replace_all(&content, base)?;
|
let content = preprocess::links::replace_all(&content, base)?;
|
||||||
println!("[*]: Testing file: {:?}", path);
|
println!("[*]: Testing file: {:?}", path);
|
||||||
|
|
||||||
//write preprocessed file to tempdir
|
// write preprocessed file to tempdir
|
||||||
let path = temp_dir.path().join(&ch.path);
|
let path = temp_dir.path().join(&ch.path);
|
||||||
let mut tmpf = utils::fs::create_file(&path)?;
|
let mut tmpf = utils::fs::create_file(&path)?;
|
||||||
tmpf.write_all(content.as_bytes())?;
|
tmpf.write_all(content.as_bytes())?;
|
||||||
|
|
||||||
let output = Command::new("rustdoc").arg(&path).arg("--test").args(&library_args).output()?;
|
let output = Command::new("rustdoc")
|
||||||
|
.arg(&path)
|
||||||
|
.arg("--test")
|
||||||
|
.args(&library_args)
|
||||||
|
.output()?;
|
||||||
|
|
||||||
if !output.status.success() {
|
if !output.status.success() {
|
||||||
bail!(ErrorKind::Subprocess("Rustdoc returned an error".to_string(), output));
|
bail!(ErrorKind::Subprocess("Rustdoc returned an error".to_string(), output));
|
||||||
|
@ -377,15 +389,15 @@ impl MDBook {
|
||||||
|
|
||||||
pub fn with_destination<T: Into<PathBuf>>(mut self, destination: T) -> Self {
|
pub fn with_destination<T: Into<PathBuf>>(mut self, destination: T) -> Self {
|
||||||
let root = self.config.get_root().to_owned();
|
let root = self.config.get_root().to_owned();
|
||||||
self.config.get_mut_html_config()
|
self.config
|
||||||
|
.get_mut_html_config()
|
||||||
.set_destination(&root, &destination.into());
|
.set_destination(&root, &destination.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn get_destination(&self) -> &Path {
|
pub fn get_destination(&self) -> &Path {
|
||||||
self.config.get_html_config()
|
self.config.get_html_config().get_destination()
|
||||||
.get_destination()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_source<T: Into<PathBuf>>(mut self, source: T) -> Self {
|
pub fn with_source<T: Into<PathBuf>>(mut self, source: T) -> Self {
|
||||||
|
|
|
@ -322,6 +322,11 @@ impl<'a> SummaryParser<'a> {
|
||||||
let section_number = self.push_numbered_section(SummaryItem::Link(it));
|
let section_number = self.push_numbered_section(SummaryItem::Link(it));
|
||||||
trace!("[*] Section number is {}", section_number);
|
trace!("[*] Section number is {}", section_number);
|
||||||
},
|
},
|
||||||
|
Event::End(Tag::Rule) => {
|
||||||
|
debug!("[*] Found a numbered chapter separator");
|
||||||
|
self.summary.numbered_chapters.push(SummaryItem::Separator);
|
||||||
|
self.state = State::NumberedChapters(0);
|
||||||
|
},
|
||||||
Event::Start(Tag::List(_)) => {
|
Event::Start(Tag::List(_)) => {
|
||||||
if let State::NumberedChapters(n) = self.state {
|
if let State::NumberedChapters(n) = self.state {
|
||||||
self.state = State::NumberedChapters(n + 1);
|
self.state = State::NumberedChapters(n + 1);
|
||||||
|
|
Loading…
Reference in New Issue