diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 12:41:35 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 12:41:35 +0000 |
commit | 7e5d7eea9c580ef4b41a765bde624af431942b96 (patch) | |
tree | 2c0d9ca12878fc4525650aa4e54d77a81a07cc09 /vendor/handlebars-3.5.5/src/partial.rs | |
parent | Adding debian version 1.70.0+dfsg1-9. (diff) | |
download | rustc-7e5d7eea9c580ef4b41a765bde624af431942b96.tar.xz rustc-7e5d7eea9c580ef4b41a765bde624af431942b96.zip |
Merging upstream version 1.70.0+dfsg2.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/handlebars-3.5.5/src/partial.rs')
-rw-r--r-- | vendor/handlebars-3.5.5/src/partial.rs | 284 |
1 files changed, 284 insertions, 0 deletions
diff --git a/vendor/handlebars-3.5.5/src/partial.rs b/vendor/handlebars-3.5.5/src/partial.rs new file mode 100644 index 000000000..fe6832299 --- /dev/null +++ b/vendor/handlebars-3.5.5/src/partial.rs @@ -0,0 +1,284 @@ +use std::collections::HashMap; + +use serde_json::value::Value as Json; + +use crate::context::{merge_json, Context}; +use crate::error::RenderError; +use crate::json::path::Path; +use crate::output::Output; +use crate::registry::Registry; +use crate::render::{Decorator, Evaluable, RenderContext, Renderable}; +use crate::template::Template; + +fn render_partial<'reg: 'rc, 'rc>( + t: &'reg Template, + d: &Decorator<'reg, 'rc>, + r: &'reg Registry<'reg>, + ctx: &'rc Context, + local_rc: &mut RenderContext<'reg, 'rc>, + out: &mut dyn Output, +) -> Result<(), RenderError> { + // partial context path + if let Some(ref param_ctx) = d.param(0) { + if let (Some(p), Some(block)) = (param_ctx.context_path(), local_rc.block_mut()) { + *block.base_path_mut() = p.clone(); + } + } + + // @partial-block + if let Some(t) = d.template() { + local_rc.set_partial("@partial-block".to_owned(), t); + } + + let result = if d.hash().is_empty() { + t.render(r, ctx, local_rc, out) + } else { + let hash_ctx = d + .hash() + .iter() + .map(|(k, v)| (k, v.value())) + .collect::<HashMap<&&str, &Json>>(); + let current_path = Path::current(); + let partial_context = + merge_json(local_rc.evaluate2(ctx, ¤t_path)?.as_json(), &hash_ctx); + let ctx = Context::wraps(&partial_context)?; + let mut partial_rc = local_rc.new_for_block(); + t.render(r, &ctx, &mut partial_rc, out) + }; + + local_rc.remove_partial("@partial-block"); + + result +} + +pub fn expand_partial<'reg: 'rc, 'rc>( + d: &Decorator<'reg, 'rc>, + r: &'reg Registry<'reg>, + ctx: &'rc Context, + rc: &mut RenderContext<'reg, 'rc>, + out: &mut dyn Output, +) -> Result<(), RenderError> { + // try eval inline partials first + if let Some(t) = d.template() { + t.eval(r, ctx, rc)?; + } + + let tname = d.name(); + if rc.is_current_template(tname) { + return Err(RenderError::new("Cannot include self in >")); + } + + let partial = rc.get_partial(tname); + + match partial { + Some(t) => { + let mut local_rc = rc.clone(); + render_partial(&t, d, r, ctx, &mut local_rc, out)?; + } + None => { + if let Some(t) = r.get_template(tname).or_else(|| d.template()) { + let mut local_rc = rc.clone(); + render_partial(t, d, r, ctx, &mut local_rc, out)?; + } + } + } + + Ok(()) +} + +#[cfg(test)] +mod test { + use crate::context::Context; + use crate::error::RenderError; + use crate::output::Output; + use crate::registry::Registry; + use crate::render::{Helper, RenderContext}; + + #[test] + fn test() { + let mut handlebars = Registry::new(); + assert!(handlebars + .register_template_string("t0", "{{> t1}}") + .is_ok()); + assert!(handlebars + .register_template_string("t1", "{{this}}") + .is_ok()); + assert!(handlebars + .register_template_string("t2", "{{#> t99}}not there{{/t99}}") + .is_ok()); + assert!(handlebars + .register_template_string("t3", "{{#*inline \"t31\"}}{{this}}{{/inline}}{{> t31}}") + .is_ok()); + assert!(handlebars + .register_template_string( + "t4", + "{{#> t5}}{{#*inline \"nav\"}}navbar{{/inline}}{{/t5}}" + ) + .is_ok()); + assert!(handlebars + .register_template_string("t5", "include {{> nav}}") + .is_ok()); + assert!(handlebars + .register_template_string("t6", "{{> t1 a}}") + .is_ok()); + assert!(handlebars + .register_template_string( + "t7", + "{{#*inline \"t71\"}}{{a}}{{/inline}}{{> t71 a=\"world\"}}" + ) + .is_ok()); + assert!(handlebars.register_template_string("t8", "{{a}}").is_ok()); + assert!(handlebars + .register_template_string("t9", "{{> t8 a=2}}") + .is_ok()); + + assert_eq!(handlebars.render("t0", &1).ok().unwrap(), "1".to_string()); + assert_eq!( + handlebars.render("t2", &1).ok().unwrap(), + "not there".to_string() + ); + assert_eq!(handlebars.render("t3", &1).ok().unwrap(), "1".to_string()); + assert_eq!( + handlebars.render("t4", &1).ok().unwrap(), + "include navbar".to_string() + ); + assert_eq!( + handlebars + .render("t6", &btreemap! {"a".to_string() => "2".to_string()}) + .ok() + .unwrap(), + "2".to_string() + ); + assert_eq!( + handlebars.render("t7", &1).ok().unwrap(), + "world".to_string() + ); + assert_eq!(handlebars.render("t9", &1).ok().unwrap(), "2".to_string()); + } + + #[test] + fn test_include_partial_block() { + let t0 = "hello {{> @partial-block}}"; + let t1 = "{{#> t0}}inner {{this}}{{/t0}}"; + + let mut handlebars = Registry::new(); + assert!(handlebars.register_template_string("t0", t0).is_ok()); + assert!(handlebars.register_template_string("t1", t1).is_ok()); + + let r0 = handlebars.render("t1", &true); + assert_eq!(r0.ok().unwrap(), "hello inner true".to_string()); + } + + #[test] + fn test_self_inclusion() { + let t0 = "hello {{> t1}} {{> t0}}"; + let t1 = "some template"; + let mut handlebars = Registry::new(); + assert!(handlebars.register_template_string("t0", t0).is_ok()); + assert!(handlebars.register_template_string("t1", t1).is_ok()); + + let r0 = handlebars.render("t0", &true); + assert!(r0.is_err()); + } + + #[test] + fn test_issue_143() { + let main_template = "one{{> two }}three{{> two }}"; + let two_partial = "--- two ---"; + + let mut handlebars = Registry::new(); + assert!(handlebars + .register_template_string("template", main_template) + .is_ok()); + assert!(handlebars + .register_template_string("two", two_partial) + .is_ok()); + + let r0 = handlebars.render("template", &true); + assert_eq!(r0.ok().unwrap(), "one--- two ---three--- two ---"); + } + + #[test] + fn test_hash_context_outscope() { + let main_template = "In: {{> p a=2}} Out: {{a}}"; + let p_partial = "{{a}}"; + + let mut handlebars = Registry::new(); + assert!(handlebars + .register_template_string("template", main_template) + .is_ok()); + assert!(handlebars.register_template_string("p", p_partial).is_ok()); + + let r0 = handlebars.render("template", &true); + assert_eq!(r0.ok().unwrap(), "In: 2 Out: "); + } + + #[test] + fn test_partial_context_hash() { + let mut hbs = Registry::new(); + hbs.register_template_string("one", "This is a test. {{> two name=\"fred\" }}") + .unwrap(); + hbs.register_template_string("two", "Lets test {{name}}") + .unwrap(); + assert_eq!( + "This is a test. Lets test fred", + hbs.render("one", &0).unwrap() + ); + } + + #[test] + fn test_partial_subexpression_context_hash() { + let mut hbs = Registry::new(); + hbs.register_template_string("one", "This is a test. {{> (x @root) name=\"fred\" }}") + .unwrap(); + hbs.register_template_string("two", "Lets test {{name}}") + .unwrap(); + + hbs.register_helper( + "x", + Box::new( + |_: &Helper<'_, '_>, + _: &Registry<'_>, + _: &Context, + _: &mut RenderContext<'_, '_>, + out: &mut dyn Output| + -> Result<(), RenderError> { + out.write("two")?; + Ok(()) + }, + ), + ); + assert_eq!( + "This is a test. Lets test fred", + hbs.render("one", &0).unwrap() + ); + } + + #[test] + fn test_nested_partial_scope() { + let t = "{{#*inline \"pp\"}}{{a}} {{b}}{{/inline}}{{#each c}}{{> pp a=2}}{{/each}}"; + let data = json!({"c": [{"b": true}, {"b": false}]}); + + let mut handlebars = Registry::new(); + assert!(handlebars.register_template_string("t", t).is_ok()); + let r0 = handlebars.render("t", &data); + assert_eq!(r0.ok().unwrap(), "2 true2 false"); + } + + #[test] + fn test_up_to_partial_level() { + let outer = r#"{{>inner name="fruit:" vegetables=fruits}}"#; + let inner = "{{#each vegetables}}{{../name}} {{this}},{{/each}}"; + + let data = json!({ "fruits": ["carrot", "tomato"] }); + + let mut handlebars = Registry::new(); + handlebars.register_template_string("outer", outer).unwrap(); + handlebars.register_template_string("inner", inner).unwrap(); + + assert_eq!( + handlebars.render("outer", &data).unwrap(), + "fruit: carrot,fruit: tomato," + ); + } +} |