(refactor) rework helpers based on new handlebars api
Signed-off-by: Ning Sun <sunng@about.me>
This commit is contained in:
parent
2bb274d424
commit
6ee6da074e
|
@ -1,8 +1,8 @@
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::collections::{VecDeque, BTreeMap};
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
use serde_json;
|
use serde_json;
|
||||||
use handlebars::{Handlebars, RenderError, RenderContext, Helper, Renderable};
|
use handlebars::{Handlebars, RenderError, RenderContext, Helper, Renderable, Context};
|
||||||
|
|
||||||
|
|
||||||
// Handlebars helper for navigation
|
// Handlebars helper for navigation
|
||||||
|
@ -11,31 +11,22 @@ pub fn previous(_h: &Helper, r: &Handlebars, rc: &mut RenderContext) -> Result<(
|
||||||
debug!("[fn]: previous (handlebars helper)");
|
debug!("[fn]: previous (handlebars helper)");
|
||||||
|
|
||||||
debug!("[*]: Get data from context");
|
debug!("[*]: Get data from context");
|
||||||
// get value from context data
|
let chapters = rc.evaluate_absolute("chapters")
|
||||||
// rc.get_path() is current json parent path, you should always use it like this
|
.and_then(|c| {
|
||||||
// param is the key of value you want to display
|
serde_json::value::from_value::<Vec<BTreeMap<String, String>>>(c.clone())
|
||||||
let chapters = rc.context()
|
.map_err(|_| RenderError::new("Could not decode the JSON data"))
|
||||||
.navigate(rc.get_path(), &VecDeque::new(), "chapters")?
|
})?;
|
||||||
.to_owned();
|
|
||||||
|
|
||||||
let current = rc.context()
|
let current = rc.evaluate_absolute("path")?
|
||||||
.navigate(rc.get_path(), &VecDeque::new(), "path")?
|
.as_str()
|
||||||
.to_string()
|
.ok_or(RenderError::new("Type error for `path`, string expected"))?
|
||||||
.replace("\"", "");
|
.replace("\"", "");
|
||||||
|
|
||||||
|
|
||||||
debug!("[*]: Decode chapters from JSON");
|
|
||||||
// Decode json format
|
|
||||||
let decoded: Vec<BTreeMap<String, String>> = match serde_json::from_str(&chapters.to_string()) {
|
|
||||||
Ok(data) => data,
|
|
||||||
Err(_) => return Err(RenderError::new("Could not decode the JSON data")),
|
|
||||||
};
|
|
||||||
let mut previous: Option<BTreeMap<String, String>> = None;
|
let mut previous: Option<BTreeMap<String, String>> = None;
|
||||||
|
|
||||||
|
|
||||||
debug!("[*]: Search for current Chapter");
|
debug!("[*]: Search for current Chapter");
|
||||||
// Search for current chapter and return previous entry
|
// Search for current chapter and return previous entry
|
||||||
for item in decoded {
|
for item in chapters {
|
||||||
|
|
||||||
match item.get("path") {
|
match item.get("path") {
|
||||||
Some(path) if !path.is_empty() => {
|
Some(path) if !path.is_empty() => {
|
||||||
|
@ -49,51 +40,41 @@ pub fn previous(_h: &Helper, r: &Handlebars, rc: &mut RenderContext) -> Result<(
|
||||||
let mut previous_chapter = BTreeMap::new();
|
let mut previous_chapter = BTreeMap::new();
|
||||||
|
|
||||||
// Chapter title
|
// Chapter title
|
||||||
match previous.get("name") {
|
previous
|
||||||
Some(n) => {
|
.get("name")
|
||||||
debug!("[*]: Inserting title: {}", n);
|
.ok_or(RenderError::new("No title found for chapter in JSON data"))
|
||||||
previous_chapter.insert("title".to_owned(), json!(n))
|
.and_then(|n| {
|
||||||
},
|
previous_chapter.insert("title".to_owned(), json!(n));
|
||||||
None => {
|
Ok(())
|
||||||
debug!("[*]: No title found for chapter");
|
})?;
|
||||||
return Err(RenderError::new("No title found for chapter in JSON data"));
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
// Chapter link
|
// Chapter link
|
||||||
|
previous
|
||||||
|
.get("path")
|
||||||
|
.ok_or(RenderError::new("No path found for chapter in JSON data"))
|
||||||
|
.and_then(|p| {
|
||||||
|
Path::new(p)
|
||||||
|
.with_extension("html")
|
||||||
|
.to_str()
|
||||||
|
.ok_or(RenderError::new("Link could not be converted to str"))
|
||||||
|
.and_then(|p| {
|
||||||
|
previous_chapter
|
||||||
|
.insert("link".to_owned(), json!(p.replace("\\", "/")));
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
})?;
|
||||||
|
|
||||||
match previous.get("path") {
|
|
||||||
Some(p) => {
|
|
||||||
// Hack for windows who tends to use `\` as separator instead of `/`
|
|
||||||
let path = Path::new(p).with_extension("html");
|
|
||||||
debug!("[*]: Inserting link: {:?}", path);
|
|
||||||
|
|
||||||
match path.to_str() {
|
|
||||||
Some(p) => {
|
|
||||||
previous_chapter.insert("link".to_owned(), json!(p.replace("\\", "/")));
|
|
||||||
},
|
|
||||||
None => return Err(RenderError::new("Link could not be converted to str")),
|
|
||||||
}
|
|
||||||
},
|
|
||||||
None => return Err(RenderError::new("No path found for chapter in JSON data")),
|
|
||||||
}
|
|
||||||
|
|
||||||
debug!("[*]: Inject in context");
|
|
||||||
// Inject in current context
|
|
||||||
let updated_context = rc.context().extend(&previous_chapter);
|
|
||||||
|
|
||||||
debug!("[*]: Render template");
|
debug!("[*]: Render template");
|
||||||
// Render template
|
// Render template
|
||||||
match _h.template() {
|
_h.template()
|
||||||
Some(t) => {
|
.ok_or(RenderError::new("Error with the handlebars template"))
|
||||||
*rc.context_mut() = updated_context;
|
.and_then(|t| {
|
||||||
t.render(r, rc)?;
|
let mut local_rc = rc.with_context(Context::wraps(&previous_chapter));
|
||||||
},
|
t.render(r, &mut local_rc)
|
||||||
None => return Err(RenderError::new("Error with the handlebars template")),
|
})?;
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
previous = Some(item.clone());
|
previous = Some(item.clone());
|
||||||
|
@ -102,7 +83,6 @@ pub fn previous(_h: &Helper, r: &Handlebars, rc: &mut RenderContext) -> Result<(
|
||||||
_ => continue,
|
_ => continue,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -115,29 +95,21 @@ pub fn next(_h: &Helper, r: &Handlebars, rc: &mut RenderContext) -> Result<(), R
|
||||||
debug!("[fn]: next (handlebars helper)");
|
debug!("[fn]: next (handlebars helper)");
|
||||||
|
|
||||||
debug!("[*]: Get data from context");
|
debug!("[*]: Get data from context");
|
||||||
// get value from context data
|
let chapters = rc.evaluate_absolute("chapters")
|
||||||
// rc.get_path() is current json parent path, you should always use it like this
|
.and_then(|c| {
|
||||||
// param is the key of value you want to display
|
serde_json::value::from_value::<Vec<BTreeMap<String, String>>>(c.clone())
|
||||||
let chapters = rc.context()
|
.map_err(|_| RenderError::new("Could not decode the JSON data"))
|
||||||
.navigate(rc.get_path(), &VecDeque::new(), "chapters")?
|
})?;
|
||||||
.to_owned();
|
let current = rc.evaluate_absolute("path")?
|
||||||
|
.as_str()
|
||||||
let current = rc.context()
|
.ok_or(RenderError::new("Type error for `path`, string expected"))?
|
||||||
.navigate(rc.get_path(), &VecDeque::new(), "path")?
|
|
||||||
.to_string()
|
|
||||||
.replace("\"", "");
|
.replace("\"", "");
|
||||||
|
|
||||||
debug!("[*]: Decode chapters from JSON");
|
|
||||||
// Decode json format
|
|
||||||
let decoded: Vec<BTreeMap<String, String>> = match serde_json::from_str(&chapters.to_string()) {
|
|
||||||
Ok(data) => data,
|
|
||||||
Err(_) => return Err(RenderError::new("Could not decode the JSON data")),
|
|
||||||
};
|
|
||||||
let mut previous: Option<BTreeMap<String, String>> = None;
|
let mut previous: Option<BTreeMap<String, String>> = None;
|
||||||
|
|
||||||
debug!("[*]: Search for current Chapter");
|
debug!("[*]: Search for current Chapter");
|
||||||
// Search for current chapter and return previous entry
|
// Search for current chapter and return previous entry
|
||||||
for item in decoded {
|
for item in chapters {
|
||||||
|
|
||||||
match item.get("path") {
|
match item.get("path") {
|
||||||
|
|
||||||
|
@ -145,10 +117,9 @@ pub fn next(_h: &Helper, r: &Handlebars, rc: &mut RenderContext) -> Result<(), R
|
||||||
|
|
||||||
if let Some(previous) = previous {
|
if let Some(previous) = previous {
|
||||||
|
|
||||||
let previous_path = match previous.get("path") {
|
let previous_path = previous
|
||||||
Some(p) => p,
|
.get("path")
|
||||||
None => return Err(RenderError::new("No path found for chapter in JSON data")),
|
.ok_or(RenderError::new("No path found for chapter in JSON data"))?;
|
||||||
};
|
|
||||||
|
|
||||||
if previous_path == ¤t {
|
if previous_path == ¤t {
|
||||||
|
|
||||||
|
@ -157,41 +128,33 @@ pub fn next(_h: &Helper, r: &Handlebars, rc: &mut RenderContext) -> Result<(), R
|
||||||
// Create new BTreeMap to extend the context: 'title' and 'link'
|
// Create new BTreeMap to extend the context: 'title' and 'link'
|
||||||
let mut next_chapter = BTreeMap::new();
|
let mut next_chapter = BTreeMap::new();
|
||||||
|
|
||||||
match item.get("name") {
|
item.get("name")
|
||||||
Some(n) => {
|
.ok_or(RenderError::new("No title found for chapter in JSON data"))
|
||||||
debug!("[*]: Inserting title: {}", n);
|
.and_then(|n| {
|
||||||
next_chapter.insert("title".to_owned(), json!(n));
|
next_chapter.insert("title".to_owned(), json!(n));
|
||||||
},
|
Ok(())
|
||||||
None => return Err(RenderError::new("No title found for chapter in JSON data")),
|
})?;
|
||||||
}
|
|
||||||
|
|
||||||
|
Path::new(path)
|
||||||
let link = Path::new(path).with_extension("html");
|
.with_extension("html")
|
||||||
debug!("[*]: Inserting link: {:?}", link);
|
.to_str()
|
||||||
|
.ok_or(RenderError::new("Link could not converted to str"))
|
||||||
match link.to_str() {
|
.and_then(|l| {
|
||||||
Some(l) => {
|
debug!("[*]: Inserting link: {:?}", l);
|
||||||
// Hack for windows who tends to use `\` as separator instead of `/`
|
// Hack for windows who tends to use `\` as separator instead of `/`
|
||||||
next_chapter.insert("link".to_owned(), json!(l.replace("\\", "/")));
|
next_chapter.insert("link".to_owned(), json!(l.replace("\\", "/")));
|
||||||
},
|
Ok(())
|
||||||
None => return Err(RenderError::new("Link could not converted to str")),
|
})?;
|
||||||
}
|
|
||||||
|
|
||||||
debug!("[*]: Inject in context");
|
|
||||||
// Inject in current context
|
|
||||||
let updated_context = rc.context().extend(&next_chapter);
|
|
||||||
|
|
||||||
debug!("[*]: Render template");
|
debug!("[*]: Render template");
|
||||||
|
|
||||||
// Render template
|
// Render template
|
||||||
match _h.template() {
|
_h.template()
|
||||||
Some(t) => {
|
.ok_or(RenderError::new("Error with the handlebars template"))
|
||||||
*rc.context_mut() = updated_context;
|
.and_then(|t| {
|
||||||
t.render(r, rc)?;
|
let mut local_rc = rc.with_context(Context::wraps(&next_chapter));
|
||||||
},
|
t.render(r, &mut local_rc)
|
||||||
None => return Err(RenderError::new("Error with the handlebars template")),
|
})?;
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,21 +15,21 @@ impl HelperDef for RenderToc {
|
||||||
// get value from context data
|
// get value from context data
|
||||||
// rc.get_path() is current json parent path, you should always use it like this
|
// rc.get_path() is current json parent path, you should always use it like this
|
||||||
// param is the key of value you want to display
|
// param is the key of value you want to display
|
||||||
let chapters = rc.context()
|
let chapters = rc.evaluate_absolute("chapters")
|
||||||
.navigate(rc.get_path(), &VecDeque::new(), "chapters")?
|
.and_then(|c| {
|
||||||
.to_owned();
|
serde_json::value::from_value::<Vec<BTreeMap<String, String>>>(c.clone())
|
||||||
let current = rc.context()
|
.map_err(|_| RenderError::new("Could not decode the JSON data"))
|
||||||
.navigate(rc.get_path(), &VecDeque::new(), "path")
|
})?;
|
||||||
.to_string()
|
let current = rc.evaluate_absolute("path")?
|
||||||
|
.as_str()
|
||||||
|
.ok_or(RenderError::new("Type error for `path`, string expected"))?
|
||||||
.replace("\"", "");
|
.replace("\"", "");
|
||||||
rc.writer.write_all("<ul class=\"chapter\">".as_bytes())?;
|
|
||||||
|
|
||||||
// Decode json format
|
rc.writer.write_all("<ul class=\"chapter\">".as_bytes())?;
|
||||||
let decoded: Vec<BTreeMap<String, String>> = serde_json::from_str(&chapters.to_string()).unwrap();
|
|
||||||
|
|
||||||
let mut current_level = 1;
|
let mut current_level = 1;
|
||||||
|
|
||||||
for item in decoded {
|
for item in chatpers {
|
||||||
|
|
||||||
// Spacer
|
// Spacer
|
||||||
if item.get("spacer").is_some() {
|
if item.get("spacer").is_some() {
|
||||||
|
|
Loading…
Reference in New Issue