mirror of
https://github.com/fooflington/selfdefined.git
synced 2025-04-22 17:19:08 +00:00
207 lines
5.3 KiB
JavaScript
207 lines
5.3 KiB
JavaScript
![]() |
const TemplatePath = require("./TemplatePath");
|
|||
|
const TemplateEngine = require("./Engines/TemplateEngine");
|
|||
|
const EleventyBaseError = require("./EleventyBaseError");
|
|||
|
const EleventyExtensionMap = require("./EleventyExtensionMap");
|
|||
|
const config = require("./Config");
|
|||
|
// const debug = require("debug")("Eleventy:TemplateRender");
|
|||
|
|
|||
|
class TemplateRenderUnknownEngineError extends EleventyBaseError {}
|
|||
|
|
|||
|
// works with full path names or short engine name
|
|||
|
class TemplateRender {
|
|||
|
constructor(tmplPath, inputDir, extensionMap) {
|
|||
|
if (!tmplPath) {
|
|||
|
throw new Error(
|
|||
|
`TemplateRender requires a tmplPath argument, instead of ${tmplPath}`
|
|||
|
);
|
|||
|
}
|
|||
|
|
|||
|
this.path = tmplPath;
|
|||
|
this.extensionMap = extensionMap;
|
|||
|
|
|||
|
// optional
|
|||
|
this.includesDir = this._normalizeIncludesDir(inputDir);
|
|||
|
|
|||
|
this.parseMarkdownWith = this.config.markdownTemplateEngine;
|
|||
|
this.parseHtmlWith = this.config.htmlTemplateEngine;
|
|||
|
|
|||
|
this.init(tmplPath);
|
|||
|
|
|||
|
this.useMarkdown = this.engineName === "md";
|
|||
|
}
|
|||
|
|
|||
|
get config() {
|
|||
|
if (!this._config) {
|
|||
|
this._config = config.getConfig();
|
|||
|
}
|
|||
|
return this._config;
|
|||
|
}
|
|||
|
|
|||
|
set config(config) {
|
|||
|
this._config = config;
|
|||
|
|
|||
|
if (this.engine) {
|
|||
|
this.engine.config = config;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
init(engineNameOrPath) {
|
|||
|
this.engineName = this.cleanupEngineName(engineNameOrPath);
|
|||
|
if (!this.engineName) {
|
|||
|
throw new TemplateRenderUnknownEngineError(
|
|||
|
`Unknown engine for ${engineNameOrPath}`
|
|||
|
);
|
|||
|
}
|
|||
|
this.engine = TemplateEngine.getEngine(this.engineName, this.includesDir);
|
|||
|
this.engine.initRequireCache(this.path);
|
|||
|
}
|
|||
|
|
|||
|
cleanupEngineName(tmplPath) {
|
|||
|
return TemplateRender._cleanupEngineName(
|
|||
|
tmplPath,
|
|||
|
this.extensionMap || EleventyExtensionMap
|
|||
|
);
|
|||
|
}
|
|||
|
static cleanupEngineName(tmplPath) {
|
|||
|
return TemplateRender._cleanupEngineName(tmplPath, EleventyExtensionMap);
|
|||
|
}
|
|||
|
static _cleanupEngineName(tmplPath, extensionMapRef) {
|
|||
|
return extensionMapRef.getKey(tmplPath);
|
|||
|
}
|
|||
|
|
|||
|
static hasEngine(tmplPath) {
|
|||
|
let name = TemplateRender.cleanupEngineName(tmplPath);
|
|||
|
return TemplateEngine.hasEngine(name);
|
|||
|
}
|
|||
|
|
|||
|
static parseEngineOverrides(engineName) {
|
|||
|
let overlappingEngineWarningCount = 0;
|
|||
|
let engines = [];
|
|||
|
let uniqueLookup = {};
|
|||
|
let usingMarkdown = false;
|
|||
|
(engineName || "")
|
|||
|
.split(",")
|
|||
|
.map(name => {
|
|||
|
return name.toLowerCase().trim();
|
|||
|
})
|
|||
|
.forEach(name => {
|
|||
|
// html is assumed (treated as plaintext by the system)
|
|||
|
if (!name || name === "html") {
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if (name === "md") {
|
|||
|
usingMarkdown = true;
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if (!uniqueLookup[name]) {
|
|||
|
engines.push(name);
|
|||
|
uniqueLookup[name] = true;
|
|||
|
|
|||
|
// we already short circuit md and html types above
|
|||
|
overlappingEngineWarningCount++;
|
|||
|
}
|
|||
|
});
|
|||
|
|
|||
|
if (overlappingEngineWarningCount > 1) {
|
|||
|
throw new Error(
|
|||
|
`Don’t mix multiple templating engines in your front matter overrides (exceptions for HTML and Markdown). You used: ${engineName}`
|
|||
|
);
|
|||
|
}
|
|||
|
|
|||
|
// markdown should always be first
|
|||
|
if (usingMarkdown) {
|
|||
|
// todo use unshift or something (no wifi here to look up docs :D)
|
|||
|
engines = ["md"].concat(engines);
|
|||
|
}
|
|||
|
|
|||
|
return engines;
|
|||
|
}
|
|||
|
|
|||
|
// used for error logging.
|
|||
|
getEnginesStr() {
|
|||
|
if (this.engineName === "md" && this.useMarkdown) {
|
|||
|
return this.parseMarkdownWith + " (and markdown)";
|
|||
|
}
|
|||
|
return this.engineName;
|
|||
|
}
|
|||
|
|
|||
|
setEngineOverride(engineName, bypassMarkdown) {
|
|||
|
let engines = TemplateRender.parseEngineOverrides(engineName);
|
|||
|
|
|||
|
// when overriding, Template Engines with HTML will instead use the Template Engine as primary and output HTML
|
|||
|
// So any HTML engine usage here will never use a preprocessor templating engine.
|
|||
|
this.setHtmlEngine(false);
|
|||
|
|
|||
|
if (!engines.length) {
|
|||
|
this.init("html");
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
this.init(engines[0]);
|
|||
|
|
|||
|
let usingMarkdown = engines[0] === "md" && !bypassMarkdown;
|
|||
|
|
|||
|
this.setUseMarkdown(usingMarkdown);
|
|||
|
|
|||
|
if (usingMarkdown) {
|
|||
|
// false means only parse markdown and not with a preprocessor template engine
|
|||
|
this.setMarkdownEngine(engines.length > 1 ? engines[1] : false);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
getEngineName() {
|
|||
|
return this.engineName;
|
|||
|
}
|
|||
|
|
|||
|
getIncludesDir() {
|
|||
|
return this.includesDir;
|
|||
|
}
|
|||
|
|
|||
|
_normalizeIncludesDir(dir) {
|
|||
|
return TemplatePath.join(
|
|||
|
dir ? dir : this.config.dir.input,
|
|||
|
this.config.dir.includes
|
|||
|
);
|
|||
|
}
|
|||
|
|
|||
|
isEngine(engine) {
|
|||
|
return this.engineName === engine;
|
|||
|
}
|
|||
|
|
|||
|
setUseMarkdown(useMarkdown) {
|
|||
|
this.useMarkdown = !!useMarkdown;
|
|||
|
}
|
|||
|
|
|||
|
setMarkdownEngine(markdownEngine) {
|
|||
|
this.parseMarkdownWith = markdownEngine;
|
|||
|
}
|
|||
|
|
|||
|
setHtmlEngine(htmlEngineName) {
|
|||
|
this.parseHtmlWith = htmlEngineName;
|
|||
|
}
|
|||
|
|
|||
|
async render(str, data) {
|
|||
|
return this.engine.render(str, data);
|
|||
|
}
|
|||
|
|
|||
|
async getCompiledTemplate(str) {
|
|||
|
// TODO refactor better, move into TemplateEngine logic
|
|||
|
if (this.engineName === "md") {
|
|||
|
return this.engine.compile(
|
|||
|
str,
|
|||
|
this.path,
|
|||
|
this.parseMarkdownWith,
|
|||
|
!this.useMarkdown
|
|||
|
);
|
|||
|
} else if (this.engineName === "html") {
|
|||
|
return this.engine.compile(str, this.path, this.parseHtmlWith);
|
|||
|
} else {
|
|||
|
return this.engine.compile(str, this.path);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
module.exports = TemplateRender;
|