Template literals come in handy for code generation

Edvard Chen
3 min readAug 14, 2022

Recently I found that JavaScript template strings are very helpful for usages like code generation

The task

Provided that I am working to transform a Vue-like DSL to normal HTML.

First, the most essential usage should be supported

<div>hello world</div>

to

<div>hello world</div>

The codegen logic probably looks like this:

function generate(ast){
// ...
return `<${ast.tag}>${ast.text}</${ast.tag}>`
}

Although the fact would be more complicated, it’s easy, right?

But once there is a user-defined variable, it would be much different. For example,

<div>{{ msg }}</div>

should be transformed to

`<div>` + msg + '</div>'

And the codgen logic would become:

generate outputs a runtime expression, which is represented in string format and returns an HTML string. Because msg is a runtime variable and it should be represented as an expression in the generated code

It’s obviously cumbersome even at the first glance since I have to decide if a snippet should be wrapped with quotes " and use the connector sign + frequently to concatenate them.

How to improve it?

Tagged template

There are 3 kinds of things we have to handle

  1. Hand-written characters like <, />
  2. Strings in the generated code like ast.tag
  3. Expressions in the generated code like ast.binding

It needs a simple and clear way to triage them. And JavaScript template strings come rescue

Besides using template strings to facilitate daily string concatenation, we can define our custom concatenation which is called “tagged templates”.

For example,

  • literals is an array that contains all hand-written literal strings
  • exps is an array that contains all occurred variables

So what my custom template will do is

  1. wrap literal strings with quotes "
  2. wrap or not wrap the variables with quotes based on their type
  3. concatenate them with plus sign +

The template’s implementation will be like this:

It is oversimplified and only for illustrative purposes

Now I can easily generate the target code like I use everyday template strings, but with a function name. No need to think about the quotes and plus any more!

Recall the 3 kinds of things I mentioned above, for expressions in the generated code, wrap them in an object’s property expression to distinguish them from the second kind

--

--