sunng87 / handlebars-rust

Rust templating with Handlebars

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Failure to parse templates with namespaced helpers that take arguments

cbgbt opened this issue · comments

I was recently trying to use handlebars to register templates which used namespaced helpers; however, it seems that the template parser fails to process cases where these helpers take arguments.

Here is an example:

use handlebars::{Context, Handlebars, Helper, Output, RenderContext, RenderError};

fn arg_helper(
    helper: &Helper<'_, '_>,
    _: &Handlebars,
    _: &Context,
    _: &mut RenderContext<'_, '_>,
    out: &mut dyn Output,
) -> Result<(), RenderError> {
    let arg1 = helper
        .param(0)
        .map(|v| v.value().clone())
        .unwrap_or_else(|| serde_json::json!(""));

    out.write(&serde_json::to_string(&arg1).unwrap()).unwrap();
    Ok(())
}

fn main() {
    let mut registry = Handlebars::new();
    registry.register_helper("namespaced.helper", Box::new(arg_helper));

    let template = "{{ namespaced.helper }}";
    registry
        .render_template(&template, &serde_json::json!({}))
        .expect("Failed to render template.");
}

This results in an InvalidSyntax error:

thread 'main' panicked at 'Failed to render template.:
RenderError {
  desc: "Failed to parse template.",
  template_name: None,
  line_no: None,
  column_no: None,
  cause: Some(TemplateError {
    reason: InvalidSyntax,
    template_name: Some("Unnamed"),
    line_no: Some(1),
    column_no: Some(22),
    segment: Some("   0 | {{ namespaced.helper \"test\" }}\n     |----------------------^-------\n") }),
  unimplemented: false
}', src/main.rs:24:10

This only fails to parse templates which take arguments. If you change the template to: {{ namespaced.helper }} then the parser succeeds.

By the way, thank you for writing and sharing this excellent library.

At the moment, . is not allowed in helper name. And if you use {{ namespaced.helper}} without parameters it's recognized as an expression. The original javascript version has the same restriction

I thought I had tested the javascript version, but I must have forgotten to add the arguments. Thanks for clarifying that! I'm happy to continue to workaround this limitation on my end.

Do you think it's worth changing this? I haven't looked too closely into the parser, but I wonder if there's a language limitation that makes this infeasabile to implement.

I'm not sure with the rational behind this either. It should be possible to change parser to support this. It sounds reasonable to have namespaced helper when you have large amount of them.

Finally got time to attempt add . for helper name. Unfortunately I found it's going to change how we parse single expression or inline helper. I decide to hold this until we see a good solution from upstream or ourself