Free email newsletter: “ES.next News

2016-09-10

Improving the syntax of EJS templates

I really like the way EJS templates work, because the meta-language (loops, if-then-else, etc.) is just JavaScript. This blog post describes ideas for improving their syntax.

EJS templates

This is an example of an EJS template:

    <ul>
    <% for(var i=0; i<supplies.length; i++) { %>
       <li><%= supplies[i] %></li>
    <% } %>
    </ul>

I see two problems with this template:

  1. It outputs empty lines for line 2 and 4.
  2. The delimiters <% and %> make the template look cluttered.

Suppressing whitespace

The first problem can be fixed by using the delimiters <%_ and _%> which suppress any whitespace generated by that line:

    <ul>
    <%_ for(var i=0; i<supplies.length; i++) { _%>
       <li><%= supplies[i] %></li>
    <%_ } _%>
    </ul>

Better control flow syntax

If control flow syntax is enabled by a single character at the beginning of a line then the template looks much nicer:

    <ul>
    # for(var i=0; i<supplies.length; i++) {
       <li><%= supplies[i] %></li>
    # }
    </ul>

The way to get this syntax is via a work-around – use a regular expression to convert:

    # foo

to:

    <%_ foo_%>

For example:

    template = template.replace(/^[ \t]*#(.*)$/mg, '<%_$1_%>');

This regular expression allows the # to be indented:

    <html>
        <body>
            # for(var i=0; i<supplies.length; i++) {
               <li><%= supplies[i] %></li>
            # }
        </body>
    </html>

One more improvement

Additionally, there is an issue for letting people change the delimiter <% to something different. Then the template could look like this:

    <ul>
    # for(var i=0; i<supplies.length; i++) {
       <li>{{= supplies[i] }}</li>
    # }
    </ul>

I find that easier to read, given that the delimiters are surrounded by HTML with lots of angle brackets.

No comments: