inital
This commit is contained in:
197
node_modules/@11ty/eleventy/src/Engines/TemplateEngineManager.js
generated
vendored
Normal file
197
node_modules/@11ty/eleventy/src/Engines/TemplateEngineManager.js
generated
vendored
Normal file
@@ -0,0 +1,197 @@
|
||||
import debugUtil from "debug";
|
||||
import EleventyBaseError from "../Errors/EleventyBaseError.js";
|
||||
import { EleventyImportFromEleventy } from "../Util/Require.js";
|
||||
|
||||
const debug = debugUtil("Eleventy:TemplateEngineManager");
|
||||
|
||||
class TemplateEngineManagerConfigError extends EleventyBaseError {}
|
||||
|
||||
class TemplateEngineManager {
|
||||
constructor(eleventyConfig) {
|
||||
if (!eleventyConfig || eleventyConfig.constructor.name !== "TemplateConfig") {
|
||||
throw new TemplateEngineManagerConfigError("Missing or invalid `config` argument.");
|
||||
}
|
||||
this.eleventyConfig = eleventyConfig;
|
||||
|
||||
this.engineCache = {};
|
||||
this.importCache = {};
|
||||
}
|
||||
|
||||
get config() {
|
||||
return this.eleventyConfig.getConfig();
|
||||
}
|
||||
|
||||
static isAlias(entry) {
|
||||
if (entry.aliasKey) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return entry.key !== entry.extension;
|
||||
}
|
||||
|
||||
static isSimpleAlias(entry) {
|
||||
if (!this.isAlias(entry)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// has keys other than key, extension, and aliasKey
|
||||
return (
|
||||
Object.keys(entry).some((key) => {
|
||||
return key !== "key" && key !== "extension" && key !== "aliasKey";
|
||||
}) === false
|
||||
);
|
||||
}
|
||||
|
||||
get keyToClassNameMap() {
|
||||
if (!this._keyToClassNameMap) {
|
||||
this._keyToClassNameMap = {
|
||||
md: "Markdown",
|
||||
html: "Html",
|
||||
njk: "Nunjucks",
|
||||
liquid: "Liquid",
|
||||
"11ty.js": "JavaScript",
|
||||
};
|
||||
|
||||
// Custom entries *can* overwrite default entries above
|
||||
if ("extensionMap" in this.config) {
|
||||
for (let entry of this.config.extensionMap) {
|
||||
// either the key does not already exist or it is not a simple alias and is an override: https://v3.11ty.dev/docs/languages/custom/#overriding-an-existing-template-language
|
||||
let existingTarget = this._keyToClassNameMap[entry.key];
|
||||
let isAlias = TemplateEngineManager.isAlias(entry);
|
||||
|
||||
if (!existingTarget && isAlias) {
|
||||
throw new Error(
|
||||
`An attempt to alias ${entry.aliasKey} to ${entry.key} was made, but ${entry.key} is not a recognized template syntax.`,
|
||||
);
|
||||
}
|
||||
|
||||
if (isAlias) {
|
||||
// only `key` and `extension`, not `compile` or other options
|
||||
if (!TemplateEngineManager.isSimpleAlias(entry)) {
|
||||
this._keyToClassNameMap[entry.aliasKey] = "Custom";
|
||||
} else {
|
||||
this._keyToClassNameMap[entry.aliasKey] = this._keyToClassNameMap[entry.key];
|
||||
}
|
||||
} else {
|
||||
// not an alias, so `key` and `extension` are the same here.
|
||||
// *can* override a built-in extension!
|
||||
this._keyToClassNameMap[entry.key] = "Custom";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return this._keyToClassNameMap;
|
||||
}
|
||||
|
||||
reset() {
|
||||
this.engineCache = {};
|
||||
}
|
||||
|
||||
getClassNameFromTemplateKey(key) {
|
||||
return this.keyToClassNameMap[key];
|
||||
}
|
||||
|
||||
hasEngine(name) {
|
||||
return !!this.getClassNameFromTemplateKey(name);
|
||||
}
|
||||
|
||||
isEngineRemovedFromCore(name) {
|
||||
return ["ejs", "hbs", "mustache", "haml", "pug"].includes(name) && !this.hasEngine(name);
|
||||
}
|
||||
|
||||
async getEngineClassByExtension(extension) {
|
||||
if (this.importCache[extension]) {
|
||||
return this.importCache[extension];
|
||||
}
|
||||
|
||||
let promise;
|
||||
|
||||
// We include these as raw strings (and not more readable variables) so they’re parsed by a bundler.
|
||||
if (extension === "md") {
|
||||
promise = EleventyImportFromEleventy("./src/Engines/Markdown.js");
|
||||
} else if (extension === "html") {
|
||||
promise = EleventyImportFromEleventy("./src/Engines/Html.js");
|
||||
} else if (extension === "njk") {
|
||||
promise = EleventyImportFromEleventy("./src/Engines/Nunjucks.js");
|
||||
} else if (extension === "liquid") {
|
||||
promise = EleventyImportFromEleventy("./src/Engines/Liquid.js");
|
||||
} else if (extension === "11ty.js") {
|
||||
promise = EleventyImportFromEleventy("./src/Engines/JavaScript.js");
|
||||
} else {
|
||||
promise = this.getCustomEngineClass();
|
||||
}
|
||||
|
||||
this.importCache[extension] = promise;
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
async getCustomEngineClass() {
|
||||
if (!this._CustomEngine) {
|
||||
this._CustomEngine = EleventyImportFromEleventy("./src/Engines/Custom.js");
|
||||
}
|
||||
return this._CustomEngine;
|
||||
}
|
||||
|
||||
async #getEngine(name, extensionMap) {
|
||||
let cls = await this.getEngineClassByExtension(name);
|
||||
let instance = new cls(name, this.eleventyConfig);
|
||||
instance.extensionMap = extensionMap;
|
||||
instance.engineManager = this;
|
||||
|
||||
let extensionEntry = extensionMap.getExtensionEntry(name);
|
||||
|
||||
// Override a built-in extension (md => md)
|
||||
// If provided a "Custom" engine using addExtension, but that engine's instance is *not* custom,
|
||||
// The user must be overriding a built-in engine i.e. addExtension('md', { ...overrideBehavior })
|
||||
let className = this.getClassNameFromTemplateKey(name);
|
||||
|
||||
if (className === "Custom" && instance.constructor.name !== "CustomEngine") {
|
||||
let CustomEngine = await this.getCustomEngineClass();
|
||||
let overrideCustomEngine = new CustomEngine(name, this.eleventyConfig);
|
||||
|
||||
// Keep track of the "default" engine 11ty would normally use
|
||||
// This allows the user to access the default engine in their override
|
||||
overrideCustomEngine.setDefaultEngine(instance);
|
||||
|
||||
instance = overrideCustomEngine;
|
||||
// Alias to a built-in extension (11ty.tsx => 11ty.js)
|
||||
} else if (
|
||||
instance.constructor.name === "CustomEngine" &&
|
||||
TemplateEngineManager.isAlias(extensionEntry)
|
||||
) {
|
||||
// add defaultRenderer for complex aliases with their own compile functions.
|
||||
let originalEngineInstance = await this.getEngine(extensionEntry.key, extensionMap);
|
||||
instance.setDefaultEngine(originalEngineInstance);
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
async getEngine(name, extensionMap) {
|
||||
// Warning about engine deprecation
|
||||
if (this.isEngineRemovedFromCore(name)) {
|
||||
throw new Error(
|
||||
`Per the 11ty Community Survey (2023), the "${name}" template language was moved from core to an officially supported plugin in v3.0. These plugins live here: https://github.com/11ty/eleventy-plugin-template-languages and are documented on their respective template language docs at https://v3.11ty.dev/docs/languages/ You are also empowered to implement *any* template language yourself using https://v3.11ty.dev/docs/languages/custom/`,
|
||||
);
|
||||
}
|
||||
|
||||
if (!this.hasEngine(name)) {
|
||||
throw new Error(`Template Engine ${name} does not exist in getEngine()`);
|
||||
}
|
||||
|
||||
// TODO these cached engines should be based on extensions not name, then we can remove the error in
|
||||
// "Double override (not aliases) throws an error" test in TemplateRenderCustomTest.js
|
||||
if (!this.engineCache[name]) {
|
||||
debug("Engine cache miss %o (should only happen once per type)", name);
|
||||
// Make sure cache key is based on name and not path
|
||||
// Custom class is used for all plugins, cache once per plugin
|
||||
this.engineCache[name] = this.#getEngine(name, extensionMap);
|
||||
}
|
||||
|
||||
return this.engineCache[name];
|
||||
}
|
||||
}
|
||||
|
||||
export default TemplateEngineManager;
|
Reference in New Issue
Block a user