68 lines
2 KiB
JavaScript
68 lines
2 KiB
JavaScript
const { set: lodashSet } = require("@11ty/lodash-custom");
|
||
|
||
const debug = require("debug")("Eleventy:ComputedDataTemplateString");
|
||
|
||
/* Calculates computed data in Template Strings.
|
||
* Ideally we would use the Proxy approach but it doesn’t work
|
||
* in some template languages that visit all available data even if
|
||
* it isn’t used in the template (Nunjucks)
|
||
*/
|
||
class ComputedDataTemplateString {
|
||
constructor(computedKeys) {
|
||
if (Array.isArray(computedKeys)) {
|
||
this.computedKeys = new Set(computedKeys);
|
||
} else {
|
||
this.computedKeys = computedKeys;
|
||
}
|
||
|
||
// is this ¯\_(lisp)_/¯
|
||
// must be strings that won’t be escaped by template languages
|
||
this.prefix = "(((11ty(((";
|
||
this.suffix = ")))11ty)))";
|
||
}
|
||
|
||
getProxyData() {
|
||
let proxyData = {};
|
||
|
||
// use these special strings as a workaround to check the rendered output
|
||
// can’t use proxies here as some template languages trigger proxy for all
|
||
// keys in data
|
||
for (let key of this.computedKeys) {
|
||
// TODO don’t allow to set eleventyComputed.page? other disallowed computed things?
|
||
lodashSet(proxyData, key, this.prefix + key + this.suffix);
|
||
}
|
||
|
||
return proxyData;
|
||
}
|
||
|
||
findVarsInOutput(output = "") {
|
||
let vars = new Set();
|
||
let splits = output.split(this.prefix);
|
||
for (let split of splits) {
|
||
let varName = split.slice(0, split.indexOf(this.suffix) < 0 ? 0 : split.indexOf(this.suffix));
|
||
if (varName) {
|
||
vars.add(varName);
|
||
}
|
||
}
|
||
return Array.from(vars);
|
||
}
|
||
|
||
async findVarsUsed(fn) {
|
||
let proxyData = this.getProxyData();
|
||
let output;
|
||
// Mitigation for #1061, errors with filters in the first pass shouldn’t fail the whole thing.
|
||
try {
|
||
output = await fn(proxyData);
|
||
} catch (e) {
|
||
debug("Computed Data first pass data resolution error: %o", e);
|
||
}
|
||
|
||
// page.outputPath on serverless urls returns false.
|
||
if (typeof output === "string") {
|
||
return this.findVarsInOutput(output);
|
||
}
|
||
return [];
|
||
}
|
||
}
|
||
|
||
module.exports = ComputedDataTemplateString;
|