diff --git a/src/loader/mod.rs b/src/loader/mod.rs index c3e64237..5e9b7891 100644 --- a/src/loader/mod.rs +++ b/src/loader/mod.rs @@ -9,7 +9,7 @@ use errors::*; mod summary; -pub use self::summary::{Summary, parse_summary}; +pub use self::summary::{Summary, Link, SummaryItem, parse_summary, SectionNumber}; /// The object in charge of parsing the source directory into a usable diff --git a/src/loader/summary.rs b/src/loader/summary.rs index 85c4f7d6..500cb06d 100644 --- a/src/loader/summary.rs +++ b/src/loader/summary.rs @@ -52,10 +52,14 @@ pub fn parse_summary(summary: &str) -> Result { /// The parsed `SUMMARY.md`, specifying how the book should be laid out. #[derive(Debug, Clone, Default, PartialEq)] pub struct Summary { - title: Option, - prefix_chapters: Vec, - numbered_chapters: Vec, - suffix_chapters: Vec, + /// An optional title for the `SUMMARY.md`, currently just ignored. + pub title: Option, + /// Chapters before the main text (e.g. an introduction). + pub prefix_chapters: Vec, + /// The main chapters in the document. + pub numbered_chapters: Vec, + /// Items which come after the main document (e.g. a conclusion). + pub suffix_chapters: Vec, } /// A struct representing an entry in the `SUMMARY.md`, possibly with nested @@ -63,15 +67,21 @@ pub struct Summary { /// /// This is roughly the equivalent of `[Some section](./path/to/file.md)`. #[derive(Debug, Clone, PartialEq)] -struct Link { - name: String, - location: PathBuf, - number: Option, - nested_items: Vec, +pub struct Link { + /// The name of the chapter. + pub name: String, + /// The location of the chapter's source file, taking the book's `src` + /// directory as the root. + pub location: PathBuf, + /// The section number, if this chapter is in the numbered section. + pub number: Option, + /// Any nested items this chapter may contain. + pub nested_items: Vec, } impl Link { - fn new, P: AsRef>(name: S, location: P) -> Link { + /// Create a new link with no nested items. + pub fn new, P: AsRef>(name: S, location: P) -> Link { Link { name: name.into(), location: location.as_ref().to_path_buf(), @@ -92,9 +102,12 @@ impl Default for Link { } } +/// An item in `SUMMARY.md` which could be either a separator or a `Link`. #[derive(Debug, Clone, PartialEq)] -enum SummaryItem { +pub enum SummaryItem { + /// A link to a chapter. Link(Link), + /// A separator (`---`). Separator, } @@ -193,13 +206,20 @@ impl<'a> SummaryParser<'a> { fn parse(mut self) -> Result { self.summary.title = self.parse_title(); + if let Some(ref title) = self.summary.title { + debug!("[*] Title is {:?}", title); + } + + while self.state != State::End { + self.step()?; + } + Ok(self.summary) } fn step(&mut self) -> Result<()> { let next_event = self.stream.next().expect("TODO: error-chain"); - trace!("[*] Current state = {:?}, Next Event = {:?}", self.state, next_event); - println!("{:?}", next_event); + trace!("[*] Current state: {:?}, next event: {:?}", self.state, next_event); match self.state { State::Begin => self.step_start(next_event)?, @@ -253,7 +273,7 @@ impl<'a> SummaryParser<'a> { }, other => { - debug!("[*] Skipping unexpected token in summary: {:?}", other); + trace!("[*] Skipping unexpected token in summary: {:?}", other); }, } @@ -310,6 +330,8 @@ impl<'a> SummaryParser<'a> { Event::Start(Tag::Item) => { let it = self.parse_item() .chain_err(|| "List items should only contain links")?; + + trace!("[*] Found a chapter: {:?}", it); self.push_numbered_section(SummaryItem::Link(it)); Ok(()) } @@ -379,7 +401,7 @@ fn stringify_events<'a>(events: Vec>) -> String { /// A section number like "1.2.3", basically just a newtype'd `Vec`. #[derive(Debug, PartialEq, Clone, Default)] -struct SectionNumber(Vec); +pub struct SectionNumber(pub Vec); impl Display for SectionNumber { fn fmt(&self, f: &mut Formatter) -> fmt::Result { diff --git a/tests/loading.rs b/tests/loading.rs new file mode 100644 index 00000000..74b22b03 --- /dev/null +++ b/tests/loading.rs @@ -0,0 +1,82 @@ +//! Integration tests for loading a book into memory + +extern crate mdbook; +extern crate env_logger; + +use std::path::PathBuf; +use mdbook::loader::{parse_summary, Link, SummaryItem, SectionNumber, Summary}; + + +const SUMMARY: &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] +#[ignore] +fn load_summary_md() { + env_logger::init().unwrap(); + + let should_be = 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![], + }) + ], + }; + + let got = parse_summary(SUMMARY).unwrap(); + println!("{:#?}", got); + + assert_eq!(got, should_be); +}