DEV Community

hong
hong

Posted on • Edited on

Truth about Template Engines Part 2

My background

This is part 2 of my articles on template engines. Specifically today I am writing about the Mustache spec.

What qualifies me to pass judgement on templating engines? I have written web and email templates for fortune 500 companies. Some of which have been large gnarly order confirmations and airline reservations full of beautiful, un-readable business logic.

Enter Mustache

When logic-less Mustache came onto the scene. It did something amazing; which was to get other programmer's to embrace it and re-write it in their language of choice. Sandi Metz writer of POODR said that "if your design is good then others would want to copy it". I think this applies. Mustache was really onto something and logic-less really made sense.

Except Mustache is not logic-less. It contains conditional and looping logic. I would say it's a minimal logic templating language. You can also become full logic by embedding lambdas into your data is too. If you are thinking adding callable functions to your json data sounds like a bad idea, it is.

Mustache is not perfect. In fact if it were, it would be the most downloaded library for JavaScript templating. It's not, Handlebars is. Proving that logic is still king.

In the following, I will outline some parts of the spec that I think need some work.

What's in a symbol?

A quick rundown of Mustache's symbols and their definitions.

symbol meaning
{{ }} delimiters
# begin section
/ end section
^ inverted sections
> partials
& unescape, safe-content
! comment
. current node operator?
< proposed layout operator

Just in real life sometimes choosing the right words can go a long way. It's clear that the choices for symbols and their meaning were JavaScript influenced. However compared to other languages it may cause some confusion.

  • '#' in many scripting languages is a comment
  • '!' is negation in many languages
  • '.' it's not mentioned in the spec, but refers to the current variable?
  • '>' vs '<' partial vs layout will be confusing if implemented

Are these symbols any better than having the actual word? To any non-programmer at first glance these symbols make reading templates worse. Compare to this:


{{if section }}

{{not section }}

{{each item }}

Truthy or Falsey

One of the tenants of Mustache is that it aims to be language agnostic. This is at a cost of clarity between language implementations.

The below Mustache template will render differently depending on which language it's rendered on.

Template:

Shown.
{{#person}}
  Never shown!
{{/person}}


Hash:

{
    "person": false  // or '', 0, "0", [], {}
}

Below is a brief table of some of the different Truthy evaluations in scripting languages.

lang '' 0 "0" {}
Php False False False True
JavaScript False False True True
Python False False True False
Ruby True True True True

This variability in the spec is in my opinion one of it's weaknesses. From a business perspective, it doesn't make any sense why this exists other than to make it easier for developers to implement the spec. Templating engine developers should not be the target audience for a template language.

I know that others have voiced their opinions on this matter and the community seems divided. However consider this conversation. "If we migrate to a new backend, our clients might see bugs in their templates because of the way Mustache is designed". Try selling that to your managers.

This might seem like a non-issue, as you are not likely to transfer your templates between languages. However when you are choosing a templating engine to be used by non-programmers, stuff like this can bite you. Also backend re-writes do happen.

Almost any standardization would be better than no standardization at all. It's just the idea that tying evaluation of of a template block to a language's own internal truth table makes no sense. After all it could be the case that I want to show that 0 items are available.

In my professional experience, it's almost always safer to be explicit when rendering a conditional block. There is no equivalent problem in other templating languages because you can always just do an '==' comparison. This is explicit.

The problem arises because Mustache aims to be logic-less which is a mismatch for some template blocks use cases. Going with Python's model of everything Falsey is good enough. Just please not PHP.

Whitespace

Whitespace is sacred. One of my biggest pet peeves with templating languages is that they always clobber whitespace. Whitespace is ambiguous. The Mustache spec is also loose with regards to whitespace. Consider the below Mustache code:

Is this a variable or section?

{{ #person }}

Some developers have solved this ambiguity by requiring that mustaches be continuous e.g. {{#person}}. However consider the below:

What's easier to read?

{{name}} vs {{ name }}

{{#person}} vs {{# person }}

In a perfect world, whitespace in general should be preserved. This is difficulty to implement as whitespace is ambiguous by nature.

Should this {{variable}} preserve spacing if it is null? Is it one or two spaces?

How about pre, post and nested newlines in a null section? Indents too? It gets complex.

         {{#mysection}}
              {{nested}}
         {{/mysection}}

The spec is unclear on all these scenarios. Some implementations have restricted spacing while others have not. It is the same with preserving whitespacing. This result is too much variability in implementations. This could be cleared up with a more clear spec.

Template Inheritance

One of the most requested features is template inheritance. This is when you have a base layout that other templates can inherit. For example a layout with a header and footer and other templates can then render the body content; optionally they can override parts of the parent layout.

My answer to this is No. Just No. This is a nice to have and perhaps should be an optional spec. However Mustache does not need this. I don't think this flows to with the concept of logic-less. Partials are already good enough. They are themselves a bit too much logic.

Wishlist for Mustache 2.0

What's better than logic-less? More logic-less! My wishlist for Mustache 2.0 involves implementing NO new features.

  • remove lambdas feature
  • remove set delimter feature
  • standardize truthiness
  • standardize whitespace rules
  • No template inheritance

Mustache 2.0 done and done

Don't get me a wrong. I'm a huge fan of mustache. However like writing code, we can refactor to make it better.

Top comments (0)