What’s wrong with template engines

We encounter this syntax quite often when using template engines:

<div>{{ item }}</div>

Of course, there are several implementations (ERB, EJS, DTL, etc.) but they all work pretty much the same.

The double curly braces hold a context object so if we have to output a list we need a for loop:

<ul id="foo" class="bar">
{% for item in list %}
<li>{{ item }}</li>
{% endfor %}

But what if we could just write the same list using methods:

Wouldn’t that be cleaner and faster to write?

Template string in Python

Python has a built-in Template called Template string:


Unlike ES6 Template literals (we’ll see later on) we cannot use methods with Template strings.

Formatted string literals in Python

Python 3.6+ also offers Formatted string literals:


The f here stands for format.

If we need to escape curly braces we can use double curly braces:

In  [1]: f'{{item}}'
Out [1]: '{item}'

Even if this syntax looks familiar, here the double curly braces do not hold a context object which is quite a contradiction compared with Djangolike and Jinjalike template languages.

With Formatted string literals we can use methods inside curly braces (e.g. f'{item.upper()}'). This little detail makes Formatted string literals way more powerful than Template string.

Template literals in JavaScript

ES6 has something called Template literals which combines template syntax with literals:


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


Now, let’s create the unordered list:


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


An example of conventions:

  • .asUl: make an unordered list;
  • .asOl: make an ordered list;
  • .asP: make a paragraph;
  • .withAttr('#foo.bar'): add attributes (id, class);
  • .withAttr('data-color="red"'): add data attribute;
  • include('base.html'): include template;
  • extend('nav.html'): extend template;

Template literals limitations

Template literals, when used as template engine, show their limitations as we start nesting tags:


We need to implement the custom method withInnerAttr() and the markup gets hard to read.

They are also pretty slow!