Skip to content

Commit

Permalink
added render_all modifier param to force all values through block tem…
Browse files Browse the repository at this point in the history
…plate rendering, instead of just object values
  • Loading branch information
iganev committed Dec 28, 2023
1 parent 345ab73 commit e18a5ed
Showing 1 changed file with 98 additions and 24 deletions.
122 changes: 98 additions & 24 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ const QUOTES_SINGLE: &str = "\'";
/// * distinct: Eliminate duplicates upon adding to output buffer
/// * quotes: Wrap each value in double quotation marks
/// * single_quote: Modifier of `quotes` to switch to single quotation mark instead
/// * render_all: Render all values using the block template, not just object values
///
/// # Example usage:
///
Expand Down Expand Up @@ -84,6 +85,15 @@ const QUOTES_SINGLE: &str = "\'";
///
/// Result: One, Two, Three, Four
///
///
/// * Where `s` is `"One"`, `arr` is `["One", "Two"]` and `obj` is `{"key0":{"label":"Two"},"key1":{"label":"Three"},"key2":{"label":"Four"}}`
///
/// `
/// {{#concat s arr obj separator=", " distinct=true render_all=true}}<{{#if label}}{{label}}{{else}}{{this}}{{/if}}/>{{/concat}}
/// `
///
/// Result: <One/>, <Two/>, <Three/>, <Four/>
///
pub struct HandlebarsConcat;

impl HelperDef for HandlebarsConcat {
Expand Down Expand Up @@ -116,6 +126,8 @@ impl HelperDef for HandlebarsConcat {
""
};

let render_all = h.hash_get("render_all").is_some(); // force all values through the block template

let template = h.template();

let mut output: Vec<String> = Vec::new();
Expand All @@ -124,37 +136,91 @@ impl HelperDef for HandlebarsConcat {
let param = param.clone();

if param.value().is_string() {
let mut value = param.value().render();
if h.is_block() && render_all {
// use block template to render strings

if quotes {
value = format!("{}{}{}", quotation_mark, value, quotation_mark);
}
let mut content = StringOutput::default();

let context_data = param.value().clone();
let context = Context::from(context_data);
let mut render_context = RenderContext::new(None);

template
.map(|t| t.render(r, &context, &mut render_context, &mut content))
.unwrap_or(Ok(()))?;

if let Ok(out) = content.into_string() {
let result = if quotes {
format!("{}{}{}", quotation_mark, out, quotation_mark)
} else {
out
};

if !result.is_empty() && (!output.contains(&result) || !distinct) {
output.push(result);
}
}
} else {
let mut value = param.value().render();

if quotes {
value = format!("{}{}{}", quotation_mark, value, quotation_mark);
}

if !output.contains(&value) || !distinct {
output.push(value);
if !output.contains(&value) || !distinct {
output.push(value);
}
}
} else if param.value().is_array() {
if let Some(ar) = param.value().as_array() {
output.append(
&mut ar
.iter()
.map(|item| item.render())
.map(|item| {
if quotes {
format!("{}{}{}", quotation_mark, item, quotation_mark)
} else {
item
}
})
.filter(|item| {
if distinct {
!output.contains(item)
if h.is_block() && render_all {
// use block template to render array elements

for array_item in ar {
let mut content = StringOutput::default();

let context_data = array_item.clone();
let context = Context::from(context_data);
let mut render_context = RenderContext::new(None);

template
.map(|t| t.render(r, &context, &mut render_context, &mut content))
.unwrap_or(Ok(()))?;

if let Ok(out) = content.into_string() {
let result = if quotes {
format!("{}{}{}", quotation_mark, out, quotation_mark)
} else {
true
out
};

if !result.is_empty() && (!output.contains(&result) || !distinct) {
output.push(result);
}
})
.collect::<Vec<String>>(),
);
}
}
} else {
output.append(
&mut ar
.iter()
.map(|item| item.render())
.map(|item| {
if quotes {
format!("{}{}{}", quotation_mark, item, quotation_mark)
} else {
item
}
})
.filter(|item| {
if distinct {
!output.contains(item)
} else {
true
}
})
.collect::<Vec<String>>(),
);
}
}
} else if param.value().is_object() {
if let Some(o) = param.value().as_object() {
Expand Down Expand Up @@ -302,5 +368,13 @@ mod tests {
r#""key0", "key1", "key2""#,
"Failed to concat object keys with quotation marks and no distinction"
);
assert_eq!(
h.render_template(
r#"{{#concat s arr obj separator=", " distinct=true render_all=true}}<{{#if label}}{{label}}{{else}}{{this}}{{/if}}/>{{/concat}}"#,
&json!({"s": "One", "arr": ["One", "Two"], "obj": {"key0":{"label":"Two"},"key1":{"label":"Three"},"key2":{"label":"Four"}}})
).expect("Render error"),
r#"<One/>, <Two/>, <Three/>, <Four/>"#,
"Failed to concat literal, array and object using block template"
);
}
}

0 comments on commit e18a5ed

Please sign in to comment.