diff --git a/src/book/book.rs b/src/book/book.rs index 6e4cecac..3acb697f 100644 --- a/src/book/book.rs +++ b/src/book/book.rs @@ -1,3 +1,4 @@ +use std::fmt::{self, Display, Formatter}; use std::path::{Path, PathBuf}; use std::collections::VecDeque; use std::fs::File; @@ -130,7 +131,6 @@ fn load_chapter>(link: &Link, src_dir: P) -> Result { f.read_to_string(&mut content)?; 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); 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)] mod tests { diff --git a/src/book/mod.rs b/src/book/mod.rs index 2fc71ff8..e8f58343 100644 --- a/src/book/mod.rs +++ b/src/book/mod.rs @@ -85,17 +85,17 @@ impl MDBook { /// ```no_run /// # extern crate mdbook; /// # use mdbook::MDBook; - /// # use mdbook::BookItem; + /// # use mdbook::book::book::BookItem; /// # #[allow(unused_variables)] /// # fn main() { /// # let book = MDBook::new("mybook"); /// for item in book.iter() { - /// match item { - /// &BookItem::Chapter(ref section, ref chapter) => {}, - /// &BookItem::Affix(ref chapter) => {}, - /// &BookItem::Spacer => {}, + /// match *item { + /// BookItem::Chapter(ref chapter) => println!("{}", chapter), + /// BookItem::Separator => {}, /// } /// } + /// panic!(); /// /// // would print something like this: /// // 1. Chapter 1 @@ -131,68 +131,44 @@ impl MDBook { 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() { - debug!("[*]: {:?} does not exist, trying to create directory", self.get_destination()); - fs::create_dir_all(self.get_destination())?; - } - - - 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() { - - // Summary does not exist, create it - debug!("[*]: {:?} does not exist, trying to create SUMMARY.md", &summary); - let mut f = File::create(&summary)?; - - debug!("[*]: Writing to SUMMARY.md"); - - writeln!(f, "# Summary")?; - writeln!(f, "")?; - writeln!(f, "- [Chapter 1](./chapter_1.md)")?; - } - } - - // parse SUMMARY.md, and create the missing item related file - self.parse_summary()?; - - 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)?; + let necessary_folders = &[root, dest, src]; + + for folder in necessary_folders { + if !folder.exists() { + fs::create_dir_all(folder)?; + debug!("{} created", folder.display()); } } + + let summary = src.join("SUMMARY.md"); + + if !summary.exists() { + debug!("[*]: Creating SUMMARY.md"); + + let mut f = File::create(&summary)?; + + writeln!(f, "# Summary")?; + writeln!(f)?; + 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 load the newly created files into memory + self.parse_summary().chain_err(|| "Couldn't parse the SUMMARY.md file")?; + debug!("[*]: init done"); Ok(()) } @@ -512,7 +488,9 @@ impl MDBook { // Construct book 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); Ok(()) } diff --git a/src/book/summary.rs b/src/book/summary.rs index c2dfe03f..f02942fe 100644 --- a/src/book/summary.rs +++ b/src/book/summary.rs @@ -264,6 +264,7 @@ impl<'a> SummaryParser<'a> { fn step_start(&mut self, event: Event<'a>) -> Result<()> { match event { 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), } diff --git a/src/lib.rs b/src/lib.rs index ef94b0b4..b4fee9a9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -87,8 +87,6 @@ extern crate serde; extern crate serde_json; extern crate tempdir; -#[cfg(test)] -extern crate tempdir; #[cfg(test)] #[macro_use] extern crate pretty_assertions; diff --git a/src/renderer/html_handlebars/hbs_renderer.rs b/src/renderer/html_handlebars/hbs_renderer.rs index 81d06dc1..1286d3aa 100644 --- a/src/renderer/html_handlebars/hbs_renderer.rs +++ b/src/renderer/html_handlebars/hbs_renderer.rs @@ -3,10 +3,9 @@ use preprocess; use renderer::Renderer; use book::MDBook; use config::PlaypenConfig; -use theme::{Theme, playpen_editor}; +use theme::{self, Theme, playpen_editor}; use book::book::{BookItem, Chapter}; use utils; -use theme::{self, Theme}; use errors::*; use regex::{Regex, Captures}; @@ -33,25 +32,9 @@ impl HtmlHandlebars { -> Result<()> { // FIXME: This should be made DRY-er and rely less on mutable state match *item { -<<<<<<< HEAD - BookItem::Chapter(_, ref ch) | - BookItem::Affix(ref ch) if !ch.path.as_os_str().is_empty() => { -======= BookItem::Chapter(ref ch) => { - if ch.path != PathBuf::new() { - - let path = ctx.book.get_source().join(&ch.path); - - 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 content = ch.content.clone(); let base = path.parent().ok_or_else( || String::from("Invalid bookitem path!"), )?; @@ -62,9 +45,7 @@ impl HtmlHandlebars { print_content.push_str(&content); // Update the context with data for this file - let path = ch.path.to_str().ok_or_else(|| { - io::Error::new(io::ErrorKind::Other, "Could not convert path to str") - })?; + let path = ch.path.to_str().ok_or_else(|| Error::from("Could not convert path to str"))?; // Non-lexical lifetimes needed :'( let title: String; @@ -407,24 +388,26 @@ fn make_data(book: &MDBook) -> Result for item in book.iter() { // Create the data to inject in the template - let mut chapter = BTreeMap::new(); + let mut chapter_data = BTreeMap::new(); match *item { BookItem::Chapter(ref ch) => { - chapter.insert("section".to_owned(), json!(ch.number.clone())); - chapter.insert("name".to_owned(), json!(ch.name)); - let path = ch.path.to_str().ok_or_else(|| { - io::Error::new(io::ErrorKind::Other, "Could not convert path to str") - })?; - chapter.insert("path".to_owned(), json!(path)); + if let Some(ref section_number) = ch.number { + chapter_data.insert("section".to_owned(), json!(section_number.to_string())); + } + + chapter_data.insert("name".to_owned(), json!(ch.name)); + 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 => { - 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));