Compound tagged template literals

A tag is a function that precedes a template literal. It receives the literals data as arguments allowing you to make modifications.

Here’s an example of a html sanitise tag

1
2
3
4
5
6
7
8
9
10
function html(strings, ...subs) {
let result = strings[0];
for (let i = 0; i < subs.length; ++i) {
result += subs[i].replace(/&/g, '&amp;') + strings[i + 1];
}
return result;
}
const sub = 'B&O Associates';
html`<p>company: ${sub}</p>`;
// '<p>company: B&amp;O Associates</p>'

Another use case is localisation…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function l10n(strings) {
let result = strings[0];
let subs = [].slice.call(arguments, 1);
const map = {
fr: {company: 'compagnie'}
}
for (let i = 0; i < subs.length; i++) {
const arr = subs[i].split('.');
result += (
arr[0] === 'l10n'
? map[arr[1]][arr[2]]
: subs[i]
) + strings[i + 1];
}
return result;
}
const company = 'l10n.fr.company';
const sub = 'B&O Associates';
l10n`<p>${company}: ${sub}</p>`;
// '<p>compagnie: B&O Associates</p>'

So after looking at these use cases I started a thinking that we may want to have html sanitisation and localisation. And I’m sure there are many other situations where you would like to chain together template tags.

So I had a quick go at creating a compound template tag function.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
function html(str) {
return str.replace(/&/g, '&amp;');
}
function l10n(str) {
const map = {
fr: {company: 'compagnie'}
}
const arr = str.split('.');
return arr[0] === 'l10n' ? map[arr[1]][arr[2]] : str;
}
function compound_tag() {
const tags = Array.from(arguments);
const fun = new Function('str', `return ${tags.reduce((acc, f) => {
acc = `${f.name}(${acc})`;
return acc;
}, 'str')}`);
return (strings, ...subs) => {
let result = strings[0];
for (let i = 0; i < subs.length; i++) {
result += fun(subs[i]) + strings[i + 1];
}
return result;
}
}
const sub = 'B&O Associates';
const company = 'l10n.fr.company';
const html_l10n = compound_tag(html, l10n);
html_l10n`<p>${company}: ${sub}</p>`;
// '<p>compagnie: B&amp;O Associates</p>'