Many tools give special treatment to literals tagged by a particular name.
const doc = html`<!DOCTYPE html>
<html lang="en-US">
<head>
<title>Hello</title>
</head>
<body>
<h1>Hello world!</h1>
</body>
</html>
`;
One might naïvely implement the html
tag as:
This, in fact, works for the case above. However, because String.raw
would concatenate the raw string literals instead of the "cooked" ones, escape sequences would not be processed.
const doc = html`<canvas>\n</canvas>`;
This may not be what you want for a "true identity" tag, where the tag is purely for markup and doesn't change the literal's value. In this case, you can create a custom tag and pass the "cooked" (i.e. escape sequences are processed) literal array to String.raw
, pretending they are raw strings.
const html = (strings, ...values) => String.raw({ raw: strings }, ...values);
const doc = html`<canvas>\n</canvas>`;
Notice the first argument is an object with a raw
property, whose value is an array-like object (with a length
property and integer indexes) representing the separated strings in the template literal. The rest of the arguments are the substitutions. Since the raw
value can be any array-like object, it can even be a string! For example, 'test'
is treated as ['t', 'e', 's', 't']
. The following is equivalent to `t${0}e${1}s${2}t`
:
String.raw({ raw: "test" }, 0, 1, 2);