The HTML5 template
element seems to mangle Mustache curly braces in the HTML output, particularly within a table
:
<template id="test">
<table>
{{#foo}}
<tr><td>{{.}}</td></tr>
{{/foo}}
</table>
</template>
<script>
const html = document.getElementById("test").innerHTML;
</script>
The inner HTML shows this:
{{#foo}}{{/foo}}<table><tr><td>{{.}}</td></tr></table>
However, if instead of a template
we use a script
element, the HTML is not mangled:
<script id="test" type="text/html">
<table>
{{#foo}}
<tr><td>{{.}}</td></tr>
{{/foo}}
</table>
</script>
The inner HTML is correct, and can be used by Mustache:
<table>{{#foo}}<tr><td>{{.}}</td></tr>{{/foo}}</table>
Why is it that this happens with template
? Is there a way to somehow disable this behavior? Otherwise, apparently, it's not a good idea to use it with a template system like Mustache?
<template>
is specifically meant for use with Web Components, which has its own templating mechanism that is integrated in the web standards. The HTML inside a <template>
element should be considered "live" and must be well-formed, so you cannot just insert arbitrary text inside <table>...</table>
without also wrapping it in <td>...</td>
.
While a <script type="not-javascript">
may feel old-fashioned and perhaps a bit makeshift, it is still the only correct way to embed arbitrary template code in an HTML document.
Alternatively, you can save your template in a separate file and import it in your JavaScript modules with the help of a bundling tool and a suitable plugin. For example, if you were to bundle your JavaScript code using Rollup and use Wontache to render your Mustache templates, you could use rollup-plugin-wontache and structure your code as follows:
template.mustache
<table>
{{#foo}}
<tr><td>{{.}}</td></tr>
{{/foo}}
</table>
script.js
import template from './template.mustache';
var htmlCode = template({foo: ['item 1', 'item 2']});
There are similar plugins for other combinations of bundling tools and Mustache rendering engines.