2015-09-05 17:26:17 +02:00
|
|
|
use std::path::Path;
|
2017-06-03 14:06:09 +08:00
|
|
|
use std::collections::BTreeMap;
|
2015-07-31 18:34:43 +02:00
|
|
|
|
2016-11-03 01:58:42 +01:00
|
|
|
use serde_json;
|
2017-10-03 17:25:23 +05:45
|
|
|
use handlebars::{Context, Handlebars, Helper, RenderContext, RenderError, Renderable};
|
2015-07-31 18:34:43 +02:00
|
|
|
|
2016-12-23 08:10:42 +00:00
|
|
|
|
2015-07-31 18:34:43 +02:00
|
|
|
// Handlebars helper for navigation
|
|
|
|
|
|
2017-02-15 22:34:37 -05:00
|
|
|
pub fn previous(_h: &Helper, r: &Handlebars, rc: &mut RenderContext) -> Result<(), RenderError> {
|
2015-08-03 22:09:26 +02:00
|
|
|
debug!("[fn]: previous (handlebars helper)");
|
2015-07-31 18:34:43 +02:00
|
|
|
|
2015-08-03 22:09:26 +02:00
|
|
|
debug!("[*]: Get data from context");
|
2017-10-03 17:25:23 +05:45
|
|
|
let chapters = rc.evaluate_absolute("chapters").and_then(|c| {
|
|
|
|
|
serde_json::value::from_value::<Vec<BTreeMap<String, String>>>(c.clone())
|
|
|
|
|
.map_err(|_| RenderError::new("Could not decode the JSON data"))
|
|
|
|
|
})?;
|
2017-06-03 14:06:09 +08:00
|
|
|
|
|
|
|
|
let current = rc.evaluate_absolute("path")?
|
2017-10-03 17:25:23 +05:45
|
|
|
.as_str()
|
|
|
|
|
.ok_or_else(|| RenderError::new("Type error for `path`, string expected"))?
|
|
|
|
|
.replace("\"", "");
|
2015-07-31 18:34:43 +02:00
|
|
|
|
2015-08-03 22:09:26 +02:00
|
|
|
let mut previous: Option<BTreeMap<String, String>> = None;
|
2015-07-31 18:34:43 +02:00
|
|
|
|
2015-08-03 22:09:26 +02:00
|
|
|
debug!("[*]: Search for current Chapter");
|
|
|
|
|
// Search for current chapter and return previous entry
|
2017-06-03 14:06:09 +08:00
|
|
|
for item in chapters {
|
2015-08-03 22:09:26 +02:00
|
|
|
match item.get("path") {
|
2015-09-16 22:46:23 -04:00
|
|
|
Some(path) if !path.is_empty() => {
|
2015-07-31 18:34:43 +02:00
|
|
|
if path == ¤t {
|
2015-08-03 22:09:26 +02:00
|
|
|
debug!("[*]: Found current chapter");
|
2016-03-17 22:31:28 +01:00
|
|
|
if let Some(previous) = previous {
|
2015-08-03 22:09:26 +02:00
|
|
|
debug!("[*]: Creating BTreeMap to inject in context");
|
|
|
|
|
// Create new BTreeMap to extend the context: 'title' and 'link'
|
|
|
|
|
let mut previous_chapter = BTreeMap::new();
|
|
|
|
|
|
2015-08-11 22:55:51 +02:00
|
|
|
// Chapter title
|
2017-10-03 17:25:23 +05:45
|
|
|
previous.get("name")
|
|
|
|
|
.ok_or_else(|| {
|
|
|
|
|
RenderError::new("No title found for chapter in \
|
|
|
|
|
JSON data")
|
|
|
|
|
})
|
|
|
|
|
.and_then(|n| {
|
|
|
|
|
previous_chapter.insert("title".to_owned(), json!(n));
|
|
|
|
|
Ok(())
|
|
|
|
|
})?;
|
2017-06-03 14:06:09 +08:00
|
|
|
|
2015-08-11 22:55:51 +02:00
|
|
|
|
|
|
|
|
// Chapter link
|
2017-10-03 17:25:23 +05:45
|
|
|
previous.get("path")
|
|
|
|
|
.ok_or_else(|| {
|
|
|
|
|
RenderError::new("No path found for chapter in \
|
|
|
|
|
JSON data")
|
|
|
|
|
})
|
|
|
|
|
.and_then(|p| {
|
|
|
|
|
Path::new(p).with_extension("html")
|
|
|
|
|
.to_str()
|
|
|
|
|
.ok_or_else(|| {
|
|
|
|
|
RenderError::new("Link could not be \
|
|
|
|
|
converted to str")
|
|
|
|
|
})
|
|
|
|
|
.and_then(|p| {
|
|
|
|
|
previous_chapter
|
|
|
|
|
.insert("link".to_owned(), json!(p.replace("\\", "/")));
|
|
|
|
|
Ok(())
|
|
|
|
|
})
|
|
|
|
|
})?;
|
2015-08-11 22:55:51 +02:00
|
|
|
|
2015-08-03 22:09:26 +02:00
|
|
|
|
|
|
|
|
debug!("[*]: Render template");
|
|
|
|
|
// Render template
|
2017-09-11 19:38:10 +02:00
|
|
|
_h.template()
|
2017-10-03 17:25:23 +05:45
|
|
|
.ok_or_else(|| RenderError::new("Error with the handlebars template"))
|
|
|
|
|
.and_then(|t| {
|
|
|
|
|
let mut local_rc = rc.with_context(Context::wraps(&previous_chapter)?);
|
|
|
|
|
t.render(r, &mut local_rc)
|
|
|
|
|
})?;
|
2015-08-03 22:09:26 +02:00
|
|
|
}
|
|
|
|
|
break;
|
2016-03-17 22:31:28 +01:00
|
|
|
} else {
|
2015-08-03 22:09:26 +02:00
|
|
|
previous = Some(item.clone());
|
|
|
|
|
}
|
2017-10-03 17:25:23 +05:45
|
|
|
}
|
2015-08-03 22:09:26 +02:00
|
|
|
_ => continue,
|
2015-07-31 18:34:43 +02:00
|
|
|
}
|
|
|
|
|
}
|
2015-08-11 22:55:51 +02:00
|
|
|
|
2015-07-31 18:34:43 +02:00
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-02-15 22:34:37 -05:00
|
|
|
pub fn next(_h: &Helper, r: &Handlebars, rc: &mut RenderContext) -> Result<(), RenderError> {
|
2015-08-04 12:51:07 +02:00
|
|
|
debug!("[fn]: next (handlebars helper)");
|
|
|
|
|
|
|
|
|
|
debug!("[*]: Get data from context");
|
2017-10-03 17:25:23 +05:45
|
|
|
let chapters = rc.evaluate_absolute("chapters").and_then(|c| {
|
|
|
|
|
serde_json::value::from_value::<Vec<BTreeMap<String, String>>>(c.clone())
|
|
|
|
|
.map_err(|_| RenderError::new("Could not decode the JSON data"))
|
|
|
|
|
})?;
|
2017-06-03 14:06:09 +08:00
|
|
|
let current = rc.evaluate_absolute("path")?
|
2017-10-03 17:25:23 +05:45
|
|
|
.as_str()
|
|
|
|
|
.ok_or_else(|| RenderError::new("Type error for `path`, string expected"))?
|
|
|
|
|
.replace("\"", "");
|
2015-08-04 12:51:07 +02:00
|
|
|
|
|
|
|
|
let mut previous: Option<BTreeMap<String, String>> = None;
|
2015-07-31 18:34:43 +02:00
|
|
|
|
2015-08-04 12:51:07 +02:00
|
|
|
debug!("[*]: Search for current Chapter");
|
|
|
|
|
// Search for current chapter and return previous entry
|
2017-06-03 14:06:09 +08:00
|
|
|
for item in chapters {
|
2015-08-04 12:51:07 +02:00
|
|
|
match item.get("path") {
|
2015-09-16 22:46:23 -04:00
|
|
|
Some(path) if !path.is_empty() => {
|
2015-08-04 12:51:07 +02:00
|
|
|
if let Some(previous) = previous {
|
2017-10-03 17:25:23 +05:45
|
|
|
let previous_path = previous.get("path").ok_or_else(|| {
|
|
|
|
|
RenderError::new("No path found for chapter in JSON data")
|
|
|
|
|
})?;
|
2015-08-11 22:55:51 +02:00
|
|
|
|
2015-08-12 19:22:53 +02:00
|
|
|
if previous_path == ¤t {
|
2015-08-04 12:51:07 +02:00
|
|
|
debug!("[*]: Found current chapter");
|
|
|
|
|
debug!("[*]: Creating BTreeMap to inject in context");
|
|
|
|
|
// Create new BTreeMap to extend the context: 'title' and 'link'
|
|
|
|
|
let mut next_chapter = BTreeMap::new();
|
|
|
|
|
|
2017-10-03 17:25:23 +05:45
|
|
|
item.get("name")
|
|
|
|
|
.ok_or_else(|| {
|
|
|
|
|
RenderError::new("No title found for chapter in JSON \
|
|
|
|
|
data")
|
|
|
|
|
})
|
2017-06-03 14:06:09 +08:00
|
|
|
.and_then(|n| {
|
|
|
|
|
next_chapter.insert("title".to_owned(), json!(n));
|
|
|
|
|
Ok(())
|
|
|
|
|
})?;
|
|
|
|
|
|
2017-10-03 17:25:23 +05:45
|
|
|
Path::new(path).with_extension("html")
|
|
|
|
|
.to_str()
|
|
|
|
|
.ok_or_else(|| {
|
|
|
|
|
RenderError::new("Link could not converted \
|
|
|
|
|
to str")
|
|
|
|
|
})
|
|
|
|
|
.and_then(|l| {
|
|
|
|
|
debug!("[*]: Inserting link: {:?}", l);
|
|
|
|
|
// Hack for windows who tends to use `\` as separator instead of `/`
|
|
|
|
|
next_chapter.insert("link".to_owned(), json!(l.replace("\\", "/")));
|
|
|
|
|
Ok(())
|
|
|
|
|
})?;
|
2015-08-04 12:51:07 +02:00
|
|
|
|
|
|
|
|
debug!("[*]: Render template");
|
2015-08-11 22:55:51 +02:00
|
|
|
|
2015-08-04 12:51:07 +02:00
|
|
|
// Render template
|
2017-10-03 17:25:23 +05:45
|
|
|
_h.template()
|
|
|
|
|
.ok_or_else(|| RenderError::new("Error with the handlebars template"))
|
|
|
|
|
.and_then(|t| {
|
|
|
|
|
let mut local_rc = rc.with_context(Context::wraps(&next_chapter)?);
|
|
|
|
|
t.render(r, &mut local_rc)
|
|
|
|
|
})?;
|
2016-03-17 22:31:28 +01:00
|
|
|
break;
|
2015-08-04 12:51:07 +02:00
|
|
|
}
|
2015-07-31 18:34:43 +02:00
|
|
|
}
|
2015-08-04 12:51:07 +02:00
|
|
|
|
|
|
|
|
previous = Some(item.clone());
|
2017-10-03 17:25:23 +05:45
|
|
|
}
|
2015-08-11 22:55:51 +02:00
|
|
|
|
2015-08-04 12:51:07 +02:00
|
|
|
_ => continue,
|
2015-07-31 18:34:43 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|