Merge pull request #2283 from sunng87/feature/hbd-5

feat: upgrade handlebars to 5.0
This commit is contained in:
Eric Huss 2024-01-04 21:00:18 +00:00 committed by GitHub
commit 59d3717159
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 63 additions and 31 deletions

4
Cargo.lock generated
View File

@ -610,9 +610,9 @@ dependencies = [
[[package]] [[package]]
name = "handlebars" name = "handlebars"
version = "4.5.0" version = "5.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "faa67bab9ff362228eb3d00bd024a4965d8231bbb7921167f0cfa66c6626b225" checksum = "94eae21d01d20dabef65d8eda734d83df6e2dea8166788804be9bd6bc92448fa"
dependencies = [ dependencies = [
"log", "log",
"pest", "pest",

View File

@ -23,7 +23,7 @@ clap = { version = "4.3.12", features = ["cargo", "wrap_help"] }
clap_complete = "4.3.2" clap_complete = "4.3.2"
once_cell = "1.17.1" once_cell = "1.17.1"
env_logger = "0.10.0" env_logger = "0.10.0"
handlebars = "4.3.7" handlebars = "5.0"
log = "0.4.17" log = "0.4.17"
memchr = "2.5.0" memchr = "2.5.0"
opener = "0.6.1" opener = "0.6.1"

View File

@ -1,7 +1,9 @@
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::path::Path; use std::path::Path;
use handlebars::{Context, Handlebars, Helper, Output, RenderContext, RenderError, Renderable}; use handlebars::{
Context, Handlebars, Helper, Output, RenderContext, RenderError, RenderErrorReason, Renderable,
};
use crate::utils; use crate::utils;
use log::{debug, trace}; use log::{debug, trace};
@ -26,9 +28,9 @@ impl Target {
) -> Result<Option<StringMap>, RenderError> { ) -> Result<Option<StringMap>, RenderError> {
match *self { match *self {
Target::Next => { Target::Next => {
let previous_path = previous_item let previous_path = previous_item.get("path").ok_or_else(|| {
.get("path") RenderErrorReason::Other("No path found for chapter in JSON data".to_owned())
.ok_or_else(|| RenderError::new("No path found for chapter in JSON data"))?; })?;
if previous_path == base_path { if previous_path == base_path {
return Ok(Some(current_item.clone())); return Ok(Some(current_item.clone()));
@ -54,15 +56,18 @@ fn find_chapter(
debug!("Get data from context"); debug!("Get data from context");
let chapters = rc.evaluate(ctx, "@root/chapters").and_then(|c| { let chapters = rc.evaluate(ctx, "@root/chapters").and_then(|c| {
serde_json::value::from_value::<Vec<StringMap>>(c.as_json().clone()) serde_json::value::from_value::<Vec<StringMap>>(c.as_json().clone()).map_err(|_| {
.map_err(|_| RenderError::new("Could not decode the JSON data")) RenderErrorReason::Other("Could not decode the JSON data".to_owned()).into()
})
})?; })?;
let base_path = rc let base_path = rc
.evaluate(ctx, "@root/path")? .evaluate(ctx, "@root/path")?
.as_json() .as_json()
.as_str() .as_str()
.ok_or_else(|| RenderError::new("Type error for `path`, string expected"))? .ok_or_else(|| {
RenderErrorReason::Other("Type error for `path`, string expected".to_owned())
})?
.replace('\"', ""); .replace('\"', "");
if !rc.evaluate(ctx, "@root/is_index")?.is_missing() { if !rc.evaluate(ctx, "@root/is_index")?.is_missing() {
@ -108,7 +113,7 @@ fn find_chapter(
} }
fn render( fn render(
_h: &Helper<'_, '_>, _h: &Helper<'_>,
r: &Handlebars<'_>, r: &Handlebars<'_>,
ctx: &Context, ctx: &Context,
rc: &mut RenderContext<'_, '_>, rc: &mut RenderContext<'_, '_>,
@ -122,7 +127,9 @@ fn render(
.evaluate(ctx, "@root/path")? .evaluate(ctx, "@root/path")?
.as_json() .as_json()
.as_str() .as_str()
.ok_or_else(|| RenderError::new("Type error for `path`, string expected"))? .ok_or_else(|| {
RenderErrorReason::Other("Type error for `path`, string expected".to_owned())
})?
.replace('\"', ""); .replace('\"', "");
context.insert( context.insert(
@ -132,17 +139,23 @@ fn render(
chapter chapter
.get("name") .get("name")
.ok_or_else(|| RenderError::new("No title found for chapter in JSON data")) .ok_or_else(|| {
RenderErrorReason::Other("No title found for chapter in JSON data".to_owned())
})
.map(|name| context.insert("title".to_owned(), json!(name)))?; .map(|name| context.insert("title".to_owned(), json!(name)))?;
chapter chapter
.get("path") .get("path")
.ok_or_else(|| RenderError::new("No path found for chapter in JSON data")) .ok_or_else(|| {
RenderErrorReason::Other("No path found for chapter in JSON data".to_owned())
})
.and_then(|p| { .and_then(|p| {
Path::new(p) Path::new(p)
.with_extension("html") .with_extension("html")
.to_str() .to_str()
.ok_or_else(|| RenderError::new("Link could not be converted to str")) .ok_or_else(|| {
RenderErrorReason::Other("Link could not be converted to str".to_owned())
})
.map(|p| context.insert("link".to_owned(), json!(p.replace('\\', "/")))) .map(|p| context.insert("link".to_owned(), json!(p.replace('\\', "/"))))
})?; })?;
@ -150,14 +163,14 @@ fn render(
let t = _h let t = _h
.template() .template()
.ok_or_else(|| RenderError::new("Error with the handlebars template"))?; .ok_or_else(|| RenderErrorReason::Other("Error with the handlebars template".to_owned()))?;
let local_ctx = Context::wraps(&context)?; let local_ctx = Context::wraps(&context)?;
let mut local_rc = rc.clone(); let mut local_rc = rc.clone();
t.render(r, &local_ctx, &mut local_rc, out) t.render(r, &local_ctx, &mut local_rc, out)
} }
pub fn previous( pub fn previous(
_h: &Helper<'_, '_>, _h: &Helper<'_>,
r: &Handlebars<'_>, r: &Handlebars<'_>,
ctx: &Context, ctx: &Context,
rc: &mut RenderContext<'_, '_>, rc: &mut RenderContext<'_, '_>,
@ -173,7 +186,7 @@ pub fn previous(
} }
pub fn next( pub fn next(
_h: &Helper<'_, '_>, _h: &Helper<'_>,
r: &Handlebars<'_>, r: &Handlebars<'_>,
ctx: &Context, ctx: &Context,
rc: &mut RenderContext<'_, '_>, rc: &mut RenderContext<'_, '_>,

View File

@ -1,8 +1,10 @@
use handlebars::{Context, Handlebars, Helper, Output, RenderContext, RenderError}; use handlebars::{
Context, Handlebars, Helper, Output, RenderContext, RenderError, RenderErrorReason,
};
use log::trace; use log::trace;
pub fn theme_option( pub fn theme_option(
h: &Helper<'_, '_>, h: &Helper<'_>,
_r: &Handlebars<'_>, _r: &Handlebars<'_>,
ctx: &Context, ctx: &Context,
rc: &mut RenderContext<'_, '_>, rc: &mut RenderContext<'_, '_>,
@ -11,14 +13,21 @@ pub fn theme_option(
trace!("theme_option (handlebars helper)"); trace!("theme_option (handlebars helper)");
let param = h.param(0).and_then(|v| v.value().as_str()).ok_or_else(|| { let param = h.param(0).and_then(|v| v.value().as_str()).ok_or_else(|| {
RenderError::new("Param 0 with String type is required for theme_option helper.") RenderErrorReason::ParamTypeMismatchForName(
"theme_option",
"0".to_owned(),
"string".to_owned(),
)
})?; })?;
let default_theme = rc.evaluate(ctx, "@root/default_theme")?; let default_theme = rc.evaluate(ctx, "@root/default_theme")?;
let default_theme_name = default_theme let default_theme_name = default_theme.as_json().as_str().ok_or_else(|| {
.as_json() RenderErrorReason::ParamTypeMismatchForName(
.as_str() "theme_option",
.ok_or_else(|| RenderError::new("Type error for `default_theme`, string expected"))?; "default_theme".to_owned(),
"string".to_owned(),
)
})?;
out.write(param)?; out.write(param)?;
if param.to_lowercase() == default_theme_name.to_lowercase() { if param.to_lowercase() == default_theme_name.to_lowercase() {

View File

@ -4,7 +4,9 @@ use std::{cmp::Ordering, collections::BTreeMap};
use crate::utils; use crate::utils;
use crate::utils::bracket_escape; use crate::utils::bracket_escape;
use handlebars::{Context, Handlebars, Helper, HelperDef, Output, RenderContext, RenderError}; use handlebars::{
Context, Handlebars, Helper, HelperDef, Output, RenderContext, RenderError, RenderErrorReason,
};
// Handlebars helper to construct TOC // Handlebars helper to construct TOC
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
@ -15,7 +17,7 @@ pub struct RenderToc {
impl HelperDef for RenderToc { impl HelperDef for RenderToc {
fn call<'reg: 'rc, 'rc>( fn call<'reg: 'rc, 'rc>(
&self, &self,
_h: &Helper<'reg, 'rc>, _h: &Helper<'rc>,
_r: &'reg Handlebars<'_>, _r: &'reg Handlebars<'_>,
ctx: &'rc Context, ctx: &'rc Context,
rc: &mut RenderContext<'reg, 'rc>, rc: &mut RenderContext<'reg, 'rc>,
@ -26,13 +28,17 @@ impl HelperDef for RenderToc {
// param is the key of value you want to display // param is the key of value you want to display
let chapters = rc.evaluate(ctx, "@root/chapters").and_then(|c| { let chapters = rc.evaluate(ctx, "@root/chapters").and_then(|c| {
serde_json::value::from_value::<Vec<BTreeMap<String, String>>>(c.as_json().clone()) serde_json::value::from_value::<Vec<BTreeMap<String, String>>>(c.as_json().clone())
.map_err(|_| RenderError::new("Could not decode the JSON data")) .map_err(|_| {
RenderErrorReason::Other("Could not decode the JSON data".to_owned()).into()
})
})?; })?;
let current_path = rc let current_path = rc
.evaluate(ctx, "@root/path")? .evaluate(ctx, "@root/path")?
.as_json() .as_json()
.as_str() .as_str()
.ok_or_else(|| RenderError::new("Type error for `path`, string expected"))? .ok_or_else(|| {
RenderErrorReason::Other("Type error for `path`, string expected".to_owned())
})?
.replace('\"', ""); .replace('\"', "");
let current_section = rc let current_section = rc
@ -46,13 +52,17 @@ impl HelperDef for RenderToc {
.evaluate(ctx, "@root/fold_enable")? .evaluate(ctx, "@root/fold_enable")?
.as_json() .as_json()
.as_bool() .as_bool()
.ok_or_else(|| RenderError::new("Type error for `fold_enable`, bool expected"))?; .ok_or_else(|| {
RenderErrorReason::Other("Type error for `fold_enable`, bool expected".to_owned())
})?;
let fold_level = rc let fold_level = rc
.evaluate(ctx, "@root/fold_level")? .evaluate(ctx, "@root/fold_level")?
.as_json() .as_json()
.as_u64() .as_u64()
.ok_or_else(|| RenderError::new("Type error for `fold_level`, u64 expected"))?; .ok_or_else(|| {
RenderErrorReason::Other("Type error for `fold_level`, u64 expected".to_owned())
})?;
out.write("<ol class=\"chapter\">")?; out.write("<ol class=\"chapter\">")?;