69 lines
2 KiB
JavaScript
69 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;
|