Template literals as template engine
Why template literals?
In What's a template? I've briefly shown some of the existing framework templating systems. Since building the
different underlying template engines (aka the tools that know how to display the firstName
in the template) are a bit complex,
I will show you an alternative using a less tricky approach that comes from the standards: template literals
Note that I've made a little experiment using JSX, if you're interested in.
Our first HTML elements
Let's put our hands on!
The first step is to create a folder and a file at ./framework/element.js
:
const div = (strings, ...args) => console.log(strings, args);
const firstName = "Marvin";
const lastName = "Frachet";
div`Hello ${firstName} ${lastName} !`;
TIP: Tagged templates
On the follow line:
div`Hello ${firstName} ${lastName} !`;
div
is what we call a tag
. It allows to make some specific computations on the following template literals.
It's available by default in ES6 without any additional plugins!
Run the following command to check the result of such a bunch of code:
$ node ./framework/element.js
[ 'Hello ', ' ', ' !' ] [ 'Marvin', 'Frachet' ]
TIP: Tagged templates parameters
While using tagged template literals
, the first argument is an array of strings corresponding to the static string of the evaluated element. In the previous example, the static strings are Hello
, space
, and !
.
The second argument concerns the interpolated values. ...args
is called spreading the parameters. It will convert every
arguments (without knowing how much of them) into an array that we will be able to manage.
Okay, let's now create a real understandable string from this content. For this, I will use Array.reduce
function.
const div = (strings, ...args) =>
strings.reduce(
(acc, currentString, index) => acc + currentString + (args[index] || ""),
""
);
const firstName = "Marvin";
const lastName = "Frachet";
const template = div`Hello ${firstName} ${lastName} !`;
console.log(template); // It prints `Hello Marvin Frachet !`
If you're not familiar with Array.reduce
, it's the same as:
const div = (strings, ...args) => {
let acc = "";
for(const currentString of strings) {
const interpolatedString = (args[index] || ""):
acc += currentString + interpolatedString;
}
return acc;
};
It's great, we have now a tagged template literals
that is called div
. As you may have imagined, we'll use it later to display the content in the DOM.
Abstracting for others HTML elements
As developers, we're lazy people and we don't like code duplication. Let's abstract a bit the element creation so that we can use other HTML elements easily:
const createElement = tagName => (strings, ...args) => ({
type: tagName, // this will be useful for the next chapter
template: strings.reduce(
(acc, currentString, index) => acc + currentString + (args[index] || ""),
""
)
});
const div = createElement("div");
const p = createElement("p");
const firstName = "Marvin";
const lastName = "Frachet";
//const template = div`Hello ${firstName} ${lastName} !`;
const { template } = p`Hello ${firstName} ${lastName} !`;
console.log(template);