summaryrefslogtreecommitdiffstats
path: root/vendor/handlebars/src/decorators
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
commit698f8c2f01ea549d77d7dc3338a12e04c11057b9 (patch)
tree173a775858bd501c378080a10dca74132f05bc50 /vendor/handlebars/src/decorators
parentInitial commit. (diff)
downloadrustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.tar.xz
rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.zip
Adding upstream version 1.64.0+dfsg1.upstream/1.64.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/handlebars/src/decorators')
-rw-r--r--vendor/handlebars/src/decorators/inline.rs64
-rw-r--r--vendor/handlebars/src/decorators/mod.rs300
2 files changed, 364 insertions, 0 deletions
diff --git a/vendor/handlebars/src/decorators/inline.rs b/vendor/handlebars/src/decorators/inline.rs
new file mode 100644
index 000000000..373abbc7b
--- /dev/null
+++ b/vendor/handlebars/src/decorators/inline.rs
@@ -0,0 +1,64 @@
+use crate::context::Context;
+use crate::decorators::{DecoratorDef, DecoratorResult};
+use crate::error::RenderError;
+use crate::registry::Registry;
+use crate::render::{Decorator, RenderContext};
+
+#[derive(Clone, Copy)]
+pub struct InlineDecorator;
+
+fn get_name<'reg: 'rc, 'rc>(d: &Decorator<'reg, 'rc>) -> Result<String, RenderError> {
+ d.param(0)
+ .ok_or_else(|| RenderError::new("Param required for decorator \"inline\""))
+ .and_then(|v| {
+ v.value()
+ .as_str()
+ .map(|v| v.to_owned())
+ .ok_or_else(|| RenderError::new("inline name must be string"))
+ })
+}
+
+impl DecoratorDef for InlineDecorator {
+ fn call<'reg: 'rc, 'rc>(
+ &self,
+ d: &Decorator<'reg, 'rc>,
+ _: &'reg Registry<'reg>,
+ _: &'rc Context,
+ rc: &mut RenderContext<'reg, 'rc>,
+ ) -> DecoratorResult {
+ let name = get_name(d)?;
+
+ let template = d
+ .template()
+ .ok_or_else(|| RenderError::new("inline should have a block"))?;
+
+ rc.set_partial(name, template);
+ Ok(())
+ }
+}
+
+pub static INLINE_DECORATOR: InlineDecorator = InlineDecorator;
+
+#[cfg(test)]
+mod test {
+ use crate::context::Context;
+ use crate::registry::Registry;
+ use crate::render::{Evaluable, RenderContext};
+ use crate::template::Template;
+
+ #[test]
+ fn test_inline() {
+ let t0 =
+ Template::compile("{{#*inline \"hello\"}}the hello world inline partial.{{/inline}}")
+ .ok()
+ .unwrap();
+
+ let hbs = Registry::new();
+
+ let ctx = Context::null();
+ let mut rc = RenderContext::new(None);
+ t0.elements[0].eval(&hbs, &ctx, &mut rc).unwrap();
+
+ assert!(rc.get_partial(&"hello".to_owned()).is_some());
+ }
+}
diff --git a/vendor/handlebars/src/decorators/mod.rs b/vendor/handlebars/src/decorators/mod.rs
new file mode 100644
index 000000000..b8bad900f
--- /dev/null
+++ b/vendor/handlebars/src/decorators/mod.rs
@@ -0,0 +1,300 @@
+use crate::context::Context;
+use crate::error::RenderError;
+use crate::registry::Registry;
+use crate::render::{Decorator, RenderContext};
+
+pub use self::inline::INLINE_DECORATOR;
+
+pub type DecoratorResult = Result<(), RenderError>;
+
+/// Decorator Definition
+///
+/// Implement this trait to define your own decorators. Currently decorator
+/// shares same definition with helper.
+///
+/// In handlebars, it is recommended to use decorator to change context data and update helper
+/// definition.
+/// ## Updating context data
+///
+/// In decorator, you can change some context data you are about to render.
+///
+/// ```
+/// use handlebars::*;
+///
+/// fn update_data<'reg: 'rc, 'rc>(_: &Decorator, _: &Handlebars, ctx: &Context, rc: &mut RenderContext)
+/// -> Result<(), RenderError> {
+/// // modify json object
+/// let mut new_ctx = ctx.clone();
+/// {
+/// let mut data = new_ctx.data_mut();
+/// if let Some(ref mut m) = data.as_object_mut() {
+/// m.insert("hello".to_string(), to_json("world"));
+/// }
+/// }
+/// rc.set_context(new_ctx);
+/// Ok(())
+/// }
+///
+/// ```
+///
+/// ## Define local helper
+///
+/// You can override behavior of a helper from position of decorator to the end of template.
+///
+/// ```
+/// use handlebars::*;
+///
+/// fn override_helper(_: &Decorator, _: &Handlebars, _: &Context, rc: &mut RenderContext)
+/// -> Result<(), RenderError> {
+/// let new_helper = |h: &Helper, _: &Handlebars, _: &Context, rc: &mut RenderContext, out: &mut dyn Output|
+/// -> Result<(), RenderError> {
+/// // your helper logic
+/// Ok(())
+/// };
+/// rc.register_local_helper("distance", Box::new(new_helper));
+/// Ok(())
+/// }
+/// ```
+///
+pub trait DecoratorDef {
+ fn call<'reg: 'rc, 'rc>(
+ &'reg self,
+ d: &Decorator<'reg, 'rc>,
+ r: &'reg Registry<'reg>,
+ ctx: &'rc Context,
+ rc: &mut RenderContext<'reg, 'rc>,
+ ) -> DecoratorResult;
+}
+
+/// Implement DecoratorDef for bare function so we can use function as decorator
+impl<
+ F: for<'reg, 'rc> Fn(
+ &Decorator<'reg, 'rc>,
+ &'reg Registry<'reg>,
+ &'rc Context,
+ &mut RenderContext<'reg, 'rc>,
+ ) -> DecoratorResult,
+ > DecoratorDef for F
+{
+ fn call<'reg: 'rc, 'rc>(
+ &'reg self,
+ d: &Decorator<'reg, 'rc>,
+ reg: &'reg Registry<'reg>,
+ ctx: &'rc Context,
+ rc: &mut RenderContext<'reg, 'rc>,
+ ) -> DecoratorResult {
+ (*self)(d, reg, ctx, rc)
+ }
+}
+
+mod inline;
+
+#[cfg(test)]
+mod test {
+ use crate::context::Context;
+ use crate::error::RenderError;
+ use crate::json::value::{as_string, to_json};
+ use crate::output::Output;
+ use crate::registry::Registry;
+ use crate::render::{Decorator, Helper, RenderContext};
+
+ #[test]
+ fn test_register_decorator() {
+ let mut handlebars = Registry::new();
+ handlebars
+ .register_template_string("t0", "{{*foo}}".to_string())
+ .unwrap();
+
+ let data = btreemap! {
+ "hello".to_string() => "world".to_string()
+ };
+
+ assert!(handlebars.render("t0", &data).is_err());
+
+ handlebars.register_decorator(
+ "foo",
+ Box::new(
+ |_: &Decorator<'_, '_>,
+ _: &Registry<'_>,
+ _: &Context,
+ _: &mut RenderContext<'_, '_>|
+ -> Result<(), RenderError> { Ok(()) },
+ ),
+ );
+ assert_eq!(handlebars.render("t0", &data).ok().unwrap(), "".to_string());
+ }
+
+ // updating context data disabled for now
+ #[test]
+ fn test_update_data_with_decorator() {
+ let mut handlebars = Registry::new();
+ handlebars
+ .register_template_string("t0", "{{hello}}{{*foo}}{{hello}}".to_string())
+ .unwrap();
+
+ let data = btreemap! {
+ "hello".to_string() => "world".to_string()
+ };
+
+ handlebars.register_decorator(
+ "foo",
+ Box::new(
+ |_: &Decorator<'_, '_>,
+ _: &Registry<'_>,
+ ctx: &Context,
+ rc: &mut RenderContext<'_, '_>|
+ -> Result<(), RenderError> {
+ // modify json object
+ let mut new_ctx = ctx.clone();
+ {
+ let data = new_ctx.data_mut();
+ if let Some(ref mut m) = data.as_object_mut().as_mut() {
+ m.insert("hello".to_string(), to_json("war"));
+ }
+ }
+ rc.set_context(new_ctx);
+ Ok(())
+ },
+ ),
+ );
+
+ assert_eq!(
+ handlebars.render("t0", &data).ok().unwrap(),
+ "worldwar".to_string()
+ );
+
+ let data2 = 0;
+ handlebars.register_decorator(
+ "bar",
+ Box::new(
+ |d: &Decorator<'_, '_>,
+ _: &Registry<'_>,
+ _: &Context,
+ rc: &mut RenderContext<'_, '_>|
+ -> Result<(), RenderError> {
+ // modify value
+ let v = d
+ .param(0)
+ .and_then(|v| Context::wraps(v.value()).ok())
+ .unwrap_or(Context::null());
+ rc.set_context(v);
+ Ok(())
+ },
+ ),
+ );
+ handlebars
+ .register_template_string("t1", "{{this}}{{*bar 1}}{{this}}".to_string())
+ .unwrap();
+ assert_eq!(
+ handlebars.render("t1", &data2).ok().unwrap(),
+ "01".to_string()
+ );
+
+ handlebars
+ .register_template_string(
+ "t2",
+ "{{this}}{{*bar \"string_literal\"}}{{this}}".to_string(),
+ )
+ .unwrap();
+ assert_eq!(
+ handlebars.render("t2", &data2).ok().unwrap(),
+ "0string_literal".to_string()
+ );
+
+ handlebars
+ .register_template_string("t3", "{{this}}{{*bar}}{{this}}".to_string())
+ .unwrap();
+ assert_eq!(
+ handlebars.render("t3", &data2).ok().unwrap(),
+ "0".to_string()
+ );
+ }
+
+ #[test]
+ fn test_local_helper_with_decorator() {
+ let mut handlebars = Registry::new();
+ handlebars
+ .register_template_string(
+ "t0",
+ "{{distance 4.5}},{{*foo \"miles\"}}{{distance 10.1}},{{*bar}}{{distance 3.4}}"
+ .to_string(),
+ )
+ .unwrap();
+
+ handlebars.register_helper(
+ "distance",
+ Box::new(
+ |h: &Helper<'_, '_>,
+ _: &Registry<'_>,
+ _: &Context,
+ _: &mut RenderContext<'_, '_>,
+ out: &mut dyn Output|
+ -> Result<(), RenderError> {
+ let s = format!(
+ "{}m",
+ h.param(0)
+ .as_ref()
+ .map(|v| v.value())
+ .unwrap_or(&to_json(0))
+ );
+ out.write(s.as_ref())?;
+ Ok(())
+ },
+ ),
+ );
+ handlebars.register_decorator(
+ "foo",
+ Box::new(
+ |d: &Decorator<'_, '_>,
+ _: &Registry<'_>,
+ _: &Context,
+ rc: &mut RenderContext<'_, '_>|
+ -> Result<(), RenderError> {
+ let new_unit = d
+ .param(0)
+ .as_ref()
+ .and_then(|v| as_string(v.value()))
+ .unwrap_or("")
+ .to_owned();
+ let new_helper = move |h: &Helper<'_, '_>,
+ _: &Registry<'_>,
+ _: &Context,
+ _: &mut RenderContext<'_, '_>,
+ out: &mut dyn Output|
+ -> Result<(), RenderError> {
+ let s = format!(
+ "{}{}",
+ h.param(0)
+ .as_ref()
+ .map(|v| v.value())
+ .unwrap_or(&to_json(0)),
+ new_unit
+ );
+ out.write(s.as_ref())?;
+ Ok(())
+ };
+
+ rc.register_local_helper("distance", Box::new(new_helper));
+ Ok(())
+ },
+ ),
+ );
+ handlebars.register_decorator(
+ "bar",
+ Box::new(
+ |_: &Decorator<'_, '_>,
+ _: &Registry<'_>,
+ _: &Context,
+ rc: &mut RenderContext<'_, '_>|
+ -> Result<(), RenderError> {
+ rc.unregister_local_helper("distance");
+ Ok(())
+ },
+ ),
+ );
+ assert_eq!(
+ handlebars.render("t0", &0).ok().unwrap(),
+ "4.5m,10.1miles,3.4m".to_owned()
+ );
+ }
+}