Add `--auto-summary` option.
Add a `Summary::from_source` function to generate the book's summary from the sources directory structure.
This commit is contained in:
parent
ffa8284743
commit
f767167808
|
@ -1,3 +1,4 @@
|
||||||
|
use std::borrow::Cow;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::fmt::{self, Display, Formatter};
|
use std::fmt::{self, Display, Formatter};
|
||||||
use std::fs::{self, File};
|
use std::fs::{self, File};
|
||||||
|
@ -11,19 +12,27 @@ use crate::errors::*;
|
||||||
/// Load a book into memory from its `src/` directory.
|
/// Load a book into memory from its `src/` directory.
|
||||||
pub fn load_book<P: AsRef<Path>>(src_dir: P, cfg: &BuildConfig) -> Result<Book> {
|
pub fn load_book<P: AsRef<Path>>(src_dir: P, cfg: &BuildConfig) -> Result<Book> {
|
||||||
let src_dir = src_dir.as_ref();
|
let src_dir = src_dir.as_ref();
|
||||||
let summary_md = src_dir.join("SUMMARY.md");
|
|
||||||
|
|
||||||
let mut summary_content = String::new();
|
let summary = if !cfg.auto_summary {
|
||||||
File::open(&summary_md)
|
let summary_md = src_dir.join("SUMMARY.md");
|
||||||
.with_context(|| format!("Couldn't open SUMMARY.md in {:?} directory", src_dir))?
|
|
||||||
.read_to_string(&mut summary_content)?;
|
|
||||||
|
|
||||||
let summary = parse_summary(&summary_content)
|
let mut summary_content = String::new();
|
||||||
.with_context(|| format!("Summary parsing failed for file={:?}", summary_md))?;
|
File::open(&summary_md)
|
||||||
|
.with_context(|| format!("Couldn't open SUMMARY.md in {:?} directory", src_dir))?
|
||||||
|
.read_to_string(&mut summary_content)?;
|
||||||
|
|
||||||
if cfg.create_missing {
|
let summary = parse_summary(&summary_content)
|
||||||
create_missing(src_dir, &summary).with_context(|| "Unable to create missing chapters")?;
|
.with_context(|| format!("Summary parsing failed for file={:?}", summary_md))?;
|
||||||
}
|
|
||||||
|
if cfg.create_missing {
|
||||||
|
create_missing(src_dir, &summary)
|
||||||
|
.with_context(|| "Unable to create missing chapters")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
summary
|
||||||
|
} else {
|
||||||
|
Summary::from_sources(src_dir)?
|
||||||
|
};
|
||||||
|
|
||||||
load_book_from_disk(&summary, src_dir)
|
load_book_from_disk(&summary, src_dir)
|
||||||
}
|
}
|
||||||
|
@ -53,7 +62,10 @@ fn create_missing(src_dir: &Path, summary: &Summary) -> Result<()> {
|
||||||
let mut f = File::create(&filename).with_context(|| {
|
let mut f = File::create(&filename).with_context(|| {
|
||||||
format!("Unable to create missing file: {}", filename.display())
|
format!("Unable to create missing file: {}", filename.display())
|
||||||
})?;
|
})?;
|
||||||
writeln!(f, "# {}", link.name)?;
|
|
||||||
|
if let Some(name) = &link.name {
|
||||||
|
writeln!(f, "# {}", name)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -253,7 +265,7 @@ fn load_chapter<P: AsRef<Path>>(
|
||||||
let src_dir = src_dir.as_ref();
|
let src_dir = src_dir.as_ref();
|
||||||
|
|
||||||
let mut ch = if let Some(ref link_location) = link.location {
|
let mut ch = if let Some(ref link_location) = link.location {
|
||||||
debug!("Loading {} ({})", link.name, link_location.display());
|
debug!("Loading {}", link);
|
||||||
|
|
||||||
let location = if link_location.is_absolute() {
|
let location = if link_location.is_absolute() {
|
||||||
link_location.clone()
|
link_location.clone()
|
||||||
|
@ -265,9 +277,8 @@ fn load_chapter<P: AsRef<Path>>(
|
||||||
.with_context(|| format!("Chapter file not found, {}", link_location.display()))?;
|
.with_context(|| format!("Chapter file not found, {}", link_location.display()))?;
|
||||||
|
|
||||||
let mut content = String::new();
|
let mut content = String::new();
|
||||||
f.read_to_string(&mut content).with_context(|| {
|
f.read_to_string(&mut content)
|
||||||
format!("Unable to read \"{}\" ({})", link.name, location.display())
|
.with_context(|| format!("Unable to read {}", link))?;
|
||||||
})?;
|
|
||||||
|
|
||||||
if content.as_bytes().starts_with(b"\xef\xbb\xbf") {
|
if content.as_bytes().starts_with(b"\xef\xbb\xbf") {
|
||||||
content.replace_range(..3, "");
|
content.replace_range(..3, "");
|
||||||
|
@ -277,16 +288,21 @@ fn load_chapter<P: AsRef<Path>>(
|
||||||
.strip_prefix(&src_dir)
|
.strip_prefix(&src_dir)
|
||||||
.expect("Chapters are always inside a book");
|
.expect("Chapters are always inside a book");
|
||||||
|
|
||||||
Chapter::new(&link.name, content, stripped, parent_names.clone())
|
let name = match &link.name {
|
||||||
|
Some(name) => Cow::Borrowed(name.as_str()),
|
||||||
|
None => Cow::Owned(read_chapter_title(&content)),
|
||||||
|
};
|
||||||
|
|
||||||
|
Chapter::new(&name, content, stripped, parent_names.clone())
|
||||||
} else {
|
} else {
|
||||||
Chapter::new_draft(&link.name, parent_names.clone())
|
Chapter::new_draft(link.name.as_ref().unwrap().as_str(), parent_names.clone())
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut sub_item_parents = parent_names;
|
let mut sub_item_parents = parent_names;
|
||||||
|
|
||||||
ch.number = link.number.clone();
|
ch.number = link.number.clone();
|
||||||
|
|
||||||
sub_item_parents.push(link.name.clone());
|
sub_item_parents.push(ch.name.clone());
|
||||||
let sub_items = link
|
let sub_items = link
|
||||||
.nested_items
|
.nested_items
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -298,6 +314,23 @@ fn load_chapter<P: AsRef<Path>>(
|
||||||
Ok(ch)
|
Ok(ch)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Read a chapter title from its source file.
|
||||||
|
fn read_chapter_title(content: &str) -> String {
|
||||||
|
let mut pulldown_parser = pulldown_cmark::Parser::new(content);
|
||||||
|
|
||||||
|
while let Some(event) = pulldown_parser.next() {
|
||||||
|
if let pulldown_cmark::Event::Start(pulldown_cmark::Tag::Heading(1)) = event {
|
||||||
|
if let Some(pulldown_cmark::Event::Text(title)) = pulldown_parser.next() {
|
||||||
|
return title.to_string();
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
"Untitled".to_string()
|
||||||
|
}
|
||||||
|
|
||||||
/// A depth-first iterator over the items in a book.
|
/// A depth-first iterator over the items in a book.
|
||||||
///
|
///
|
||||||
/// # Note
|
/// # Note
|
||||||
|
@ -604,7 +637,7 @@ And here is some \
|
||||||
let (_, temp) = dummy_link();
|
let (_, temp) = dummy_link();
|
||||||
let summary = Summary {
|
let summary = Summary {
|
||||||
numbered_chapters: vec![SummaryItem::Link(Link {
|
numbered_chapters: vec![SummaryItem::Link(Link {
|
||||||
name: String::from("Empty"),
|
name: Some(String::from("Empty")),
|
||||||
location: Some(PathBuf::from("")),
|
location: Some(PathBuf::from("")),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})],
|
})],
|
||||||
|
@ -624,7 +657,7 @@ And here is some \
|
||||||
|
|
||||||
let summary = Summary {
|
let summary = Summary {
|
||||||
numbered_chapters: vec![SummaryItem::Link(Link {
|
numbered_chapters: vec![SummaryItem::Link(Link {
|
||||||
name: String::from("nested"),
|
name: Some(String::from("nested")),
|
||||||
location: Some(dir),
|
location: Some(dir),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})],
|
})],
|
||||||
|
|
|
@ -81,7 +81,7 @@ impl BookBuilder {
|
||||||
|
|
||||||
self.write_book_toml()?;
|
self.write_book_toml()?;
|
||||||
|
|
||||||
match MDBook::load(&self.root) {
|
match MDBook::load(&self.root, false) {
|
||||||
Ok(book) => Ok(book),
|
Ok(book) => Ok(book),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
error!("{}", e);
|
error!("{}", e);
|
||||||
|
|
|
@ -47,7 +47,10 @@ pub struct MDBook {
|
||||||
|
|
||||||
impl MDBook {
|
impl MDBook {
|
||||||
/// Load a book from its root directory on disk.
|
/// Load a book from its root directory on disk.
|
||||||
pub fn load<P: Into<PathBuf>>(book_root: P) -> Result<MDBook> {
|
///
|
||||||
|
/// If `auto_summary` is set, the book's summary is automatically generated
|
||||||
|
/// from the root directory structure.
|
||||||
|
pub fn load<P: Into<PathBuf>>(book_root: P, auto_summary: bool) -> Result<MDBook> {
|
||||||
let book_root = book_root.into();
|
let book_root = book_root.into();
|
||||||
let config_location = book_root.join("book.toml");
|
let config_location = book_root.join("book.toml");
|
||||||
|
|
||||||
|
@ -68,6 +71,10 @@ impl MDBook {
|
||||||
Config::default()
|
Config::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if auto_summary {
|
||||||
|
config.build.auto_summary = true;
|
||||||
|
}
|
||||||
|
|
||||||
config.update_from_env();
|
config.update_from_env();
|
||||||
|
|
||||||
if log_enabled!(log::Level::Trace) {
|
if log_enabled!(log::Level::Trace) {
|
||||||
|
@ -128,7 +135,7 @@ impl MDBook {
|
||||||
/// ```no_run
|
/// ```no_run
|
||||||
/// # use mdbook::MDBook;
|
/// # use mdbook::MDBook;
|
||||||
/// # use mdbook::book::BookItem;
|
/// # use mdbook::book::BookItem;
|
||||||
/// # let book = MDBook::load("mybook").unwrap();
|
/// # let book = MDBook::load("mybook", false).unwrap();
|
||||||
/// for item in book.iter() {
|
/// for item in book.iter() {
|
||||||
/// match *item {
|
/// match *item {
|
||||||
/// BookItem::Chapter(ref chapter) => {},
|
/// BookItem::Chapter(ref chapter) => {},
|
||||||
|
|
|
@ -66,6 +66,91 @@ pub struct Summary {
|
||||||
pub suffix_chapters: Vec<SummaryItem>,
|
pub suffix_chapters: Vec<SummaryItem>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Summary {
|
||||||
|
/// Create a summary from the book's sources directory.
|
||||||
|
///
|
||||||
|
/// Each file is imported as a book chapter.
|
||||||
|
/// Each folder is imported as a book chapter and must contain
|
||||||
|
/// a `README.md` file defining the chapter's title and content.
|
||||||
|
/// Any file/folder inside the directory is imported as a sub-chapter.
|
||||||
|
/// The file/folder name is used to compose the chapter's link.
|
||||||
|
///
|
||||||
|
/// Chapters are added to the book in alphabetical order, using the file/folder name.
|
||||||
|
pub fn from_sources<P: AsRef<Path>>(src_dir: P) -> std::io::Result<Summary> {
|
||||||
|
let mut summary = Summary {
|
||||||
|
title: None,
|
||||||
|
prefix_chapters: Vec::new(),
|
||||||
|
numbered_chapters: Vec::new(),
|
||||||
|
suffix_chapters: Vec::new(),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Checks if the given path must be considered.
|
||||||
|
fn include_path(path: &Path) -> bool {
|
||||||
|
if let Some(name) = path.file_name() {
|
||||||
|
if name == "README.md" || name == "SUMMARY.md" {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read a directory recursively and return the found summary items.
|
||||||
|
fn read_dir<P: AsRef<Path>>(dir: P) -> std::io::Result<Vec<SummaryItem>> {
|
||||||
|
let mut links = Vec::new();
|
||||||
|
|
||||||
|
for entry in std::fs::read_dir(dir)? {
|
||||||
|
let entry = entry?;
|
||||||
|
let entry_path = entry.path();
|
||||||
|
|
||||||
|
if include_path(&entry_path) {
|
||||||
|
let metadata = std::fs::metadata(&entry_path)?;
|
||||||
|
|
||||||
|
if metadata.is_file() {
|
||||||
|
links.push(Link::new_unnamed(entry_path))
|
||||||
|
} else {
|
||||||
|
let chapter_path = entry_path.join("README.md");
|
||||||
|
if chapter_path.is_file() {
|
||||||
|
let mut link = Link::new_unnamed(chapter_path);
|
||||||
|
link.nested_items = read_dir(entry_path)?;
|
||||||
|
links.push(link)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Items are sorted by name.
|
||||||
|
links.sort_by(|a, b| {
|
||||||
|
a.location
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.cmp(b.location.as_ref().unwrap())
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(links.into_iter().map(SummaryItem::Link).collect())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Associate the correct section number to each summary item.
|
||||||
|
fn number_items(items: &mut [SummaryItem], number: &[u32]) {
|
||||||
|
let mut n = 1;
|
||||||
|
for item in items {
|
||||||
|
if let SummaryItem::Link(link) = item {
|
||||||
|
let mut entry_number = number.to_vec();
|
||||||
|
entry_number.push(n);
|
||||||
|
n += 1;
|
||||||
|
number_items(&mut link.nested_items, &entry_number);
|
||||||
|
link.number = Some(SectionNumber(entry_number))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
summary.numbered_chapters = read_dir(src_dir)?;
|
||||||
|
number_items(&mut summary.numbered_chapters, &[]);
|
||||||
|
|
||||||
|
Ok(summary)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A struct representing an entry in the `SUMMARY.md`, possibly with nested
|
/// A struct representing an entry in the `SUMMARY.md`, possibly with nested
|
||||||
/// entries.
|
/// entries.
|
||||||
///
|
///
|
||||||
|
@ -73,7 +158,7 @@ pub struct Summary {
|
||||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
pub struct Link {
|
pub struct Link {
|
||||||
/// The name of the chapter.
|
/// The name of the chapter.
|
||||||
pub name: String,
|
pub name: Option<String>,
|
||||||
/// The location of the chapter's source file, taking the book's `src`
|
/// The location of the chapter's source file, taking the book's `src`
|
||||||
/// directory as the root.
|
/// directory as the root.
|
||||||
pub location: Option<PathBuf>,
|
pub location: Option<PathBuf>,
|
||||||
|
@ -87,7 +172,17 @@ impl Link {
|
||||||
/// Create a new link with no nested items.
|
/// Create a new link with no nested items.
|
||||||
pub fn new<S: Into<String>, P: AsRef<Path>>(name: S, location: P) -> Link {
|
pub fn new<S: Into<String>, P: AsRef<Path>>(name: S, location: P) -> Link {
|
||||||
Link {
|
Link {
|
||||||
name: name.into(),
|
name: Some(name.into()),
|
||||||
|
location: Some(location.as_ref().to_path_buf()),
|
||||||
|
number: None,
|
||||||
|
nested_items: Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a new unnamed link with no nested items.
|
||||||
|
pub fn new_unnamed<P: AsRef<Path>>(location: P) -> Link {
|
||||||
|
Link {
|
||||||
|
name: None,
|
||||||
location: Some(location.as_ref().to_path_buf()),
|
location: Some(location.as_ref().to_path_buf()),
|
||||||
number: None,
|
number: None,
|
||||||
nested_items: Vec::new(),
|
nested_items: Vec::new(),
|
||||||
|
@ -98,7 +193,7 @@ impl Link {
|
||||||
impl Default for Link {
|
impl Default for Link {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Link {
|
Link {
|
||||||
name: String::new(),
|
name: None,
|
||||||
location: Some(PathBuf::new()),
|
location: Some(PathBuf::new()),
|
||||||
number: None,
|
number: None,
|
||||||
nested_items: Vec::new(),
|
nested_items: Vec::new(),
|
||||||
|
@ -106,6 +201,22 @@ impl Default for Link {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for Link {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match &self.name {
|
||||||
|
Some(name) => write!(f, "\"{}\"", name)?,
|
||||||
|
None => write!(f, "unnamed chapter")?,
|
||||||
|
}
|
||||||
|
|
||||||
|
match &self.location {
|
||||||
|
Some(location) => write!(f, " ({})", location.display())?,
|
||||||
|
None => write!(f, " [draft]")?,
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// An item in `SUMMARY.md` which could be either a separator or a `Link`.
|
/// An item in `SUMMARY.md` which could be either a separator or a `Link`.
|
||||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
pub enum SummaryItem {
|
pub enum SummaryItem {
|
||||||
|
@ -344,7 +455,7 @@ impl<'a> SummaryParser<'a> {
|
||||||
};
|
};
|
||||||
|
|
||||||
Link {
|
Link {
|
||||||
name,
|
name: Some(name),
|
||||||
location: path,
|
location: path,
|
||||||
number: None,
|
number: None,
|
||||||
nested_items: Vec::new(),
|
nested_items: Vec::new(),
|
||||||
|
@ -489,15 +600,7 @@ impl<'a> SummaryParser<'a> {
|
||||||
|
|
||||||
let mut number = parent.clone();
|
let mut number = parent.clone();
|
||||||
number.0.push(num_existing_items as u32 + 1);
|
number.0.push(num_existing_items as u32 + 1);
|
||||||
trace!(
|
trace!("Found chapter: {} {}", number, link);
|
||||||
"Found chapter: {} {} ({})",
|
|
||||||
number,
|
|
||||||
link.name,
|
|
||||||
link.location
|
|
||||||
.as_ref()
|
|
||||||
.map(|p| p.to_str().unwrap_or(""))
|
|
||||||
.unwrap_or("[draft]")
|
|
||||||
);
|
|
||||||
|
|
||||||
link.number = Some(number);
|
link.number = Some(number);
|
||||||
|
|
||||||
|
@ -676,12 +779,12 @@ mod tests {
|
||||||
|
|
||||||
let should_be = vec![
|
let should_be = vec![
|
||||||
SummaryItem::Link(Link {
|
SummaryItem::Link(Link {
|
||||||
name: String::from("First"),
|
name: Some(String::from("First")),
|
||||||
location: Some(PathBuf::from("./first.md")),
|
location: Some(PathBuf::from("./first.md")),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}),
|
}),
|
||||||
SummaryItem::Link(Link {
|
SummaryItem::Link(Link {
|
||||||
name: String::from("Second"),
|
name: Some(String::from("Second")),
|
||||||
location: Some(PathBuf::from("./second.md")),
|
location: Some(PathBuf::from("./second.md")),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}),
|
}),
|
||||||
|
@ -717,7 +820,7 @@ mod tests {
|
||||||
fn parse_a_link() {
|
fn parse_a_link() {
|
||||||
let src = "[First](./first.md)";
|
let src = "[First](./first.md)";
|
||||||
let should_be = Link {
|
let should_be = Link {
|
||||||
name: String::from("First"),
|
name: Some(String::from("First")),
|
||||||
location: Some(PathBuf::from("./first.md")),
|
location: Some(PathBuf::from("./first.md")),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
@ -738,7 +841,7 @@ mod tests {
|
||||||
fn parse_a_numbered_chapter() {
|
fn parse_a_numbered_chapter() {
|
||||||
let src = "- [First](./first.md)\n";
|
let src = "- [First](./first.md)\n";
|
||||||
let link = Link {
|
let link = Link {
|
||||||
name: String::from("First"),
|
name: Some(String::from("First")),
|
||||||
location: Some(PathBuf::from("./first.md")),
|
location: Some(PathBuf::from("./first.md")),
|
||||||
number: Some(SectionNumber(vec![1])),
|
number: Some(SectionNumber(vec![1])),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
@ -759,18 +862,18 @@ mod tests {
|
||||||
|
|
||||||
let should_be = vec![
|
let should_be = vec![
|
||||||
SummaryItem::Link(Link {
|
SummaryItem::Link(Link {
|
||||||
name: String::from("First"),
|
name: Some(String::from("First")),
|
||||||
location: Some(PathBuf::from("./first.md")),
|
location: Some(PathBuf::from("./first.md")),
|
||||||
number: Some(SectionNumber(vec![1])),
|
number: Some(SectionNumber(vec![1])),
|
||||||
nested_items: vec![SummaryItem::Link(Link {
|
nested_items: vec![SummaryItem::Link(Link {
|
||||||
name: String::from("Nested"),
|
name: Some(String::from("Nested")),
|
||||||
location: Some(PathBuf::from("./nested.md")),
|
location: Some(PathBuf::from("./nested.md")),
|
||||||
number: Some(SectionNumber(vec![1, 1])),
|
number: Some(SectionNumber(vec![1, 1])),
|
||||||
nested_items: Vec::new(),
|
nested_items: Vec::new(),
|
||||||
})],
|
})],
|
||||||
}),
|
}),
|
||||||
SummaryItem::Link(Link {
|
SummaryItem::Link(Link {
|
||||||
name: String::from("Second"),
|
name: Some(String::from("Second")),
|
||||||
location: Some(PathBuf::from("./second.md")),
|
location: Some(PathBuf::from("./second.md")),
|
||||||
number: Some(SectionNumber(vec![2])),
|
number: Some(SectionNumber(vec![2])),
|
||||||
nested_items: Vec::new(),
|
nested_items: Vec::new(),
|
||||||
|
@ -791,13 +894,13 @@ mod tests {
|
||||||
|
|
||||||
let should_be = vec![
|
let should_be = vec![
|
||||||
SummaryItem::Link(Link {
|
SummaryItem::Link(Link {
|
||||||
name: String::from("First"),
|
name: Some(String::from("First")),
|
||||||
location: Some(PathBuf::from("./first.md")),
|
location: Some(PathBuf::from("./first.md")),
|
||||||
number: Some(SectionNumber(vec![1])),
|
number: Some(SectionNumber(vec![1])),
|
||||||
nested_items: Vec::new(),
|
nested_items: Vec::new(),
|
||||||
}),
|
}),
|
||||||
SummaryItem::Link(Link {
|
SummaryItem::Link(Link {
|
||||||
name: String::from("Second"),
|
name: Some(String::from("Second")),
|
||||||
location: Some(PathBuf::from("./second.md")),
|
location: Some(PathBuf::from("./second.md")),
|
||||||
number: Some(SectionNumber(vec![2])),
|
number: Some(SectionNumber(vec![2])),
|
||||||
nested_items: Vec::new(),
|
nested_items: Vec::new(),
|
||||||
|
@ -819,24 +922,24 @@ mod tests {
|
||||||
|
|
||||||
let should_be = vec![
|
let should_be = vec![
|
||||||
SummaryItem::Link(Link {
|
SummaryItem::Link(Link {
|
||||||
name: String::from("First"),
|
name: Some(String::from("First")),
|
||||||
location: Some(PathBuf::from("./first.md")),
|
location: Some(PathBuf::from("./first.md")),
|
||||||
number: Some(SectionNumber(vec![1])),
|
number: Some(SectionNumber(vec![1])),
|
||||||
nested_items: Vec::new(),
|
nested_items: Vec::new(),
|
||||||
}),
|
}),
|
||||||
SummaryItem::Link(Link {
|
SummaryItem::Link(Link {
|
||||||
name: String::from("Second"),
|
name: Some(String::from("Second")),
|
||||||
location: Some(PathBuf::from("./second.md")),
|
location: Some(PathBuf::from("./second.md")),
|
||||||
number: Some(SectionNumber(vec![2])),
|
number: Some(SectionNumber(vec![2])),
|
||||||
nested_items: Vec::new(),
|
nested_items: Vec::new(),
|
||||||
}),
|
}),
|
||||||
SummaryItem::PartTitle(String::from("Title 2")),
|
SummaryItem::PartTitle(String::from("Title 2")),
|
||||||
SummaryItem::Link(Link {
|
SummaryItem::Link(Link {
|
||||||
name: String::from("Third"),
|
name: Some(String::from("Third")),
|
||||||
location: Some(PathBuf::from("./third.md")),
|
location: Some(PathBuf::from("./third.md")),
|
||||||
number: Some(SectionNumber(vec![3])),
|
number: Some(SectionNumber(vec![3])),
|
||||||
nested_items: vec![SummaryItem::Link(Link {
|
nested_items: vec![SummaryItem::Link(Link {
|
||||||
name: String::from("Fourth"),
|
name: Some(String::from("Fourth")),
|
||||||
location: Some(PathBuf::from("./fourth.md")),
|
location: Some(PathBuf::from("./fourth.md")),
|
||||||
number: Some(SectionNumber(vec![3, 1])),
|
number: Some(SectionNumber(vec![3, 1])),
|
||||||
nested_items: Vec::new(),
|
nested_items: Vec::new(),
|
||||||
|
@ -859,13 +962,13 @@ mod tests {
|
||||||
let src = "- [First](./first.md)\n\n## Subheading\n\n- [Second](./second.md)\n";
|
let src = "- [First](./first.md)\n\n## Subheading\n\n- [Second](./second.md)\n";
|
||||||
let should_be = vec![
|
let should_be = vec![
|
||||||
SummaryItem::Link(Link {
|
SummaryItem::Link(Link {
|
||||||
name: String::from("First"),
|
name: Some(String::from("First")),
|
||||||
location: Some(PathBuf::from("./first.md")),
|
location: Some(PathBuf::from("./first.md")),
|
||||||
number: Some(SectionNumber(vec![1])),
|
number: Some(SectionNumber(vec![1])),
|
||||||
nested_items: Vec::new(),
|
nested_items: Vec::new(),
|
||||||
}),
|
}),
|
||||||
SummaryItem::Link(Link {
|
SummaryItem::Link(Link {
|
||||||
name: String::from("Second"),
|
name: Some(String::from("Second")),
|
||||||
location: Some(PathBuf::from("./second.md")),
|
location: Some(PathBuf::from("./second.md")),
|
||||||
number: Some(SectionNumber(vec![2])),
|
number: Some(SectionNumber(vec![2])),
|
||||||
nested_items: Vec::new(),
|
nested_items: Vec::new(),
|
||||||
|
@ -887,7 +990,7 @@ mod tests {
|
||||||
|
|
||||||
let got = parser.parse_numbered(&mut 0, &mut SectionNumber::default());
|
let got = parser.parse_numbered(&mut 0, &mut SectionNumber::default());
|
||||||
let should_be = vec![SummaryItem::Link(Link {
|
let should_be = vec![SummaryItem::Link(Link {
|
||||||
name: String::from("Empty"),
|
name: Some(String::from("Empty")),
|
||||||
location: None,
|
location: None,
|
||||||
number: Some(SectionNumber(vec![1])),
|
number: Some(SectionNumber(vec![1])),
|
||||||
nested_items: Vec::new(),
|
nested_items: Vec::new(),
|
||||||
|
@ -905,21 +1008,21 @@ mod tests {
|
||||||
"- [First](./first.md)\n---\n- [Second](./second.md)\n---\n- [Third](./third.md)\n";
|
"- [First](./first.md)\n---\n- [Second](./second.md)\n---\n- [Third](./third.md)\n";
|
||||||
let should_be = vec![
|
let should_be = vec![
|
||||||
SummaryItem::Link(Link {
|
SummaryItem::Link(Link {
|
||||||
name: String::from("First"),
|
name: Some(String::from("First")),
|
||||||
location: Some(PathBuf::from("./first.md")),
|
location: Some(PathBuf::from("./first.md")),
|
||||||
number: Some(SectionNumber(vec![1])),
|
number: Some(SectionNumber(vec![1])),
|
||||||
nested_items: Vec::new(),
|
nested_items: Vec::new(),
|
||||||
}),
|
}),
|
||||||
SummaryItem::Separator,
|
SummaryItem::Separator,
|
||||||
SummaryItem::Link(Link {
|
SummaryItem::Link(Link {
|
||||||
name: String::from("Second"),
|
name: Some(String::from("Second")),
|
||||||
location: Some(PathBuf::from("./second.md")),
|
location: Some(PathBuf::from("./second.md")),
|
||||||
number: Some(SectionNumber(vec![2])),
|
number: Some(SectionNumber(vec![2])),
|
||||||
nested_items: Vec::new(),
|
nested_items: Vec::new(),
|
||||||
}),
|
}),
|
||||||
SummaryItem::Separator,
|
SummaryItem::Separator,
|
||||||
SummaryItem::Link(Link {
|
SummaryItem::Link(Link {
|
||||||
name: String::from("Third"),
|
name: Some(String::from("Third")),
|
||||||
location: Some(PathBuf::from("./third.md")),
|
location: Some(PathBuf::from("./third.md")),
|
||||||
number: Some(SectionNumber(vec![3])),
|
number: Some(SectionNumber(vec![3])),
|
||||||
nested_items: Vec::new(),
|
nested_items: Vec::new(),
|
||||||
|
@ -940,7 +1043,7 @@ mod tests {
|
||||||
fn add_space_for_multi_line_chapter_names() {
|
fn add_space_for_multi_line_chapter_names() {
|
||||||
let src = "- [Chapter\ntitle](./chapter.md)";
|
let src = "- [Chapter\ntitle](./chapter.md)";
|
||||||
let should_be = vec![SummaryItem::Link(Link {
|
let should_be = vec![SummaryItem::Link(Link {
|
||||||
name: String::from("Chapter title"),
|
name: Some(String::from("Chapter title")),
|
||||||
location: Some(PathBuf::from("./chapter.md")),
|
location: Some(PathBuf::from("./chapter.md")),
|
||||||
number: Some(SectionNumber(vec![1])),
|
number: Some(SectionNumber(vec![1])),
|
||||||
nested_items: Vec::new(),
|
nested_items: Vec::new(),
|
||||||
|
@ -959,13 +1062,13 @@ mod tests {
|
||||||
let src = "- [test1](./test%20link1.md)\n- [test2](<./test link2.md>)";
|
let src = "- [test1](./test%20link1.md)\n- [test2](<./test link2.md>)";
|
||||||
let should_be = vec![
|
let should_be = vec![
|
||||||
SummaryItem::Link(Link {
|
SummaryItem::Link(Link {
|
||||||
name: String::from("test1"),
|
name: Some(String::from("test1")),
|
||||||
location: Some(PathBuf::from("./test link1.md")),
|
location: Some(PathBuf::from("./test link1.md")),
|
||||||
number: Some(SectionNumber(vec![1])),
|
number: Some(SectionNumber(vec![1])),
|
||||||
nested_items: Vec::new(),
|
nested_items: Vec::new(),
|
||||||
}),
|
}),
|
||||||
SummaryItem::Link(Link {
|
SummaryItem::Link(Link {
|
||||||
name: String::from("test2"),
|
name: Some(String::from("test2")),
|
||||||
location: Some(PathBuf::from("./test link2.md")),
|
location: Some(PathBuf::from("./test link2.md")),
|
||||||
number: Some(SectionNumber(vec![2])),
|
number: Some(SectionNumber(vec![2])),
|
||||||
nested_items: Vec::new(),
|
nested_items: Vec::new(),
|
||||||
|
@ -1030,7 +1133,7 @@ mod tests {
|
||||||
|
|
||||||
let new_affix_item = |name, location| {
|
let new_affix_item = |name, location| {
|
||||||
SummaryItem::Link(Link {
|
SummaryItem::Link(Link {
|
||||||
name: String::from(name),
|
name: Some(String::from(name)),
|
||||||
location: Some(PathBuf::from(location)),
|
location: Some(PathBuf::from(location)),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
})
|
||||||
|
@ -1048,7 +1151,7 @@ mod tests {
|
||||||
|
|
||||||
let new_numbered_item = |name, location, numbers: &[u32], nested_items| {
|
let new_numbered_item = |name, location, numbers: &[u32], nested_items| {
|
||||||
SummaryItem::Link(Link {
|
SummaryItem::Link(Link {
|
||||||
name: String::from(name),
|
name: Some(String::from(name)),
|
||||||
location: Some(PathBuf::from(location)),
|
location: Some(PathBuf::from(location)),
|
||||||
number: Some(SectionNumber(numbers.to_vec())),
|
number: Some(SectionNumber(numbers.to_vec())),
|
||||||
nested_items,
|
nested_items,
|
||||||
|
|
|
@ -17,12 +17,16 @@ pub fn make_subcommand<'a, 'b>() -> App<'a, 'b> {
|
||||||
(Defaults to the Current Directory when omitted)'",
|
(Defaults to the Current Directory when omitted)'",
|
||||||
)
|
)
|
||||||
.arg_from_usage("-o, --open 'Opens the compiled book in a web browser'")
|
.arg_from_usage("-o, --open 'Opens the compiled book in a web browser'")
|
||||||
|
.arg_from_usage(
|
||||||
|
"--auto-summary 'Automatically generate the book's summary{n}\
|
||||||
|
from the sources directory structure.'",
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build command implementation
|
// Build command implementation
|
||||||
pub fn execute(args: &ArgMatches) -> Result<()> {
|
pub fn execute(args: &ArgMatches) -> Result<()> {
|
||||||
let book_dir = get_book_dir(args);
|
let book_dir = get_book_dir(args);
|
||||||
let mut book = MDBook::load(&book_dir)?;
|
let mut book = MDBook::load(&book_dir, args.is_present("auto-summary"))?;
|
||||||
|
|
||||||
if let Some(dest_dir) = args.value_of("dest-dir") {
|
if let Some(dest_dir) = args.value_of("dest-dir") {
|
||||||
book.config.build.build_dir = dest_dir.into();
|
book.config.build.build_dir = dest_dir.into();
|
||||||
|
|
|
@ -18,12 +18,16 @@ pub fn make_subcommand<'a, 'b>() -> App<'a, 'b> {
|
||||||
"[dir] 'Root directory for the book{n}\
|
"[dir] 'Root directory for the book{n}\
|
||||||
(Defaults to the Current Directory when omitted)'",
|
(Defaults to the Current Directory when omitted)'",
|
||||||
)
|
)
|
||||||
|
.arg_from_usage(
|
||||||
|
"--auto-summary 'Automatically generate the book's summary{n}\
|
||||||
|
from the sources directory structure.'",
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clean command implementation
|
// Clean command implementation
|
||||||
pub fn execute(args: &ArgMatches) -> mdbook::errors::Result<()> {
|
pub fn execute(args: &ArgMatches) -> mdbook::errors::Result<()> {
|
||||||
let book_dir = get_book_dir(args);
|
let book_dir = get_book_dir(args);
|
||||||
let book = MDBook::load(&book_dir)?;
|
let book = MDBook::load(&book_dir, args.is_present("auto-summary"))?;
|
||||||
|
|
||||||
let dir_to_remove = match args.value_of("dest-dir") {
|
let dir_to_remove = match args.value_of("dest-dir") {
|
||||||
Some(dest_dir) => dest_dir.into(),
|
Some(dest_dir) => dest_dir.into(),
|
||||||
|
|
|
@ -49,12 +49,16 @@ pub fn make_subcommand<'a, 'b>() -> App<'a, 'b> {
|
||||||
.help("Port to use for HTTP connections"),
|
.help("Port to use for HTTP connections"),
|
||||||
)
|
)
|
||||||
.arg_from_usage("-o, --open 'Opens the book server in a web browser'")
|
.arg_from_usage("-o, --open 'Opens the book server in a web browser'")
|
||||||
|
.arg_from_usage(
|
||||||
|
"--auto-summary 'Automatically generate the book's summary{n}\
|
||||||
|
from the sources directory structure.'",
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Serve command implementation
|
// Serve command implementation
|
||||||
pub fn execute(args: &ArgMatches) -> Result<()> {
|
pub fn execute(args: &ArgMatches) -> Result<()> {
|
||||||
let book_dir = get_book_dir(args);
|
let book_dir = get_book_dir(args);
|
||||||
let mut book = MDBook::load(&book_dir)?;
|
let mut book = MDBook::load(&book_dir, args.is_present("auto-summary"))?;
|
||||||
|
|
||||||
let port = args.value_of("port").unwrap();
|
let port = args.value_of("port").unwrap();
|
||||||
let hostname = args.value_of("hostname").unwrap();
|
let hostname = args.value_of("hostname").unwrap();
|
||||||
|
@ -110,7 +114,7 @@ pub fn execute(args: &ArgMatches) -> Result<()> {
|
||||||
info!("Building book...");
|
info!("Building book...");
|
||||||
|
|
||||||
// FIXME: This area is really ugly because we need to re-set livereload :(
|
// FIXME: This area is really ugly because we need to re-set livereload :(
|
||||||
let result = MDBook::load(&book_dir).and_then(|mut b| {
|
let result = MDBook::load(&book_dir, args.is_present("auto-summary")).and_then(|mut b| {
|
||||||
update_config(&mut b);
|
update_config(&mut b);
|
||||||
b.build()
|
b.build()
|
||||||
});
|
});
|
||||||
|
|
|
@ -25,6 +25,10 @@ pub fn make_subcommand<'a, 'b>() -> App<'a, 'b> {
|
||||||
.multiple(true)
|
.multiple(true)
|
||||||
.empty_values(false)
|
.empty_values(false)
|
||||||
.help("A comma-separated list of directories to add to {n}the crate search path when building tests"))
|
.help("A comma-separated list of directories to add to {n}the crate search path when building tests"))
|
||||||
|
.arg_from_usage(
|
||||||
|
"--auto-summary 'Automatically generate the book's summary{n}\
|
||||||
|
from the sources directory structure.'"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// test command implementation
|
// test command implementation
|
||||||
|
@ -34,7 +38,7 @@ pub fn execute(args: &ArgMatches) -> Result<()> {
|
||||||
.map(std::iter::Iterator::collect)
|
.map(std::iter::Iterator::collect)
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
let book_dir = get_book_dir(args);
|
let book_dir = get_book_dir(args);
|
||||||
let mut book = MDBook::load(&book_dir)?;
|
let mut book = MDBook::load(&book_dir, args.is_present("auto-summary"))?;
|
||||||
|
|
||||||
if let Some(dest_dir) = args.value_of("dest-dir") {
|
if let Some(dest_dir) = args.value_of("dest-dir") {
|
||||||
book.config.build.build_dir = dest_dir.into();
|
book.config.build.build_dir = dest_dir.into();
|
||||||
|
|
|
@ -23,12 +23,16 @@ pub fn make_subcommand<'a, 'b>() -> App<'a, 'b> {
|
||||||
(Defaults to the Current Directory when omitted)'",
|
(Defaults to the Current Directory when omitted)'",
|
||||||
)
|
)
|
||||||
.arg_from_usage("-o, --open 'Open the compiled book in a web browser'")
|
.arg_from_usage("-o, --open 'Open the compiled book in a web browser'")
|
||||||
|
.arg_from_usage(
|
||||||
|
"--auto-summary 'Automatically generate the book's summary{n}\
|
||||||
|
from the sources directory structure.'",
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Watch command implementation
|
// Watch command implementation
|
||||||
pub fn execute(args: &ArgMatches) -> Result<()> {
|
pub fn execute(args: &ArgMatches) -> Result<()> {
|
||||||
let book_dir = get_book_dir(args);
|
let book_dir = get_book_dir(args);
|
||||||
let mut book = MDBook::load(&book_dir)?;
|
let mut book = MDBook::load(&book_dir, args.is_present("auto-summary"))?;
|
||||||
|
|
||||||
let update_config = |book: &mut MDBook| {
|
let update_config = |book: &mut MDBook| {
|
||||||
if let Some(dest_dir) = args.value_of("dest-dir") {
|
if let Some(dest_dir) = args.value_of("dest-dir") {
|
||||||
|
@ -44,7 +48,7 @@ pub fn execute(args: &ArgMatches) -> Result<()> {
|
||||||
|
|
||||||
trigger_on_change(&book, |paths, book_dir| {
|
trigger_on_change(&book, |paths, book_dir| {
|
||||||
info!("Files changed: {:?}\nBuilding book...\n", paths);
|
info!("Files changed: {:?}\nBuilding book...\n", paths);
|
||||||
let result = MDBook::load(&book_dir).and_then(|mut b| {
|
let result = MDBook::load(&book_dir, args.is_present("auto-summary")).and_then(|mut b| {
|
||||||
update_config(&mut b);
|
update_config(&mut b);
|
||||||
b.build()
|
b.build()
|
||||||
});
|
});
|
||||||
|
|
|
@ -444,6 +444,8 @@ pub struct BuildConfig {
|
||||||
/// Should the default preprocessors always be used when they are
|
/// Should the default preprocessors always be used when they are
|
||||||
/// compatible with the renderer?
|
/// compatible with the renderer?
|
||||||
pub use_default_preprocessors: bool,
|
pub use_default_preprocessors: bool,
|
||||||
|
/// Automatically build the book's summary from the directory structure.
|
||||||
|
pub auto_summary: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for BuildConfig {
|
impl Default for BuildConfig {
|
||||||
|
@ -452,6 +454,7 @@ impl Default for BuildConfig {
|
||||||
build_dir: PathBuf::from("book"),
|
build_dir: PathBuf::from("book"),
|
||||||
create_missing: true,
|
create_missing: true,
|
||||||
use_default_preprocessors: true,
|
use_default_preprocessors: true,
|
||||||
|
auto_summary: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -769,6 +772,7 @@ mod tests {
|
||||||
build_dir: PathBuf::from("outputs"),
|
build_dir: PathBuf::from("outputs"),
|
||||||
create_missing: false,
|
create_missing: false,
|
||||||
use_default_preprocessors: true,
|
use_default_preprocessors: true,
|
||||||
|
auto_summary: false,
|
||||||
};
|
};
|
||||||
let rust_should_be = RustConfig { edition: None };
|
let rust_should_be = RustConfig { edition: None };
|
||||||
let playground_should_be = Playground {
|
let playground_should_be = Playground {
|
||||||
|
@ -962,6 +966,7 @@ mod tests {
|
||||||
build_dir: PathBuf::from("my-book"),
|
build_dir: PathBuf::from("my-book"),
|
||||||
create_missing: true,
|
create_missing: true,
|
||||||
use_default_preprocessors: true,
|
use_default_preprocessors: true,
|
||||||
|
auto_summary: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
let html_should_be = HtmlConfig {
|
let html_should_be = HtmlConfig {
|
||||||
|
|
|
@ -52,7 +52,7 @@
|
||||||
//!
|
//!
|
||||||
//! let root_dir = "/path/to/book/root";
|
//! let root_dir = "/path/to/book/root";
|
||||||
//!
|
//!
|
||||||
//! let mut md = MDBook::load(root_dir)
|
//! let mut md = MDBook::load(root_dir, false)
|
||||||
//! .expect("Unable to load the book");
|
//! .expect("Unable to load the book");
|
||||||
//! md.build().expect("Building failed");
|
//! md.build().expect("Building failed");
|
||||||
//! ```
|
//! ```
|
||||||
|
|
|
@ -183,7 +183,7 @@ mod tests {
|
||||||
|
|
||||||
fn guide() -> MDBook {
|
fn guide() -> MDBook {
|
||||||
let example = Path::new(env!("CARGO_MANIFEST_DIR")).join("guide");
|
let example = Path::new(env!("CARGO_MANIFEST_DIR")).join("guide");
|
||||||
MDBook::load(example).unwrap()
|
MDBook::load(example, false).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -33,7 +33,7 @@ fn example_doesnt_support_not_supported() {
|
||||||
fn ask_the_preprocessor_to_blow_up() {
|
fn ask_the_preprocessor_to_blow_up() {
|
||||||
let dummy_book = DummyBook::new();
|
let dummy_book = DummyBook::new();
|
||||||
let temp = dummy_book.build().unwrap();
|
let temp = dummy_book.build().unwrap();
|
||||||
let mut md = MDBook::load(temp.path()).unwrap();
|
let mut md = MDBook::load(temp.path(), false).unwrap();
|
||||||
md.with_preprocessor(example());
|
md.with_preprocessor(example());
|
||||||
|
|
||||||
md.config
|
md.config
|
||||||
|
@ -49,7 +49,7 @@ fn ask_the_preprocessor_to_blow_up() {
|
||||||
fn process_the_dummy_book() {
|
fn process_the_dummy_book() {
|
||||||
let dummy_book = DummyBook::new();
|
let dummy_book = DummyBook::new();
|
||||||
let temp = dummy_book.build().unwrap();
|
let temp = dummy_book.build().unwrap();
|
||||||
let mut md = MDBook::load(temp.path()).unwrap();
|
let mut md = MDBook::load(temp.path(), false).unwrap();
|
||||||
md.with_preprocessor(example());
|
md.with_preprocessor(example());
|
||||||
|
|
||||||
md.build().unwrap();
|
md.build().unwrap();
|
||||||
|
|
|
@ -95,7 +95,7 @@ fn run_mdbook_init_with_custom_book_and_src_locations() {
|
||||||
let contents = fs::read_to_string(temp.path().join("book.toml")).unwrap();
|
let contents = fs::read_to_string(temp.path().join("book.toml")).unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
contents,
|
contents,
|
||||||
"[book]\nauthors = []\nlanguage = \"en\"\nmultilingual = false\nsrc = \"in\"\n\n[build]\nbuild-dir = \"out\"\ncreate-missing = true\nuse-default-preprocessors = true\n"
|
"[book]\nauthors = []\nlanguage = \"en\"\nmultilingual = false\nsrc = \"in\"\n\n[build]\nauto-summary = false\nbuild-dir = \"out\"\ncreate-missing = true\nuse-default-preprocessors = true\n"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ const TOC_SECOND_LEVEL: &[&str] = &[
|
||||||
#[test]
|
#[test]
|
||||||
fn build_the_dummy_book() {
|
fn build_the_dummy_book() {
|
||||||
let temp = DummyBook::new().build().unwrap();
|
let temp = DummyBook::new().build().unwrap();
|
||||||
let md = MDBook::load(temp.path()).unwrap();
|
let md = MDBook::load(temp.path(), false).unwrap();
|
||||||
|
|
||||||
md.build().unwrap();
|
md.build().unwrap();
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ fn build_the_dummy_book() {
|
||||||
#[test]
|
#[test]
|
||||||
fn by_default_mdbook_generates_rendered_content_in_the_book_directory() {
|
fn by_default_mdbook_generates_rendered_content_in_the_book_directory() {
|
||||||
let temp = DummyBook::new().build().unwrap();
|
let temp = DummyBook::new().build().unwrap();
|
||||||
let md = MDBook::load(temp.path()).unwrap();
|
let md = MDBook::load(temp.path(), false).unwrap();
|
||||||
|
|
||||||
assert!(!temp.path().join("book").exists());
|
assert!(!temp.path().join("book").exists());
|
||||||
md.build().unwrap();
|
md.build().unwrap();
|
||||||
|
@ -63,7 +63,7 @@ fn by_default_mdbook_generates_rendered_content_in_the_book_directory() {
|
||||||
#[test]
|
#[test]
|
||||||
fn make_sure_bottom_level_files_contain_links_to_chapters() {
|
fn make_sure_bottom_level_files_contain_links_to_chapters() {
|
||||||
let temp = DummyBook::new().build().unwrap();
|
let temp = DummyBook::new().build().unwrap();
|
||||||
let md = MDBook::load(temp.path()).unwrap();
|
let md = MDBook::load(temp.path(), false).unwrap();
|
||||||
md.build().unwrap();
|
md.build().unwrap();
|
||||||
|
|
||||||
let dest = temp.path().join("book");
|
let dest = temp.path().join("book");
|
||||||
|
@ -85,7 +85,7 @@ fn make_sure_bottom_level_files_contain_links_to_chapters() {
|
||||||
#[test]
|
#[test]
|
||||||
fn check_correct_cross_links_in_nested_dir() {
|
fn check_correct_cross_links_in_nested_dir() {
|
||||||
let temp = DummyBook::new().build().unwrap();
|
let temp = DummyBook::new().build().unwrap();
|
||||||
let md = MDBook::load(temp.path()).unwrap();
|
let md = MDBook::load(temp.path(), false).unwrap();
|
||||||
md.build().unwrap();
|
md.build().unwrap();
|
||||||
|
|
||||||
let first = temp.path().join("book").join("first");
|
let first = temp.path().join("book").join("first");
|
||||||
|
@ -117,7 +117,7 @@ fn check_correct_cross_links_in_nested_dir() {
|
||||||
#[test]
|
#[test]
|
||||||
fn check_correct_relative_links_in_print_page() {
|
fn check_correct_relative_links_in_print_page() {
|
||||||
let temp = DummyBook::new().build().unwrap();
|
let temp = DummyBook::new().build().unwrap();
|
||||||
let md = MDBook::load(temp.path()).unwrap();
|
let md = MDBook::load(temp.path(), false).unwrap();
|
||||||
md.build().unwrap();
|
md.build().unwrap();
|
||||||
|
|
||||||
let first = temp.path().join("book");
|
let first = temp.path().join("book");
|
||||||
|
@ -138,7 +138,7 @@ fn check_correct_relative_links_in_print_page() {
|
||||||
#[test]
|
#[test]
|
||||||
fn rendered_code_has_playground_stuff() {
|
fn rendered_code_has_playground_stuff() {
|
||||||
let temp = DummyBook::new().build().unwrap();
|
let temp = DummyBook::new().build().unwrap();
|
||||||
let md = MDBook::load(temp.path()).unwrap();
|
let md = MDBook::load(temp.path(), false).unwrap();
|
||||||
md.build().unwrap();
|
md.build().unwrap();
|
||||||
|
|
||||||
let nested = temp.path().join("book/first/nested.html");
|
let nested = temp.path().join("book/first/nested.html");
|
||||||
|
@ -153,7 +153,7 @@ fn rendered_code_has_playground_stuff() {
|
||||||
#[test]
|
#[test]
|
||||||
fn anchors_include_text_between_but_not_anchor_comments() {
|
fn anchors_include_text_between_but_not_anchor_comments() {
|
||||||
let temp = DummyBook::new().build().unwrap();
|
let temp = DummyBook::new().build().unwrap();
|
||||||
let md = MDBook::load(temp.path()).unwrap();
|
let md = MDBook::load(temp.path(), false).unwrap();
|
||||||
md.build().unwrap();
|
md.build().unwrap();
|
||||||
|
|
||||||
let nested = temp.path().join("book/first/nested.html");
|
let nested = temp.path().join("book/first/nested.html");
|
||||||
|
@ -167,7 +167,7 @@ fn anchors_include_text_between_but_not_anchor_comments() {
|
||||||
#[test]
|
#[test]
|
||||||
fn rustdoc_include_hides_the_unspecified_part_of_the_file() {
|
fn rustdoc_include_hides_the_unspecified_part_of_the_file() {
|
||||||
let temp = DummyBook::new().build().unwrap();
|
let temp = DummyBook::new().build().unwrap();
|
||||||
let md = MDBook::load(temp.path()).unwrap();
|
let md = MDBook::load(temp.path(), false).unwrap();
|
||||||
md.build().unwrap();
|
md.build().unwrap();
|
||||||
|
|
||||||
let nested = temp.path().join("book/first/nested.html");
|
let nested = temp.path().join("book/first/nested.html");
|
||||||
|
@ -191,7 +191,7 @@ fn chapter_content_appears_in_rendered_document() {
|
||||||
];
|
];
|
||||||
|
|
||||||
let temp = DummyBook::new().build().unwrap();
|
let temp = DummyBook::new().build().unwrap();
|
||||||
let md = MDBook::load(temp.path()).unwrap();
|
let md = MDBook::load(temp.path(), false).unwrap();
|
||||||
md.build().unwrap();
|
md.build().unwrap();
|
||||||
|
|
||||||
let destination = temp.path().join("book");
|
let destination = temp.path().join("book");
|
||||||
|
@ -251,7 +251,7 @@ fn root_index_html() -> Result<Document> {
|
||||||
let temp = DummyBook::new()
|
let temp = DummyBook::new()
|
||||||
.build()
|
.build()
|
||||||
.with_context(|| "Couldn't create the dummy book")?;
|
.with_context(|| "Couldn't create the dummy book")?;
|
||||||
MDBook::load(temp.path())?
|
MDBook::load(temp.path(), false)?
|
||||||
.build()
|
.build()
|
||||||
.with_context(|| "Book building failed")?;
|
.with_context(|| "Book building failed")?;
|
||||||
|
|
||||||
|
@ -350,7 +350,7 @@ fn create_missing_file_with_config() {
|
||||||
#[test]
|
#[test]
|
||||||
fn able_to_include_playground_files_in_chapters() {
|
fn able_to_include_playground_files_in_chapters() {
|
||||||
let temp = DummyBook::new().build().unwrap();
|
let temp = DummyBook::new().build().unwrap();
|
||||||
let md = MDBook::load(temp.path()).unwrap();
|
let md = MDBook::load(temp.path(), false).unwrap();
|
||||||
md.build().unwrap();
|
md.build().unwrap();
|
||||||
|
|
||||||
let second = temp.path().join("book/second.html");
|
let second = temp.path().join("book/second.html");
|
||||||
|
@ -368,7 +368,7 @@ fn able_to_include_playground_files_in_chapters() {
|
||||||
#[test]
|
#[test]
|
||||||
fn able_to_include_files_in_chapters() {
|
fn able_to_include_files_in_chapters() {
|
||||||
let temp = DummyBook::new().build().unwrap();
|
let temp = DummyBook::new().build().unwrap();
|
||||||
let md = MDBook::load(temp.path()).unwrap();
|
let md = MDBook::load(temp.path(), false).unwrap();
|
||||||
md.build().unwrap();
|
md.build().unwrap();
|
||||||
|
|
||||||
let includes = temp.path().join("book/first/includes.html");
|
let includes = temp.path().join("book/first/includes.html");
|
||||||
|
@ -386,7 +386,7 @@ fn able_to_include_files_in_chapters() {
|
||||||
#[test]
|
#[test]
|
||||||
fn recursive_includes_are_capped() {
|
fn recursive_includes_are_capped() {
|
||||||
let temp = DummyBook::new().build().unwrap();
|
let temp = DummyBook::new().build().unwrap();
|
||||||
let md = MDBook::load(temp.path()).unwrap();
|
let md = MDBook::load(temp.path(), false).unwrap();
|
||||||
md.build().unwrap();
|
md.build().unwrap();
|
||||||
|
|
||||||
let recursive = temp.path().join("book/first/recursive.html");
|
let recursive = temp.path().join("book/first/recursive.html");
|
||||||
|
@ -400,7 +400,7 @@ Around the world, around the world"];
|
||||||
fn example_book_can_build() {
|
fn example_book_can_build() {
|
||||||
let example_book_dir = dummy_book::new_copy_of_example_book().unwrap();
|
let example_book_dir = dummy_book::new_copy_of_example_book().unwrap();
|
||||||
|
|
||||||
let md = MDBook::load(example_book_dir.path()).unwrap();
|
let md = MDBook::load(example_book_dir.path(), false).unwrap();
|
||||||
|
|
||||||
md.build().unwrap();
|
md.build().unwrap();
|
||||||
}
|
}
|
||||||
|
@ -418,7 +418,7 @@ fn book_with_a_reserved_filename_does_not_build() {
|
||||||
let mut summary_file = fs::File::create(summary_path).unwrap();
|
let mut summary_file = fs::File::create(summary_path).unwrap();
|
||||||
writeln!(summary_file, "[print](print.md)").unwrap();
|
writeln!(summary_file, "[print](print.md)").unwrap();
|
||||||
|
|
||||||
let md = MDBook::load(tmp_dir.path()).unwrap();
|
let md = MDBook::load(tmp_dir.path(), false).unwrap();
|
||||||
let got = md.build();
|
let got = md.build();
|
||||||
assert!(got.is_err());
|
assert!(got.is_err());
|
||||||
}
|
}
|
||||||
|
@ -457,7 +457,7 @@ fn theme_dir_overrides_work_correctly() {
|
||||||
|
|
||||||
write_file(&theme_dir, "index.hbs", &index).unwrap();
|
write_file(&theme_dir, "index.hbs", &index).unwrap();
|
||||||
|
|
||||||
let md = MDBook::load(book_dir).unwrap();
|
let md = MDBook::load(book_dir, false).unwrap();
|
||||||
md.build().unwrap();
|
md.build().unwrap();
|
||||||
|
|
||||||
let built_index = book_dir.join("book").join("index.html");
|
let built_index = book_dir.join("book").join("index.html");
|
||||||
|
@ -467,7 +467,7 @@ fn theme_dir_overrides_work_correctly() {
|
||||||
#[test]
|
#[test]
|
||||||
fn no_index_for_print_html() {
|
fn no_index_for_print_html() {
|
||||||
let temp = DummyBook::new().build().unwrap();
|
let temp = DummyBook::new().build().unwrap();
|
||||||
let md = MDBook::load(temp.path()).unwrap();
|
let md = MDBook::load(temp.path(), false).unwrap();
|
||||||
md.build().unwrap();
|
md.build().unwrap();
|
||||||
|
|
||||||
let print_html = temp.path().join("book/print.html");
|
let print_html = temp.path().join("book/print.html");
|
||||||
|
@ -480,7 +480,7 @@ fn no_index_for_print_html() {
|
||||||
#[test]
|
#[test]
|
||||||
fn markdown_options() {
|
fn markdown_options() {
|
||||||
let temp = DummyBook::new().build().unwrap();
|
let temp = DummyBook::new().build().unwrap();
|
||||||
let md = MDBook::load(temp.path()).unwrap();
|
let md = MDBook::load(temp.path(), false).unwrap();
|
||||||
md.build().unwrap();
|
md.build().unwrap();
|
||||||
|
|
||||||
let path = temp.path().join("book/first/markdown.html");
|
let path = temp.path().join("book/first/markdown.html");
|
||||||
|
@ -516,7 +516,7 @@ fn markdown_options() {
|
||||||
#[test]
|
#[test]
|
||||||
fn redirects_are_emitted_correctly() {
|
fn redirects_are_emitted_correctly() {
|
||||||
let temp = DummyBook::new().build().unwrap();
|
let temp = DummyBook::new().build().unwrap();
|
||||||
let mut md = MDBook::load(temp.path()).unwrap();
|
let mut md = MDBook::load(temp.path(), false).unwrap();
|
||||||
|
|
||||||
// override the "outputs.html.redirect" table
|
// override the "outputs.html.redirect" table
|
||||||
let redirects: HashMap<PathBuf, String> = vec![
|
let redirects: HashMap<PathBuf, String> = vec![
|
||||||
|
@ -555,7 +555,7 @@ fn edit_url_has_default_src_dir_edit_url() {
|
||||||
|
|
||||||
write_file(temp.path(), "book.toml", book_toml.as_bytes()).unwrap();
|
write_file(temp.path(), "book.toml", book_toml.as_bytes()).unwrap();
|
||||||
|
|
||||||
let md = MDBook::load(temp.path()).unwrap();
|
let md = MDBook::load(temp.path(), false).unwrap();
|
||||||
md.build().unwrap();
|
md.build().unwrap();
|
||||||
|
|
||||||
let index_html = temp.path().join("book").join("index.html");
|
let index_html = temp.path().join("book").join("index.html");
|
||||||
|
@ -581,7 +581,7 @@ fn edit_url_has_configured_src_dir_edit_url() {
|
||||||
|
|
||||||
write_file(temp.path(), "book.toml", book_toml.as_bytes()).unwrap();
|
write_file(temp.path(), "book.toml", book_toml.as_bytes()).unwrap();
|
||||||
|
|
||||||
let md = MDBook::load(temp.path()).unwrap();
|
let md = MDBook::load(temp.path(), false).unwrap();
|
||||||
md.build().unwrap();
|
md.build().unwrap();
|
||||||
|
|
||||||
let index_html = temp.path().join("book").join("index.html");
|
let index_html = temp.path().join("book").join("index.html");
|
||||||
|
@ -619,7 +619,7 @@ mod search {
|
||||||
#[allow(clippy::float_cmp)]
|
#[allow(clippy::float_cmp)]
|
||||||
fn book_creates_reasonable_search_index() {
|
fn book_creates_reasonable_search_index() {
|
||||||
let temp = DummyBook::new().build().unwrap();
|
let temp = DummyBook::new().build().unwrap();
|
||||||
let md = MDBook::load(temp.path()).unwrap();
|
let md = MDBook::load(temp.path(), false).unwrap();
|
||||||
md.build().unwrap();
|
md.build().unwrap();
|
||||||
|
|
||||||
let index = read_book_index(temp.path());
|
let index = read_book_index(temp.path());
|
||||||
|
@ -671,7 +671,7 @@ mod search {
|
||||||
fn get_fixture() -> serde_json::Value {
|
fn get_fixture() -> serde_json::Value {
|
||||||
if GENERATE_FIXTURE {
|
if GENERATE_FIXTURE {
|
||||||
let temp = DummyBook::new().build().unwrap();
|
let temp = DummyBook::new().build().unwrap();
|
||||||
let md = MDBook::load(temp.path()).unwrap();
|
let md = MDBook::load(temp.path(), false).unwrap();
|
||||||
md.build().unwrap();
|
md.build().unwrap();
|
||||||
|
|
||||||
let src = read_book_index(temp.path());
|
let src = read_book_index(temp.path());
|
||||||
|
@ -699,7 +699,7 @@ mod search {
|
||||||
#[test]
|
#[test]
|
||||||
fn search_index_hasnt_changed_accidentally() {
|
fn search_index_hasnt_changed_accidentally() {
|
||||||
let temp = DummyBook::new().build().unwrap();
|
let temp = DummyBook::new().build().unwrap();
|
||||||
let md = MDBook::load(temp.path()).unwrap();
|
let md = MDBook::load(temp.path(), false).unwrap();
|
||||||
md.build().unwrap();
|
md.build().unwrap();
|
||||||
|
|
||||||
let book_index = read_book_index(temp.path());
|
let book_index = read_book_index(temp.path());
|
||||||
|
|
|
@ -7,7 +7,7 @@ use mdbook::MDBook;
|
||||||
#[test]
|
#[test]
|
||||||
fn mdbook_can_correctly_test_a_passing_book() {
|
fn mdbook_can_correctly_test_a_passing_book() {
|
||||||
let temp = DummyBook::new().with_passing_test(true).build().unwrap();
|
let temp = DummyBook::new().with_passing_test(true).build().unwrap();
|
||||||
let mut md = MDBook::load(temp.path()).unwrap();
|
let mut md = MDBook::load(temp.path(), false).unwrap();
|
||||||
|
|
||||||
let result = md.test(vec![]);
|
let result = md.test(vec![]);
|
||||||
assert!(
|
assert!(
|
||||||
|
@ -20,7 +20,7 @@ fn mdbook_can_correctly_test_a_passing_book() {
|
||||||
#[test]
|
#[test]
|
||||||
fn mdbook_detects_book_with_failing_tests() {
|
fn mdbook_detects_book_with_failing_tests() {
|
||||||
let temp = DummyBook::new().with_passing_test(false).build().unwrap();
|
let temp = DummyBook::new().with_passing_test(false).build().unwrap();
|
||||||
let mut md = MDBook::load(temp.path()).unwrap();
|
let mut md = MDBook::load(temp.path(), false).unwrap();
|
||||||
|
|
||||||
assert!(md.test(vec![]).is_err());
|
assert!(md.test(vec![]).is_err());
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue