Everything compiles and all the tests pass.

This commit is contained in:
Michael Bryan 2017-08-21 11:34:34 +08:00
parent d39352aa45
commit 3a51e4a27c
5 changed files with 66 additions and 96 deletions

View File

@ -1,3 +1,4 @@
use std::fmt::{self, Display, Formatter};
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::collections::VecDeque; use std::collections::VecDeque;
use std::fs::File; use std::fs::File;
@ -130,7 +131,6 @@ fn load_chapter<P: AsRef<Path>>(link: &Link, src_dir: P) -> Result<Chapter> {
f.read_to_string(&mut content)?; f.read_to_string(&mut content)?;
let stripped = location.strip_prefix(&src_dir).expect("Chapters are always inside a book"); let stripped = location.strip_prefix(&src_dir).expect("Chapters are always inside a book");
println!("{} {} => {}", src_dir.display(), location.display(), stripped.display());
let mut ch = Chapter::new(&link.name, content, stripped); let mut ch = Chapter::new(&link.name, content, stripped);
ch.number = link.number.clone(); ch.number = link.number.clone();
@ -174,6 +174,16 @@ impl<'a> Iterator for BookItems<'a> {
} }
} }
impl Display for Chapter {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
if let Some(ref section_number) = self.number {
write!(f, "{} ", section_number)?;
}
write!(f, "{}", self.name)
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {

View File

@ -85,17 +85,17 @@ impl MDBook {
/// ```no_run /// ```no_run
/// # extern crate mdbook; /// # extern crate mdbook;
/// # use mdbook::MDBook; /// # use mdbook::MDBook;
/// # use mdbook::BookItem; /// # use mdbook::book::book::BookItem;
/// # #[allow(unused_variables)] /// # #[allow(unused_variables)]
/// # fn main() { /// # fn main() {
/// # let book = MDBook::new("mybook"); /// # let book = MDBook::new("mybook");
/// for item in book.iter() { /// for item in book.iter() {
/// match item { /// match *item {
/// &BookItem::Chapter(ref section, ref chapter) => {}, /// BookItem::Chapter(ref chapter) => println!("{}", chapter),
/// &BookItem::Affix(ref chapter) => {}, /// BookItem::Separator => {},
/// &BookItem::Spacer => {},
/// } /// }
/// } /// }
/// panic!();
/// ///
/// // would print something like this: /// // would print something like this:
/// // 1. Chapter 1 /// // 1. Chapter 1
@ -131,67 +131,43 @@ impl MDBook {
debug!("[fn]: init"); debug!("[fn]: init");
if !self.config.get_root().exists() {
fs::create_dir_all(&self.config.get_root()).unwrap();
info!("{:?} created", &self.config.get_root());
}
{ {
let root = self.config.get_root();
let dest = self.get_destination();
let src = self.config.get_source();
if !self.get_destination().exists() { let necessary_folders = &[root, dest, src];
debug!("[*]: {:?} does not exist, trying to create directory", self.get_destination());
fs::create_dir_all(self.get_destination())?; for folder in necessary_folders {
if !folder.exists() {
fs::create_dir_all(folder)?;
debug!("{} created", folder.display());
}
} }
let summary = src.join("SUMMARY.md");
if !self.config.get_source().exists() {
debug!("[*]: {:?} does not exist, trying to create directory", self.config.get_source());
fs::create_dir_all(self.config.get_source())?;
}
let summary = self.config.get_source().join("SUMMARY.md");
if !summary.exists() { if !summary.exists() {
debug!("[*]: Creating SUMMARY.md");
// Summary does not exist, create it
debug!("[*]: {:?} does not exist, trying to create SUMMARY.md", &summary);
let mut f = File::create(&summary)?; let mut f = File::create(&summary)?;
debug!("[*]: Writing to SUMMARY.md");
writeln!(f, "# Summary")?; writeln!(f, "# Summary")?;
writeln!(f, "")?; writeln!(f)?;
writeln!(f, "- [Chapter 1](./chapter_1.md)")?; writeln!(f, "- [Chapter 1](./chapter_1.md)")?;
} }
let ch_1 = src.join("chapter_1.md");
if !ch_1.exists() {
debug!("[*] Creating {}", ch_1.display());
let mut f = File::create(&ch_1)?;
writeln!(f, "# Chapter 1")?;
}
} }
// parse SUMMARY.md, and create the missing item related file // parse SUMMARY.md and load the newly created files into memory
self.parse_summary()?; self.parse_summary().chain_err(|| "Couldn't parse the SUMMARY.md file")?;
debug!("[*]: constructing paths for missing files");
for item in self.iter() {
debug!("[*]: item: {:?}", item);
let ch = match *item {
BookItem::Separator => continue,
BookItem::Chapter(ref ch) => ch,
};
if !ch.path.as_os_str().is_empty() {
let path = self.config.get_source().join(&ch.path);
if !path.exists() {
if !self.create_missing {
return Err(format!("'{}' referenced from SUMMARY.md does not exist.", path.to_string_lossy())
.into());
}
debug!("[*]: {:?} does not exist, trying to create file", path);
::std::fs::create_dir_all(path.parent().unwrap())?;
let mut f = File::create(path)?;
// debug!("[*]: Writing to {:?}", path);
writeln!(f, "# {}", ch.name)?;
}
}
}
debug!("[*]: init done"); debug!("[*]: init done");
Ok(()) Ok(())
@ -512,7 +488,9 @@ impl MDBook {
// Construct book // Construct book
fn parse_summary(&mut self) -> Result<()> { fn parse_summary(&mut self) -> Result<()> {
let book = load_book(self.get_source().join("SUMMARY.md"))?; let src = self.config.get_source();
let book = load_book(&src)?;
self.content = Some(book); self.content = Some(book);
Ok(()) Ok(())
} }

View File

@ -264,6 +264,7 @@ impl<'a> SummaryParser<'a> {
fn step_start(&mut self, event: Event<'a>) -> Result<()> { fn step_start(&mut self, event: Event<'a>) -> Result<()> {
match event { match event {
Event::Start(Tag::Paragraph) => self.state = State::PrefixChapters, Event::Start(Tag::Paragraph) => self.state = State::PrefixChapters,
Event::Start(Tag::List(_)) => self.state = State::NumberedChapters(0),
other => bail!("Expected a start of paragraph but got {:?}", other), other => bail!("Expected a start of paragraph but got {:?}", other),
} }

View File

@ -87,8 +87,6 @@ extern crate serde;
extern crate serde_json; extern crate serde_json;
extern crate tempdir; extern crate tempdir;
#[cfg(test)]
extern crate tempdir;
#[cfg(test)] #[cfg(test)]
#[macro_use] #[macro_use]
extern crate pretty_assertions; extern crate pretty_assertions;

View File

@ -3,10 +3,9 @@ use preprocess;
use renderer::Renderer; use renderer::Renderer;
use book::MDBook; use book::MDBook;
use config::PlaypenConfig; use config::PlaypenConfig;
use theme::{Theme, playpen_editor}; use theme::{self, Theme, playpen_editor};
use book::book::{BookItem, Chapter}; use book::book::{BookItem, Chapter};
use utils; use utils;
use theme::{self, Theme};
use errors::*; use errors::*;
use regex::{Regex, Captures}; use regex::{Regex, Captures};
@ -33,25 +32,9 @@ impl HtmlHandlebars {
-> Result<()> { -> Result<()> {
// FIXME: This should be made DRY-er and rely less on mutable state // FIXME: This should be made DRY-er and rely less on mutable state
match *item { match *item {
<<<<<<< HEAD
BookItem::Chapter(_, ref ch) |
BookItem::Affix(ref ch) if !ch.path.as_os_str().is_empty() => {
=======
BookItem::Chapter(ref ch) => { BookItem::Chapter(ref ch) => {
if ch.path != PathBuf::new() {
let path = ctx.book.get_source().join(&ch.path); let path = ctx.book.get_source().join(&ch.path);
let content = ch.content.clone();
debug!("[*]: Opening file: {:?}", path);
let mut f = File::open(&path)?;
let mut content: String = String::new();
debug!("[*]: Reading file");
f.read_to_string(&mut content)?;
>>>>>>> Removed old bookitem.md, now everyone uses the correct BookItem
let path = ctx.book.get_source().join(&ch.path);
let content = utils::fs::file_to_string(&path)?;
let base = path.parent().ok_or_else( let base = path.parent().ok_or_else(
|| String::from("Invalid bookitem path!"), || String::from("Invalid bookitem path!"),
)?; )?;
@ -62,9 +45,7 @@ impl HtmlHandlebars {
print_content.push_str(&content); print_content.push_str(&content);
// Update the context with data for this file // Update the context with data for this file
let path = ch.path.to_str().ok_or_else(|| { let path = ch.path.to_str().ok_or_else(|| Error::from("Could not convert path to str"))?;
io::Error::new(io::ErrorKind::Other, "Could not convert path to str")
})?;
// Non-lexical lifetimes needed :'( // Non-lexical lifetimes needed :'(
let title: String; let title: String;
@ -407,24 +388,26 @@ fn make_data(book: &MDBook) -> Result<serde_json::Map<String, serde_json::Value>
for item in book.iter() { for item in book.iter() {
// Create the data to inject in the template // Create the data to inject in the template
let mut chapter = BTreeMap::new(); let mut chapter_data = BTreeMap::new();
match *item { match *item {
BookItem::Chapter(ref ch) => { BookItem::Chapter(ref ch) => {
chapter.insert("section".to_owned(), json!(ch.number.clone())); if let Some(ref section_number) = ch.number {
chapter.insert("name".to_owned(), json!(ch.name)); chapter_data.insert("section".to_owned(), json!(section_number.to_string()));
let path = ch.path.to_str().ok_or_else(|| { }
io::Error::new(io::ErrorKind::Other, "Could not convert path to str")
})?; chapter_data.insert("name".to_owned(), json!(ch.name));
chapter.insert("path".to_owned(), json!(path)); let path = ch.path.to_str()
.ok_or_else(|| Error::from("Could not convert path to str"))?;
chapter_data.insert("path".to_owned(), json!(path));
}, },
BookItem::Separator => { BookItem::Separator => {
chapter.insert("spacer".to_owned(), json!("_spacer_")); chapter_data.insert("spacer".to_owned(), json!("_spacer_"));
}, },
} }
chapters.push(chapter); chapters.push(chapter_data);
} }
data.insert("chapters".to_owned(), json!(chapters)); data.insert("chapters".to_owned(), json!(chapters));