Why not leverage ES template strings? From what I can see it would support the same features (interpolating global JS, passing individual helper functions in, etc) natively.
I've built a teeny tiny template engine around this, allowing me to consume any string at all, and treat it like an ES template string: github.com/tomhodgins/jsts-engine
function jstsEngine(string = '', environment = {}) {
return new Function(
...Object.keys(environment),
'output={}',
'return [`' + string + '`, output]'
)(...Object.values(environment))
}
So I wonder what your template engine offers that ^ that template engine wouldn't support.
Here's an excerpt from a text file where I use it:
<ul class=toc>
${
galleries
.map(gallery => `
<li>
<a
href=${site.url}gallery/${helpers.slug(gallery.title)}.html
style="background-image: url(${helpers.randomArrayItem(gallery.images)});"
>
<span>${gallery.title}</span>
</a>
`)
.join('\n')
}
</ul>
So it can be used to template any language as well, here I'm templating HTML. Where you see things like ${gallery.title} that's reading a value directly, where you see things like ${helpers.slug()} or ${helpers.randomArrayItem()} you're seeing me run content through a JS helper function I also made available to the template engine. And as you can see here, it's all nestable too. You can interpolate inside the things you're interpolating too.