2 use std
::collections
::BTreeMap
;
5 use handlebars
::{Context, Handlebars, Helper, RenderContext, RenderError, Renderable}
;
7 type StringMap
= BTreeMap
<String
, String
>;
9 /// Target for `find_chapter`.
16 /// Returns target if found.
20 current_path
: &String
,
21 current_item
: &StringMap
,
22 previous_item
: &StringMap
,
23 ) -> Result
<Option
<StringMap
>, RenderError
> {
26 let previous_path
= previous_item
28 .ok_or_else(|| RenderError
::new("No path found for chapter in JSON data"))?
;
30 if previous_path
== base_path
{
31 return Ok(Some(current_item
.clone()));
35 &Target
::Previous
=> {
36 if current_path
== base_path
{
37 return Ok(Some(previous_item
.clone()));
46 fn find_chapter(rc
: &mut RenderContext
, target
: Target
) -> Result
<Option
<StringMap
>, RenderError
> {
47 debug
!("Get data from context");
49 let chapters
= rc
.evaluate_absolute("chapters", true).and_then(|c
| {
50 serde_json
::value
::from_value
::<Vec
<StringMap
>>(c
.clone())
51 .map_err(|_
| RenderError
::new("Could not decode the JSON data"))
54 let base_path
= rc
.evaluate_absolute("path", true)?
56 .ok_or_else(|| RenderError
::new("Type error for `path`, string expected"))?
59 let mut previous
: Option
<StringMap
> = None
;
61 debug
!("Search for chapter");
63 for item
in chapters
{
64 match item
.get("path") {
65 Some(path
) if !path
.is_empty() => {
66 if let Some(previous
) = previous
{
67 if let Some(item
) = target
.find(&base_path
, &path
, &item
, &previous
)?
{
68 return Ok(Some(item
));
72 previous
= Some(item
.clone());
84 rc
: &mut RenderContext
,
86 ) -> Result
<(), RenderError
> {
87 trace
!("Creating BTreeMap to inject in context");
89 let mut context
= BTreeMap
::new();
93 .ok_or_else(|| RenderError
::new("No title found for chapter in JSON data"))
94 .map(|name
| context
.insert("title".to_owned(), json
!(name
)))?
;
98 .ok_or_else(|| RenderError
::new("No path found for chapter in JSON data"))
101 .with_extension("html")
103 .ok_or_else(|| RenderError
::new("Link could not be converted to str"))
104 .map(|p
| context
.insert("link".to_owned(), json
!(p
.replace("\\", "/"))))
107 trace
!("Render template");
110 .ok_or_else(|| RenderError
::new("Error with the handlebars template"))
112 let mut local_rc
= rc
.with_context(Context
::wraps(&context
)?
);
113 t
.render(r
, &mut local_rc
)
119 pub fn previous(_h
: &Helper
, r
: &Handlebars
, rc
: &mut RenderContext
) -> Result
<(), RenderError
> {
120 trace
!("previous (handlebars helper)");
122 if let Some(previous
) = find_chapter(rc
, Target
::Previous
)?
{
123 render(_h
, r
, rc
, &previous
)?
;
129 pub fn next(_h
: &Helper
, r
: &Handlebars
, rc
: &mut RenderContext
) -> Result
<(), RenderError
> {
130 trace
!("next (handlebars helper)");
132 if let Some(next
) = find_chapter(rc
, Target
::Next
)?
{
133 render(_h
, r
, rc
, &next
)?
;
143 static TEMPLATE
: &'
static str =
144 "{{#previous}}{{title}}: {{link}}{{/previous}}|{{#next}}{{title}}: {{link}}{{/next}}";
147 fn test_next_previous() {
167 let mut h
= Handlebars
::new();
168 h
.register_helper("previous", Box
::new(previous
));
169 h
.register_helper("next", Box
::new(next
));
172 h
.render_template(TEMPLATE
, &data
).unwrap(),
173 "one: one.html|three: three.html"
198 let mut h
= Handlebars
::new();
199 h
.register_helper("previous", Box
::new(previous
));
200 h
.register_helper("next", Box
::new(next
));
203 h
.render_template(TEMPLATE
, &data
).unwrap(),
211 "path": "three.path",
228 let mut h
= Handlebars
::new();
229 h
.register_helper("previous", Box
::new(previous
));
230 h
.register_helper("next", Box
::new(next
));
233 h
.render_template(TEMPLATE
, &data
).unwrap(),