Started integrating some of the feedback from budziq
This commit is contained in:
parent
b925c7c41c
commit
4202ead962
|
@ -1,5 +1,3 @@
|
||||||
#![allow(missing_docs, unused_variables, unused_imports, dead_code)]
|
|
||||||
|
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
|
|
|
@ -9,30 +9,8 @@
|
||||||
//!
|
//!
|
||||||
//! ```rust,no_run
|
//! ```rust,no_run
|
||||||
//! # fn run() -> mdbook::errors::Result<()> {
|
//! # fn run() -> mdbook::errors::Result<()> {
|
||||||
//! use mdbook::loader::Loader;
|
//! use mdbook::loader::load_book;
|
||||||
//! let loader = Loader::new("./src/");
|
//! let book = load_book("./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);
|
|
||||||
//! # Ok(())
|
//! # Ok(())
|
||||||
//! # }
|
//! # }
|
||||||
//! # fn main() { run().unwrap() }
|
//! # fn main() { run().unwrap() }
|
||||||
|
@ -48,51 +26,24 @@ use errors::*;
|
||||||
mod summary;
|
mod summary;
|
||||||
mod book;
|
mod book;
|
||||||
|
|
||||||
pub use self::summary::{Summary, Link, SummaryItem, parse_summary, SectionNumber};
|
pub use self::book::{Book, BookItems, BookItem, Chapter};
|
||||||
pub use self::book::{Book, BookItems, load_book_from_disk, 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
|
/// Load a book into memory from its `src/` directory.
|
||||||
/// `Book` struct.
|
pub fn load_book<P: AsRef<Path>>(src_dir: P) -> Result<Book> {
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
let src_dir = src_dir.as_ref();
|
||||||
pub struct Loader {
|
let summary_md = src_dir.join("SUMMARY.md");
|
||||||
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();
|
let mut summary_content = String::new();
|
||||||
File::open(summary_md)?.read_to_string(&mut summary_content)?;
|
File::open(summary_md)
|
||||||
|
.chain_err(|| "Couldn't open SUMMARY.md")?
|
||||||
|
.read_to_string(&mut summary_content)?;
|
||||||
|
|
||||||
summary::parse_summary(&summary_content)
|
let summary = parse_summary(&summary_content).chain_err(
|
||||||
}
|
|| "Summary parsing failed",
|
||||||
|
)?;
|
||||||
|
|
||||||
fn find_summary(&self) -> Result<PathBuf> {
|
load_book_from_disk(&summary, src_dir)
|
||||||
// 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"))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
#![allow(dead_code, unused_variables)]
|
|
||||||
|
|
||||||
use std::fmt::{self, Formatter, Display};
|
use std::fmt::{self, Formatter, Display};
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
105
tests/loading.rs
105
tests/loading.rs
|
@ -7,117 +7,16 @@ extern crate env_logger;
|
||||||
extern crate tempdir;
|
extern crate tempdir;
|
||||||
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::fs::File;
|
|
||||||
use std::io::Write;
|
|
||||||
|
|
||||||
use mdbook::loader::{parse_summary, Link, SummaryItem, SectionNumber, Summary, Loader};
|
use mdbook::loader::load_book;
|
||||||
use tempdir::TempDir;
|
|
||||||
|
|
||||||
|
|
||||||
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]
|
#[test]
|
||||||
fn load_the_example_book() {
|
fn load_the_example_book() {
|
||||||
let example_src_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
let example_src_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
||||||
.join("book-example")
|
.join("book-example")
|
||||||
.join("src");
|
.join("src");
|
||||||
let loader = Loader::new(example_src_dir);
|
|
||||||
|
|
||||||
let book = loader.load().unwrap();
|
let book = load_book(example_src_dir).unwrap();
|
||||||
println!("{:#?}", book);
|
println!("{:#?}", book);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue