Last active
February 8, 2024 08:26
-
-
Save jonschlinkert/58286a4fb931da6205c0166ec7e46522 to your computer and use it in GitHub Desktop.
PoC of an async template engine using native template literals and async-await. Response to https://twitter.com/doowb/status/1072688034485805058
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const compile = (input, helpers, thisArg) => { | |
return async data => { | |
let ctx = { ...thisArg, ...data }; | |
let keys = []; | |
let vals = []; | |
if (helpers) { | |
for (let key of Object.keys(helpers)) { | |
if (ctx[key] === void 0) { | |
ctx[key] = (...args) => helpers[key].call(ctx, ...args); | |
} | |
} | |
} | |
for (let key in ctx) { | |
if (ctx.hasOwnProperty(key)) { | |
keys.push(key); | |
vals.push(ctx[key]); | |
} | |
} | |
let isPromise = val => typeof val === 'function' || val instanceof Promise; | |
let resolve = (input, ctx) => { | |
return typeof input === 'function' ? input.call(ctx, ctx) : input; | |
}; | |
ctx.compile = compile; | |
ctx.render = (str, locals) => compile(str)({ ...ctx, ...locals }); | |
while (isPromise(input)) input = await resolve(input, ctx); | |
let source = `return ((async () => \`${input.replace(/\${/g, '${await ')}\`))()`; | |
return await Function(keys, source).apply(ctx, vals); | |
}; | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
const fs = require('fs'); | |
const path = require('path'); | |
const util = require('util'); | |
const compile = require('./es6-engine'); | |
const readfile = util.promisify(fs.readFile); | |
const { prompt } = require('enquirer'); | |
let partials = {}; | |
let helpers = { | |
read(name) { | |
return readfile(path.resolve(process.cwd(), name), 'utf8'); | |
}, | |
log(...args) { | |
console.log(...args); | |
return ''; | |
}, | |
prompt(question) { | |
return prompt(question).then(answers => { | |
this[question.name] = answers[question.name]; | |
return ''; | |
}); | |
}, | |
async partial(name, locals) { | |
return this.render(await partials[name], locals); | |
}, | |
include(name, locals) { | |
return this.render(helpers.read(name), locals); | |
} | |
}; | |
let registerPartial = (name, str) => { | |
partials[name] = compile(str, helpers); | |
}; | |
registerPartial('fixture3', helpers.read('fixture3.txt')); | |
// "compile()" takes a string, or a promise that returns a string | |
let value = helpers.read('fixture1.txt'); | |
let render = compile(value, helpers); | |
render({ name: 'Brian' }) | |
.then(console.log) | |
.catch(console.log); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Hi, my name is: ${include("fixture2.txt")} | |
Hi, my name is: ${include("fixture2.txt", { name: 'Bob' })} | |
Hi, my name is: ${partial("fixture3", { name: 'Alice' })} | |
${prompt({ type: 'input', name: 'name', message: 'Name?' })} | |
Hi, my name is: ${include("fixture2.txt")} | |
${log(this)} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
${name}!!! |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment