Started integrating some of the feedback from budziq

This commit is contained in:
Michael Bryan 2017-07-08 14:28:47 +08:00
parent 2670510fa4
commit 773784a256
4 changed files with 22 additions and 176 deletions

View File

@ -1,5 +1,3 @@
#![allow(missing_docs, unused_variables, unused_imports, dead_code)]
use std::path::Path;
use std::collections::VecDeque;
use std::fs::File;

View File

@ -9,30 +9,8 @@
//!
//! ```rust,no_run
//! # fn run() -> mdbook::errors::Result<()> {
//! use mdbook::loader::Loader;
//! let loader = Loader::new("./src/");
//! let book = loader.load()?;
//! # Ok(())
//! # }
//! # fn main() { run().unwrap() }
//! ```
//!
//! Alternatively, if you are using the `mdbook` crate as a library and
//! only want to read the `SUMMARY.md` file without having to load the
//! entire book from disk, you can use the `parse_summary()` function.
//!
//! ```rust
//! # fn run() -> mdbook::errors::Result<()> {
//! use mdbook::loader::parse_summary;
//! let src = "# Book Summary
//!
//! [Introduction](./index.md)
//! - [First Chapter](./first/index.md)
//! - [Sub-Section](./first/subsection.md)
//! - [Second Chapter](./second/index.md)
//! ";
//! let summary = parse_summary(src)?;
//! println!("{:#?}", summary);
//! use mdbook::loader::load_book;
//! let book = load_book("./src/")?;
//! # Ok(())
//! # }
//! # fn main() { run().unwrap() }
@ -48,51 +26,24 @@ use errors::*;
mod summary;
mod book;
pub use self::summary::{Summary, Link, SummaryItem, parse_summary, SectionNumber};
pub use self::book::{Book, BookItems, load_book_from_disk, BookItem, Chapter};
pub use self::book::{Book, BookItems, BookItem, Chapter};
use self::book::load_book_from_disk;
use self::summary::parse_summary;
/// The object in charge of parsing the source directory into a usable
/// `Book` struct.
#[derive(Debug, Clone, PartialEq)]
pub struct Loader {
source_directory: PathBuf,
}
impl Loader {
/// Create a new loader which uses the provided source directory.
pub fn new<P: AsRef<Path>>(source_directory: P) -> Loader {
Loader { source_directory: source_directory.as_ref().to_path_buf() }
}
/// Parse the summary file and use it to load a book from disk.
pub fn load(&self) -> Result<Book> {
let summary_md = self.find_summary().chain_err(
|| "Couldn't find `SUMMARY.md`",
)?;
let summary = self.parse_summary(&summary_md).chain_err(
|| "Couldn't parse `SUMMARY.md`",
)?;
let src_dir = match summary_md.parent() {
Some(parent) => parent,
None => bail!("SUMMARY.md doesn't have a parent... wtf?"),
};
load_book_from_disk(&summary, src_dir)
}
/// Parse a `SUMMARY.md` file.
pub fn parse_summary<P: AsRef<Path>>(&self, summary_md: P) -> Result<Summary> {
let mut summary_content = String::new();
File::open(summary_md)?.read_to_string(&mut summary_content)?;
summary::parse_summary(&summary_content)
}
fn find_summary(&self) -> Result<PathBuf> {
// TODO: use Piston's find_folder to make locating SUMMARY.md easier.
// https://github.com/PistonDevelopers/find_folder
Ok(self.source_directory.join("SUMMARY.md"))
}
/// Load a book into memory from its `src/` directory.
pub fn load_book<P: AsRef<Path>>(src_dir: P) -> Result<Book> {
let src_dir = src_dir.as_ref();
let summary_md = src_dir.join("SUMMARY.md");
let mut summary_content = String::new();
File::open(summary_md)
.chain_err(|| "Couldn't open SUMMARY.md")?
.read_to_string(&mut summary_content)?;
let summary = parse_summary(&summary_content).chain_err(
|| "Summary parsing failed",
)?;
load_book_from_disk(&summary, src_dir)
}

View File

@ -1,5 +1,3 @@
#![allow(dead_code, unused_variables)]
use std::fmt::{self, Formatter, Display};
use std::ops::{Deref, DerefMut};
use std::path::{Path, PathBuf};

View File

@ -7,117 +7,16 @@ extern crate env_logger;
extern crate tempdir;
use std::path::PathBuf;
use std::fs::File;
use std::io::Write;
use mdbook::loader::{parse_summary, Link, SummaryItem, SectionNumber, Summary, Loader};
use tempdir::TempDir;
use mdbook::loader::load_book;
const SUMMARY: &'static str = "
# Summary
[Introduction](/intro.md)
---
[A Prefix Chapter](/some_prefix.md)
- [First Chapter](/chapter_1/index.md)
- [Some Subsection](/chapter_1/subsection.md)
---
[Conclusion](/conclusion.md)
";
#[test]
fn parse_summary_md() {
env_logger::init().ok();
let should_be = expected_summary();
let got = parse_summary(SUMMARY).unwrap();
println!("{:#?}", got);
assert_eq!(got, should_be);
}
#[test]
fn parse_summary_using_loader() {
env_logger::init().ok();
let temp = TempDir::new("book").unwrap();
let summary_md = temp.path().join("SUMMARY.md");
File::create(&summary_md)
.unwrap()
.write_all(SUMMARY.as_bytes())
.unwrap();
let loader = Loader::new(temp.path());
let got = loader.parse_summary(&summary_md).unwrap();
let should_be = expected_summary();
assert_eq!(got, should_be);
}
/// This is what the SUMMARY should be parsed as
fn expected_summary() -> Summary {
Summary {
title: Some(String::from("Summary")),
prefix_chapters: vec![
SummaryItem::Link(Link {
name: String::from("Introduction"),
location: PathBuf::from("/intro.md"),
number: None,
nested_items: vec![],
}),
SummaryItem::Separator,
SummaryItem::Link(Link {
name: String::from("A Prefix Chapter"),
location: PathBuf::from("/some_prefix.md"),
number: None,
nested_items: vec![],
}),
],
numbered_chapters: vec![
SummaryItem::Link(Link {
name: String::from("First Chapter"),
location: PathBuf::from("/chapter_1/index.md"),
number: Some(SectionNumber(vec![1])),
nested_items: vec![
SummaryItem::Link(Link {
name: String::from("Some Subsection"),
location: PathBuf::from("/chapter_1/subsection.md"),
number: Some(SectionNumber(vec![1, 1])),
nested_items: vec![],
}),
],
}),
],
suffix_chapters: vec![
SummaryItem::Separator,
SummaryItem::Link(Link {
name: String::from("Conclusion"),
location: PathBuf::from("/conclusion.md"),
number: None,
nested_items: vec![],
}),
],
}
}
#[test]
fn load_the_example_book() {
let example_src_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("book-example")
.join("src");
let loader = Loader::new(example_src_dir);
let book = loader.load().unwrap();
let book = load_book(example_src_dir).unwrap();
println!("{:#?}", book);
}