diff --git a/src/renderer/html_handlebars/hbs_renderer.rs b/src/renderer/html_handlebars/hbs_renderer.rs index 810ba766..d7f47858 100644 --- a/src/renderer/html_handlebars/hbs_renderer.rs +++ b/src/renderer/html_handlebars/hbs_renderer.rs @@ -38,7 +38,9 @@ impl HtmlHandlebars { BookItem::Chapter(ref ch) => { let content = ch.content.clone(); - let base = ch.path.parent().expect("All chapters must have a parent directory"); + let base = ch.path.parent() + .map(|dir| ctx.src_dir.join(dir)) + .expect("All chapters must have a parent directory"); // Parse and expand links let content = preprocess::links::replace_all(&content, base)?; @@ -239,13 +241,14 @@ impl HtmlHandlebars { impl Renderer for HtmlHandlebars { fn render(&self, book: &MDBook) -> Result<()> { let html_config = book.config.html_config().unwrap_or_default(); + let src_dir = book.root.join(&book.config.book.src); debug!("[fn]: render"); let mut handlebars = Handlebars::new(); let theme_dir = match html_config.theme { - Some(ref theme) => theme, - None => Path::new("theme"), + Some(ref theme) => theme.to_path_buf(), + None => src_dir.join("theme"), }; let theme = theme::Theme::new(theme_dir); @@ -282,6 +285,7 @@ impl Renderer for HtmlHandlebars { book: book, handlebars: &handlebars, destination: destination.to_path_buf(), + src_dir: src_dir.clone(), data: data.clone(), is_index: i == 0, html_config: html_config.clone(), @@ -595,6 +599,7 @@ struct RenderItemContext<'a> { handlebars: &'a Handlebars, book: &'a MDBook, destination: PathBuf, + src_dir: PathBuf, data: serde_json::Map, is_index: bool, html_config: HtmlConfig, diff --git a/tests/dummy_book/src/example.rs b/tests/dummy_book/src/example.rs new file mode 100644 index 00000000..6b49705c --- /dev/null +++ b/tests/dummy_book/src/example.rs @@ -0,0 +1,6 @@ +fn main() { + println!("Hello World!"); +# +# // You can even hide lines! :D +# println!("I am hidden! Expand the code snippet to see me"); +} diff --git a/tests/dummy_book/src/second.md b/tests/dummy_book/src/second.md index abeaa6af..539d17f8 100644 --- a/tests/dummy_book/src/second.md +++ b/tests/dummy_book/src/second.md @@ -1 +1,5 @@ -# Second Chapter \ No newline at end of file +# Second Chapter + +This makes sure you can insert runnable Rust files. + +{{#playpen example.rs}} \ No newline at end of file diff --git a/tests/init.rs b/tests/init.rs index be3fc603..3515a7be 100644 --- a/tests/init.rs +++ b/tests/init.rs @@ -2,6 +2,7 @@ extern crate mdbook; extern crate tempdir; use std::path::PathBuf; +use std::fs; use mdbook::MDBook; use mdbook::config::Config; use tempdir::TempDir; @@ -63,7 +64,7 @@ fn book_toml_isnt_required() { let temp = TempDir::new("mdbook").unwrap(); let md = MDBook::init(temp.path()).build().unwrap(); - assert!(!temp.path().join("book.toml").exists()); + let _ = fs::remove_file(temp.path().join("book.toml")); md.read_config().unwrap().build().unwrap(); } diff --git a/tests/rendered_output.rs b/tests/rendered_output.rs index 0fcd07a5..7e595620 100644 --- a/tests/rendered_output.rs +++ b/tests/rendered_output.rs @@ -10,7 +10,6 @@ mod dummy_book; use dummy_book::{assert_contains_strings, DummyBook}; use std::fs::{remove_file, File}; -use std::io::Write; use std::path::Path; use std::ffi::OsStr; use walkdir::{DirEntry, WalkDir, WalkDirIterator}; @@ -256,46 +255,45 @@ fn check_spacers() { /// not exist. #[test] fn failure_on_missing_file() { - let (md, _temp) = create_missing_setup(Some(false)); + let (mut md, _temp) = create_missing_setup(false); // On failure, `build()` does not return a specific error, so assume // any error is a failure due to a missing file. - assert!(md.read_config().unwrap().build().is_err()); + assert!(md.build().is_err()); } /// Ensure a missing file is created if `create-missing` is true. #[test] fn create_missing_file_with_config() { - let (md, temp) = create_missing_setup(Some(true)); + let (mut md, temp) = create_missing_setup(true); - md.read_config().unwrap().build().unwrap(); + md.build().unwrap(); assert!(temp.path().join("src").join("intro.md").exists()); } -/// Ensure a missing file is created if `create-missing` is not set (the default -/// is true). -#[test] -fn create_missing_file_without_config() { - let (md, temp) = create_missing_setup(None); - - md.read_config().unwrap().build().unwrap(); - assert!(temp.path().join("src").join("intro.md").exists()); -} - -fn create_missing_setup(create_missing: Option) -> (MDBook, TempDir) { +fn create_missing_setup(create_missing: bool) -> (MDBook, TempDir) { let temp = DummyBook::new().build().unwrap(); - let md = MDBook::load(temp.path()).unwrap(); - - let mut file = File::create(temp.path().join("book.toml")).unwrap(); - match create_missing { - Some(true) => file.write_all(b"[build]\ncreate-missing = true\n").unwrap(), - Some(false) => file.write_all(b"[build]\ncreate-missing = false\n") - .unwrap(), - None => (), - } - file.flush().unwrap(); + let mut md = MDBook::load(temp.path()).unwrap(); + md.config.build.create_missing = create_missing; remove_file(temp.path().join("src").join("intro.md")).unwrap(); (md, temp) } + +/// This makes sure you can include a Rust file with `{{#playpen example.rs}}`. +/// Specification is in `book-example/src/format/rust.md` +#[test] +fn able_to_include_rust_files_in_chapters() { + let temp = DummyBook::new().build().unwrap(); + let mut md = MDBook::load(temp.path()).unwrap(); + md.build().unwrap(); + + let second = temp.path().join("book/second.html"); + + let playpen_strings = &[ + r#"class="playpen""#, + r#"println!("Hello World!");"#, + ]; + assert_contains_strings(second, playpen_strings); +}