In this blog post, we look at problems that arise when template literals contain whitespace:
I’m using the library common-tags by Declan de Wet (with “useful template literal tags for dealing with strings in ES6”) to demonstrate solutions for some of these problems.
Occasionally, you have long lines that you want to break up. common-tag’s tag function oneLine
lets you do that:
console.log(oneLine`
a
single
line
with
many
words
`);
// a single line with many words
Template literals let you embed multi-line text content inside JavaScript. The main challenge is that the text must both have proper indentation and fit nicely into its JavaScript surroundings:
function foo() {
console.log(`<ul>
<li>first</li>
<li>second</li>
</ul>`);
}
This does not look good: The initial <ul>
is out of place at the end of the line and subsequent lines don’t respect JavaScript’s indentation. The output of foo()
looks like this:
<ul>
<li>first</li>
<li>second</li>
</ul>
As a work-around one can use trim()
to gain more freedom w.r.t. the first and the last line:
function foo() {
console.log(`
<ul>
<li>first</li>
<li>second</li>
</ul>
`.trim());
}
The output is the same and the embedded text looks nicer, but the indentation problem remains.
A tag function like common-tag’s stripIndent
can help:
function foo() {
const ul = stripIndent`
<ul>
<li>first</li>
<li>second</li>
</ul>
`;
}
The idea is to determine which line has the smallest indent and to remove that indent from all lines. Additionally, leading and trailing whitespace is trimmed.
If you use template literals for templating, you often write code like this:
console.log(stripIndent`
<ul>
${['foo', 'bar'].map(x => `<li>${x}</li>`).join('\n')}
</ul>
`);
The problem is that the output is not properly indented:
<ul>
<li>foo</li>
<li>bar</li>
</ul>
That’s because the line breaks inserted via join()
are not followed by the correct indentation.
common-tags has the tag function html
which detects Arrays returned from substitutions (${}
) and inserts them correctly. No need for join()
, anymore:
console.log(html`
<ul>
${['foo', 'bar'].map(x => `<li>${x}</li>`)}
</ul>
`);
Now the output looks like this:
<ul>
<li>foo</li>
<li>bar</li>
</ul>
Alas, common-tags does not indent inserted strings correctly:
console.log(`
<ul>
${'<li>foo</li>\n<li>bar</li>'}
</ul>
`);
Here, the output is:
<ul>
<li>foo</li>
<li>bar</li>
</ul>
The line break between the </li>
and the <li>
is not followed by the correct indentation.