diff --git a/src/renderer/html_handlebars/hbs_renderer.rs b/src/renderer/html_handlebars/hbs_renderer.rs index b4d73854..d6663ea8 100644 --- a/src/renderer/html_handlebars/hbs_renderer.rs +++ b/src/renderer/html_handlebars/hbs_renderer.rs @@ -219,12 +219,17 @@ impl HtmlHandlebars { } fn register_hbs_helpers(&self, handlebars: &mut Handlebars, html_config: &HtmlConfig) { + let HtmlConfig { no_section_label, ref rewrite_to_dir, .. } = *html_config; handlebars.register_helper("toc", Box::new(helpers::toc::RenderToc { - no_section_label: html_config.no_section_label, - rewrite_to_dir: html_config.rewrite_to_dir.to_owned(), + no_section_label, + rewrite_to_dir: rewrite_to_dir.to_owned(), + })); + handlebars.register_helper("previous", Box::new(helpers::navigation::Previous { + rewrite_to_dir: rewrite_to_dir.to_owned(), + })); + handlebars.register_helper("next", Box::new(helpers::navigation::Next { + rewrite_to_dir: rewrite_to_dir.to_owned(), })); - handlebars.register_helper("previous", Box::new(helpers::navigation::previous)); - handlebars.register_helper("next", Box::new(helpers::navigation::next)); } /// Copy across any additional CSS and JavaScript files which the book diff --git a/src/renderer/html_handlebars/helpers/mod.rs b/src/renderer/html_handlebars/helpers/mod.rs index ce122e9f..57df3301 100644 --- a/src/renderer/html_handlebars/helpers/mod.rs +++ b/src/renderer/html_handlebars/helpers/mod.rs @@ -1,2 +1,38 @@ +use std::path::{Path, PathBuf}; + pub mod toc; pub mod navigation; + +/// Rewrite filename of path to directory index if matches any of filename +/// pattern in `rewrite_names`. +/// +/// * `path` - Path reference. +/// * `rewrite_names` - Array of filename pattern to be rewritten. +pub fn rewrite_to_dir_index>(path: P, rewrite_names: &[String]) -> PathBuf { + let p = path.as_ref(); + for name in rewrite_names.iter() { + if name.as_str() == p.file_name().unwrap_or_default() { + return p.with_file_name(""); + } + } + return p.to_owned(); +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn rewrite_to_dir_success() { + let names = vec!["index.html".to_owned(), "index.md".to_owned()]; + + let path = PathBuf::from("index.html"); + assert_eq!(rewrite_to_dir_index(&path, &names), PathBuf::from("")); + + let path = PathBuf::from("index.md"); + assert_eq!(rewrite_to_dir_index(&path, &names), PathBuf::from("")); + + let path = PathBuf::from("index.asp"); + assert_eq!(rewrite_to_dir_index(&path, &names), path); + } +} diff --git a/src/renderer/html_handlebars/helpers/navigation.rs b/src/renderer/html_handlebars/helpers/navigation.rs index 429e3dd3..d9c21e6a 100644 --- a/src/renderer/html_handlebars/helpers/navigation.rs +++ b/src/renderer/html_handlebars/helpers/navigation.rs @@ -2,7 +2,10 @@ use std::path::Path; use std::collections::BTreeMap; use serde_json; -use handlebars::{Context, Handlebars, Helper, RenderContext, RenderError, Renderable}; +use handlebars::{Context, Handlebars, Helper, HelperDef, RenderContext, RenderError, Renderable}; + +use super::rewrite_to_dir_index; + type StringMap = BTreeMap; @@ -83,6 +86,7 @@ fn render( r: &Handlebars, rc: &mut RenderContext, chapter: &StringMap, + rewrite_names: &[String], ) -> Result<(), RenderError> { trace!("Creating BTreeMap to inject in context"); @@ -97,8 +101,7 @@ fn render( .get("path") .ok_or_else(|| RenderError::new("No path found for chapter in JSON data")) .and_then(|p| { - Path::new(p) - .with_extension("html") + rewrite_to_dir_index(Path::new(p).with_extension("html"), rewrite_names) .to_str() .ok_or_else(|| RenderError::new("Link could not be converted to str")) .map(|p| context.insert("link".to_owned(), json!(p.replace("\\", "/")))) @@ -116,24 +119,48 @@ fn render( Ok(()) } -pub fn previous(_h: &Helper, r: &Handlebars, rc: &mut RenderContext) -> Result<(), RenderError> { - trace!("previous (handlebars helper)"); - - if let Some(previous) = find_chapter(rc, Target::Previous)? { - render(_h, r, rc, &previous)?; - } - - Ok(()) +pub struct Previous { + pub rewrite_to_dir: Vec, } -pub fn next(_h: &Helper, r: &Handlebars, rc: &mut RenderContext) -> Result<(), RenderError> { - trace!("next (handlebars helper)"); - - if let Some(next) = find_chapter(rc, Target::Next)? { - render(_h, r, rc, &next)?; +impl Default for Previous { + fn default() -> Self { + Self { rewrite_to_dir: vec![] } } +} - Ok(()) +impl HelperDef for Previous { + fn call(&self, _h: &Helper, r: &Handlebars, rc: &mut RenderContext) -> Result<(), RenderError> { + trace!("previous (handlebars helper)"); + + if let Some(previous) = find_chapter(rc, Target::Previous)? { + render(_h, r, rc, &previous, &self.rewrite_to_dir)?; + } + + Ok(()) + } +} + +pub struct Next { + pub rewrite_to_dir: Vec, +} + +impl Default for Next { + fn default() -> Self { + Self { rewrite_to_dir: vec![] } + } +} + +impl HelperDef for Next { + fn call(&self, _h: &Helper, r: &Handlebars, rc: &mut RenderContext) -> Result<(), RenderError> { + trace!("next (handlebars helper)"); + + if let Some(next) = find_chapter(rc, Target::Next)? { + render(_h, r, rc, &next, &self.rewrite_to_dir)?; + } + + Ok(()) + } } #[cfg(test)] @@ -165,8 +192,8 @@ mod tests { }); let mut h = Handlebars::new(); - h.register_helper("previous", Box::new(previous)); - h.register_helper("next", Box::new(next)); + h.register_helper("previous", Box::new(Previous::default())); + h.register_helper("next", Box::new(Next::default())); assert_eq!( h.render_template(TEMPLATE, &data).unwrap(), @@ -196,8 +223,8 @@ mod tests { }); let mut h = Handlebars::new(); - h.register_helper("previous", Box::new(previous)); - h.register_helper("next", Box::new(next)); + h.register_helper("previous", Box::new(Previous::default())); + h.register_helper("next", Box::new(Next::default())); assert_eq!( h.render_template(TEMPLATE, &data).unwrap(), @@ -226,8 +253,8 @@ mod tests { }); let mut h = Handlebars::new(); - h.register_helper("previous", Box::new(previous)); - h.register_helper("next", Box::new(next)); + h.register_helper("previous", Box::new(Previous::default())); + h.register_helper("next", Box::new(Next::default())); assert_eq!( h.render_template(TEMPLATE, &data).unwrap(), diff --git a/src/renderer/html_handlebars/helpers/toc.rs b/src/renderer/html_handlebars/helpers/toc.rs index 2ade3e21..5fcee0fa 100644 --- a/src/renderer/html_handlebars/helpers/toc.rs +++ b/src/renderer/html_handlebars/helpers/toc.rs @@ -1,10 +1,12 @@ -use std::path::{Path, PathBuf}; +use std::path::Path; use std::collections::BTreeMap; use serde_json; use handlebars::{Handlebars, Helper, HelperDef, RenderContext, RenderError}; use pulldown_cmark::{html, Event, Parser, Tag}; +use super::rewrite_to_dir_index; + // Handlebars helper to construct TOC pub struct RenderToc { pub no_section_label: bool, @@ -72,7 +74,7 @@ impl HelperDef for RenderToc { let tmp = { // To be recognized by browsers, rewrite extenstion to `.html`. let path = Path::new(path).with_extension("html"); - self.rewrite_directory_index(&path) + rewrite_to_dir_index(&path, &self.rewrite_to_dir) } .to_str() .unwrap() @@ -140,41 +142,4 @@ impl HelperDef for RenderToc { rc.writer.write_all(b"")?; Ok(()) } - -} - -impl RenderToc { - // Rewrite filenames matches any in `rewrite_to_dir` to directory index. - fn rewrite_directory_index(&self, path: &Path) -> PathBuf { - for filename in self.rewrite_to_dir.iter() { - if filename.as_str() == path.file_name().unwrap_or_default() { - return path.with_file_name(""); - } - } - return path.to_owned(); - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn rewrite_dir_success() { - let render = RenderToc { - no_section_label: true, - rewrite_to_dir: vec![ - "index.html".to_owned(), - "index.md".to_owned(), - ], - }; - let path = PathBuf::from("index.html"); - assert_eq!(render.rewrite_directory_index(&path), PathBuf::from("")); - - let path = PathBuf::from("index.md"); - assert_eq!(render.rewrite_directory_index(&path), PathBuf::from("")); - - let path = PathBuf::from("index.asp"); - assert_eq!(render.rewrite_directory_index(&path), path); - } }