Made sure the dummy book can build
This commit is contained in:
parent
8b21da9950
commit
21498631b3
|
@ -1,3 +1,4 @@
|
||||||
|
[book]
|
||||||
title = "mdBook Documentation"
|
title = "mdBook Documentation"
|
||||||
description = "Create book from markdown files. Like Gitbook but implemented in Rust"
|
description = "Create book from markdown files. Like Gitbook but implemented in Rust"
|
||||||
author = "Mathieu David"
|
author = "Mathieu David"
|
||||||
|
|
|
@ -3,7 +3,6 @@ use std::io::Write;
|
||||||
use clap::{App, ArgMatches, SubCommand};
|
use clap::{App, ArgMatches, SubCommand};
|
||||||
use mdbook::MDBook;
|
use mdbook::MDBook;
|
||||||
use mdbook::errors::Result;
|
use mdbook::errors::Result;
|
||||||
use mdbook::config::Config;
|
|
||||||
use get_book_dir;
|
use get_book_dir;
|
||||||
|
|
||||||
// Create clap subcommand arguments
|
// Create clap subcommand arguments
|
||||||
|
|
|
@ -2,7 +2,7 @@ use std::fmt::{self, Display, Formatter};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::{Read, Write};
|
use std::io::Read;
|
||||||
|
|
||||||
use super::summary::{parse_summary, Link, SectionNumber, Summary, SummaryItem};
|
use super::summary::{parse_summary, Link, SectionNumber, Summary, SummaryItem};
|
||||||
use errors::*;
|
use errors::*;
|
||||||
|
@ -14,9 +14,8 @@ pub fn load_book<P: AsRef<Path>>(src_dir: P) -> Result<Book> {
|
||||||
let summary_md = src_dir.join("SUMMARY.md");
|
let summary_md = src_dir.join("SUMMARY.md");
|
||||||
|
|
||||||
let mut summary_content = String::new();
|
let mut summary_content = String::new();
|
||||||
File::open(summary_md)
|
File::open(summary_md).chain_err(|| "Couldn't open SUMMARY.md")?
|
||||||
.chain_err(|| "Couldn't open SUMMARY.md")?
|
.read_to_string(&mut summary_content)?;
|
||||||
.read_to_string(&mut summary_content)?;
|
|
||||||
|
|
||||||
let summary = parse_summary(&summary_content).chain_err(|| "Summary parsing failed")?;
|
let summary = parse_summary(&summary_content).chain_err(|| "Summary parsing failed")?;
|
||||||
|
|
||||||
|
@ -111,10 +110,7 @@ fn load_book_from_disk<P: AsRef<Path>>(summary: &Summary, src_dir: P) -> Result<
|
||||||
fn load_summary_item<P: AsRef<Path>>(item: &SummaryItem, src_dir: P) -> Result<BookItem> {
|
fn load_summary_item<P: AsRef<Path>>(item: &SummaryItem, src_dir: P) -> Result<BookItem> {
|
||||||
match *item {
|
match *item {
|
||||||
SummaryItem::Separator => Ok(BookItem::Separator),
|
SummaryItem::Separator => Ok(BookItem::Separator),
|
||||||
SummaryItem::Link(ref link) => {
|
SummaryItem::Link(ref link) => load_chapter(link, src_dir).map(|c| BookItem::Chapter(c)),
|
||||||
let file = src_dir.as_ref().join(&link.location);
|
|
||||||
load_chapter(link, src_dir).map(|c| BookItem::Chapter(c))
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,22 +124,22 @@ fn load_chapter<P: AsRef<Path>>(link: &Link, src_dir: P) -> Result<Chapter> {
|
||||||
src_dir.join(&link.location)
|
src_dir.join(&link.location)
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut f = File::open(&location).chain_err(|| format!("Chapter file not found, {}", link.location.display()))?;
|
let mut f = File::open(&location).chain_err(|| {
|
||||||
|
format!("Chapter file not found, {}", link.location.display())
|
||||||
|
})?;
|
||||||
|
|
||||||
let mut content = String::new();
|
let mut content = String::new();
|
||||||
f.read_to_string(&mut content)?;
|
f.read_to_string(&mut content)?;
|
||||||
|
|
||||||
let stripped = location
|
let stripped = location.strip_prefix(&src_dir)
|
||||||
.strip_prefix(&src_dir)
|
.expect("Chapters are always inside a book");
|
||||||
.expect("Chapters are always inside a book");
|
|
||||||
|
|
||||||
let mut ch = Chapter::new(&link.name, content, stripped);
|
let mut ch = Chapter::new(&link.name, content, stripped);
|
||||||
ch.number = link.number.clone();
|
ch.number = link.number.clone();
|
||||||
|
|
||||||
let sub_items = link.nested_items
|
let sub_items = link.nested_items.iter()
|
||||||
.iter()
|
.map(|i| load_summary_item(i, src_dir))
|
||||||
.map(|i| load_summary_item(i, src_dir))
|
.collect::<Result<Vec<_>>>()?;
|
||||||
.collect::<Result<Vec<_>>>()?;
|
|
||||||
|
|
||||||
ch.sub_items = sub_items;
|
ch.sub_items = sub_items;
|
||||||
|
|
||||||
|
@ -195,14 +191,14 @@ mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use tempdir::TempDir;
|
use tempdir::TempDir;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::fs;
|
|
||||||
|
|
||||||
const DUMMY_SRC: &'static str = "
|
const DUMMY_SRC: &'static str = "
|
||||||
# Dummy Chapter
|
# Dummy Chapter
|
||||||
|
|
||||||
this is some dummy text.
|
this is some dummy text.
|
||||||
|
|
||||||
And here is some more text.
|
And here is some \
|
||||||
|
more text.
|
||||||
";
|
";
|
||||||
|
|
||||||
/// Create a dummy `Link` in a temporary directory.
|
/// Create a dummy `Link` in a temporary directory.
|
||||||
|
@ -210,10 +206,9 @@ And here is some more text.
|
||||||
let temp = TempDir::new("book").unwrap();
|
let temp = TempDir::new("book").unwrap();
|
||||||
|
|
||||||
let chapter_path = temp.path().join("chapter_1.md");
|
let chapter_path = temp.path().join("chapter_1.md");
|
||||||
File::create(&chapter_path)
|
File::create(&chapter_path).unwrap()
|
||||||
.unwrap()
|
.write(DUMMY_SRC.as_bytes())
|
||||||
.write(DUMMY_SRC.as_bytes())
|
.unwrap();
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let link = Link::new("Chapter 1", chapter_path);
|
let link = Link::new("Chapter 1", chapter_path);
|
||||||
|
|
||||||
|
@ -226,10 +221,9 @@ And here is some more text.
|
||||||
|
|
||||||
let second_path = temp_dir.path().join("second.md");
|
let second_path = temp_dir.path().join("second.md");
|
||||||
|
|
||||||
File::create(&second_path)
|
File::create(&second_path).unwrap()
|
||||||
.unwrap()
|
.write_all("Hello World!".as_bytes())
|
||||||
.write_all("Hello World!".as_bytes())
|
.unwrap();
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
|
|
||||||
let mut second = Link::new("Nested Chapter 1", &second_path);
|
let mut second = Link::new("Nested Chapter 1", &second_path);
|
||||||
|
@ -339,9 +333,17 @@ And here is some more text.
|
||||||
number: None,
|
number: None,
|
||||||
path: PathBuf::from("Chapter_1/index.md"),
|
path: PathBuf::from("Chapter_1/index.md"),
|
||||||
sub_items: vec![
|
sub_items: vec![
|
||||||
BookItem::Chapter(Chapter::new("Hello World", String::new(), "Chapter_1/hello.md")),
|
BookItem::Chapter(Chapter::new(
|
||||||
|
"Hello World",
|
||||||
|
String::new(),
|
||||||
|
"Chapter_1/hello.md",
|
||||||
|
)),
|
||||||
BookItem::Separator,
|
BookItem::Separator,
|
||||||
BookItem::Chapter(Chapter::new("Goodbye World", String::new(), "Chapter_1/goodbye.md")),
|
BookItem::Chapter(Chapter::new(
|
||||||
|
"Goodbye World",
|
||||||
|
String::new(),
|
||||||
|
"Chapter_1/goodbye.md",
|
||||||
|
)),
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
BookItem::Separator,
|
BookItem::Separator,
|
||||||
|
@ -354,12 +356,11 @@ And here is some more text.
|
||||||
assert_eq!(got.len(), 5);
|
assert_eq!(got.len(), 5);
|
||||||
|
|
||||||
// checking the chapter names are in the order should be sufficient here...
|
// checking the chapter names are in the order should be sufficient here...
|
||||||
let chapter_names: Vec<String> = got.into_iter()
|
let chapter_names: Vec<String> = got.into_iter().filter_map(|i| match *i {
|
||||||
.filter_map(|i| match *i {
|
BookItem::Chapter(ref ch) => Some(ch.name.clone()),
|
||||||
BookItem::Chapter(ref ch) => Some(ch.name.clone()),
|
_ => None,
|
||||||
_ => None,
|
})
|
||||||
})
|
.collect();
|
||||||
.collect();
|
|
||||||
let should_be: Vec<_> = vec![
|
let should_be: Vec<_> = vec![
|
||||||
String::from("Chapter 1"),
|
String::from("Chapter 1"),
|
||||||
String::from("Hello World"),
|
String::from("Hello World"),
|
||||||
|
|
|
@ -6,12 +6,11 @@ pub use self::book::{Book, BookItem, BookItems, Chapter};
|
||||||
pub use self::init::BookBuilder;
|
pub use self::init::BookBuilder;
|
||||||
|
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::fs::{self, File};
|
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
use tempdir::TempDir;
|
use tempdir::TempDir;
|
||||||
|
|
||||||
use {theme, utils};
|
use utils;
|
||||||
use renderer::{HtmlHandlebars, Renderer};
|
use renderer::{HtmlHandlebars, Renderer};
|
||||||
use preprocess;
|
use preprocess;
|
||||||
use errors::*;
|
use errors::*;
|
||||||
|
@ -104,17 +103,14 @@ impl MDBook {
|
||||||
BookBuilder::new(book_root)
|
BookBuilder::new(book_root)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The `build()` method is the one where everything happens.
|
/// Tells the renderer to build our book and put it in the build directory.
|
||||||
/// First it parses `SUMMARY.md` to construct the book's structure
|
|
||||||
/// in the form of a `Vec<BookItem>` and then calls `render()`
|
|
||||||
/// method of the current renderer.
|
|
||||||
///
|
|
||||||
/// It is the renderer who generates all the output files.
|
|
||||||
pub fn build(&mut self) -> Result<()> {
|
pub fn build(&mut self) -> Result<()> {
|
||||||
debug!("[fn]: build");
|
debug!("[fn]: build");
|
||||||
|
|
||||||
// Clean output directory
|
let dest = self.get_destination();
|
||||||
utils::fs::remove_dir_content(&self.get_destination())?;
|
if dest.exists() {
|
||||||
|
utils::fs::remove_dir_content(&dest).chain_err(|| "Unable to clear output directory")?;
|
||||||
|
}
|
||||||
|
|
||||||
self.renderer.render(self)
|
self.renderer.render(self)
|
||||||
}
|
}
|
||||||
|
@ -122,9 +118,8 @@ impl MDBook {
|
||||||
pub fn write_file<P: AsRef<Path>>(&self, filename: P, content: &[u8]) -> Result<()> {
|
pub fn write_file<P: AsRef<Path>>(&self, filename: P, content: &[u8]) -> Result<()> {
|
||||||
let path = self.get_destination().join(filename);
|
let path = self.get_destination().join(filename);
|
||||||
|
|
||||||
utils::fs::create_file(&path)?
|
utils::fs::create_file(&path)?.write_all(content)
|
||||||
.write_all(content)
|
.map_err(|e| e.into())
|
||||||
.map_err(|e| e.into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses the `book.json` file (if it exists) to extract
|
/// Parses the `book.json` file (if it exists) to extract
|
||||||
|
@ -175,18 +170,16 @@ impl MDBook {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn test(&mut self, library_paths: Vec<&str>) -> Result<()> {
|
pub fn test(&mut self, library_paths: Vec<&str>) -> Result<()> {
|
||||||
let library_args: Vec<&str> = (0..library_paths.len())
|
let library_args: Vec<&str> = (0..library_paths.len()).map(|_| "-L")
|
||||||
.map(|_| "-L")
|
.zip(library_paths.into_iter())
|
||||||
.zip(library_paths.into_iter())
|
.flat_map(|x| vec![x.0, x.1])
|
||||||
.flat_map(|x| vec![x.0, x.1])
|
.collect();
|
||||||
.collect();
|
|
||||||
let temp_dir = TempDir::new("mdbook")?;
|
let temp_dir = TempDir::new("mdbook")?;
|
||||||
for item in self.iter() {
|
for item in self.iter() {
|
||||||
if let BookItem::Chapter(ref ch) = *item {
|
if let BookItem::Chapter(ref ch) = *item {
|
||||||
if !ch.path.as_os_str().is_empty() {
|
if !ch.path.as_os_str().is_empty() {
|
||||||
let path = self.get_source().join(&ch.path);
|
let path = self.get_source().join(&ch.path);
|
||||||
let base = path.parent()
|
let base = path.parent().ok_or_else(|| String::from("Invalid bookitem path!"))?;
|
||||||
.ok_or_else(|| String::from("Invalid bookitem path!"))?;
|
|
||||||
let content = utils::fs::file_to_string(&path)?;
|
let content = utils::fs::file_to_string(&path)?;
|
||||||
// Parse and expand links
|
// Parse and expand links
|
||||||
let content = preprocess::links::replace_all(&content, base)?;
|
let content = preprocess::links::replace_all(&content, base)?;
|
||||||
|
@ -197,11 +190,10 @@ impl MDBook {
|
||||||
let mut tmpf = utils::fs::create_file(&path)?;
|
let mut tmpf = utils::fs::create_file(&path)?;
|
||||||
tmpf.write_all(content.as_bytes())?;
|
tmpf.write_all(content.as_bytes())?;
|
||||||
|
|
||||||
let output = Command::new("rustdoc")
|
let output = Command::new("rustdoc").arg(&path)
|
||||||
.arg(&path)
|
.arg("--test")
|
||||||
.arg("--test")
|
.args(&library_args)
|
||||||
.args(&library_args)
|
.output()?;
|
||||||
.output()?;
|
|
||||||
|
|
||||||
if !output.status.success() {
|
if !output.status.success() {
|
||||||
bail!(ErrorKind::Subprocess(
|
bail!(ErrorKind::Subprocess(
|
||||||
|
|
|
@ -370,8 +370,9 @@ impl<'a> SummaryParser<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
Event::End(Tag::Item) => { /* Ignore */ },
|
||||||
other => {
|
other => {
|
||||||
trace!("[*] skipping unexpected token: {:?}", other);
|
trace!("[*] ignoring token: {:?}", other);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
|
|
||||||
- [First Chapter](./first/index.md)
|
- [First Chapter](./first/index.md)
|
||||||
- [Nested Chapter](./first/nested.md)
|
- [Nested Chapter](./first/nested.md)
|
||||||
---
|
|
||||||
- [Second Chapter](./second.md)
|
- [Second Chapter](./second.md)
|
||||||
|
|
||||||
[Conclusion](./conclusion.md)
|
[Conclusion](./conclusion.md)
|
||||||
|
|
|
@ -18,7 +18,7 @@ fn base_mdbook_init_should_create_default_content() {
|
||||||
assert!(!temp.path().join(file).exists());
|
assert!(!temp.path().join(file).exists());
|
||||||
}
|
}
|
||||||
|
|
||||||
let md = MDBook::init(temp.path()).build().unwrap();
|
MDBook::init(temp.path()).build().unwrap();
|
||||||
|
|
||||||
for file in &created_files {
|
for file in &created_files {
|
||||||
let target = temp.path().join(file);
|
let target = temp.path().join(file);
|
||||||
|
|
Loading…
Reference in New Issue