Skip to content

Add rewrite_to_dir config to rewrite index file path #684

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,8 @@ pub struct HtmlConfig {
pub livereload_url: Option<String>,
/// Should section labels be rendered?
pub no_section_label: bool,
/// Filenames listed here would be rewritten to directory index `/`.
pub rewrite_to_dir: Vec<String>,
/// Search settings. If `None`, the default will be used.
pub search: Option<Search>,
}
Expand Down
14 changes: 11 additions & 3 deletions src/renderer/html_handlebars/hbs_renderer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,9 +219,17 @@ impl HtmlHandlebars {
}

fn register_hbs_helpers(&self, handlebars: &mut Handlebars, html_config: &HtmlConfig) {
handlebars.register_helper("toc", Box::new(helpers::toc::RenderToc {no_section_label: html_config.no_section_label}));
handlebars.register_helper("previous", Box::new(helpers::navigation::previous));
handlebars.register_helper("next", Box::new(helpers::navigation::next));
let HtmlConfig { no_section_label, ref rewrite_to_dir, .. } = *html_config;
handlebars.register_helper("toc", Box::new(helpers::toc::RenderToc {
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(),
}));
}

/// Copy across any additional CSS and JavaScript files which the book
Expand Down
36 changes: 36 additions & 0 deletions src/renderer/html_handlebars/helpers/mod.rs
Original file line number Diff line number Diff line change
@@ -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<P: AsRef<Path>>(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);
}
}
65 changes: 46 additions & 19 deletions src/renderer/html_handlebars/helpers/navigation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<String, String>;

Expand Down Expand Up @@ -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");

Expand All @@ -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("\\", "/"))))
Expand All @@ -116,24 +119,48 @@ fn render(
Ok(())
}

pub fn previous(_h: &Helper, r: &Handlebars, rc: &mut RenderContext) -> Result<(), RenderError> {
trace!("previous (handlebars helper)");
pub struct Previous {
pub rewrite_to_dir: Vec<String>,
}

if let Some(previous) = find_chapter(rc, Target::Previous)? {
render(_h, r, rc, &previous)?;
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 fn next(_h: &Helper, r: &Handlebars, rc: &mut RenderContext) -> Result<(), RenderError> {
trace!("next (handlebars helper)");
pub struct Next {
pub rewrite_to_dir: Vec<String>,
}

if let Some(next) = find_chapter(rc, Target::Next)? {
render(_h, r, rc, &next)?;
impl Default for Next {
fn default() -> Self {
Self { rewrite_to_dir: vec![] }
}
}

Ok(())
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)]
Expand Down Expand Up @@ -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(),
Expand Down Expand Up @@ -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(),
Expand Down Expand Up @@ -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(),
Expand Down
11 changes: 8 additions & 3 deletions src/renderer/html_handlebars/helpers/toc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ 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
#[derive(Clone, Copy)]
pub struct RenderToc {
pub no_section_label: bool,
pub rewrite_to_dir: Vec<String>,
}

impl HelperDef for RenderToc {
Expand Down Expand Up @@ -69,8 +71,11 @@ impl HelperDef for RenderToc {
if !path.is_empty() {
rc.writer.write_all(b"<a href=\"")?;

let tmp = Path::new(item.get("path").expect("Error: path should be Some(_)"))
.with_extension("html")
let tmp = {
// To be recognized by browsers, rewrite extenstion to `.html`.
let path = Path::new(path).with_extension("html");
rewrite_to_dir_index(&path, &self.rewrite_to_dir)
}
.to_str()
.unwrap()
// Hack for windows who tends to use `\` as separator instead of `/`
Expand Down