devsite/node_modules/@11ty/eleventy/src/EleventyExtensionMap.js
2024-07-07 18:49:38 -07:00

269 lines
6.6 KiB
JavaScript

const { TemplatePath } = require("@11ty/eleventy-utils");
const TemplateEngineManager = require("./TemplateEngineManager");
const TemplateConfig = require("./TemplateConfig");
const EleventyBaseError = require("./EleventyBaseError");
class EleventyExtensionMapConfigError extends EleventyBaseError {}
class EleventyExtensionMap {
constructor(formatKeys, config) {
if (!config) {
throw new EleventyExtensionMapConfigError("Missing `config` argument.");
}
if (config instanceof TemplateConfig) {
this.eleventyConfig = config;
}
this._config = config;
this.formatKeys = formatKeys;
this.setFormats(formatKeys);
this._spiderJsDepsCache = {};
}
setFormats(formatKeys = []) {
this.unfilteredFormatKeys = formatKeys.map(function (key) {
return key.trim().toLowerCase();
});
this.validTemplateLanguageKeys = this.unfilteredFormatKeys.filter((key) =>
this.hasExtension(key)
);
this.passthroughCopyKeys = this.unfilteredFormatKeys.filter((key) => !this.hasExtension(key));
}
set config(cfg) {
this._config = cfg;
}
get config() {
if (this._config instanceof TemplateConfig) {
return this._config.getConfig();
}
return this._config;
}
get engineManager() {
if (!this._engineManager) {
this._engineManager = new TemplateEngineManager(this.eleventyConfig);
}
return this._engineManager;
}
reset() {
this.engineManager.reset();
}
/* Used for layout path resolution */
getFileList(path, dir) {
if (!path) {
return [];
}
let files = [];
this.validTemplateLanguageKeys.forEach(
function (key) {
this.getExtensionsFromKey(key).forEach(function (extension) {
files.push((dir ? dir + "/" : "") + path + "." + extension);
});
}.bind(this)
);
return files;
}
// Warning: this would false positive on an include, but is only used
// on paths found from the file system glob search.
// TODO: Method name might just need to be renamed to something more accurate.
isFullTemplateFilePath(path) {
for (let extension of this.validTemplateLanguageKeys) {
if (path.endsWith(`.${extension}`)) {
return true;
}
}
return false;
}
getCustomExtensionEntry(extension) {
if (!this.config.extensionMap) {
return;
}
for (let entry of this.config.extensionMap) {
if (entry.extension === extension) {
return entry;
}
}
}
getValidExtensionsForPath(path) {
let extensions = new Set();
for (let extension in this.extensionToKeyMap) {
if (path.endsWith(`.${extension}`)) {
extensions.add(extension);
}
}
// if multiple extensions are valid, sort from longest to shortest
// e.g. .11ty.js and .js
let sorted = Array.from(extensions)
.filter((extension) => this.validTemplateLanguageKeys.includes(extension))
.sort((a, b) => b.length - a.length);
return sorted;
}
shouldSpiderJavaScriptDependencies(path) {
let extensions = this.getValidExtensionsForPath(path);
for (let extension of extensions) {
if (extension in this._spiderJsDepsCache) {
return this._spiderJsDepsCache[extension];
}
let cls = this.engineManager.getEngineClassByExtension(extension);
if (cls) {
let entry = this.getCustomExtensionEntry(extension);
let shouldSpider = cls.shouldSpiderJavaScriptDependencies(entry);
this._spiderJsDepsCache[extension] = shouldSpider;
return shouldSpider;
}
}
return false;
}
getPassthroughCopyGlobs(inputDir) {
return this._getGlobs(this.passthroughCopyKeys, inputDir);
}
getValidGlobs(inputDir) {
return this._getGlobs(this.validTemplateLanguageKeys, inputDir);
}
getGlobs(inputDir) {
return this._getGlobs(this.unfilteredFormatKeys, inputDir);
}
_getGlobs(formatKeys, inputDir) {
let dir = TemplatePath.convertToRecursiveGlobSync(inputDir);
let extensions = [];
for (let key of formatKeys) {
if (this.hasExtension(key)) {
for (let extension of this.getExtensionsFromKey(key)) {
extensions.push(extension);
}
} else {
extensions.push(key);
}
}
let globs = [];
if (extensions.length === 1) {
globs.push(`${dir}/*.${extensions[0]}`);
} else if (extensions.length > 1) {
globs.push(`${dir}/*.{${extensions.join(",")}}`);
}
return globs;
}
hasExtension(key) {
for (var extension in this.extensionToKeyMap) {
if (this.extensionToKeyMap[extension] === key) {
return true;
}
}
return false;
}
getExtensionsFromKey(key) {
let extensions = [];
for (var extension in this.extensionToKeyMap) {
if (this.extensionToKeyMap[extension] === key) {
extensions.push(extension);
}
}
return extensions;
}
// Only `addExtension` configuration API extensions
getExtensionEntriesFromKey(key) {
let entries = [];
if ("extensionMap" in this.config) {
for (let entry of this.config.extensionMap) {
if (entry.key === key) {
entries.push(entry);
}
}
}
return entries;
}
hasEngine(pathOrKey) {
return !!this.getKey(pathOrKey);
}
getKey(pathOrKey) {
pathOrKey = (pathOrKey || "").toLowerCase();
for (var extension in this.extensionToKeyMap) {
let key = this.extensionToKeyMap[extension];
if (pathOrKey === extension) {
return key;
} else if (pathOrKey.endsWith("." + extension)) {
return key;
}
}
}
removeTemplateExtension(path) {
for (var extension in this.extensionToKeyMap) {
if (path === extension || path.endsWith("." + extension)) {
return path.slice(
0,
path.length - 1 - extension.length < 0 ? 0 : path.length - 1 - extension.length
);
}
}
return path;
}
// keys are file extensions
// values are template language keys
get extensionToKeyMap() {
if (!this._extensionToKeyMap) {
this._extensionToKeyMap = {
ejs: "ejs",
md: "md",
html: "html",
hbs: "hbs",
mustache: "mustache",
haml: "haml",
pug: "pug",
njk: "njk",
liquid: "liquid",
"11ty.js": "11ty.js",
"11ty.cjs": "11ty.js",
};
if ("extensionMap" in this.config) {
for (let entry of this.config.extensionMap) {
this._extensionToKeyMap[entry.extension] = entry.key;
}
}
}
return this._extensionToKeyMap;
}
getReadableFileExtensions() {
return Object.keys(this.extensionToKeyMap).join(" ");
}
}
module.exports = EleventyExtensionMap;