chapter.content, .src_path, .dest_path

This commit is contained in:
Gambhiro 2017-01-13 17:01:59 +00:00
parent da9c57e6f5
commit 0713d49e7b
9 changed files with 383 additions and 208 deletions

View File

@ -16,6 +16,8 @@ pub struct BookConfig {
// Paths // Paths
// TODO test if dest and src behaves correctly when mdbook.dest_base and mdbook.src_base is not 'book' and 'src'
pub dest: PathBuf, pub dest: PathBuf,
pub src: PathBuf, pub src: PathBuf,
@ -84,9 +86,9 @@ impl BookConfig {
conf conf
} }
/// Parses recognized keys from a BTreeMap one by one. Not trying to /// Parses keys from a BTreeMap one by one. Not trying to directly
/// directly de-serialize to `BookConfig` so that we can provide some /// de-serialize to `BookConfig` so that we can provide some convenient
/// convenient shorthands for the user. /// shorthands for the user.
/// ///
/// `book.toml` is a user interface, not an app data store, we never have to /// `book.toml` is a user interface, not an app data store, we never have to
/// write data back to it. /// write data back to it.

View File

@ -3,6 +3,7 @@ extern crate toml;
use regex::Regex; use regex::Regex;
use std::ffi::OsStr;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::fs::File; use std::fs::File;
use std::error::Error; use std::error::Error;
@ -40,18 +41,30 @@ pub struct Chapter {
/// The title of the chapter. /// The title of the chapter.
pub title: String, pub title: String,
/// The Markdown content of the chapter without the optional TOML header.
pub content: Option<String>,
/// Path to the chapter's markdown file, relative to the book's source /// Path to the chapter's markdown file, relative to the book's source
/// directory. /// directory.
/// ///
/// `book.src.join(chapter.path)` points to the Markdown file, and /// Use `.content` to access the Markdown text when possible, instead of
/// `book.dest.join(chapter.path).with_extension("html")` points to the /// reading the Markdown file with `.src_path`.
/// output html file. This way if the user had a custom folder structure in ///
/// their source folder, this is re-created in the destination folder. /// `book.get_src_base().join(chapter.get_src_path())` should point to the
pub path: PathBuf, /// Markdown file.
///
/// This way if the user had a custom folder structure in their source
/// folder, this is re-created in the destination folder.
///
/// When this is `None`, the chapter is treated as as draft. An output file
/// is not rendered, but it appears in the TOC grayed out.
src_path: Option<PathBuf>,
/// Optional destination path to write to. Used when changing the first /// Destination path to write to, relative to the book's source directory.
/// chapter's path to index.html. ///
pub dest_path: Option<PathBuf>, /// `book.get_dest_base().join(chapter.get_dest_path())` should point to the
/// output HTML file.
dest_path: Option<PathBuf>,
/// Links to the corresponding translations. /// Links to the corresponding translations.
pub translation_links: Option<Vec<TranslationLink>>, pub translation_links: Option<Vec<TranslationLink>>,
@ -65,6 +78,8 @@ pub struct Chapter {
/// The description of the chapter. /// The description of the chapter.
pub description: Option<String>, pub description: Option<String>,
/// TODO use this in the template
/// CSS class that will be added to the page-level wrap div to allow /// CSS class that will be added to the page-level wrap div to allow
/// customized chapter styles. /// customized chapter styles.
pub css_class: Option<String>, pub css_class: Option<String>,
@ -74,7 +89,8 @@ impl Default for Chapter {
fn default() -> Chapter { fn default() -> Chapter {
Chapter { Chapter {
title: "Untitled".to_string(), title: "Untitled".to_string(),
path: PathBuf::from("src".to_string()).join("untitled.md"), content: None,
src_path: None,
dest_path: None, dest_path: None,
translation_links: None, translation_links: None,
authors: None, authors: None,
@ -87,10 +103,18 @@ impl Default for Chapter {
impl Chapter { impl Chapter {
pub fn new(title: String, path: PathBuf) -> Chapter { pub fn new(title: String, src_path: PathBuf) -> Chapter {
let mut chapter = Chapter::default(); let mut chapter = Chapter::default();
chapter.title = title; chapter.title = title;
chapter.path = path;
if src_path.as_os_str().len() > 0 {
chapter.src_path = Some(src_path.clone());
chapter.dest_path = Some(src_path.clone().with_extension("html"));
} else {
chapter.src_path = None;
chapter.dest_path = None;
}
chapter chapter
} }
@ -98,7 +122,8 @@ impl Chapter {
debug!("[fn] Chapter::parse_or_create() : {:?}", &self); debug!("[fn] Chapter::parse_or_create() : {:?}", &self);
let src_path = &book_src_dir.join(&self.path).to_owned(); if let Some(p) = self.get_src_path() {
let src_path = &book_src_dir.join(&p).to_owned();
if !src_path.exists() { if !src_path.exists() {
debug!("[*] Creating: {:?}", src_path); debug!("[*] Creating: {:?}", src_path);
match create_with_str(src_path, &format!("# {}", self.title)) { match create_with_str(src_path, &format!("# {}", self.title)) {
@ -113,7 +138,9 @@ impl Chapter {
match File::open(src_path) { match File::open(src_path) {
Err(e) => { return Err(format!("Read error: {:?}", e)); }, Err(e) => { return Err(format!("Read error: {:?}", e)); },
Ok(mut f) => { Ok(mut f) => {
// TODO try! here and return error
f.read_to_string(&mut text); f.read_to_string(&mut text);
self.content = Some(utils::strip_toml_header(&text));
} }
} }
@ -132,6 +159,7 @@ impl Chapter {
} }
None => {}, None => {},
} }
}
Ok(self) Ok(self)
} }
@ -199,33 +227,67 @@ impl Chapter {
self self
} }
/// FIXME chapter content should be read when parsing SUMMARY.md so that you // TODO not being used?
/// don't have to pass around the Book struct for getting the src dir
/// Reads in the chapter's content from the markdown file. Chapter doesn't // /// Reads in the chapter's content from the markdown file. Chapter doesn't
/// know the book's src folder, hence the `book_src_dir` argument. // /// know the book's src folder, hence the `book_src_dir` argument.
pub fn read_content_using(&self, book_src_dir: &PathBuf) -> Result<String, Box<Error>> { // pub fn read_content_using(&self, book_src_dir: &PathBuf) -> Result<String, Box<Error>> {
// let p = match self.get_src_path() {
// Some(x) => x,
// None => {
// return Err(Box::new(io::Error::new(
// io::ErrorKind::Other,
// format!("src_path is None"))
// ));
// }
// };
let src_path = book_src_dir.join(&self.path); // let src_path = book_src_dir.join(&p);
if !src_path.exists() { // if !src_path.exists() {
return Err(Box::new(io::Error::new( // return Err(Box::new(io::Error::new(
io::ErrorKind::Other, // io::ErrorKind::Other,
format!("Doesn't exist: {:?}", src_path)) // format!("Doesn't exist: {:?}", src_path))
)); // ));
// }
// debug!("[*]: Opening file: {:?}", src_path);
// let mut f = try!(File::open(&src_path));
// let mut content: String = String::new();
// debug!("[*]: Reading file");
// try!(f.read_to_string(&mut content));
// content = utils::strip_toml_header(&content);
// Ok(content)
// }
pub fn get_src_path(&self) -> Option<PathBuf> {
self.src_path.clone()
} }
debug!("[*]: Opening file: {:?}", src_path); pub fn set_src_path(&mut self, path: PathBuf) -> &mut Chapter {
if path.as_os_str() == OsStr::new(".") {
self.src_path = Some(PathBuf::from("".to_string()));
} else {
self.src_path = Some(path.to_owned());
}
self
}
let mut f = try!(File::open(&src_path)); pub fn get_dest_path(&self) -> Option<PathBuf> {
let mut content: String = String::new(); self.dest_path.clone()
}
debug!("[*]: Reading file"); pub fn set_dest_path(&mut self, path: PathBuf) -> &mut Chapter {
try!(f.read_to_string(&mut content)); if path.as_os_str() == OsStr::new(".") {
self.dest_path = Some(PathBuf::from("".to_string()));
content = utils::strip_toml_header(&content); } else {
self.dest_path = Some(path.to_owned());
Ok(content) }
self
} }
} }

View File

@ -39,7 +39,7 @@ pub struct MDBook {
template_dir: PathBuf, template_dir: PathBuf,
/// Input base for all books, relative to `project_root`. Defaults to `src`. /// Input base for all books, relative to `project_root`. Defaults to `src`.
src_base: PathBuf,// FIXME use this src_base: PathBuf,
/// Output base for all books, relative to `project_root`. Defaults to /// Output base for all books, relative to `project_root`. Defaults to
/// `book`. /// `book`.
@ -262,6 +262,11 @@ impl MDBook {
config.remove("project_root"); config.remove("project_root");
} }
if let Some(a) = config.get("src_base") {
self.set_src_base(&PathBuf::from(&a.to_string()));
}
config.remove("src_base");
if let Some(a) = config.get("dest_base") { if let Some(a) = config.get("dest_base") {
self.set_dest_base(&PathBuf::from(&a.to_string())); self.set_dest_base(&PathBuf::from(&a.to_string()));
} }
@ -300,6 +305,9 @@ impl MDBook {
// keys to the default source and destination folder such as `/src/en` // keys to the default source and destination folder such as `/src/en`
// and `./book/en`. This may be overridden if set specifically. // and `./book/en`. This may be overridden if set specifically.
// TODO if no is_main_book = true was set in the config, find the first
// translation (as in the config) and mark it as the main.
if let Some(a) = config.get("translations") { if let Some(a) = config.get("translations") {
if let Some(b) = a.as_table() { if let Some(b) = a.as_table() {

View File

@ -134,12 +134,12 @@ backmatter."#;
let i = match item { let i = match item {
TocItem::Numbered(mut content) => { TocItem::Numbered(mut content) => {
found_first = true; found_first = true;
content.chapter.dest_path = Some(PathBuf::from("index.html".to_string())); content.chapter.set_dest_path(PathBuf::from("index.html".to_string()));
TocItem::Numbered(content) TocItem::Numbered(content)
}, },
TocItem::Unnumbered(mut content) => { TocItem::Unnumbered(mut content) => {
found_first = true; found_first = true;
content.chapter.dest_path = Some(PathBuf::from("index.html".to_string())); content.chapter.set_dest_path(PathBuf::from("index.html".to_string()));
TocItem::Unnumbered(content) TocItem::Unnumbered(content)
}, },
TocItem::Unlisted(content) => { TocItem::Unlisted(content) => {

View File

@ -45,6 +45,7 @@ impl Renderer for HtmlHandlebars {
//try!(utils::fs::remove_dir_content(&book_project.get_dest_base())); //try!(utils::fs::remove_dir_content(&book_project.get_dest_base()));
// TODO talk to the user
try!(self.render(&book_project)); try!(self.render(&book_project));
Ok(()) Ok(())
@ -190,18 +191,11 @@ impl Renderer for HtmlHandlebars {
TocItem::Unnumbered(ref i) | TocItem::Unnumbered(ref i) |
TocItem::Unlisted(ref i) => { TocItem::Unlisted(ref i) => {
let mut chapter: Chapter = i.chapter.clone(); let mut chapter: Chapter = i.chapter.clone();
chapter.dest_path = Some(PathBuf::from("index.html".to_string())); chapter.set_dest_path(PathBuf::from("index.html".to_string()));
// almost the same as process_chapter(), but we have to // almost the same as process_chapter(), but we have to
// manipulate path_to_root in data and rendered_path // manipulate path_to_root in data and rendered_path
let mut content = try!(chapter.read_content_using(&book.config.src));
// Parse for playpen links
if let Some(p) = book.config.get_src().join(&chapter.path).parent() {
content = helpers::playpen::render_playpen(&content, p);
}
let mut data = try!(make_data(&book, &chapter, &book_project.livereload_script)); let mut data = try!(make_data(&book, &chapter, &book_project.livereload_script));
data.remove("path_to_root"); data.remove("path_to_root");
@ -211,7 +205,7 @@ impl Renderer for HtmlHandlebars {
debug!("[*]: Render template"); debug!("[*]: Render template");
let rendered_content = try!(handlebars.render("page", &data)); let rendered_content = try!(handlebars.render("page", &data));
let p = chapter.dest_path.unwrap(); let p = chapter.get_dest_path().unwrap();
let rendered_path = &book_project.get_dest_base().join(&p); let rendered_path = &book_project.get_dest_base().join(&p);
debug!("[*]: Create file {:?}", rendered_path); debug!("[*]: Create file {:?}", rendered_path);
@ -230,38 +224,14 @@ impl Renderer for HtmlHandlebars {
try!(self.process_items(&book.toc, &book, &book_project.livereload_script, &handlebars)); try!(self.process_items(&book.toc, &book, &book_project.livereload_script, &handlebars));
// Write print.html // Write print.html
// FIXME chapter should have its content so that we don't have to duplicate process_chapter() here if let Some(content) = self.collect_print_content_markdown(&book.toc, &book) {
if let Some(mut content) = self.collect_print_content_markdown(&book.toc, &book) {
let mut chapter: Chapter = Chapter::new(book.config.title.to_owned(), PathBuf::from("")); let mut chapter: Chapter = Chapter::new(book.config.title.to_owned(), PathBuf::from(""));
chapter.dest_path = Some(PathBuf::from("print.html")); chapter.set_dest_path(PathBuf::from("print.html"));
chapter.content = Some(content);
// FIXME this is process_chapter() except we replace content in data try!(self.process_chapter(&chapter, &book, &None, &handlebars));
let mut data = try!(make_data(&book, &chapter, &None));
content = utils::render_markdown(&content);
if let Some(p) = book.config.get_src().join(&chapter.path).parent() {
content = helpers::playpen::render_playpen(&content, p);
}
data.remove("content");
data.insert("content".to_owned(), content.to_json());
let rendered_content = try!(handlebars.render("page", &data));
let p = match chapter.dest_path.clone() {
Some(x) => x,
None => chapter.path.with_extension("html")
};
let rendered_path = &book.config.get_dest().join(&p);
let mut file = try!(utils::fs::create_file(rendered_path));
try!(file.write_all(&rendered_content.into_bytes()));
} }
} }
@ -283,13 +253,7 @@ impl HtmlHandlebars {
TocItem::Numbered(ref i) | TocItem::Numbered(ref i) |
TocItem::Unnumbered(ref i) | TocItem::Unnumbered(ref i) |
TocItem::Unlisted(ref i) => { TocItem::Unlisted(ref i) => {
// FIXME chapters with path "" are interpreted as draft now, if let Some(_) = i.chapter.get_dest_path() {
// not rendered here, and displayed gray in the TOC. Either
// path should be instead an Option or all chapter output
// should be used from setting dest_path, which is already
// Option but currently only used for rendering a chapter as
// index.html.
if i.chapter.path.as_os_str().len() > 0 {
try!(self.process_chapter(&i.chapter, book, livereload_script, handlebars)); try!(self.process_chapter(&i.chapter, book, livereload_script, handlebars));
} }
@ -313,10 +277,8 @@ impl HtmlHandlebars {
TocItem::Numbered(ref i) | TocItem::Numbered(ref i) |
TocItem::Unnumbered(ref i) | TocItem::Unnumbered(ref i) |
TocItem::Unlisted(ref i) => { TocItem::Unlisted(ref i) => {
if i.chapter.path.as_os_str().len() > 0 { if let Some(content) = i.chapter.content.clone() {
if let Ok(x) = i.chapter.read_content_using(&book.config.src) { text.push_str(&content);
text.push_str(&x);
}
} }
if let Some(ref subs) = i.sub_items { if let Some(ref subs) = i.sub_items {
@ -351,9 +313,14 @@ impl HtmlHandlebars {
debug!("[*]: Render template"); debug!("[*]: Render template");
let rendered_content = try!(handlebars.render("page", &data)); let rendered_content = try!(handlebars.render("page", &data));
let p = match chapter.dest_path.clone() { let p = match chapter.get_dest_path() {
Some(x) => x, Some(x) => x,
None => chapter.path.with_extension("html") None => {
return Err(Box::new(io::Error::new(
io::ErrorKind::Other,
format!("process_chapter(), dest_path is None: {:#?}", chapter))
));
}
}; };
let rendered_path = &book.config.get_dest().join(&p); let rendered_path = &book.config.get_dest().join(&p);
@ -391,20 +358,15 @@ fn make_data(book: &Book,
// Chapter data // Chapter data
let mut path = if let Some(ref dest_path) = chapter.dest_path { match chapter.get_dest_path() {
PathBuf::from(dest_path) Some(mut path) => {
} else { if book.config.is_multilang {
chapter.path.clone() path = PathBuf::from(&book.config.language.code).join(&path);
};
if book.config.is_multilang && path.as_os_str().len() > 0 {
let p = PathBuf::from(&book.config.language.code);
path = p.join(path);
} }
match path.to_str() { match path.to_str() {
Some(p) => { Some(p) => {
data.insert("path".to_owned(), p.to_json()); data.insert("path".to_owned(), p.to_json());
data.insert("path_to_root".to_owned(), utils::fs::path_to_root(&path).to_json());
}, },
None => { None => {
return Err(Box::new(io::Error::new( return Err(Box::new(io::Error::new(
@ -413,25 +375,33 @@ fn make_data(book: &Book,
)) ))
}, },
} }
},
None => {
return Err(Box::new(io::Error::new(
io::ErrorKind::Other,
format!("make_data(), dest_path is None: {:#?}", chapter))
));
}
}
match chapter.read_content_using(&book.config.src) { match chapter.content.clone() {
Ok(mut content) => { Some(mut content) => {
content = utils::render_markdown(&content); content = utils::render_markdown(&content);
// Parse for playpen links // Parse for playpen links
if let Some(p) = book.config.get_src().join(&chapter.path).parent() { if let Some(a) = chapter.get_src_path() {
if let Some(p) = book.config.get_src().join(&a).parent() {
content = helpers::playpen::render_playpen(&content, p); content = helpers::playpen::render_playpen(&content, p);
} }
}
data.insert("content".to_owned(), content.to_json()); data.insert("content".to_owned(), content.to_json());
}, },
Err(e) => { None => {
debug!("Couldn't read chapter content: {:#?}", e); debug!("Chapter has dest_path but doesn't have content: {:#?}", chapter);
}, },
} }
data.insert("path_to_root".to_owned(), utils::fs::path_to_root(&path).to_json());
if let Some(ref links) = chapter.translation_links { if let Some(ref links) = chapter.translation_links {
data.insert("translation_links".to_owned(), links.to_json()); data.insert("translation_links".to_owned(), links.to_json());
} }
@ -473,33 +443,28 @@ fn items_to_chapters(items: &Vec<TocItem>, book: &Book)
fn process_chapter_and_subs(i: &TocContent, book: &Book) fn process_chapter_and_subs(i: &TocContent, book: &Book)
-> Result<Vec<serde_json::Map<String, serde_json::Value>>, Box<Error>> { -> Result<Vec<serde_json::Map<String, serde_json::Value>>, Box<Error>> {
let mut chapters = vec![]; let mut chapters_data = vec![];
// Create the data to inject in the template // Create the data to inject in the template
let mut chapter = serde_json::Map::new(); let mut data = serde_json::Map::new();
let ch = &i.chapter; let chapter = &i.chapter;
if let Some(_) = i.section { if let Some(_) = i.section {
let s = i.section_as_string(); let s = i.section_as_string();
chapter.insert("section".to_owned(), s.to_json()); data.insert("section".to_owned(), s.to_json());
} }
chapter.insert("title".to_owned(), ch.title.to_json()); data.insert("title".to_owned(), chapter.title.to_json());
let mut path = if let Some(ref dest_path) = ch.dest_path { match chapter.get_dest_path() {
PathBuf::from(dest_path) Some(mut path) => {
} else { if book.config.is_multilang {
ch.path.clone() path = PathBuf::from(&book.config.language.code).join(&path);
};
if book.config.is_multilang && path.as_os_str().len() > 0 {
let p = PathBuf::from(&book.config.language.code);
path = p.join(path);
} }
match path.to_str() { match path.to_str() {
Some(p) => { Some(p) => {
chapter.insert("path".to_owned(), p.to_json()); data.insert("path".to_owned(), p.to_json());
data.insert("path_to_root".to_owned(), utils::fs::path_to_root(&path).to_json());
}, },
None => { None => {
return Err(Box::new(io::Error::new( return Err(Box::new(io::Error::new(
@ -508,13 +473,17 @@ fn process_chapter_and_subs(i: &TocContent, book: &Book)
)) ))
}, },
} }
},
// is draft chapter
None => {}
}
chapters.push(chapter); chapters_data.push(data);
if let Some(ref subs) = i.sub_items { if let Some(ref subs) = i.sub_items {
let mut sub_chs = try!(items_to_chapters(&subs, book)); let mut sub_chs = try!(items_to_chapters(&subs, book));
chapters.append(&mut sub_chs); chapters_data.append(&mut sub_chs);
} }
Ok(chapters) Ok(chapters_data)
} }

View File

@ -18,5 +18,6 @@ fn it_parses_when_exists() {
// test that the author is parsed from the TOML header // test that the author is parsed from the TOML header
expected.authors = Some(vec![Author::new("H.P. Lovecraft")]); expected.authors = Some(vec![Author::new("H.P. Lovecraft")]);
assert_eq!(format!("{:?}", result), format!("{:?}", expected)); assert!(result.content.unwrap().contains("Nemesis, 1917"));
assert_eq!(format!("{:?}", result.authors), format!("{:?}", expected.authors));
} }

View File

@ -12,7 +12,7 @@ fn it_renders_multilanguage_book() {
let renderer = HtmlHandlebars::new(); let renderer = HtmlHandlebars::new();
if let Err(e) = renderer.build(&path) { if let Err(e) = renderer.build(&path) {
println!("{:#?}", e); panic!("{:#?}", e);
} }
let mut proj = MDBook::new(&path); let mut proj = MDBook::new(&path);
@ -29,22 +29,27 @@ fn it_renders_multilanguage_book() {
s = utils::fs::file_to_string(&chapter_path).unwrap(); s = utils::fs::file_to_string(&chapter_path).unwrap();
assert!(s.contains("<title>Alice's Adventures in Wonderland</title>")); assert!(s.contains("<title>Alice's Adventures in Wonderland</title>"));
assert!(s.contains("<h1>Alice's Adventures in Wonderland</h1>")); assert!(s.contains("<h1>Alice's Adventures in Wonderland</h1>"));
assert!(s.contains("<base href=\"\">"));
// Test if each translation was rendered // Test if each translation was rendered
chapter_path = book_path.join("tears.html"); chapter_path = book_path.join("tears.html");
s = utils::fs::file_to_string(&chapter_path).unwrap(); s = utils::fs::file_to_string(&chapter_path).unwrap();
assert!(s.contains("<h1>The Pool of Tears</h1>")); assert!(s.contains("<h1>The Pool of Tears</h1>"));
assert!(s.contains("<base href=\"../\">"));
assert!(s.contains("li><a href=\"en/tears.html\" class=\"active\"><strong>2.</strong> The Pool of Tears</a></li>"));
book_path = proj.translations.get("fr").unwrap().config.get_dest(); book_path = proj.translations.get("fr").unwrap().config.get_dest();
chapter_path = book_path.join("larmes.html"); chapter_path = book_path.join("larmes.html");
s = utils::fs::file_to_string(&chapter_path).unwrap(); s = utils::fs::file_to_string(&chapter_path).unwrap();
assert!(s.contains("<h1>La mare aux larmes</h1>")); assert!(s.contains("<h1>La mare aux larmes</h1>"));
assert!(s.contains("<base href=\"../\">"));
book_path = proj.translations.get("hu").unwrap().config.get_dest(); book_path = proj.translations.get("hu").unwrap().config.get_dest();
chapter_path = book_path.join("konnyto.html"); chapter_path = book_path.join("konnyto.html");
s = utils::fs::file_to_string(&chapter_path).unwrap(); s = utils::fs::file_to_string(&chapter_path).unwrap();
assert!(s.contains("<h1>Könnytó</h1>")); assert!(s.contains("<h1>Könnytó</h1>"));
assert!(s.contains("<base href=\"../\">"));
// Test if book's asset files were copied // Test if book's asset files were copied
@ -66,4 +71,21 @@ fn it_renders_multilanguage_book() {
assert!(s.contains("<a href=\"en/index.html\">en</a>")); assert!(s.contains("<a href=\"en/index.html\">en</a>"));
assert!(s.contains("<a href=\"hu/index.html\">hu</a>")); assert!(s.contains("<a href=\"hu/index.html\">hu</a>"));
assert!(s.contains("<a href=\"fr/index.html\">fr</a>")); assert!(s.contains("<a href=\"fr/index.html\">fr</a>"));
// Test if print.html is produced for each translations
book_path = proj.translations.get("en").unwrap().config.get_dest();
chapter_path = book_path.join("print.html");
s = utils::fs::file_to_string(&chapter_path).unwrap();
assert!(s.contains("<h1>The Pool of Tears</h1>"));
book_path = proj.translations.get("fr").unwrap().config.get_dest();
chapter_path = book_path.join("print.html");
s = utils::fs::file_to_string(&chapter_path).unwrap();
assert!(s.contains("<h1>La mare aux larmes</h1>"));
book_path = proj.translations.get("hu").unwrap().config.get_dest();
chapter_path = book_path.join("print.html");
s = utils::fs::file_to_string(&chapter_path).unwrap();
assert!(s.contains("<h1>Könnytó</h1>"));
} }

View File

@ -107,6 +107,7 @@ indent_spaces = 2
[[translations.en]] [[translations.en]]
title = "Alice's Adventures in Wonderland" title = "Alice's Adventures in Wonderland"
author = "Lewis Carroll" author = "Lewis Carroll"
is_main_book = true
[[translations.hu]] [[translations.hu]]
title = "Alice Csodaországban" title = "Alice Csodaországban"
@ -141,6 +142,8 @@ name = "Kosztolányi Dezső"
conf.authors = vec![Author::new("Lewis Carroll")]; conf.authors = vec![Author::new("Lewis Carroll")];
conf.src = expected.get_project_root().join("src").join("en"); conf.src = expected.get_project_root().join("src").join("en");
conf.dest = expected.get_project_root().join("book").join("en"); conf.dest = expected.get_project_root().join("book").join("en");
conf.is_multilang = true;
conf.is_main_book = true;
let mut book = Book::default(); let mut book = Book::default();
book.config = conf; book.config = conf;
@ -155,6 +158,8 @@ name = "Kosztolányi Dezső"
conf.translators = Some(vec![Author::new("Kosztolányi Dezső")]); conf.translators = Some(vec![Author::new("Kosztolányi Dezső")]);
conf.src = expected.get_project_root().join("src").join("hu"); conf.src = expected.get_project_root().join("src").join("hu");
conf.dest = expected.get_project_root().join("book").join("hu"); conf.dest = expected.get_project_root().join("book").join("hu");
conf.is_multilang = true;
conf.is_main_book = false;
let mut book = Book::default(); let mut book = Book::default();
book.config = conf; book.config = conf;

View File

@ -38,10 +38,14 @@ fn it_parses_summary_to_tocitems() {
TocContent { TocContent {
chapter: Chapter { chapter: Chapter {
title: "Introduction", title: "Introduction",
path: "misc/introduction.md", content: None,
src_path: Some(
"misc/introduction.md"
),
dest_path: Some( dest_path: Some(
"index.html" "index.html"
), ),
translation_links: None,
authors: None, authors: None,
translators: None, translators: None,
description: None, description: None,
@ -55,8 +59,14 @@ fn it_parses_summary_to_tocitems() {
TocContent { TocContent {
chapter: Chapter { chapter: Chapter {
title: "mdBook", title: "mdBook",
path: "README.md", content: None,
dest_path: None, src_path: Some(
"README.md"
),
dest_path: Some(
"README.html"
),
translation_links: None,
authors: None, authors: None,
translators: None, translators: None,
description: None, description: None,
@ -74,8 +84,14 @@ fn it_parses_summary_to_tocitems() {
TocContent { TocContent {
chapter: Chapter { chapter: Chapter {
title: "Command Line Tool", title: "Command Line Tool",
path: "cli/cli-tool.md", content: None,
dest_path: None, src_path: Some(
"cli/cli-tool.md"
),
dest_path: Some(
"cli/cli-tool.html"
),
translation_links: None,
authors: None, authors: None,
translators: None, translators: None,
description: None, description: None,
@ -87,8 +103,14 @@ fn it_parses_summary_to_tocitems() {
TocContent { TocContent {
chapter: Chapter { chapter: Chapter {
title: "init", title: "init",
path: "cli/init.md", content: None,
dest_path: None, src_path: Some(
"cli/init.md"
),
dest_path: Some(
"cli/init.html"
),
translation_links: None,
authors: None, authors: None,
translators: None, translators: None,
description: None, description: None,
@ -107,8 +129,14 @@ fn it_parses_summary_to_tocitems() {
TocContent { TocContent {
chapter: Chapter { chapter: Chapter {
title: "build", title: "build",
path: "cli/build.md", content: None,
dest_path: None, src_path: Some(
"cli/build.md"
),
dest_path: Some(
"cli/build.html"
),
translation_links: None,
authors: None, authors: None,
translators: None, translators: None,
description: None, description: None,
@ -127,8 +155,14 @@ fn it_parses_summary_to_tocitems() {
TocContent { TocContent {
chapter: Chapter { chapter: Chapter {
title: "watch", title: "watch",
path: "cli/watch.md", content: None,
dest_path: None, src_path: Some(
"cli/watch.md"
),
dest_path: Some(
"cli/watch.html"
),
translation_links: None,
authors: None, authors: None,
translators: None, translators: None,
description: None, description: None,
@ -147,8 +181,14 @@ fn it_parses_summary_to_tocitems() {
TocContent { TocContent {
chapter: Chapter { chapter: Chapter {
title: "serve", title: "serve",
path: "cli/serve.md", content: None,
dest_path: None, src_path: Some(
"cli/serve.md"
),
dest_path: Some(
"cli/serve.html"
),
translation_links: None,
authors: None, authors: None,
translators: None, translators: None,
description: None, description: None,
@ -167,8 +207,14 @@ fn it_parses_summary_to_tocitems() {
TocContent { TocContent {
chapter: Chapter { chapter: Chapter {
title: "test", title: "test",
path: "cli/test.md", content: None,
dest_path: None, src_path: Some(
"cli/test.md"
),
dest_path: Some(
"cli/test.html"
),
translation_links: None,
authors: None, authors: None,
translators: None, translators: None,
description: None, description: None,
@ -196,8 +242,14 @@ fn it_parses_summary_to_tocitems() {
TocContent { TocContent {
chapter: Chapter { chapter: Chapter {
title: "Format", title: "Format",
path: "format/format.md", content: None,
dest_path: None, src_path: Some(
"format/format.md"
),
dest_path: Some(
"format/format.html"
),
translation_links: None,
authors: None, authors: None,
translators: None, translators: None,
description: None, description: None,
@ -209,8 +261,14 @@ fn it_parses_summary_to_tocitems() {
TocContent { TocContent {
chapter: Chapter { chapter: Chapter {
title: "SUMMARY.md", title: "SUMMARY.md",
path: "format/summary.md", content: None,
dest_path: None, src_path: Some(
"format/summary.md"
),
dest_path: Some(
"format/summary.html"
),
translation_links: None,
authors: None, authors: None,
translators: None, translators: None,
description: None, description: None,
@ -229,8 +287,14 @@ fn it_parses_summary_to_tocitems() {
TocContent { TocContent {
chapter: Chapter { chapter: Chapter {
title: "Configuration", title: "Configuration",
path: "format/config.md", content: None,
dest_path: None, src_path: Some(
"format/config.md"
),
dest_path: Some(
"format/config.html"
),
translation_links: None,
authors: None, authors: None,
translators: None, translators: None,
description: None, description: None,
@ -249,8 +313,14 @@ fn it_parses_summary_to_tocitems() {
TocContent { TocContent {
chapter: Chapter { chapter: Chapter {
title: "Theme", title: "Theme",
path: "format/theme/theme.md", content: None,
dest_path: None, src_path: Some(
"format/theme/theme.md"
),
dest_path: Some(
"format/theme/theme.html"
),
translation_links: None,
authors: None, authors: None,
translators: None, translators: None,
description: None, description: None,
@ -262,8 +332,14 @@ fn it_parses_summary_to_tocitems() {
TocContent { TocContent {
chapter: Chapter { chapter: Chapter {
title: "index.hbs", title: "index.hbs",
path: "format/theme/index-hbs.md", content: None,
dest_path: None, src_path: Some(
"format/theme/index-hbs.md"
),
dest_path: Some(
"format/theme/index-hbs.html"
),
translation_links: None,
authors: None, authors: None,
translators: None, translators: None,
description: None, description: None,
@ -283,8 +359,14 @@ fn it_parses_summary_to_tocitems() {
TocContent { TocContent {
chapter: Chapter { chapter: Chapter {
title: "Syntax highlighting", title: "Syntax highlighting",
path: "format/theme/syntax-highlighting.md", content: None,
dest_path: None, src_path: Some(
"format/theme/syntax-highlighting.md"
),
dest_path: Some(
"format/theme/syntax-highlighting.html"
),
translation_links: None,
authors: None, authors: None,
translators: None, translators: None,
description: None, description: None,
@ -314,8 +396,14 @@ fn it_parses_summary_to_tocitems() {
TocContent { TocContent {
chapter: Chapter { chapter: Chapter {
title: "MathJax Support", title: "MathJax Support",
path: "format/mathjax.md", content: None,
dest_path: None, src_path: Some(
"format/mathjax.md"
),
dest_path: Some(
"format/mathjax.html"
),
translation_links: None,
authors: None, authors: None,
translators: None, translators: None,
description: None, description: None,
@ -334,8 +422,14 @@ fn it_parses_summary_to_tocitems() {
TocContent { TocContent {
chapter: Chapter { chapter: Chapter {
title: "Rust code specific features", title: "Rust code specific features",
path: "format/rust.md", content: None,
dest_path: None, src_path: Some(
"format/rust.md"
),
dest_path: Some(
"format/rust.html"
),
translation_links: None,
authors: None, authors: None,
translators: None, translators: None,
description: None, description: None,
@ -363,8 +457,14 @@ fn it_parses_summary_to_tocitems() {
TocContent { TocContent {
chapter: Chapter { chapter: Chapter {
title: "Rust Library", title: "Rust Library",
path: "lib/lib.md", content: None,
dest_path: None, src_path: Some(
"lib/lib.md"
),
dest_path: Some(
"lib/lib.html"
),
translation_links: None,
authors: None, authors: None,
translators: None, translators: None,
description: None, description: None,
@ -383,8 +483,14 @@ fn it_parses_summary_to_tocitems() {
TocContent { TocContent {
chapter: Chapter { chapter: Chapter {
title: "Contributors", title: "Contributors",
path: "misc/contributors.md", content: None,
dest_path: None, src_path: Some(
"misc/contributors.md"
),
dest_path: Some(
"misc/contributors.html"
),
translation_links: None,
authors: None, authors: None,
translators: None, translators: None,
description: None, description: None,