UNPKG

template-templates

Version:

Use incredibly efficient and stupidly-tiny functions to parse plain template-strings.

210 lines (144 loc) 5.25 kB
# template-templates Use incredibly efficient and stupidly-tiny functions to parse plain [template-string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals). Your target will [need to support those](https://caniuse.com/#feat=template-literals) for it to work. It's meant to just be a zero-dependency ultra-tiny way to get compiled templates, using a familiar syntax. See [it running, here](http://konsumer.js.org/template-templates/). ## really stupidly-tiny ``` 206 B: template-templates.cjs.gz 171 B: template-templates.cjs.br 183 B: template-templates.modern.js.gz 161 B: template-templates.modern.js.br 208 B: template-templates.mjs.gz 179 B: template-templates.mjs.br 290 B: template-templates.umd.js.gz 237 B: template-templates.umd.js.br ``` ## installation Add it to you project: ``` npm i template-templates ``` ## usage *TLDR*: If you just want to see a code-example, have a look at the [unit-test](https://github.com/konsumer/template-templates/blob/master/test/template-template.test.js) First, let's imagine we have a file named `demo.tpl` that looks like this: ``` Hi ${name}, ${news === 'good' ? 'We are delighted to inform you that' : 'We regret having to break this bad news to you, but' } ${reason} Signed Your Eternal Friends at ${company}, ${agent} ``` This is just a regular [template-string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals). Variables are expanded into the scope. ### node There are 2 different ways to use it, which are performance-wise about the same: ```js import tt from 'template-templates' import { readFile } from 'fs/promises' // load the file contents const tstring = await readFile('demo.tpl', 'utf8') // these are some vars I'm going to pass to the template const vars = { name: 'Mr. Anderson', company: 'MegaCorp', agent: 'Agent Smith', news: 'bad', reason: 'your cat died.' } // first example, just gimme the string, in one-use: console.log(tt(tstring, vars)) // second example: compile it for ultimate performance with re-use // give it a list of valid vars const template = tt.compile(tstring, Object.keys(vars)) // use it console.log(template(vars)) /* Hi Mr. Anderson, We regret having to break this bad news to you, but your cat died. Signed Your Eternal Friends at MegaCorp, Agent Smith */ ``` If you change your variables for good news, that works too: ```js const vars = { name: 'Mr. Anderson', company: 'MegaCorp', agent: 'Agent Smith', news: 'good', reason: 'you won the lottery.' } console.log(tt(tstring, vars)) /* Hi Mr. Anderson, We are delighted to inform you that you won the lottery. Signed Your Eternal Friends at MegaCorp, Agent Smith */ ``` ### browser You can use it the same way in a browser. Let's imagine you want to fetch that same template, from above: ```html <script type="module"> import tt from 'https://esm.run/template-templates' const vars = { name: 'Mr. Anderson', company: 'MegaCorp', agent: 'Agent Smith', news: 'bad', reason: 'your cat died.' } const tstring = await fetch('./demo.tpl').then(r => r.text()) console.log(tt(tstring, vars)) </script> ``` You can also see an example that uses inline-templates, [here](https://github.com/konsumer/template-templates/blob/master/test/demo.html). ### advanced #### back-ticks You can use back-ticks directly in your template, if you need to, which normally you would have to escape: ``` This is a markdown string with `code`. ``` #### plugins You can give it util functions, in it's variables, and use them, if you like. Think of this as "plugins": ```js import tt from 'template-templates' import { pluralize } from 'inflection' const tstring = 'You have ${count} ${pluralize(thing, count)}.' const vars = { pluralize, count: 10, thing: 'marble' } console.log(tt(tstring, vars)) /* You have 10 marbles. */ ``` #### pre-compiling There isn't really a huge performance difference between using `compile` first, or the immediate-mode. The downside is that you have to tell it what variables are going to be valid, but this should be pretty simple, in most cases. This technique shines in a place like a build script, where you want all the template functions, already working, without needing access to file-system to load templates, or have a dependency on `template-templates` in the output: ```js import tt from 'template-templates' import glob from 'glob-promise' import { readFile, writeFile } from 'fs/promises' import { basename } from 'path' const out = [] for (const file of await glob('./templates/*.tpl')) { const name = basename(file, '.tpl') out.push(`export const ${name} = ${tt.compile(await readFile(file, 'utf8'), ['name', 'company', 'agent', 'news', 'reason']).toString()}`)) } await writeFile('templates.js', out.join('\n\n')) ``` then you can use them later: ```js import { demo } from './templates.js' console.log(demo({ name: 'Mr. Anderson', company: 'MegaCorp', agent: 'Agent Smith', news: 'good', reason: 'you won the lottery.' })) ``` I might use this technique, for example, if I don't want to include `template-templates` in the output, and I don't want to worry about how to work with the filesystem.