What’s wrong with template engines

This is the syntax many template engines use:

<div>{{ my_string }}</div>

If we have a list and we need a loop to output an unordered list it gets pretty weird:

<div>
<ul>
{% for item in my_list %}
<li>{{ item }}</li>
{% endfor %}
</ul>
</div>

What if we could just do:

<div>
${my_list.as_ul}
</div>

In order to add a class attribute, what if we could just do:

<div>
${my_string.with_class("pull-right")}
</div>
Wouldn’t that be cleaner, readable and faster to write?

I’ll go through my thesis referencing two widely used programming languages: the more diffuse language JavaScript and the more loved language Python.

Fine writing instruments by Marek Kubica (CC BY-SA 2.0)

Template string in Python

Python has a built-in Template called Template string that looks like this:

"${my_string}ed"

It uses ${} much like the ES6 Template literal that we’ll see later but with some big limitation: we cannot add a method inside the curly braces so the following syntax will not be possible: "${my_string.upper()}"

Formatted string literals in Python

Python 3.6+ also offers Formatted string literals support that looks like this:

f"{my_string}ed"

The f here means format(). Also note there is no $ sign because this is not a template but a formatted string (by definition).

We can escape the curly braces using double curly braces like this:

f"{{my_string}}ed"
Out [1]: '{my_string}ed'
The double curly braces are used by many template engines (Jinja2, DTL, etc.) to hold objects but using the built-in string literals the first curly brace will escape the next one!

Using the Formatted string literals we can add a method inside the curly braces so this is possible: f"{my_string.upper()}"

This detail makes Formatted string literals way more powerful than Template string.

Template literals in JavaScript

JavaScript has now something called Template literals which combines the syntax of the template with the power of the literals:

`${myString}`

Using the Template literals we can add methods inside the curly braces:

`${myString.toUpperCase()}`

Now, let’s create an unordered list:

<div>
${myArray.asUl}
</div>

Of course, to make this work, we need to create the getter asUl inside a class that inherits from the Array. This is pretty easy to achieve but it’s not part of this article (stay tuned).

Template literals limitations

Template literals come with some limitations depending upon your needs, for instance if we want to add an id inside the <ul> tag and a class inside each <li> tag we can write something like:

<div>
${myArray.asUl.withId("nav").withInnerClass("text-lowercase")}
</div>

So we need to implement a custom method withInnerClass() but this still looks readable, doesn’t it. It looks even more readable refraining the camelCase naming convention:

<div>
${my_list.as_ul.with_id("nav").with_inner_class("text-lowercase")}
</div>

Indeed, this now looks like something I’d do in Python, using a functional programming approach.

Can I use Formatted string literals in a template?

I won’t suggest that!

Formatted string literals are not designed to be used in a template: for instance, inside a script, you’ll have to escape all the curly braces…

You can instead use Formatted string literals to build a template engine that draws inspiration from the Template literals in JavaScript or the Python Template string.

Python doesn’t offer Template literals and the idea of a template engine that makes use of both, the Template string syntax and the Formatted string literals strength, often tickle me.

Conclusion

Template engines are still a big deal in server side technology nowadays and they are booming in front end frameworks so I encourage you to rethink the syntax: make it cleaner, be consistent… especially if you are writing a template engine for your company!

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.