diff --git a/Cargo.toml b/Cargo.toml index cc2f11ef..9451e2f2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,9 +16,9 @@ exclude = [ [dependencies] clap = "2.19.2" -handlebars = { version = "0.23.0", features = ["serde_type"] } -serde = "0.8" -serde_json = "0.8" +handlebars = { version = "0.25.0", features = ["serde_type"] } +serde = "0.9" +serde_json = "0.9" pulldown-cmark = "0.0.8" log = "0.3" env_logger = "0.3" diff --git a/src/book/bookconfig.rs b/src/book/bookconfig.rs index 63c668d1..f0c2f241 100644 --- a/src/book/bookconfig.rs +++ b/src/book/bookconfig.rs @@ -214,9 +214,9 @@ pub fn json_value_to_toml_value(json: serde_json::Value) -> toml::Value { match json { serde_json::Value::Null => toml::Value::String("".to_string()), serde_json::Value::Bool(x) => toml::Value::Boolean(x), - serde_json::Value::I64(x) => toml::Value::Integer(x), - serde_json::Value::U64(x) => toml::Value::Integer(x as i64), - serde_json::Value::F64(x) => toml::Value::Float(x), + serde_json::Value::Number(ref x) if x.is_i64() => toml::Value::Integer(x.as_i64().unwrap()), + serde_json::Value::Number(ref x) if x.is_u64() => toml::Value::Integer(x.as_i64().unwrap()), + serde_json::Value::Number(x) => toml::Value::Float(x.as_f64().unwrap()), serde_json::Value::String(x) => toml::Value::String(x), serde_json::Value::Array(x) => { toml::Value::Array(x.iter().map(|v| json_value_to_toml_value(v.to_owned())).collect()) diff --git a/src/book/bookitem.rs b/src/book/bookitem.rs index 2d5bf976..bebd73bd 100644 --- a/src/book/bookitem.rs +++ b/src/book/bookitem.rs @@ -1,4 +1,5 @@ use serde::{Serialize, Serializer}; +use serde::ser::SerializeStruct; use std::path::PathBuf; #[derive(Debug, Clone)] @@ -36,11 +37,11 @@ impl Chapter { impl Serialize for Chapter { - fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer { - let mut state = try!(serializer.serialize_struct("Chapter", 2)); - try!(serializer.serialize_struct_elt(&mut state, "name", self.name.clone())); - try!(serializer.serialize_struct_elt(&mut state, "path", self.path.clone())); - serializer.serialize_struct_end(state) + fn serialize(&self, serializer: S) -> Result where S: Serializer { + let mut struct_ = try!(serializer.serialize_struct("Chapter", 2)); + try!(struct_.serialize_field("name", &self.name)); + try!(struct_.serialize_field("path", &self.path)); + struct_.end() } } diff --git a/src/lib.rs b/src/lib.rs index f85de104..0a59f9e7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -70,6 +70,7 @@ //! Make sure to take a look at it. extern crate serde; +#[macro_use] extern crate serde_json; extern crate handlebars; extern crate pulldown_cmark; diff --git a/src/renderer/html_handlebars/hbs_renderer.rs b/src/renderer/html_handlebars/hbs_renderer.rs index 68f6c475..b122ed14 100644 --- a/src/renderer/html_handlebars/hbs_renderer.rs +++ b/src/renderer/html_handlebars/hbs_renderer.rs @@ -13,7 +13,6 @@ use std::collections::BTreeMap; use handlebars::Handlebars; use serde_json; -use serde_json::value::ToJson; pub struct HtmlHandlebars; @@ -84,10 +83,10 @@ impl Renderer for HtmlHandlebars { // Update the context with data for this file let path = ch.path.to_str().ok_or(io::Error::new(io::ErrorKind::Other, "Could not convert path to str"))?; - data.insert("path".to_owned(), path.to_json()); - data.insert("content".to_owned(), content.to_json()); - data.insert("chapter_title".to_owned(), ch.name.to_json()); - data.insert("path_to_root".to_owned(), utils::fs::path_to_root(&ch.path).to_json()); + data.insert("path".to_owned(), json!(path)); + data.insert("content".to_owned(), json!(content)); + data.insert("chapter_title".to_owned(), json!(ch.name)); + data.insert("path_to_root".to_owned(), json!(utils::fs::path_to_root(&ch.path))); // Render the handlebars template with the data debug!("[*]: Render template"); @@ -128,9 +127,9 @@ impl Renderer for HtmlHandlebars { // Print version // Update the context with data for this file - data.insert("path".to_owned(), "print.md".to_json()); - data.insert("content".to_owned(), print_content.to_json()); - data.insert("path_to_root".to_owned(), utils::fs::path_to_root(Path::new("print.md")).to_json()); + data.insert("path".to_owned(), json!("print.md")); + data.insert("content".to_owned(), json!(print_content)); + data.insert("path_to_root".to_owned(), json!(utils::fs::path_to_root(Path::new("print.md")))); // Render the handlebars template with the data debug!("[*]: Render template"); @@ -167,12 +166,12 @@ fn make_data(book: &MDBook) -> Result debug!("[fn]: make_data"); let mut data = serde_json::Map::new(); - data.insert("language".to_owned(), "en".to_json()); - data.insert("title".to_owned(), book.get_title().to_json()); - data.insert("description".to_owned(), book.get_description().to_json()); - data.insert("favicon".to_owned(), "favicon.png".to_json()); + data.insert("language".to_owned(), json!("en")); + data.insert("title".to_owned(), json!(book.get_title())); + data.insert("description".to_owned(), json!(book.get_description())); + data.insert("favicon".to_owned(), json!("favicon.png")); if let Some(livereload) = book.get_livereload() { - data.insert("livereload".to_owned(), livereload.to_json()); + data.insert("livereload".to_owned(), json!(livereload)); } let mut chapters = vec![]; @@ -183,20 +182,20 @@ fn make_data(book: &MDBook) -> Result match *item { BookItem::Affix(ref ch) => { - chapter.insert("name".to_owned(), ch.name.to_json()); + chapter.insert("name".to_owned(), json!(ch.name)); let path = ch.path.to_str().ok_or(io::Error::new(io::ErrorKind::Other, "Could not convert path to str"))?; - chapter.insert("path".to_owned(), path.to_json()); + chapter.insert("path".to_owned(), json!(path)); }, BookItem::Chapter(ref s, ref ch) => { - chapter.insert("section".to_owned(), s.to_json()); - chapter.insert("name".to_owned(), ch.name.to_json()); + chapter.insert("section".to_owned(), json!(s)); + chapter.insert("name".to_owned(), json!(ch.name)); let path = ch.path.to_str().ok_or(io::Error::new(io::ErrorKind::Other, "Could not convert path to str"))?; - chapter.insert("path".to_owned(), path.to_json()); + chapter.insert("path".to_owned(), json!(path)); }, BookItem::Spacer => { - chapter.insert("spacer".to_owned(), "_spacer_".to_json()); + chapter.insert("spacer".to_owned(), json!("_spacer_")); }, } @@ -204,7 +203,7 @@ fn make_data(book: &MDBook) -> Result chapters.push(chapter); } - data.insert("chapters".to_owned(), chapters.to_json()); + data.insert("chapters".to_owned(), json!(chapters)); debug!("[*]: JSON constructed"); Ok(data) diff --git a/src/renderer/html_handlebars/helpers/navigation.rs b/src/renderer/html_handlebars/helpers/navigation.rs index 58c90100..50dd7a4a 100644 --- a/src/renderer/html_handlebars/helpers/navigation.rs +++ b/src/renderer/html_handlebars/helpers/navigation.rs @@ -2,22 +2,21 @@ use std::path::Path; use std::collections::{VecDeque, BTreeMap}; use serde_json; -use serde_json::value::ToJson; -use handlebars::{Handlebars, RenderError, RenderContext, Helper, Context, Renderable}; +use handlebars::{Handlebars, RenderError, RenderContext, Helper, Renderable}; // Handlebars helper for navigation -pub fn previous(c: &Context, _h: &Helper, r: &Handlebars, rc: &mut RenderContext) -> Result<(), RenderError> { +pub fn previous(_h: &Helper, r: &Handlebars, rc: &mut RenderContext) -> Result<(), RenderError> { debug!("[fn]: previous (handlebars helper)"); debug!("[*]: Get data from context"); // get value from context data // 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 - let chapters = c.navigate(rc.get_path(), &VecDeque::new(), "chapters"); + let chapters = rc.context().navigate(rc.get_path(), &VecDeque::new(), "chapters").to_owned(); - let current = c.navigate(rc.get_path(), &VecDeque::new(), "path") + let current = rc.context().navigate(rc.get_path(), &VecDeque::new(), "path") .to_string() .replace("\"", ""); @@ -50,7 +49,7 @@ pub fn previous(c: &Context, _h: &Helper, r: &Handlebars, rc: &mut RenderContext match previous.get("name") { Some(n) => { debug!("[*]: Inserting title: {}", n); - previous_chapter.insert("title".to_owned(), n.to_json()) + previous_chapter.insert("title".to_owned(), json!(n)) }, None => { debug!("[*]: No title found for chapter"); @@ -68,7 +67,7 @@ pub fn previous(c: &Context, _h: &Helper, r: &Handlebars, rc: &mut RenderContext match path.to_str() { Some(p) => { - previous_chapter.insert("link".to_owned(), p.replace("\\", "/").to_json()); + previous_chapter.insert("link".to_owned(), json!(p.replace("\\", "/"))); }, None => return Err(RenderError::new("Link could not be converted to str")), } @@ -78,13 +77,14 @@ pub fn previous(c: &Context, _h: &Helper, r: &Handlebars, rc: &mut RenderContext debug!("[*]: Inject in context"); // Inject in current context - let updated_context = c.extend(&previous_chapter); + let updated_context = rc.context().extend(&previous_chapter); debug!("[*]: Render template"); // Render template match _h.template() { Some(t) => { - try!(t.render(&updated_context, r, rc)); + *rc.context_mut() = updated_context; + try!(t.render(r, rc)); }, None => return Err(RenderError::new("Error with the handlebars template")), } @@ -108,16 +108,16 @@ pub fn previous(c: &Context, _h: &Helper, r: &Handlebars, rc: &mut RenderContext -pub fn next(c: &Context, _h: &Helper, r: &Handlebars, rc: &mut RenderContext) -> Result<(), RenderError> { +pub fn next(_h: &Helper, r: &Handlebars, rc: &mut RenderContext) -> Result<(), RenderError> { debug!("[fn]: next (handlebars helper)"); debug!("[*]: Get data from context"); // get value from context data // 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 - let chapters = c.navigate(rc.get_path(), &VecDeque::new(), "chapters"); + let chapters = rc.context().navigate(rc.get_path(), &VecDeque::new(), "chapters").to_owned(); - let current = c.navigate(rc.get_path(), &VecDeque::new(), "path") + let current = rc.context().navigate(rc.get_path(), &VecDeque::new(), "path") .to_string() .replace("\"", ""); @@ -154,7 +154,7 @@ pub fn next(c: &Context, _h: &Helper, r: &Handlebars, rc: &mut RenderContext) -> match item.get("name") { Some(n) => { debug!("[*]: Inserting title: {}", n); - next_chapter.insert("title".to_owned(), n.to_json()); + next_chapter.insert("title".to_owned(), json!(n)); }, None => return Err(RenderError::new("No title found for chapter in JSON data")), } @@ -166,21 +166,22 @@ pub fn next(c: &Context, _h: &Helper, r: &Handlebars, rc: &mut RenderContext) -> match link.to_str() { Some(l) => { // Hack for windows who tends to use `\` as separator instead of `/` - next_chapter.insert("link".to_owned(), l.replace("\\", "/").to_json()); + next_chapter.insert("link".to_owned(), json!(l.replace("\\", "/"))); }, None => return Err(RenderError::new("Link could not converted to str")), } debug!("[*]: Inject in context"); // Inject in current context - let updated_context = c.extend(&next_chapter); + let updated_context = rc.context().extend(&next_chapter); debug!("[*]: Render template"); // Render template match _h.template() { Some(t) => { - try!(t.render(&updated_context, r, rc)); + *rc.context_mut() = updated_context; + try!(t.render(r, rc)); }, None => return Err(RenderError::new("Error with the handlebars template")), } diff --git a/src/renderer/html_handlebars/helpers/toc.rs b/src/renderer/html_handlebars/helpers/toc.rs index 07a6b36d..7d19dfff 100644 --- a/src/renderer/html_handlebars/helpers/toc.rs +++ b/src/renderer/html_handlebars/helpers/toc.rs @@ -2,7 +2,7 @@ use std::path::Path; use std::collections::{VecDeque, BTreeMap}; use serde_json; -use handlebars::{Handlebars, HelperDef, RenderError, RenderContext, Helper, Context}; +use handlebars::{Handlebars, HelperDef, RenderError, RenderContext, Helper}; use pulldown_cmark::{Parser, html, Event, Tag}; // Handlebars helper to construct TOC @@ -10,13 +10,13 @@ use pulldown_cmark::{Parser, html, Event, Tag}; pub struct RenderToc; impl HelperDef for RenderToc { - fn call(&self, c: &Context, _h: &Helper, _: &Handlebars, rc: &mut RenderContext) -> Result<(), RenderError> { + fn call(&self, _h: &Helper, _: &Handlebars, rc: &mut RenderContext) -> Result<(), RenderError> { // get value from context data // 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 - let chapters = c.navigate(rc.get_path(), &VecDeque::new(), "chapters"); - let current = c.navigate(rc.get_path(), &VecDeque::new(), "path").to_string().replace("\"", ""); + let chapters = rc.context().navigate(rc.get_path(), &VecDeque::new(), "chapters").to_owned(); + let current = rc.context().navigate(rc.get_path(), &VecDeque::new(), "path").to_string().replace("\"", ""); try!(rc.writer.write("
    ".as_bytes())); // Decode json format