Everything compiles and all the tests pass.
This commit is contained in:
parent
d39352aa45
commit
3a51e4a27c
|
@ -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 {
|
||||||
|
|
100
src/book/mod.rs
100
src/book/mod.rs
|
@ -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,68 +131,44 @@ 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 !self.config.get_source().exists() {
|
if !folder.exists() {
|
||||||
debug!("[*]: {:?} does not exist, trying to create directory", self.config.get_source());
|
fs::create_dir_all(folder)?;
|
||||||
fs::create_dir_all(self.config.get_source())?;
|
debug!("{} created", folder.display());
|
||||||
}
|
|
||||||
|
|
||||||
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 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");
|
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(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -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),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
|
||||||
|
|
||||||
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 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(
|
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));
|
||||||
|
|
Loading…
Reference in New Issue