made clippy and rustfmt happy
This commit is contained in:
parent
01bab56faf
commit
131a404064
|
@ -27,14 +27,15 @@ impl Loader {
|
||||||
|
|
||||||
/// Parse the summary file and use it to load a book from disk.
|
/// Parse the summary file and use it to load a book from disk.
|
||||||
pub fn load(&self) -> Result<()> {
|
pub fn load(&self) -> Result<()> {
|
||||||
let summary = self.parse_summary()
|
let summary = self.parse_summary().chain_err(
|
||||||
.chain_err(|| "Couldn't parse `SUMMARY.md`")?;
|
|| "Couldn't parse `SUMMARY.md`",
|
||||||
|
)?;
|
||||||
|
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse the `SUMMARY.md` file.
|
/// Parse the `SUMMARY.md` file.
|
||||||
fn parse_summary(&self) -> Result<Summary> {
|
pub fn parse_summary(&self) -> Result<Summary> {
|
||||||
let path = self.source_directory.join("SUMMARY.md");
|
let path = self.source_directory.join("SUMMARY.md");
|
||||||
|
|
||||||
let mut summary_content = String::new();
|
let mut summary_content = String::new();
|
||||||
|
@ -42,5 +43,4 @@ impl Loader {
|
||||||
|
|
||||||
summary::parse_summary(&summary_content)
|
summary::parse_summary(&summary_content)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -285,20 +285,58 @@ impl<'a> SummaryParser<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Try to parse the title line.
|
/// Parse the numbered chapters.
|
||||||
fn parse_title(&mut self) -> Option<String> {
|
///
|
||||||
if let Some(Event::Start(Tag::Header(1))) = self.stream.next() {
|
/// If the event is the start of a list item, consume the entire item and
|
||||||
debug!("[*] Found a h1 in the SUMMARY");
|
/// add a new link to the summary with `push_numbered_section`.
|
||||||
|
///
|
||||||
|
/// If the event is the start of a new list, bump the nesting level.
|
||||||
|
///
|
||||||
|
/// If the event is the end of a list, decrement the nesting level. When
|
||||||
|
/// the nesting level would go negative, we've finished the numbered
|
||||||
|
/// section and need to parse the suffix section.
|
||||||
|
///
|
||||||
|
/// Otherwise, ignore the event.
|
||||||
|
fn step_numbered(&mut self, event: Event, nesting: u32) -> Result<()> {
|
||||||
|
match event {
|
||||||
|
Event::Start(Tag::Item) => {
|
||||||
|
let it = self.parse_item()
|
||||||
|
.chain_err(|| "List items should only contain links")?;
|
||||||
|
|
||||||
let tags = collect_events!(self.stream, Tag::Header(1));
|
debug!("[*] Found a chapter: {:?} ({})", it.name, it.location.display());
|
||||||
|
let section_number = self.push_numbered_section(SummaryItem::Link(it));
|
||||||
// TODO: How do we deal with headings like "# My **awesome** summary"?
|
trace!("[*] Section number is {}", section_number);
|
||||||
// for now, I'm just going to scan through and concatenate the
|
},
|
||||||
// Event::Text tags, skipping any styling.
|
Event::Start(Tag::List(_)) => {
|
||||||
Some(stringify_events(tags))
|
match self.state {
|
||||||
} else {
|
State::NumberedChapters(n) => {
|
||||||
None
|
let new_nest = n + 1;
|
||||||
|
self.state = State::NumberedChapters(new_nest);
|
||||||
|
trace!("[*] Nesting level increased to {}", new_nest);
|
||||||
|
},
|
||||||
|
other => unreachable!(),
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
Event::End(Tag::List(_)) => {
|
||||||
|
match self.state {
|
||||||
|
State::NumberedChapters(n) => {
|
||||||
|
if n == 0 {
|
||||||
|
trace!("[*] Finished parsing the numbered chapters");
|
||||||
|
self.state = State::SuffixChapters;
|
||||||
|
} else {
|
||||||
|
trace!("[*] Nesting level decreased to {}", n - 1);
|
||||||
|
self.state = State::NumberedChapters(n - 1);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
other => unreachable!(),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
other => {
|
||||||
|
trace!("[*] skipping unexpected token: {:?}", other);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn step_suffix(&mut self, event: Event<'a>) -> Result<()> {
|
fn step_suffix(&mut self, event: Event<'a>) -> Result<()> {
|
||||||
|
@ -348,70 +386,34 @@ impl<'a> SummaryParser<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse the numbered chapters.
|
/// Try to parse the title line.
|
||||||
///
|
fn parse_title(&mut self) -> Option<String> {
|
||||||
/// If the event is the start of a list item, consume the entire item and
|
if let Some(Event::Start(Tag::Header(1))) = self.stream.next() {
|
||||||
/// add a new link to the summary with `push_numbered_section`.
|
debug!("[*] Found a h1 in the SUMMARY");
|
||||||
///
|
|
||||||
/// If the event is the start of a new list, bump the nesting level.
|
|
||||||
///
|
|
||||||
/// If the event is the end of a list, decrement the nesting level. When
|
|
||||||
/// the nesting level would go negative, we've finished the numbered
|
|
||||||
/// section and need to parse the suffix section.
|
|
||||||
///
|
|
||||||
/// Otherwise, ignore the event.
|
|
||||||
fn step_numbered(&mut self, event: Event, nesting: u32) -> Result<()> {
|
|
||||||
match event {
|
|
||||||
Event::Start(Tag::Item) => {
|
|
||||||
let it = self.parse_item()
|
|
||||||
.chain_err(|| "List items should only contain links")?;
|
|
||||||
|
|
||||||
debug!("[*] Found a chapter: {:?} ({})", it.name, it.location.display());
|
let tags = collect_events!(self.stream, Tag::Header(1));
|
||||||
let section_number = self.push_numbered_section(SummaryItem::Link(it));
|
|
||||||
trace!("[*] Section number is {}", section_number);
|
|
||||||
}
|
|
||||||
Event::Start(Tag::List(_)) => {
|
|
||||||
match self.state {
|
|
||||||
State::NumberedChapters(n) => {
|
|
||||||
let new_nest = n + 1;
|
|
||||||
self.state = State::NumberedChapters(new_nest);
|
|
||||||
trace!("[*] Nesting level increased to {}", new_nest);
|
|
||||||
}
|
|
||||||
other => unreachable!(),
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
// TODO: How do we deal with headings like "# My **awesome** summary"?
|
||||||
Event::End(Tag::List(_)) => {
|
// for now, I'm just going to scan through and concatenate the
|
||||||
match self.state {
|
// Event::Text tags, skipping any styling.
|
||||||
State::NumberedChapters(n) => {
|
Some(stringify_events(tags))
|
||||||
if n == 0 {
|
|
||||||
trace!("[*] Finished parsing the numbered chapters");
|
|
||||||
self.state = State::SuffixChapters;
|
|
||||||
} else {
|
} else {
|
||||||
trace!("[*] Nesting level decreased to {}", n - 1);
|
None
|
||||||
self.state = State::NumberedChapters(n - 1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
other => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
other => {
|
|
||||||
trace!("[*] skipping unexpected token: {:?}", other);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Push a new section at the end of the current nesting level.
|
/// Push a new section at the end of the current nesting level.
|
||||||
fn push_numbered_section(&mut self, item: SummaryItem) -> SectionNumber {
|
fn push_numbered_section(&mut self, item: SummaryItem) -> SectionNumber {
|
||||||
if let State::NumberedChapters(level) = self.state {
|
if let State::NumberedChapters(level) = self.state {
|
||||||
push_item_at_nesting_level(&mut self.summary.numbered_chapters,
|
push_item_at_nesting_level(
|
||||||
|
&mut self.summary.numbered_chapters,
|
||||||
item,
|
item,
|
||||||
level as usize,
|
level as usize,
|
||||||
SectionNumber::default())
|
SectionNumber::default(),
|
||||||
.chain_err(|| format!("The parser should always ensure we add the next \
|
).chain_err(|| {
|
||||||
item at the correct level ({}:{})", module_path!(), line!()))
|
format!("The parser should always ensure we add the next \
|
||||||
|
item at the correct level ({}:{})", module_path!(), line!())
|
||||||
|
})
|
||||||
.unwrap()
|
.unwrap()
|
||||||
} else {
|
} else {
|
||||||
// this method should only ever be called when parsing a numbered
|
// this method should only ever be called when parsing a numbered
|
||||||
|
@ -430,17 +432,14 @@ impl<'a> SummaryParser<'a> {
|
||||||
/// Given a particular level (e.g. 3), go that many levels down the `Link`'s
|
/// Given a particular level (e.g. 3), go that many levels down the `Link`'s
|
||||||
/// nested items then append the provided item to the last `Link` in the
|
/// nested items then append the provided item to the last `Link` in the
|
||||||
/// list.
|
/// list.
|
||||||
fn push_item_at_nesting_level(links: &mut Vec<SummaryItem>,
|
fn push_item_at_nesting_level(links: &mut Vec<SummaryItem>, mut item: SummaryItem, level: usize, mut section_number: SectionNumber)
|
||||||
mut item: SummaryItem,
|
-> Result<SectionNumber> {
|
||||||
level: usize,
|
|
||||||
mut section_number: SectionNumber) -> Result<SectionNumber> {
|
|
||||||
if level == 0 {
|
if level == 0 {
|
||||||
// set the section number, if applicable
|
// set the section number, if applicable
|
||||||
section_number.push(links.len() as u32 + 1);
|
section_number.push(links.len() as u32 + 1);
|
||||||
|
|
||||||
match &mut item {
|
if let SummaryItem::Link(ref mut l) = item {
|
||||||
&mut SummaryItem::Link(ref mut l) => l.number = Some(section_number.clone()),
|
l.number = Some(section_number.clone());
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
links.push(item);
|
links.push(item);
|
||||||
|
@ -451,12 +450,13 @@ fn push_item_at_nesting_level(links: &mut Vec<SummaryItem>,
|
||||||
|
|
||||||
// FIXME: This bit needs simplifying!
|
// FIXME: This bit needs simplifying!
|
||||||
let (index, last_link) =
|
let (index, last_link) =
|
||||||
links.iter_mut()
|
links
|
||||||
|
.iter_mut()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.filter_map(|(i, item)| item.maybe_link_mut().map(|l| (i, l)))
|
.filter_map(|(i, item)| item.maybe_link_mut().map(|l| (i, l)))
|
||||||
.rev()
|
.rev()
|
||||||
.next()
|
.next()
|
||||||
.ok_or(format!("Can't recurse any further, summary needs to be {} more levels deep", level))?;
|
.ok_or_else(|| format!("Can't recurse any further, summary needs to be {} more levels deep", level))?;
|
||||||
|
|
||||||
section_number.push(index as u32 + 1);
|
section_number.push(index as u32 + 1);
|
||||||
push_item_at_nesting_level(&mut last_link.nested_items, item, level - 1, section_number)
|
push_item_at_nesting_level(&mut last_link.nested_items, item, level - 1, section_number)
|
||||||
|
@ -466,7 +466,7 @@ fn push_item_at_nesting_level(links: &mut Vec<SummaryItem>,
|
||||||
|
|
||||||
|
|
||||||
/// Extracts the text from formatted markdown.
|
/// Extracts the text from formatted markdown.
|
||||||
fn stringify_events<'a>(events: Vec<Event<'a>>) -> String {
|
fn stringify_events(events: Vec<Event>) -> String {
|
||||||
events
|
events
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(|t| match t {
|
.filter_map(|t| match t {
|
||||||
|
@ -680,7 +680,12 @@ mod tests {
|
||||||
.nested_items[0].maybe_link_mut()
|
.nested_items[0].maybe_link_mut()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.nested_items.len() , 0);
|
.nested_items.len() , 0);
|
||||||
let got = push_item_at_nesting_level(&mut links, SummaryItem::Link(Link::new("Dummy", "")), 3, SectionNumber::default()).unwrap();
|
let got = push_item_at_nesting_level(
|
||||||
|
&mut links,
|
||||||
|
SummaryItem::Link(Link::new("Dummy", "")),
|
||||||
|
3,
|
||||||
|
SectionNumber::default(),
|
||||||
|
).unwrap();
|
||||||
assert_eq!(links[0].maybe_link_mut().unwrap()
|
assert_eq!(links[0].maybe_link_mut().unwrap()
|
||||||
.nested_items[1].maybe_link_mut()
|
.nested_items[1].maybe_link_mut()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
|
|
@ -4,9 +4,14 @@
|
||||||
extern crate pretty_assertions;
|
extern crate pretty_assertions;
|
||||||
extern crate mdbook;
|
extern crate mdbook;
|
||||||
extern crate env_logger;
|
extern crate env_logger;
|
||||||
|
extern crate tempdir;
|
||||||
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use mdbook::loader::{parse_summary, Link, SummaryItem, SectionNumber, Summary};
|
use std::fs::File;
|
||||||
|
use std::io::Write;
|
||||||
|
|
||||||
|
use mdbook::loader::{parse_summary, Link, SummaryItem, SectionNumber, Summary, Loader};
|
||||||
|
use tempdir::TempDir;
|
||||||
|
|
||||||
|
|
||||||
const SUMMARY: &'static str = "
|
const SUMMARY: &'static str = "
|
||||||
|
@ -28,10 +33,35 @@ const SUMMARY: &'static str = "
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_summary_md() {
|
fn parse_summary_md() {
|
||||||
env_logger::init().unwrap();
|
env_logger::init().ok();
|
||||||
|
|
||||||
// Hard-code the structure `SUMMARY` *should* be parsed into.
|
let should_be = expected_summary();
|
||||||
let should_be = 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().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")),
|
title: Some(String::from("Summary")),
|
||||||
|
|
||||||
prefix_chapters: vec![
|
prefix_chapters: vec![
|
||||||
|
@ -73,12 +103,7 @@ fn parse_summary_md() {
|
||||||
location: PathBuf::from("/conclusion.md"),
|
location: PathBuf::from("/conclusion.md"),
|
||||||
number: None,
|
number: None,
|
||||||
nested_items: vec![],
|
nested_items: vec![],
|
||||||
})
|
}),
|
||||||
],
|
],
|
||||||
};
|
}
|
||||||
|
|
||||||
let got = parse_summary(SUMMARY).unwrap();
|
|
||||||
println!("{:#?}", got);
|
|
||||||
|
|
||||||
assert_eq!(got, should_be);
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue