@onereach/content-builder-template-compiler
Version:
Compiles template literals with data records
131 lines (113 loc) • 3.79 kB
JavaScript
const _ = require("lodash");
module.exports = {
getTemplateCompiler(data, parent, root = data, index = '') {
function getTemplateCompiler(data, parent = data, root = data, index = '') {
function evalExpression(strings, ...values) {
if (strings.length === 1) return strings[0];
if (strings.length === 2 && strings[0] === '' && strings[1] === '') return values[0];
return strings.reduce((acc, item, idx) => {
acc += item;
if (idx < values.length) acc += values[idx];
return acc;
}, '');
}
function compileData(exp) {
if (typeof exp !== 'string') return exp;
const vars = ["$data", "$parent", "$root", "$index", "_evalExpression"];
const {
keys,
values
} = Object.entries(data).reduce(
(memo, [key, value]) => {
if (vars.indexOf(key) === -1) {
memo.keys.push(key);
memo.values.push(value);
}
return memo;
}, {
keys: [],
values: []
}
);
return new Function(
...vars,
...keys,
`return _evalExpression\`${exp.replaceAll('`', '\\`')}\``
)(data, parent, root, index, evalExpression, ...values);
}
return function compile(template, key, keySuffix) {
if (template == null) return template;
if (!['string', 'object'].includes(typeof template)) {
return template;
}
if (typeof template === 'string') {
const s = compileData(template);
if (key === 'key' && keySuffix !== undefined) {
return `${s}--${keySuffix}`;
}
return s;
}
if (Array.isArray(template)) {
return template.reduce(
(acc, item, key) => acc.concat(compile(item, key)),
[]
);
}
if (template && Object.prototype.hasOwnProperty.call(template, 'urn')) {
if (template['$repeat'] !== undefined) {
let {
$repeat: items,
...tmpl
} = template;
if (typeof items === 'string') {
items = compile(items, '$repeat');
}
if (Array.isArray(items)) {
const listItems = _.reduce(
items,
(acc, item, index) => {
const compile = getTemplateCompiler(item, data, root, index);
return acc.concat(compile(tmpl, index, index));
},
[]
);
return listItems;
}
}
if (template['$data'] !== undefined) {
let {
$data: newData,
...tmpl
} = template;
if (typeof newData === 'string') {
newData = compile(newData, '$data');
}
if (newData !== undefined) {
let compile = getTemplateCompiler(newData, data, root, index);
return compile(tmpl, key, keySuffix);
}
}
if (template['$when'] !== undefined) {
let {
$when: condition,
...tmpl
} = template;
if (typeof condition === 'string') {
condition = compile(condition, '$when');
}
if (!condition) return [];
return compile(tmpl, key, keySuffix);
}
}
return Object.keys(template).reduce(
(memo, key) => {
return Object.assign(memo, {
[key]: compile(template[key], key, keySuffix)
})
}, {}
);
}
}
return getTemplateCompiler(data, parent, root, index);
}
};