Auto merge of #13249 - WeiTheShinobi:update_dependency_handlebars, r=epage

Update dependency handlebars to v5 for mdman.

### What does this PR try to resolve?

issue #13238
- update dependency handlebars 4.5.0 -> 5.0.0
- fix code to fit the changes of Handlebars API
- RenderError::new() is deprecated. Use RenderErrorReason instead

### How should we test and review this PR?
pass all tests in /crates/mdman/tests
This commit is contained in:
bors 2024-01-04 16:03:50 +00:00
commit 87eb374d49
3 changed files with 60 additions and 36 deletions

4
Cargo.lock generated
View file

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

View file

@ -48,7 +48,7 @@ git2-curl = "0.19.0"
gix = { version = "0.57.1", default-features = false, features = ["blocking-http-transport-curl", "progress-tree", "revision"] }
gix-features-for-configuration-only = { version = "0.37.1", package = "gix-features", features = [ "parallel" ] }
glob = "0.3.1"
handlebars = { version = "4.5.0", features = ["dir_source"] }
handlebars = { version = "5.0.0", features = ["dir_source"] }
hex = "0.4.3"
hmac = "0.12.1"
home = "0.5.9"

View file

@ -1,14 +1,16 @@
//! Handlebars template processing.
use crate::format::Formatter;
use anyhow::Error;
use handlebars::{
handlebars_helper, Context, Decorator, Handlebars, Helper, HelperDef, HelperResult, Output,
RenderContext, RenderError, Renderable,
};
use std::collections::HashMap;
use std::path::Path;
use anyhow::Error;
use handlebars::{
handlebars_helper, Context, Decorator, DirectorySourceOptions, Handlebars, Helper, HelperDef,
HelperResult, Output, RenderContext, RenderError, RenderErrorReason, Renderable,
};
use crate::format::Formatter;
type FormatterRef<'a> = &'a (dyn Formatter + Send + Sync);
/// Processes the handlebars template at the given file.
@ -22,7 +24,12 @@ pub fn expand(file: &Path, formatter: FormatterRef<'_>) -> Result<String, Error>
handlebars.register_decorator("set", Box::new(set_decorator));
handlebars.register_template_file("template", file)?;
let includes = file.parent().unwrap().join("includes");
handlebars.register_templates_directory(".md", includes)?;
let options = DirectorySourceOptions {
tpl_extension: ".md".to_string(),
hidden: false,
temporary: false,
};
handlebars.register_templates_directory(includes, options)?;
let man_name = file
.file_stem()
.expect("expected filename")
@ -42,14 +49,16 @@ struct OptionsHelper<'a> {
impl HelperDef for OptionsHelper<'_> {
fn call<'reg: 'rc, 'rc>(
&self,
h: &Helper<'reg, 'rc>,
h: &Helper<'rc>,
r: &'reg Handlebars<'reg>,
ctx: &'rc Context,
rc: &mut RenderContext<'reg, 'rc>,
out: &mut dyn Output,
) -> HelperResult {
if in_options(rc) {
return Err(RenderError::new("options blocks cannot be nested"));
return Err(
RenderErrorReason::Other("options blocks cannot be nested".to_string()).into(),
);
}
// Prevent nested {{#options}}.
set_in_context(rc, "__MDMAN_IN_OPTIONS", serde_json::Value::Bool(true));
@ -57,7 +66,12 @@ impl HelperDef for OptionsHelper<'_> {
out.write(&s)?;
let t = match h.template() {
Some(t) => t,
None => return Err(RenderError::new("options block must not be empty")),
None => {
return Err(RenderErrorReason::Other(
"options block must not be empty".to_string(),
)
.into());
}
};
let block = t.renders(r, ctx, rc)?;
out.write(&block)?;
@ -83,20 +97,23 @@ struct OptionHelper<'a> {
impl HelperDef for OptionHelper<'_> {
fn call<'reg: 'rc, 'rc>(
&self,
h: &Helper<'reg, 'rc>,
h: &Helper<'rc>,
r: &'reg Handlebars<'reg>,
ctx: &'rc Context,
rc: &mut RenderContext<'reg, 'rc>,
out: &mut dyn Output,
) -> HelperResult {
if !in_options(rc) {
return Err(RenderError::new("option must be in options block"));
return Err(
RenderErrorReason::Other("option must be in options block".to_string()).into(),
);
}
let params = h.params();
if params.is_empty() {
return Err(RenderError::new(
"option block must have at least one param",
));
return Err(RenderErrorReason::Other(
"option block must have at least one param".to_string(),
)
.into());
}
// Convert params to strings.
let params = params
@ -105,12 +122,19 @@ impl HelperDef for OptionHelper<'_> {
param
.value()
.as_str()
.ok_or_else(|| RenderError::new("option params must be strings"))
.ok_or_else(|| {
RenderErrorReason::Other("option params must be strings".to_string())
})
.into()
})
.collect::<Result<Vec<&str>, RenderError>>()?;
.collect::<Result<Vec<&str>, RenderErrorReason>>()?;
let t = match h.template() {
Some(t) => t,
None => return Err(RenderError::new("option block must not be empty")),
None => {
return Err(
RenderErrorReason::Other("option block must not be empty".to_string()).into(),
);
}
};
// Render the block.
let block = t.renders(r, ctx, rc)?;
@ -127,7 +151,7 @@ impl HelperDef for OptionHelper<'_> {
let option = self
.formatter
.render_option(&params, &block, man_name)
.map_err(|e| RenderError::new(format!("option render failed: {}", e)))?;
.map_err(|e| RenderErrorReason::Other(format!("option render failed: {}", e)))?;
out.write(&option)?;
Ok(())
}
@ -141,7 +165,7 @@ struct ManLinkHelper<'a> {
impl HelperDef for ManLinkHelper<'_> {
fn call<'reg: 'rc, 'rc>(
&self,
h: &Helper<'reg, 'rc>,
h: &Helper<'rc>,
_r: &'reg Handlebars<'reg>,
_ctx: &'rc Context,
_rc: &mut RenderContext<'reg, 'rc>,
@ -149,22 +173,22 @@ impl HelperDef for ManLinkHelper<'_> {
) -> HelperResult {
let params = h.params();
if params.len() != 2 {
return Err(RenderError::new("{{man}} must have two arguments"));
return Err(
RenderErrorReason::Other("{{man}} must have two arguments".to_string()).into(),
);
}
let name = params[0]
.value()
.as_str()
.ok_or_else(|| RenderError::new("man link name must be a string"))?;
let section = params[1]
.value()
.as_u64()
.ok_or_else(|| RenderError::new("man link section must be an integer"))?;
let section =
u8::try_from(section).map_err(|_e| RenderError::new("section number too large"))?;
let name = params[0].value().as_str().ok_or_else(|| {
RenderErrorReason::Other("man link name must be a string".to_string())
})?;
let section = params[1].value().as_u64().ok_or_else(|| {
RenderErrorReason::Other("man link section must be an integer".to_string())
})?;
let section = u8::try_from(section)
.map_err(|_e| RenderErrorReason::Other("section number too large".to_string()))?;
let link = self
.formatter
.linkify_man_to_md(name, section)
.map_err(|e| RenderError::new(format!("failed to linkify man: {}", e)))?;
.map_err(|e| RenderErrorReason::Other(format!("failed to linkify man: {}", e)))?;
out.write(&link)?;
Ok(())
}
@ -174,7 +198,7 @@ impl HelperDef for ManLinkHelper<'_> {
///
/// This sets a variable to a value within the template context.
fn set_decorator(
d: &Decorator<'_, '_>,
d: &Decorator<'_>,
_: &Handlebars<'_>,
_ctx: &Context,
rc: &mut RenderContext<'_, '_>,