Use a more powerful template engine for signatures/text modules, e.g. LiquidJS

I just tried to use a custom user attribute signature_salutation in a group signature, but with a small twist: for most users this attribute will be empty, and therefore I only want the respective snippet to be replaced with text when the attribute is actually set. I put the following line into my signature:

#{user.signature_salutation}#{user.firstname} #{user.lastname}

I expected that #{user.signature_salutation} would expand to an empty string and therefore have no effect on the signature when its attribute is unset, but unfortunately Zammad’s rather simple replaceTags engine will always replace empty strings with -. This probably makes sense in many situations, but in this special case it’s very impractical.

I looked at the code and considered adding some kind of default value mechanism so that I might write something like #{user.signature_salutation|} where whatever follows the | would be a default value, but that feels like a very limited solution for a very specific problem. So instead I looked around for an existing template engine that might fit the requirements, and I’ve found LiquidJS.

LiquidJS is a JavaScript port of the Liquid template engine written in Ruby, which has the following purpose:

Liquid is a template engine which was written with very specific requirements:

  • It has to have beautiful and simple markup. Template engines which don’t produce good looking markup are no fun to use.
  • It needs to be non evaling and secure. Liquid templates are made so that users can edit them. You don’t want to run code on your server which your users wrote.
  • It has to be stateless. Compile and render steps have to be separate so that the expensive parsing and compiling can be done once and later on you can just render it passing in a hash with local variables and objects.

Why you should use Liquid

  • You want to allow your users to edit the appearance of your application but don’t want them to run insecure code on your server .

This seems to fit the requirements quite nicely - it should be easy to integrate, secure enough to expose to admins and agents, and looking at the documentation, it seems to be very powerful. It would probably solve my use case very easily - when using this engine, you could just remove the - behavior, and then only print - when the template actually requires it:

{{ user.some_attribute | default: "-" }}

As the syntax doesn’t conflict with Zammad’s built-in template engine, they could peacefully co-exist. The old engine could then be removed after a transition period.

Looking at the documentation, I bet this would allow for a lot of cool stuff. I can also imagine further use cases, e.g. in the text fields in schedulers/triggers/macros/email filters:

  • email filters
    • take an arbitrary email header, and turn it into a tag:
      Match: X-My-Product-Version: [contains] regex:^\d{1,5}\.\d{1,5}$
      Perform action: [Tag] [add] {{ mail.headers.X-My-Product-Version | prepend: "version_"}}
  • macros
    • set the ticket to pending close in 31 days:
      Action: [State]: [pending close]
      Action: [Pending till]: {{'now' | date: "%s" | plus: 2678400 }}
  • triggers/schedulers:
    • set pending close with a relative pending till date; see above
    • use templates in email/SMS/internal notes

This topic was automatically closed after 416 days. New replies are no longer allowed.