mirror of
https://github.com/fooflington/selfdefined.git
synced 2025-09-16 12:39:05 +00:00
update
This commit is contained in:
35
node_modules/@11ty/eleventy/src/Benchmark.js
generated
vendored
Normal file
35
node_modules/@11ty/eleventy/src/Benchmark.js
generated
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
class Benchmark {
|
||||
constructor() {
|
||||
this.reset();
|
||||
}
|
||||
|
||||
reset() {
|
||||
this.timeSpent = 0;
|
||||
this.beforeDates = [];
|
||||
}
|
||||
|
||||
before() {
|
||||
this.beforeDates.push(new Date());
|
||||
}
|
||||
|
||||
after() {
|
||||
if (!this.beforeDates.length) {
|
||||
throw new Error("You called Benchmark after() without a before().");
|
||||
}
|
||||
|
||||
let before = this.beforeDates.pop();
|
||||
if (!this.beforeDates.length) {
|
||||
this.timeSpent += new Date().getTime() - before.getTime();
|
||||
}
|
||||
}
|
||||
|
||||
getTotal() {
|
||||
return this.timeSpent;
|
||||
}
|
||||
|
||||
getTotalString() {
|
||||
return this.timeSpent > 0 ? ` (${this.timeSpent}ms)` : "";
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Benchmark;
|
73
node_modules/@11ty/eleventy/src/BenchmarkGroup.js
generated
vendored
Normal file
73
node_modules/@11ty/eleventy/src/BenchmarkGroup.js
generated
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
const chalk = require("chalk");
|
||||
|
||||
const Benchmark = require("./Benchmark");
|
||||
const debugWarn = require("debug")("Eleventy:Warnings");
|
||||
|
||||
class BenchmarkGroup {
|
||||
constructor() {
|
||||
this.benchmarks = {};
|
||||
this.start = new Date();
|
||||
this.isVerbose = true;
|
||||
this.minimumThresholdMs = 0;
|
||||
}
|
||||
|
||||
reset() {
|
||||
this.start = new Date();
|
||||
|
||||
for (var type in this.benchmarks) {
|
||||
this.benchmarks[type].reset();
|
||||
}
|
||||
}
|
||||
|
||||
// TODO make this async
|
||||
add(type, callback) {
|
||||
let benchmark = (this.benchmarks[type] = new Benchmark());
|
||||
|
||||
return function(...args) {
|
||||
benchmark.before();
|
||||
let ret = callback.call(this, ...args);
|
||||
benchmark.after();
|
||||
return ret;
|
||||
};
|
||||
}
|
||||
|
||||
setMinimumThresholdMs(minimumThresholdMs) {
|
||||
let val = parseInt(minimumThresholdMs, 10);
|
||||
if (isNaN(val)) {
|
||||
throw new Error("`setMinimumThresholdMs` expects a number argument.");
|
||||
}
|
||||
this.minimumThresholdMs = val;
|
||||
}
|
||||
|
||||
get(type) {
|
||||
this.benchmarks[type] = new Benchmark();
|
||||
return this.benchmarks[type];
|
||||
}
|
||||
|
||||
finish(label, thresholdPercent, isVerbose) {
|
||||
let totalTimeSpent = new Date().getTime() - this.start.getTime();
|
||||
thresholdPercent = thresholdPercent !== undefined ? thresholdPercent : 10;
|
||||
for (var type in this.benchmarks) {
|
||||
let bench = this.benchmarks[type];
|
||||
let totalForBenchmark = bench.getTotal();
|
||||
let percent = (totalForBenchmark * 100) / totalTimeSpent;
|
||||
if (
|
||||
percent > thresholdPercent &&
|
||||
totalForBenchmark >= this.minimumThresholdMs
|
||||
) {
|
||||
let str = chalk.yellow(
|
||||
`Benchmark (${label}): ${type} took ${bench.getTotal()}ms (${percent.toFixed(
|
||||
1
|
||||
)}%)`
|
||||
);
|
||||
if (isVerbose) {
|
||||
console.log(str);
|
||||
}
|
||||
|
||||
debugWarn(str);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = BenchmarkGroup;
|
47
node_modules/@11ty/eleventy/src/BenchmarkManager.js
generated
vendored
Normal file
47
node_modules/@11ty/eleventy/src/BenchmarkManager.js
generated
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
const BenchmarkGroup = require("./BenchmarkGroup");
|
||||
|
||||
class BenchmarkManager {
|
||||
constructor() {
|
||||
this.benches = {};
|
||||
this.isVerbose = true;
|
||||
}
|
||||
|
||||
reset() {
|
||||
for (var j in this.benches) {
|
||||
this.benches[j].reset();
|
||||
}
|
||||
}
|
||||
|
||||
setVerboseOutput(isVerbose) {
|
||||
this.isVerbose = !!isVerbose;
|
||||
}
|
||||
|
||||
getBenchmarkGroup(name) {
|
||||
if (!this.benches[name]) {
|
||||
this.benches[name] = new BenchmarkGroup();
|
||||
}
|
||||
|
||||
return this.benches[name];
|
||||
}
|
||||
|
||||
getAll() {
|
||||
return this.benches;
|
||||
}
|
||||
|
||||
get(name) {
|
||||
if (name) {
|
||||
return this.getBenchmarkGroup(name);
|
||||
}
|
||||
|
||||
return this.getAll();
|
||||
}
|
||||
|
||||
finish(thresholdPercent) {
|
||||
for (var j in this.benches) {
|
||||
this.benches[j].finish(j, thresholdPercent, this.isVerbose);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let manager = new BenchmarkManager();
|
||||
module.exports = manager;
|
7
node_modules/@11ty/eleventy/src/Config.js
generated
vendored
Normal file
7
node_modules/@11ty/eleventy/src/Config.js
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
const TemplateConfig = require("./TemplateConfig");
|
||||
const debug = require("debug")("Eleventy:Config");
|
||||
|
||||
debug("Setting up global TemplateConfig.");
|
||||
let config = new TemplateConfig();
|
||||
|
||||
module.exports = config;
|
451
node_modules/@11ty/eleventy/src/Eleventy.js
generated
vendored
Normal file
451
node_modules/@11ty/eleventy/src/Eleventy.js
generated
vendored
Normal file
@@ -0,0 +1,451 @@
|
||||
const pkg = require("../package.json");
|
||||
const TemplatePath = require("./TemplatePath");
|
||||
const TemplateData = require("./TemplateData");
|
||||
const TemplateWriter = require("./TemplateWriter");
|
||||
const EleventyErrorHandler = require("./EleventyErrorHandler");
|
||||
const EleventyServe = require("./EleventyServe");
|
||||
const EleventyWatchTargets = require("./EleventyWatchTargets");
|
||||
const EleventyFiles = require("./EleventyFiles");
|
||||
const templateCache = require("./TemplateCache");
|
||||
const simplePlural = require("./Util/Pluralize");
|
||||
const config = require("./Config");
|
||||
const bench = require("./BenchmarkManager");
|
||||
const debug = require("debug")("Eleventy");
|
||||
|
||||
class Eleventy {
|
||||
constructor(input, output) {
|
||||
this.config = config.getConfig();
|
||||
this.configPath = null;
|
||||
this.isVerbose = true;
|
||||
this.isDebug = false;
|
||||
this.isDryRun = false;
|
||||
|
||||
this.start = new Date();
|
||||
this.formatsOverride = null;
|
||||
this.eleventyServe = new EleventyServe();
|
||||
|
||||
this.rawInput = input;
|
||||
this.rawOutput = output;
|
||||
|
||||
this.watchTargets = new EleventyWatchTargets();
|
||||
this.watchTargets.watchJavaScriptDependencies = this.config.watchJavaScriptDependencies;
|
||||
}
|
||||
|
||||
get input() {
|
||||
return this.rawInput || this.config.dir.input;
|
||||
}
|
||||
|
||||
get inputDir() {
|
||||
return TemplatePath.getDir(this.input);
|
||||
}
|
||||
|
||||
get outputDir() {
|
||||
let dir = this.rawOutput || this.config.dir.output;
|
||||
if (dir !== this._savedOutputDir) {
|
||||
this.eleventyServe.setOutputDir(dir);
|
||||
}
|
||||
this._savedOutputDir = dir;
|
||||
|
||||
return dir;
|
||||
}
|
||||
|
||||
setDryRun(isDryRun) {
|
||||
this.isDryRun = !!isDryRun;
|
||||
}
|
||||
|
||||
setPassthroughAll(isPassthroughAll) {
|
||||
this.isPassthroughAll = !!isPassthroughAll;
|
||||
}
|
||||
|
||||
setPathPrefix(pathPrefix) {
|
||||
if (pathPrefix || pathPrefix === "") {
|
||||
config.setPathPrefix(pathPrefix);
|
||||
this.config = config.getConfig();
|
||||
}
|
||||
}
|
||||
|
||||
setWatchTargets(watchTargets) {
|
||||
this.watchTargets = watchTargets;
|
||||
}
|
||||
|
||||
setConfigPathOverride(configPath) {
|
||||
if (configPath) {
|
||||
this.configPath = configPath;
|
||||
|
||||
config.setProjectConfigPath(configPath);
|
||||
this.config = config.getConfig();
|
||||
}
|
||||
}
|
||||
|
||||
async restart() {
|
||||
debug("Restarting");
|
||||
this.start = new Date();
|
||||
templateCache.clear();
|
||||
bench.reset();
|
||||
this.eleventyFiles.restart();
|
||||
|
||||
// reload package.json values (if applicable)
|
||||
// TODO only reset this if it changed
|
||||
delete require.cache[TemplatePath.absolutePath("package.json")];
|
||||
|
||||
await this.init();
|
||||
}
|
||||
|
||||
finish() {
|
||||
bench.finish();
|
||||
|
||||
(this.logger || console).log(this.logFinished());
|
||||
debug("Finished writing templates.");
|
||||
}
|
||||
|
||||
logFinished() {
|
||||
if (!this.writer) {
|
||||
throw new Error(
|
||||
"Did you call Eleventy.init to create the TemplateWriter instance? Hint: you probably didn’t."
|
||||
);
|
||||
}
|
||||
|
||||
let ret = [];
|
||||
|
||||
let writeCount = this.writer.getWriteCount();
|
||||
let copyCount = this.writer.getCopyCount();
|
||||
if (this.isDryRun) {
|
||||
ret.push("Pretended to");
|
||||
}
|
||||
if (copyCount) {
|
||||
ret.push(
|
||||
`${this.isDryRun ? "Copy" : "Copied"} ${copyCount} ${simplePlural(
|
||||
copyCount,
|
||||
"item",
|
||||
"items"
|
||||
)} and`
|
||||
);
|
||||
}
|
||||
ret.push(
|
||||
`${this.isDryRun ? "Process" : "Processed"} ${writeCount} ${simplePlural(
|
||||
writeCount,
|
||||
"file",
|
||||
"files"
|
||||
)}`
|
||||
);
|
||||
|
||||
let time = ((new Date() - this.start) / 1000).toFixed(2);
|
||||
ret.push(`in ${time} ${simplePlural(time, "second", "seconds")}`);
|
||||
|
||||
if (writeCount >= 10) {
|
||||
ret.push(
|
||||
`(${((time * 1000) / writeCount).toFixed(1)}ms each, v${pkg.version})`
|
||||
);
|
||||
} else {
|
||||
ret.push(`(v${pkg.version})`);
|
||||
}
|
||||
|
||||
return ret.join(" ");
|
||||
}
|
||||
|
||||
async init() {
|
||||
let formats = this.formatsOverride || this.config.templateFormats;
|
||||
this.eleventyFiles = new EleventyFiles(
|
||||
this.input,
|
||||
this.outputDir,
|
||||
formats,
|
||||
this.isPassthroughAll
|
||||
);
|
||||
this.eleventyFiles.init();
|
||||
|
||||
this.templateData = new TemplateData(this.inputDir);
|
||||
this.eleventyFiles.setTemplateData(this.templateData);
|
||||
|
||||
this.writer = new TemplateWriter(
|
||||
this.input,
|
||||
this.outputDir,
|
||||
formats,
|
||||
this.templateData,
|
||||
this.isPassthroughAll
|
||||
);
|
||||
|
||||
this.writer.setEleventyFiles(this.eleventyFiles);
|
||||
|
||||
// TODO maybe isVerbose -> console.log?
|
||||
debug(`Directories:
|
||||
Input: ${this.inputDir}
|
||||
Data: ${this.templateData.getDataDir()}
|
||||
Includes: ${this.eleventyFiles.getIncludesDir()}
|
||||
Layouts: ${this.eleventyFiles.getLayoutsDir()}
|
||||
Output: ${this.outputDir}
|
||||
Template Formats: ${formats.join(",")}`);
|
||||
|
||||
this.writer.setVerboseOutput(this.isVerbose);
|
||||
this.writer.setDryRun(this.isDryRun);
|
||||
|
||||
return this.templateData.cacheData();
|
||||
}
|
||||
|
||||
setIsDebug(isDebug) {
|
||||
this.isDebug = !!isDebug;
|
||||
}
|
||||
|
||||
setIsVerbose(isVerbose) {
|
||||
this.isVerbose = !!isVerbose;
|
||||
|
||||
if (this.writer) {
|
||||
this.writer.setVerboseOutput(this.isVerbose);
|
||||
}
|
||||
if (bench) {
|
||||
bench.setVerboseOutput(this.isVerbose);
|
||||
}
|
||||
}
|
||||
|
||||
setFormats(formats) {
|
||||
if (formats && formats !== "*") {
|
||||
this.formatsOverride = formats.split(",");
|
||||
}
|
||||
}
|
||||
|
||||
getVersion() {
|
||||
return require("../package.json").version;
|
||||
}
|
||||
|
||||
getHelp() {
|
||||
return `usage: eleventy
|
||||
eleventy --input=. --output=./_site
|
||||
eleventy --serve
|
||||
|
||||
Arguments:
|
||||
--version
|
||||
--input=.
|
||||
Input template files (default: \`.\`)
|
||||
--output=_site
|
||||
Write HTML output to this folder (default: \`_site\`)
|
||||
--serve
|
||||
Run web server on --port (default 8080) and watch them too
|
||||
--watch
|
||||
Wait for files to change and automatically rewrite (no web server)
|
||||
--formats=liquid,md
|
||||
Whitelist only certain template types (default: \`*\`)
|
||||
--quiet
|
||||
Don’t print all written files (off by default)
|
||||
--config=filename.js
|
||||
Override the eleventy config file path (default: \`.eleventy.js\`)
|
||||
--pathprefix='/'
|
||||
Change all url template filters to use this subdirectory.
|
||||
--dryrun
|
||||
Don’t write any files. Useful with \`DEBUG=Eleventy* npx eleventy\`
|
||||
--help`;
|
||||
}
|
||||
|
||||
resetConfig() {
|
||||
config.reset();
|
||||
|
||||
this.config = config.getConfig();
|
||||
this.eleventyServe.config = this.config;
|
||||
}
|
||||
|
||||
async _watch(path) {
|
||||
if (path) {
|
||||
path = TemplatePath.addLeadingDotSlash(path);
|
||||
}
|
||||
|
||||
if (this.active) {
|
||||
this.queuedToRun = path;
|
||||
return;
|
||||
}
|
||||
|
||||
this.active = true;
|
||||
|
||||
let localProjectConfigPath = config.getLocalProjectConfigFile();
|
||||
// reset and reload global configuration :O
|
||||
if (path === localProjectConfigPath) {
|
||||
this.resetConfig();
|
||||
}
|
||||
config.resetOnWatch();
|
||||
|
||||
await this.restart();
|
||||
this.watchTargets.clearDependencyRequireCache();
|
||||
|
||||
await this.write();
|
||||
|
||||
this.watchTargets.reset();
|
||||
await this._initWatchDependencies();
|
||||
|
||||
// Add new deps to chokidar
|
||||
this.watcher.add(this.watchTargets.getNewTargetsSinceLastReset());
|
||||
|
||||
let isInclude =
|
||||
path &&
|
||||
TemplatePath.startsWithSubPath(path, this.eleventyFiles.getIncludesDir());
|
||||
this.eleventyServe.reload(path, isInclude);
|
||||
|
||||
this.active = false;
|
||||
|
||||
if (this.queuedToRun) {
|
||||
console.log("You saved while Eleventy was running, let’s run again.");
|
||||
this.queuedToRun = false;
|
||||
await this._watch(this.queuedToRun);
|
||||
} else {
|
||||
console.log("Watching…");
|
||||
}
|
||||
}
|
||||
|
||||
get watcherBench() {
|
||||
return bench.get("Watcher");
|
||||
}
|
||||
|
||||
async initWatch() {
|
||||
this.watchTargets.add(this.eleventyFiles.getGlobWatcherFiles());
|
||||
|
||||
// Watch the local project config file
|
||||
this.watchTargets.add(config.getLocalProjectConfigFile());
|
||||
|
||||
// Template and Directory Data Files
|
||||
this.watchTargets.add(
|
||||
await this.eleventyFiles.getGlobWatcherTemplateDataFiles()
|
||||
);
|
||||
|
||||
let benchmark = this.watcherBench.get(
|
||||
"Watching JavaScript Dependencies (disable with `eleventyConfig.setWatchJavaScriptDependencies(false)`)"
|
||||
);
|
||||
benchmark.before();
|
||||
await this._initWatchDependencies();
|
||||
benchmark.after();
|
||||
}
|
||||
|
||||
async _initWatchDependencies() {
|
||||
if (!this.watchTargets.watchJavaScriptDependencies) {
|
||||
return;
|
||||
}
|
||||
|
||||
let dataDir = this.templateData.getDataDir();
|
||||
function filterOutGlobalDataFiles(path) {
|
||||
return !dataDir || path.indexOf(dataDir) === -1;
|
||||
}
|
||||
|
||||
// Template files .11ty.js
|
||||
this.watchTargets.addDependencies(this.eleventyFiles.getWatchPathCache());
|
||||
|
||||
// Config file dependencies
|
||||
this.watchTargets.addDependencies(
|
||||
config.getLocalProjectConfigFile(),
|
||||
filterOutGlobalDataFiles.bind(this)
|
||||
);
|
||||
|
||||
// Deps from Global Data (that aren’t in the global data directory, everything is watched there)
|
||||
this.watchTargets.addDependencies(
|
||||
this.templateData.getWatchPathCache(),
|
||||
filterOutGlobalDataFiles.bind(this)
|
||||
);
|
||||
|
||||
this.watchTargets.addDependencies(
|
||||
await this.eleventyFiles.getWatcherTemplateJavaScriptDataFiles()
|
||||
);
|
||||
}
|
||||
|
||||
async getWatchedFiles() {
|
||||
return this.watchTargets.getTargets();
|
||||
}
|
||||
|
||||
async watch() {
|
||||
this.watcherBench.setMinimumThresholdMs(500);
|
||||
this.watcherBench.reset();
|
||||
|
||||
const chokidar = require("chokidar");
|
||||
|
||||
this.active = false;
|
||||
this.queuedToRun = false;
|
||||
|
||||
// Note that watching indirectly depends on this for fetching dependencies from JS files
|
||||
// See: TemplateWriter:pathCache and EleventyWatchTargets
|
||||
await this.write();
|
||||
|
||||
await this.initWatch();
|
||||
|
||||
// TODO improve unwatching if JS dependencies are removed (or files are deleted)
|
||||
let rawFiles = await this.getWatchedFiles();
|
||||
debug("Watching for changes to: %o", rawFiles);
|
||||
|
||||
let ignores = this.eleventyFiles.getGlobWatcherIgnores();
|
||||
debug("Watching but ignoring changes to: %o", ignores);
|
||||
|
||||
let watcher = chokidar.watch(rawFiles, {
|
||||
ignored: ignores,
|
||||
ignoreInitial: true
|
||||
});
|
||||
|
||||
this.watcherBench.finish("Initialize --watch", 10, this.isVerbose);
|
||||
|
||||
console.log("Watching…");
|
||||
|
||||
this.watcher = watcher;
|
||||
|
||||
async function watchRun(path) {
|
||||
try {
|
||||
await this._watch(path);
|
||||
} catch (e) {
|
||||
EleventyErrorHandler.fatal(e, "Eleventy fatal watch error");
|
||||
watcher.close();
|
||||
}
|
||||
}
|
||||
|
||||
watcher.on("change", async path => {
|
||||
console.log("File changed:", path);
|
||||
await watchRun.call(this, path);
|
||||
});
|
||||
|
||||
watcher.on("add", async path => {
|
||||
console.log("File added:", path);
|
||||
await watchRun.call(this, path);
|
||||
});
|
||||
|
||||
process.on(
|
||||
"SIGINT",
|
||||
function() {
|
||||
debug("Cleaning up chokidar and browsersync (if exists) instances.");
|
||||
this.eleventyServe.close();
|
||||
this.watcher.close();
|
||||
process.exit();
|
||||
}.bind(this)
|
||||
);
|
||||
}
|
||||
|
||||
serve(port) {
|
||||
this.eleventyServe.serve(port);
|
||||
}
|
||||
|
||||
/* For testing */
|
||||
setLogger(logger) {
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
async write() {
|
||||
let ret;
|
||||
if (this.logger) {
|
||||
EleventyErrorHandler.logger = this.logger;
|
||||
}
|
||||
|
||||
try {
|
||||
let promise = this.writer.write();
|
||||
|
||||
ret = await promise;
|
||||
} catch (e) {
|
||||
EleventyErrorHandler.initialMessage(
|
||||
"Problem writing Eleventy templates",
|
||||
"error",
|
||||
"red"
|
||||
);
|
||||
EleventyErrorHandler.fatal(e);
|
||||
}
|
||||
|
||||
this.finish();
|
||||
|
||||
debug(`
|
||||
Getting frustrated? Have a suggestion/feature request/feedback?
|
||||
I want to hear it! Open an issue: https://github.com/11ty/eleventy/issues/new`);
|
||||
|
||||
// unset the logger
|
||||
EleventyErrorHandler.logger = undefined;
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Eleventy;
|
10
node_modules/@11ty/eleventy/src/EleventyBaseError.js
generated
vendored
Normal file
10
node_modules/@11ty/eleventy/src/EleventyBaseError.js
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
class EleventyBaseError extends Error {
|
||||
constructor(message, originalError) {
|
||||
super(message);
|
||||
Error.captureStackTrace(this, this.constructor);
|
||||
this.name = this.constructor.name;
|
||||
|
||||
this.originalError = originalError;
|
||||
}
|
||||
}
|
||||
module.exports = EleventyBaseError;
|
82
node_modules/@11ty/eleventy/src/EleventyCommandCheck.js
generated
vendored
Normal file
82
node_modules/@11ty/eleventy/src/EleventyCommandCheck.js
generated
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
const EleventyBaseError = require("./EleventyBaseError");
|
||||
const debug = require("debug")("Eleventy:CommandCheck");
|
||||
|
||||
class EleventyCommandCheckError extends EleventyBaseError {}
|
||||
|
||||
class EleventyCommandCheck {
|
||||
constructor(argv) {
|
||||
this.valueArgs = [
|
||||
"input",
|
||||
"output",
|
||||
"formats",
|
||||
"config",
|
||||
"pathprefix",
|
||||
"port"
|
||||
];
|
||||
|
||||
this.booleanArgs = [
|
||||
"quiet",
|
||||
"version",
|
||||
"watch",
|
||||
"dryrun",
|
||||
"help",
|
||||
"serve",
|
||||
"passthroughall"
|
||||
];
|
||||
|
||||
this.args = argv;
|
||||
this.argsMap = this.getArgumentLookupMap();
|
||||
|
||||
debug("command: eleventy ", this.toString());
|
||||
}
|
||||
|
||||
toString() {
|
||||
let cmd = [];
|
||||
|
||||
for (let valueArgName of this.valueArgs) {
|
||||
if (this.args[valueArgName]) {
|
||||
cmd.push(`--${valueArgName}=${this.args[valueArgName]}`);
|
||||
}
|
||||
}
|
||||
|
||||
for (let booleanArgName of this.booleanArgs) {
|
||||
if (this.args[booleanArgName]) {
|
||||
cmd.push(`--${booleanArgName}`);
|
||||
}
|
||||
}
|
||||
|
||||
return cmd.join(" ");
|
||||
}
|
||||
|
||||
getArgumentLookupMap() {
|
||||
let obj = {};
|
||||
for (let valueArgName of this.valueArgs) {
|
||||
obj[valueArgName] = true;
|
||||
}
|
||||
for (let booleanArgName of this.booleanArgs) {
|
||||
obj[booleanArgName] = true;
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
isKnownArgument(name) {
|
||||
// _ is the default keyless parameter
|
||||
if (name === "_") {
|
||||
return true;
|
||||
}
|
||||
|
||||
return !!this.argsMap[name];
|
||||
}
|
||||
|
||||
hasUnknownArguments() {
|
||||
for (let argName in this.args) {
|
||||
if (!this.isKnownArgument(argName)) {
|
||||
throw new EleventyCommandCheckError(
|
||||
`We don’t know what '${argName}' is. Use --help to see the list of supported commands.`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = EleventyCommandCheck;
|
3
node_modules/@11ty/eleventy/src/EleventyConfig.js
generated
vendored
Normal file
3
node_modules/@11ty/eleventy/src/EleventyConfig.js
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
const UserConfig = require("./UserConfig");
|
||||
|
||||
module.exports = new UserConfig();
|
93
node_modules/@11ty/eleventy/src/EleventyErrorHandler.js
generated
vendored
Normal file
93
node_modules/@11ty/eleventy/src/EleventyErrorHandler.js
generated
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
const chalk = require("chalk");
|
||||
const debug = require("debug")("Eleventy:EleventyErrorHandler");
|
||||
|
||||
class EleventyErrorHandler {
|
||||
static get isChalkEnabled() {
|
||||
if (this._isChalkEnabled !== undefined) {
|
||||
return this._isChalkEnabled;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static set isChalkEnabled(enabled) {
|
||||
this._isChalkEnabled = !!enabled;
|
||||
}
|
||||
|
||||
static warn(e, msg) {
|
||||
if (msg) {
|
||||
EleventyErrorHandler.initialMessage(msg, "warn", "yellow");
|
||||
}
|
||||
EleventyErrorHandler.log(e, "warn");
|
||||
}
|
||||
|
||||
static fatal(e, msg) {
|
||||
EleventyErrorHandler.error(e, msg);
|
||||
process.exitCode = 1;
|
||||
}
|
||||
|
||||
static error(e, msg) {
|
||||
if (msg) {
|
||||
EleventyErrorHandler.initialMessage(msg, "error", "red");
|
||||
}
|
||||
EleventyErrorHandler.log(e, "error");
|
||||
}
|
||||
|
||||
static log(e, type = "log", prefix = ">") {
|
||||
let ref = e;
|
||||
while (ref) {
|
||||
let nextRef = ref.originalError;
|
||||
EleventyErrorHandler.message(
|
||||
(process.env.DEBUG ? "" : `${prefix} `) +
|
||||
`${ref.message.trim()}
|
||||
|
||||
\`${ref.name}\` was thrown${!nextRef && ref.stack ? ":" : ""}`,
|
||||
type
|
||||
);
|
||||
|
||||
if (process.env.DEBUG) {
|
||||
debug(`(${type} stack): ${ref.stack}`);
|
||||
} else if (!nextRef) {
|
||||
// last error in the loop
|
||||
let prefix = " ";
|
||||
// remove duplicate error messages if the stack contains the original message output above
|
||||
//
|
||||
let stackStr = ref.stack || "";
|
||||
if (e.removeDuplicateErrorStringFromOutput) {
|
||||
stackStr = stackStr.replace(
|
||||
`${ref.name}: ${ref.message}`,
|
||||
"(Repeated output has been truncated…)"
|
||||
);
|
||||
}
|
||||
EleventyErrorHandler.message(
|
||||
prefix + stackStr.split("\n").join("\n" + prefix)
|
||||
);
|
||||
}
|
||||
ref = nextRef;
|
||||
}
|
||||
}
|
||||
|
||||
static initialMessage(message, type = "log", chalkColor = "blue") {
|
||||
if (message) {
|
||||
EleventyErrorHandler.message(
|
||||
message + ":" + (process.env.DEBUG ? "" : " (more in DEBUG output)"),
|
||||
type,
|
||||
chalkColor
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
static message(message, type = "log", chalkColor) {
|
||||
if (process.env.DEBUG) {
|
||||
debug(message);
|
||||
} else {
|
||||
let logger = EleventyErrorHandler.logger || console;
|
||||
if (chalkColor && EleventyErrorHandler.isChalkEnabled) {
|
||||
logger[type](chalk[chalkColor](message));
|
||||
} else {
|
||||
logger[type](message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = EleventyErrorHandler;
|
17
node_modules/@11ty/eleventy/src/EleventyErrorUtil.js
generated
vendored
Normal file
17
node_modules/@11ty/eleventy/src/EleventyErrorUtil.js
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
const TemplateContentPrematureUseError = require("./Errors/TemplateContentPrematureUseError");
|
||||
|
||||
class EleventyErrorUtil {
|
||||
static isPrematureTemplateContentError(e) {
|
||||
// TODO the rest of the template engines
|
||||
return (
|
||||
e instanceof TemplateContentPrematureUseError ||
|
||||
(e.originalError &&
|
||||
e.originalError.name === "RenderError" &&
|
||||
e.originalError.originalError instanceof
|
||||
TemplateContentPrematureUseError) || // Liquid
|
||||
e.message.indexOf("TemplateContentPrematureUseError") > -1
|
||||
); // Nunjucks
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = EleventyErrorUtil;
|
164
node_modules/@11ty/eleventy/src/EleventyExtensionMap.js
generated
vendored
Normal file
164
node_modules/@11ty/eleventy/src/EleventyExtensionMap.js
generated
vendored
Normal file
@@ -0,0 +1,164 @@
|
||||
const TemplatePath = require("./TemplatePath");
|
||||
const config = require("./Config");
|
||||
|
||||
class EleventyExtensionMap {
|
||||
constructor(formatKeys = []) {
|
||||
this.unfilteredFormatKeys = formatKeys.map(function(key) {
|
||||
return key.trim().toLowerCase();
|
||||
});
|
||||
|
||||
this.formatKeys = this.unfilteredFormatKeys.filter(key =>
|
||||
this.hasExtension(key)
|
||||
);
|
||||
|
||||
this.prunedFormatKeys = this.unfilteredFormatKeys.filter(
|
||||
key => !this.hasExtension(key)
|
||||
);
|
||||
}
|
||||
|
||||
get config() {
|
||||
return this.configOverride || config.getConfig();
|
||||
}
|
||||
set config(cfg) {
|
||||
this.configOverride = cfg;
|
||||
}
|
||||
|
||||
/* Used for layout path resolution */
|
||||
getFileList(path, dir) {
|
||||
if (!path) {
|
||||
return [];
|
||||
}
|
||||
|
||||
let files = [];
|
||||
this.formatKeys.forEach(
|
||||
function(key) {
|
||||
this.getExtensionsFromKey(key).forEach(function(extension) {
|
||||
files.push((dir ? dir + "/" : "") + path + "." + extension);
|
||||
});
|
||||
}.bind(this)
|
||||
);
|
||||
|
||||
return files;
|
||||
}
|
||||
|
||||
getPrunedGlobs(inputDir) {
|
||||
return this._getGlobs(this.prunedFormatKeys, inputDir);
|
||||
}
|
||||
|
||||
getGlobs(inputDir) {
|
||||
if (this.config.passthroughFileCopy) {
|
||||
return this._getGlobs(this.unfilteredFormatKeys, inputDir);
|
||||
}
|
||||
|
||||
return this._getGlobs(this.formatKeys, inputDir);
|
||||
}
|
||||
|
||||
_getGlobs(formatKeys, inputDir) {
|
||||
let dir = TemplatePath.convertToRecursiveGlob(inputDir);
|
||||
let globs = [];
|
||||
formatKeys.forEach(
|
||||
function(key) {
|
||||
if (this.hasExtension(key)) {
|
||||
this.getExtensionsFromKey(key).forEach(function(extension) {
|
||||
globs.push(dir + "/*." + extension);
|
||||
});
|
||||
} else {
|
||||
globs.push(dir + "/*." + key);
|
||||
}
|
||||
}.bind(this)
|
||||
);
|
||||
return globs;
|
||||
}
|
||||
|
||||
hasExtension(key) {
|
||||
for (var extension in EleventyExtensionMap.keyMap) {
|
||||
if (EleventyExtensionMap.keyMap[extension] === key) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
getExtensionsFromKey(key) {
|
||||
let extensions = [];
|
||||
for (var extension in this.keyMap) {
|
||||
if (this.keyMap[extension] === key) {
|
||||
extensions.push(extension);
|
||||
}
|
||||
}
|
||||
return extensions;
|
||||
}
|
||||
|
||||
getKey(pathOrKey) {
|
||||
return EleventyExtensionMap._getKey(pathOrKey, this.keyMap);
|
||||
}
|
||||
static getKey(pathOrKey) {
|
||||
return EleventyExtensionMap._getKey(pathOrKey, EleventyExtensionMap.keyMap);
|
||||
}
|
||||
static _getKey(pathOrKey, map) {
|
||||
pathOrKey = pathOrKey.toLowerCase();
|
||||
|
||||
for (var extension in map) {
|
||||
let key = map[extension];
|
||||
if (pathOrKey === extension) {
|
||||
return key;
|
||||
} else if (pathOrKey.endsWith("." + extension)) {
|
||||
return key;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
removeTemplateExtension(path) {
|
||||
return EleventyExtensionMap._removeTemplateExtension(path, this.keyMap);
|
||||
}
|
||||
static removeTemplateExtension(path) {
|
||||
return EleventyExtensionMap._removeTemplateExtension(
|
||||
path,
|
||||
EleventyExtensionMap.keyMap
|
||||
);
|
||||
}
|
||||
static _removeTemplateExtension(path, map) {
|
||||
for (var extension in map) {
|
||||
if (path === extension || path.endsWith("." + extension)) {
|
||||
return path.substr(0, path.length - 1 - extension.length);
|
||||
}
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
get keyMap() {
|
||||
return EleventyExtensionMap._getKeyMap(
|
||||
this.config.templateExtensionAliases || {}
|
||||
);
|
||||
}
|
||||
static get keyMap() {
|
||||
return EleventyExtensionMap._getKeyMap(
|
||||
config.getConfig().templateExtensionAliases || {}
|
||||
);
|
||||
}
|
||||
|
||||
// file extension => key
|
||||
static _getKeyMap(aliases) {
|
||||
let fileExtensionToKeyMap = {
|
||||
ejs: "ejs",
|
||||
md: "md",
|
||||
jstl: "jstl",
|
||||
html: "html",
|
||||
hbs: "hbs",
|
||||
mustache: "mustache",
|
||||
haml: "haml",
|
||||
pug: "pug",
|
||||
njk: "njk",
|
||||
liquid: "liquid",
|
||||
"11ty.js": "11ty.js"
|
||||
};
|
||||
|
||||
for (let extension in aliases) {
|
||||
fileExtensionToKeyMap[extension] = aliases[extension];
|
||||
}
|
||||
|
||||
return fileExtensionToKeyMap;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = EleventyExtensionMap;
|
349
node_modules/@11ty/eleventy/src/EleventyFiles.js
generated
vendored
Normal file
349
node_modules/@11ty/eleventy/src/EleventyFiles.js
generated
vendored
Normal file
@@ -0,0 +1,349 @@
|
||||
const fs = require("fs-extra");
|
||||
const fastglob = require("fast-glob");
|
||||
|
||||
const EleventyExtensionMap = require("./EleventyExtensionMap");
|
||||
const TemplateData = require("./TemplateData");
|
||||
const TemplateGlob = require("./TemplateGlob");
|
||||
const TemplatePath = require("./TemplatePath");
|
||||
const TemplatePassthroughManager = require("./TemplatePassthroughManager");
|
||||
|
||||
const config = require("./Config");
|
||||
const debug = require("debug")("Eleventy:EleventyFiles");
|
||||
// const debugDev = require("debug")("Dev:Eleventy:EleventyFiles");
|
||||
|
||||
class EleventyFiles {
|
||||
constructor(input, outputDir, formats, passthroughAll) {
|
||||
this.config = config.getConfig();
|
||||
this.input = input;
|
||||
this.inputDir = TemplatePath.getDir(this.input);
|
||||
this.outputDir = outputDir;
|
||||
|
||||
this.initConfig();
|
||||
|
||||
this.passthroughAll = !!passthroughAll;
|
||||
|
||||
this.formats = formats;
|
||||
this.extensionMap = new EleventyExtensionMap(formats);
|
||||
}
|
||||
|
||||
initConfig() {
|
||||
this.includesDir = TemplatePath.join(
|
||||
this.inputDir,
|
||||
this.config.dir.includes
|
||||
);
|
||||
|
||||
if ("layouts" in this.config.dir) {
|
||||
this.layoutsDir = TemplatePath.join(
|
||||
this.inputDir,
|
||||
this.config.dir.layouts
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
init() {
|
||||
this.initFormatsGlobs();
|
||||
this.setPassthroughManager();
|
||||
this.setupGlobs();
|
||||
}
|
||||
|
||||
restart() {
|
||||
this.passthroughManager.reset();
|
||||
this.setupGlobs();
|
||||
}
|
||||
|
||||
/* For testing */
|
||||
_setConfig(config) {
|
||||
this.config = config;
|
||||
this.initConfig();
|
||||
}
|
||||
/* For testing */
|
||||
_setExtensionMap(map) {
|
||||
this.extensionMap = map;
|
||||
}
|
||||
/* Set command root for local project paths */
|
||||
_setLocalPathRoot(dir) {
|
||||
this.localPathRoot = dir;
|
||||
}
|
||||
|
||||
setPassthroughAll(passthroughAll) {
|
||||
this.passthroughAll = !!passthroughAll;
|
||||
}
|
||||
|
||||
initFormatsGlobs() {
|
||||
// Input was a directory
|
||||
if (this.input === this.inputDir) {
|
||||
this.templateGlobs = TemplateGlob.map(
|
||||
this.extensionMap.getGlobs(this.inputDir)
|
||||
);
|
||||
} else {
|
||||
this.templateGlobs = TemplateGlob.map([this.input]);
|
||||
}
|
||||
}
|
||||
|
||||
getPassthroughManager() {
|
||||
return this.passthroughManager;
|
||||
}
|
||||
|
||||
setPassthroughManager(mgr) {
|
||||
if (!mgr) {
|
||||
mgr = new TemplatePassthroughManager();
|
||||
mgr.setInputDir(this.inputDir);
|
||||
mgr.setOutputDir(this.outputDir);
|
||||
}
|
||||
|
||||
this.passthroughManager = mgr;
|
||||
}
|
||||
|
||||
setTemplateData(templateData) {
|
||||
this.templateData = templateData;
|
||||
}
|
||||
|
||||
// TODO make this a getter
|
||||
getTemplateData() {
|
||||
if (!this.templateData) {
|
||||
this.templateData = new TemplateData(this.inputDir);
|
||||
}
|
||||
return this.templateData;
|
||||
}
|
||||
|
||||
getDataDir() {
|
||||
let data = this.getTemplateData();
|
||||
|
||||
return data.getDataDir();
|
||||
}
|
||||
|
||||
setupGlobs() {
|
||||
this.ignores = this.getIgnores();
|
||||
|
||||
if (this.passthroughAll) {
|
||||
this.watchedGlobs = TemplateGlob.map([
|
||||
TemplateGlob.normalizePath(this.input, "/**")
|
||||
]).concat(this.ignores);
|
||||
} else {
|
||||
this.watchedGlobs = this.templateGlobs.concat(this.ignores);
|
||||
}
|
||||
|
||||
this.templateGlobsWithIgnores = this.watchedGlobs.concat(
|
||||
this.getTemplateIgnores()
|
||||
);
|
||||
}
|
||||
|
||||
static getFileIgnores(ignoreFiles, defaultIfFileDoesNotExist) {
|
||||
if (!Array.isArray(ignoreFiles)) {
|
||||
ignoreFiles = [ignoreFiles];
|
||||
}
|
||||
|
||||
let ignores = [];
|
||||
let fileFound = false;
|
||||
let dirs = [];
|
||||
for (let ignorePath of ignoreFiles) {
|
||||
ignorePath = TemplatePath.normalize(ignorePath);
|
||||
|
||||
let dir = TemplatePath.getDirFromFilePath(ignorePath);
|
||||
dirs.push(dir);
|
||||
|
||||
if (fs.existsSync(ignorePath) && fs.statSync(ignorePath).size > 0) {
|
||||
fileFound = true;
|
||||
let ignoreContent = fs.readFileSync(ignorePath, "utf-8");
|
||||
|
||||
// make sure that empty .gitignore with spaces takes default ignore.
|
||||
if (ignoreContent.trim().length === 0) {
|
||||
fileFound = false;
|
||||
} else {
|
||||
ignores = ignores.concat(
|
||||
EleventyFiles.normalizeIgnoreContent(dir, ignoreContent)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!fileFound && defaultIfFileDoesNotExist) {
|
||||
ignores.push("!" + TemplateGlob.normalizePath(defaultIfFileDoesNotExist));
|
||||
for (let dir of dirs) {
|
||||
ignores.push(
|
||||
"!" + TemplateGlob.normalizePath(dir, defaultIfFileDoesNotExist)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ignores.forEach(function(path) {
|
||||
debug(`${ignoreFiles} ignoring: ${path}`);
|
||||
});
|
||||
return ignores;
|
||||
}
|
||||
|
||||
static normalizeIgnoreContent(dir, ignoreContent) {
|
||||
let ignores = [];
|
||||
|
||||
if (ignoreContent) {
|
||||
ignores = ignoreContent
|
||||
.split("\n")
|
||||
.map(line => {
|
||||
return line.trim();
|
||||
})
|
||||
.filter(line => {
|
||||
// empty lines or comments get filtered out
|
||||
return line.length > 0 && line.charAt(0) !== "#";
|
||||
})
|
||||
.map(line => {
|
||||
let path = TemplateGlob.normalizePath(dir, "/", line);
|
||||
path = TemplatePath.addLeadingDotSlash(
|
||||
TemplatePath.relativePath(path)
|
||||
);
|
||||
|
||||
try {
|
||||
// Note these folders must exist to get /** suffix
|
||||
let stat = fs.statSync(path);
|
||||
if (stat.isDirectory()) {
|
||||
return "!" + path + "/**";
|
||||
}
|
||||
return "!" + path;
|
||||
} catch (e) {
|
||||
return "!" + path;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return ignores;
|
||||
}
|
||||
|
||||
getIgnores() {
|
||||
let files = [];
|
||||
if (this.config.useGitIgnore) {
|
||||
files = files.concat(
|
||||
EleventyFiles.getFileIgnores(
|
||||
[
|
||||
TemplatePath.join(
|
||||
this.localPathRoot || TemplatePath.getWorkingDir(),
|
||||
".gitignore"
|
||||
),
|
||||
TemplatePath.join(this.inputDir, ".gitignore")
|
||||
],
|
||||
"node_modules/**"
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (this.config.eleventyignoreOverride !== false) {
|
||||
let eleventyIgnores = [
|
||||
TemplatePath.join(
|
||||
this.localPathRoot || TemplatePath.getWorkingDir(),
|
||||
".eleventyignore"
|
||||
),
|
||||
TemplatePath.join(this.inputDir, ".eleventyignore")
|
||||
];
|
||||
|
||||
files = files.concat(
|
||||
this.config.eleventyignoreOverride ||
|
||||
EleventyFiles.getFileIgnores(eleventyIgnores)
|
||||
);
|
||||
}
|
||||
|
||||
files = files.concat(TemplateGlob.map("!" + this.outputDir + "/**"));
|
||||
|
||||
return files;
|
||||
}
|
||||
|
||||
getIncludesDir() {
|
||||
return this.includesDir;
|
||||
}
|
||||
|
||||
getLayoutsDir() {
|
||||
return this.layoutsDir;
|
||||
}
|
||||
|
||||
getFileGlobs() {
|
||||
return this.templateGlobsWithIgnores;
|
||||
}
|
||||
|
||||
getRawFiles() {
|
||||
return this.templateGlobs;
|
||||
}
|
||||
|
||||
getWatchPathCache() {
|
||||
return this.pathCache;
|
||||
}
|
||||
|
||||
async getFiles() {
|
||||
let globs = this.getFileGlobs();
|
||||
|
||||
debug("Searching for: %o", globs);
|
||||
let paths = TemplatePath.addLeadingDotSlashArray(
|
||||
await fastglob(globs, {
|
||||
caseSensitiveMatch: false,
|
||||
dot: true
|
||||
})
|
||||
);
|
||||
this.pathCache = paths;
|
||||
return paths;
|
||||
}
|
||||
|
||||
getGlobWatcherFiles() {
|
||||
// TODO is it better to tie the includes and data to specific file extensions or keep the **?
|
||||
return this.templateGlobs
|
||||
.concat(this.getIncludesAndDataDirs())
|
||||
.concat(this.getPassthroughManager().getConfigPathGlobs());
|
||||
}
|
||||
|
||||
async getGlobWatcherTemplateDataFiles() {
|
||||
let templateData = this.getTemplateData();
|
||||
return await templateData.getTemplateDataFileGlob();
|
||||
}
|
||||
|
||||
// TODO this isn’t great but reduces complexity avoiding using TemplateData:getLocalDataPaths for each template in the cache
|
||||
async getWatcherTemplateJavaScriptDataFiles() {
|
||||
let globs = await this.getTemplateData().getTemplateJavaScriptDataFileGlob();
|
||||
return TemplatePath.addLeadingDotSlashArray(
|
||||
await fastglob(globs, {
|
||||
ignore: ["**/node_modules/**"],
|
||||
caseSensitiveMatch: false,
|
||||
dot: true
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
getGlobWatcherIgnores() {
|
||||
// convert to format without ! since they are passed in as a separate argument to glob watcher
|
||||
return this.ignores.map(ignore =>
|
||||
TemplatePath.stripLeadingDotSlash(ignore.substr(1))
|
||||
);
|
||||
}
|
||||
|
||||
getPassthroughPaths() {
|
||||
let paths = [];
|
||||
paths = paths.concat(this.passthroughManager.getConfigPaths());
|
||||
// These are already added in the root templateGlobs
|
||||
// paths = paths.concat(this.extensionMap.getPrunedGlobs(this.inputDir));
|
||||
return paths;
|
||||
}
|
||||
|
||||
getIncludesAndDataDirs() {
|
||||
let files = [];
|
||||
// we want this to fail on "" because we don’t want to ignore the
|
||||
// entire input directory when using ""
|
||||
if (this.config.dir.includes) {
|
||||
files = files.concat(TemplateGlob.map(this.includesDir + "/**"));
|
||||
}
|
||||
|
||||
// we want this to fail on "" because we don’t want to ignore the
|
||||
// entire input directory when using ""
|
||||
if (this.config.dir.layouts) {
|
||||
files = files.concat(TemplateGlob.map(this.layoutsDir + "/**"));
|
||||
}
|
||||
|
||||
if (this.config.dir.data && this.config.dir.data !== ".") {
|
||||
let dataDir = this.getDataDir();
|
||||
files = files.concat(TemplateGlob.map(dataDir + "/**"));
|
||||
}
|
||||
|
||||
return files;
|
||||
}
|
||||
|
||||
getTemplateIgnores() {
|
||||
return this.getIncludesAndDataDirs().map(function(dir) {
|
||||
return "!" + dir;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = EleventyFiles;
|
176
node_modules/@11ty/eleventy/src/EleventyServe.js
generated
vendored
Normal file
176
node_modules/@11ty/eleventy/src/EleventyServe.js
generated
vendored
Normal file
@@ -0,0 +1,176 @@
|
||||
const fs = require("fs-extra");
|
||||
|
||||
const TemplatePath = require("./TemplatePath");
|
||||
const config = require("./Config");
|
||||
const debug = require("debug")("EleventyServe");
|
||||
|
||||
class EleventyServe {
|
||||
constructor() {}
|
||||
|
||||
get config() {
|
||||
return this.configOverride || config.getConfig();
|
||||
}
|
||||
set config(config) {
|
||||
this.configOverride = config;
|
||||
}
|
||||
|
||||
setOutputDir(outputDir) {
|
||||
this.outputDir = outputDir;
|
||||
}
|
||||
|
||||
getPathPrefix() {
|
||||
return this.config.pathPrefix || "/";
|
||||
}
|
||||
|
||||
getRedirectDir(dirName) {
|
||||
return TemplatePath.join(this.outputDir, dirName);
|
||||
}
|
||||
getRedirectDirOverride() {
|
||||
// has a pathPrefix, add a /index.html template to redirect to /pathPrefix/
|
||||
if (this.getPathPrefix() !== "/") {
|
||||
return "_eleventy_redirect";
|
||||
}
|
||||
}
|
||||
|
||||
getRedirectFilename(dirName) {
|
||||
return TemplatePath.join(this.getRedirectDir(dirName), "index.html");
|
||||
}
|
||||
|
||||
getOptions(port) {
|
||||
let pathPrefix = this.getPathPrefix();
|
||||
|
||||
// TODO customize this in Configuration API?
|
||||
let serverConfig = {
|
||||
baseDir: this.outputDir
|
||||
};
|
||||
|
||||
let redirectDirName = this.getRedirectDirOverride();
|
||||
// has a pathPrefix, add a /index.html template to redirect to /pathPrefix/
|
||||
if (redirectDirName) {
|
||||
serverConfig.baseDir = this.getRedirectDir(redirectDirName);
|
||||
serverConfig.routes = {};
|
||||
serverConfig.routes[pathPrefix] = this.outputDir;
|
||||
|
||||
// if has a savedPathPrefix, use the /savedPathPrefix/index.html template to redirect to /pathPrefix/
|
||||
if (this.savedPathPrefix) {
|
||||
serverConfig.routes[this.savedPathPrefix] = TemplatePath.join(
|
||||
this.outputDir,
|
||||
this.savedPathPrefix
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return Object.assign(
|
||||
{
|
||||
server: serverConfig,
|
||||
port: port || 8080,
|
||||
ignore: ["node_modules"],
|
||||
watch: false,
|
||||
open: false,
|
||||
notify: false,
|
||||
index: "index.html"
|
||||
},
|
||||
this.config.browserSyncConfig
|
||||
);
|
||||
}
|
||||
|
||||
cleanupRedirect(dirName) {
|
||||
if (dirName && dirName !== "/") {
|
||||
let savedPathFilename = this.getRedirectFilename(dirName);
|
||||
|
||||
setTimeout(function() {
|
||||
if (!fs.existsSync(savedPathFilename)) {
|
||||
debug(`Cleanup redirect: Could not find ${savedPathFilename}`);
|
||||
return;
|
||||
}
|
||||
|
||||
let savedPathContent = fs.readFileSync(savedPathFilename, "utf-8");
|
||||
if (
|
||||
savedPathContent.indexOf("Browsersync pathPrefix Redirect") === -1
|
||||
) {
|
||||
debug(
|
||||
`Cleanup redirect: Found ${savedPathFilename} but it wasn’t an eleventy redirect.`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
fs.unlink(savedPathFilename, err => {
|
||||
if (!err) {
|
||||
debug(`Cleanup redirect: Deleted ${savedPathFilename}`);
|
||||
}
|
||||
});
|
||||
}, 2000);
|
||||
}
|
||||
}
|
||||
|
||||
serveRedirect(dirName) {
|
||||
fs.outputFile(
|
||||
this.getRedirectFilename(dirName),
|
||||
`<!doctype html>
|
||||
<meta http-equiv="refresh" content="0; url=${this.config.pathPrefix}">
|
||||
<title>Browsersync pathPrefix Redirect</title>
|
||||
<a href="${this.config.pathPrefix}">Go to ${this.config.pathPrefix}</a>`
|
||||
);
|
||||
}
|
||||
|
||||
serve(port) {
|
||||
// only load on serve—this is pretty expensive
|
||||
const browserSync = require("browser-sync");
|
||||
this.server = browserSync.create();
|
||||
|
||||
let pathPrefix = this.getPathPrefix();
|
||||
|
||||
if (this.savedPathPrefix && pathPrefix !== this.savedPathPrefix) {
|
||||
let redirectFilename = this.getRedirectFilename(this.savedPathPrefix);
|
||||
if (!fs.existsSync(redirectFilename)) {
|
||||
debug(
|
||||
`Redirecting BrowserSync from ${
|
||||
this.savedPathPrefix
|
||||
} to ${pathPrefix}`
|
||||
);
|
||||
this.serveRedirect(this.savedPathPrefix);
|
||||
} else {
|
||||
debug(
|
||||
`Config updated with a new pathPrefix. Tried to set up a transparent redirect but found a template already existing at ${redirectFilename}. You’ll have to navigate manually.`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let redirectDirName = this.getRedirectDirOverride();
|
||||
// has a pathPrefix, add a /index.html template to redirect to /pathPrefix/
|
||||
if (redirectDirName) {
|
||||
this.serveRedirect(redirectDirName);
|
||||
}
|
||||
|
||||
this.cleanupRedirect(this.savedPathPrefix);
|
||||
this.server.init(this.getOptions(port));
|
||||
|
||||
// this needs to happen after `.getOptions`
|
||||
this.savedPathPrefix = pathPrefix;
|
||||
}
|
||||
|
||||
close() {
|
||||
if (this.server) {
|
||||
this.server.exit();
|
||||
}
|
||||
}
|
||||
|
||||
reload(path, isInclude) {
|
||||
if (this.server) {
|
||||
if (this.getPathPrefix() !== this.savedPathPrefix) {
|
||||
this.server.exit();
|
||||
this.serve();
|
||||
} else {
|
||||
// Is a CSS input file and is not in the includes folder
|
||||
// TODO check output path file extension of this template (not input path)
|
||||
if (path && path.split(".").pop() === "css" && !isInclude) {
|
||||
this.server.reload("*.css");
|
||||
} else {
|
||||
this.server.reload();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = EleventyServe;
|
125
node_modules/@11ty/eleventy/src/EleventyWatchTargets.js
generated
vendored
Normal file
125
node_modules/@11ty/eleventy/src/EleventyWatchTargets.js
generated
vendored
Normal file
@@ -0,0 +1,125 @@
|
||||
const dependencyTree = require("dependency-tree");
|
||||
const TemplatePath = require("./TemplatePath");
|
||||
|
||||
class EleventyWatchTargets {
|
||||
constructor() {
|
||||
this.targets = new Set();
|
||||
this.dependencies = new Set();
|
||||
this.newTargets = new Set();
|
||||
this._watchJavaScriptDependencies = true;
|
||||
}
|
||||
|
||||
set watchJavaScriptDependencies(watch) {
|
||||
this._watchJavaScriptDependencies = !!watch;
|
||||
}
|
||||
|
||||
get watchJavaScriptDependencies() {
|
||||
return this._watchJavaScriptDependencies;
|
||||
}
|
||||
|
||||
_normalizeTargets(targets) {
|
||||
if (!targets) {
|
||||
return [];
|
||||
} else if (Array.isArray(targets)) {
|
||||
return targets;
|
||||
}
|
||||
|
||||
return [targets];
|
||||
}
|
||||
|
||||
reset() {
|
||||
this.newTargets = new Set();
|
||||
}
|
||||
|
||||
isWatched(target) {
|
||||
return this.targets.has(target);
|
||||
}
|
||||
|
||||
addRaw(targets, isDependency) {
|
||||
for (let target of targets) {
|
||||
let path = TemplatePath.addLeadingDotSlash(target);
|
||||
if (!this.isWatched(path)) {
|
||||
this.newTargets.add(path);
|
||||
}
|
||||
|
||||
this.targets.add(path);
|
||||
|
||||
if (isDependency) {
|
||||
this.dependencies.add(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// add only a target
|
||||
add(targets) {
|
||||
targets = this._normalizeTargets(targets);
|
||||
this.addRaw(targets);
|
||||
}
|
||||
|
||||
// add only a target’s dependencies
|
||||
addDependencies(targets, filterCallback) {
|
||||
if (!this.watchJavaScriptDependencies) {
|
||||
return;
|
||||
}
|
||||
|
||||
targets = this._normalizeTargets(targets);
|
||||
|
||||
let deps = this.getJavaScriptDependenciesFromList(targets);
|
||||
if (filterCallback) {
|
||||
deps = deps.filter(filterCallback);
|
||||
}
|
||||
|
||||
this.addRaw(deps, true);
|
||||
}
|
||||
|
||||
setWriter(templateWriter) {
|
||||
this.writer = templateWriter;
|
||||
}
|
||||
|
||||
getJavaScriptDependenciesFromList(files = []) {
|
||||
let depSet = new Set();
|
||||
files
|
||||
.filter(file => file.endsWith(".js")) // TODO does this need to work with aliasing? what other JS extensions will have deps?
|
||||
.forEach(file => {
|
||||
dependencyTree
|
||||
.toList({
|
||||
filename: file,
|
||||
directory: TemplatePath.absolutePath(),
|
||||
filter: function(path) {
|
||||
return path.indexOf("node_modules") === -1;
|
||||
}
|
||||
})
|
||||
.map(dependency => {
|
||||
return TemplatePath.addLeadingDotSlash(
|
||||
TemplatePath.relativePath(dependency)
|
||||
);
|
||||
})
|
||||
.filter(dependency => {
|
||||
return (
|
||||
dependency !== file && dependency.indexOf("node_modules") === -1
|
||||
);
|
||||
})
|
||||
.forEach(dependency => {
|
||||
depSet.add(dependency);
|
||||
});
|
||||
});
|
||||
|
||||
return Array.from(depSet);
|
||||
}
|
||||
|
||||
clearDependencyRequireCache() {
|
||||
for (let path of this.dependencies) {
|
||||
delete require.cache[TemplatePath.absolutePath(path)];
|
||||
}
|
||||
}
|
||||
|
||||
getNewTargetsSinceLastReset() {
|
||||
return Array.from(this.newTargets);
|
||||
}
|
||||
|
||||
getTargets() {
|
||||
return Array.from(this.targets);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = EleventyWatchTargets;
|
57
node_modules/@11ty/eleventy/src/Engines/Ejs.js
generated
vendored
Normal file
57
node_modules/@11ty/eleventy/src/Engines/Ejs.js
generated
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
const ejsLib = require("ejs");
|
||||
const TemplateEngine = require("./TemplateEngine");
|
||||
const config = require("../Config");
|
||||
|
||||
class Ejs extends TemplateEngine {
|
||||
constructor(name, includesDir) {
|
||||
super(name, includesDir);
|
||||
|
||||
this.ejsOptions = {};
|
||||
|
||||
this.setLibrary(this.config.libraryOverrides.ejs);
|
||||
this.setEjsOptions(this.config.ejsOptions);
|
||||
}
|
||||
|
||||
setLibrary(lib) {
|
||||
this.ejsLib = lib || ejsLib;
|
||||
this.setEngineLib(this.ejsLib);
|
||||
}
|
||||
|
||||
getEngine() {
|
||||
return this.ejsLib;
|
||||
}
|
||||
|
||||
setEjsOptions(options) {
|
||||
this.ejsOptions = options;
|
||||
}
|
||||
|
||||
getEjsOptions() {
|
||||
let includesDir = super.getIncludesDir();
|
||||
|
||||
return Object.assign(
|
||||
{
|
||||
root: "./" + includesDir,
|
||||
compileDebug: true,
|
||||
filename: "./" + includesDir
|
||||
},
|
||||
this.ejsOptions || {}
|
||||
);
|
||||
}
|
||||
|
||||
async compile(str, inputPath) {
|
||||
let options = this.getEjsOptions();
|
||||
if (!inputPath || inputPath === "ejs" || inputPath === "md") {
|
||||
// do nothing
|
||||
} else {
|
||||
options.filename = inputPath;
|
||||
}
|
||||
|
||||
let fn = this.ejsLib.compile(str, options);
|
||||
|
||||
return function(data) {
|
||||
return fn(data);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Ejs;
|
22
node_modules/@11ty/eleventy/src/Engines/Haml.js
generated
vendored
Normal file
22
node_modules/@11ty/eleventy/src/Engines/Haml.js
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
const HamlLib = require("hamljs");
|
||||
const TemplateEngine = require("./TemplateEngine");
|
||||
const config = require("../Config");
|
||||
|
||||
class Haml extends TemplateEngine {
|
||||
constructor(name, includesDir) {
|
||||
super(name, includesDir);
|
||||
|
||||
this.setLibrary(this.config.libraryOverrides.haml);
|
||||
}
|
||||
|
||||
setLibrary(lib) {
|
||||
this.hamlLib = lib || HamlLib;
|
||||
this.setEngineLib(lib);
|
||||
}
|
||||
|
||||
async compile(str) {
|
||||
return this.hamlLib.compile(str);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Haml;
|
66
node_modules/@11ty/eleventy/src/Engines/Handlebars.js
generated
vendored
Normal file
66
node_modules/@11ty/eleventy/src/Engines/Handlebars.js
generated
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
const HandlebarsLib = require("handlebars");
|
||||
const TemplateEngine = require("./TemplateEngine");
|
||||
const config = require("../Config");
|
||||
|
||||
class Handlebars extends TemplateEngine {
|
||||
constructor(name, includesDir) {
|
||||
super(name, includesDir);
|
||||
|
||||
this.setLibrary(this.config.libraryOverrides.hbs);
|
||||
}
|
||||
|
||||
setLibrary(lib) {
|
||||
this.handlebarsLib = lib || HandlebarsLib;
|
||||
this.setEngineLib(this.handlebarsLib);
|
||||
|
||||
let partials = super.getPartials();
|
||||
for (let name in partials) {
|
||||
this.handlebarsLib.registerPartial(name, partials[name]);
|
||||
}
|
||||
|
||||
// TODO these all go to the same place (addHelper), add warnings for overwrites
|
||||
this.addHelpers(this.config.handlebarsHelpers);
|
||||
this.addShortcodes(this.config.handlebarsShortcodes);
|
||||
this.addPairedShortcodes(this.config.handlebarsPairedShortcodes);
|
||||
}
|
||||
|
||||
addHelper(name, callback) {
|
||||
this.handlebarsLib.registerHelper(name, callback);
|
||||
}
|
||||
|
||||
addHelpers(helpers) {
|
||||
for (let name in helpers) {
|
||||
this.addHelper(name, helpers[name]);
|
||||
}
|
||||
}
|
||||
|
||||
addShortcodes(shortcodes) {
|
||||
for (let name in shortcodes) {
|
||||
this.addHelper(name, shortcodes[name]);
|
||||
}
|
||||
}
|
||||
|
||||
addPairedShortcodes(shortcodes) {
|
||||
for (let name in shortcodes) {
|
||||
let callback = shortcodes[name];
|
||||
this.addHelper(name, function(...args) {
|
||||
let options = args[args.length - 1];
|
||||
let content = "";
|
||||
if (options && options.fn) {
|
||||
content = options.fn(this);
|
||||
}
|
||||
|
||||
return callback.apply(this, [content, ...args]);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async compile(str, inputPath) {
|
||||
let fn = this.handlebarsLib.compile(str);
|
||||
return function(data) {
|
||||
return fn(data);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Handlebars;
|
24
node_modules/@11ty/eleventy/src/Engines/Html.js
generated
vendored
Normal file
24
node_modules/@11ty/eleventy/src/Engines/Html.js
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
const TemplateEngine = require("./TemplateEngine");
|
||||
|
||||
class Html extends TemplateEngine {
|
||||
async compile(str, inputPath, preTemplateEngine) {
|
||||
if (preTemplateEngine) {
|
||||
let engine = TemplateEngine.getEngine(
|
||||
preTemplateEngine,
|
||||
super.getIncludesDir()
|
||||
);
|
||||
let fn = await engine.compile(str, inputPath);
|
||||
|
||||
return async function(data) {
|
||||
return fn(data);
|
||||
};
|
||||
} else {
|
||||
return function(data) {
|
||||
// do nothing with data if parseHtmlWith is falsy
|
||||
return str;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Html;
|
121
node_modules/@11ty/eleventy/src/Engines/JavaScript.js
generated
vendored
Normal file
121
node_modules/@11ty/eleventy/src/Engines/JavaScript.js
generated
vendored
Normal file
@@ -0,0 +1,121 @@
|
||||
const TemplateEngine = require("./TemplateEngine");
|
||||
const TemplatePath = require("../TemplatePath");
|
||||
const EleventyBaseError = require("../EleventyBaseError");
|
||||
|
||||
class JavaScriptTemplateInvalidDataFormatError extends EleventyBaseError {}
|
||||
|
||||
class JavaScript extends TemplateEngine {
|
||||
constructor(name, includesDir) {
|
||||
super(name, includesDir);
|
||||
this.instances = {};
|
||||
}
|
||||
|
||||
normalize(result) {
|
||||
if (Buffer.isBuffer(result)) {
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// String, Buffer, Promise
|
||||
// Function, Class
|
||||
// Object
|
||||
_getInstance(mod) {
|
||||
let noop = function() {
|
||||
return "";
|
||||
};
|
||||
|
||||
if (typeof mod === "string" || mod instanceof Buffer || mod.then) {
|
||||
return { render: () => mod };
|
||||
} else if (typeof mod === "function") {
|
||||
if (
|
||||
mod.prototype &&
|
||||
("data" in mod.prototype || "render" in mod.prototype)
|
||||
) {
|
||||
if (!("render" in mod.prototype)) {
|
||||
mod.prototype.render = noop;
|
||||
}
|
||||
return new mod();
|
||||
} else {
|
||||
return { render: mod };
|
||||
}
|
||||
} else if ("data" in mod || "render" in mod) {
|
||||
if (!("render" in mod)) {
|
||||
mod.render = noop;
|
||||
}
|
||||
return mod;
|
||||
}
|
||||
}
|
||||
|
||||
getInstanceFromInputPath(inputPath) {
|
||||
if (this.instances[inputPath]) {
|
||||
return this.instances[inputPath];
|
||||
}
|
||||
|
||||
const mod = this._getRequire(inputPath);
|
||||
let inst = this._getInstance(mod);
|
||||
|
||||
this.instances[inputPath] = inst;
|
||||
return inst;
|
||||
}
|
||||
|
||||
_getRequire(inputPath) {
|
||||
let requirePath = TemplatePath.absolutePath(inputPath);
|
||||
return require(requirePath);
|
||||
}
|
||||
|
||||
needsToReadFileContents() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// only remove from cache once on startup (if it already exists)
|
||||
initRequireCache(inputPath) {
|
||||
let requirePath = TemplatePath.absolutePath(inputPath);
|
||||
if (requirePath in require.cache) {
|
||||
delete require.cache[requirePath];
|
||||
}
|
||||
|
||||
if (inputPath in this.instances) {
|
||||
delete this.instances[inputPath];
|
||||
}
|
||||
}
|
||||
|
||||
async getExtraDataFromFile(inputPath) {
|
||||
let inst = this.getInstanceFromInputPath(inputPath);
|
||||
if (inst && "data" in inst) {
|
||||
// get extra data from `data` method,
|
||||
// either as a function or getter or object literal
|
||||
let result = await (typeof inst.data === "function"
|
||||
? inst.data()
|
||||
: inst.data);
|
||||
if (typeof result !== "object") {
|
||||
throw new JavaScriptTemplateInvalidDataFormatError(
|
||||
`Invalid data format returned from ${inputPath}: typeof ${typeof result}`
|
||||
);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
async compile(str, inputPath) {
|
||||
let inst;
|
||||
if (str) {
|
||||
// When str has a value, it's being used for permalinks in data
|
||||
inst = this._getInstance(str);
|
||||
} else {
|
||||
// For normal templates, str will be falsy.
|
||||
inst = this.getInstanceFromInputPath(inputPath);
|
||||
}
|
||||
|
||||
if (inst && "render" in inst) {
|
||||
Object.assign(inst, this.config.javascriptFunctions);
|
||||
|
||||
return function(data) {
|
||||
return this.normalize(inst.render.call(inst, data));
|
||||
}.bind(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = JavaScript;
|
63
node_modules/@11ty/eleventy/src/Engines/JavaScriptTemplateLiteral.js
generated
vendored
Normal file
63
node_modules/@11ty/eleventy/src/Engines/JavaScriptTemplateLiteral.js
generated
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
const javascriptStringify = require("javascript-stringify");
|
||||
const TemplateEngine = require("./TemplateEngine");
|
||||
const EleventyBaseError = require("../EleventyBaseError");
|
||||
|
||||
class JavaScriptTemplateLiteralCompileError extends EleventyBaseError {}
|
||||
|
||||
class JavaScriptTemplateLiteral extends TemplateEngine {
|
||||
// add ` around template if it doesn’t exist.
|
||||
static normalizeTicks(str) {
|
||||
// TODO make this work with tagged templates html``
|
||||
let trimmedStr = str.trim();
|
||||
if (
|
||||
trimmedStr.charAt(0) === "`" &&
|
||||
trimmedStr.charAt(trimmedStr.length - 1) === "`"
|
||||
) {
|
||||
str =
|
||||
"`" +
|
||||
trimmedStr.substr(1, trimmedStr.length - 2).replace(/`/g, "\\`") +
|
||||
"`";
|
||||
} else {
|
||||
str =
|
||||
"`" +
|
||||
str.replace(/`/g, "\\`") +
|
||||
(trimmedStr.charAt(trimmedStr.length - 1) === "`" ? "\n" : "") +
|
||||
"`";
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
async compile(str, inputPath) {
|
||||
return function(data) {
|
||||
// avoid `with`
|
||||
let dataStr = "";
|
||||
for (let j in data) {
|
||||
dataStr += `let ${j} = ${javascriptStringify.stringify(
|
||||
data[j],
|
||||
null,
|
||||
null,
|
||||
{
|
||||
references: true
|
||||
}
|
||||
)};\n`;
|
||||
}
|
||||
|
||||
let evalStr = `${dataStr}\n${JavaScriptTemplateLiteral.normalizeTicks(
|
||||
str
|
||||
)};`;
|
||||
try {
|
||||
// TODO switch to https://www.npmjs.com/package/es6-template-strings
|
||||
let val = eval(evalStr);
|
||||
return val;
|
||||
} catch (e) {
|
||||
throw new JavaScriptTemplateLiteralCompileError(
|
||||
`Broken ES6 template:\n${evalStr}`,
|
||||
e
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = JavaScriptTemplateLiteral;
|
199
node_modules/@11ty/eleventy/src/Engines/Liquid.js
generated
vendored
Normal file
199
node_modules/@11ty/eleventy/src/Engines/Liquid.js
generated
vendored
Normal file
@@ -0,0 +1,199 @@
|
||||
const moo = require("moo");
|
||||
const LiquidLib = require("liquidjs");
|
||||
const TemplateEngine = require("./TemplateEngine");
|
||||
const TemplatePath = require("../TemplatePath");
|
||||
// const debug = require("debug")("Eleventy:Liquid");
|
||||
|
||||
class Liquid extends TemplateEngine {
|
||||
constructor(name, includesDir) {
|
||||
super(name, includesDir);
|
||||
|
||||
this.liquidOptions = {};
|
||||
|
||||
this.setLibrary(this.config.libraryOverrides.liquid);
|
||||
this.setLiquidOptions(this.config.liquidOptions);
|
||||
|
||||
this.argLexer = moo.compile({
|
||||
number: /[0-9]+\.*[0-9]*/,
|
||||
doubleQuoteString: /"(?:\\["\\]|[^\n"\\])*"/,
|
||||
singleQuoteString: /'(?:\\['\\]|[^\n'\\])*'/,
|
||||
keyword: /[a-zA-Z0-9\.\-\_]+/,
|
||||
"ignore:whitespace": /[, \t]+/ // includes comma separator
|
||||
});
|
||||
}
|
||||
|
||||
setLibrary(lib) {
|
||||
this.liquidLibOverride = lib;
|
||||
|
||||
// warning, the include syntax supported here does not exactly match what Jekyll uses.
|
||||
this.liquidLib = lib || LiquidLib(this.getLiquidOptions());
|
||||
this.setEngineLib(this.liquidLib);
|
||||
|
||||
this.addFilters(this.config.liquidFilters);
|
||||
|
||||
// TODO these all go to the same place (addTag), add warnings for overwrites
|
||||
this.addCustomTags(this.config.liquidTags);
|
||||
this.addAllShortcodes(this.config.liquidShortcodes);
|
||||
this.addAllPairedShortcodes(this.config.liquidPairedShortcodes);
|
||||
}
|
||||
|
||||
setLiquidOptions(options) {
|
||||
this.liquidOptions = options;
|
||||
|
||||
this.setLibrary(this.liquidLibOverride);
|
||||
}
|
||||
|
||||
getLiquidOptions() {
|
||||
let defaults = {
|
||||
root: [super.getIncludesDir()], // overrides in compile with inputPath below
|
||||
extname: ".liquid",
|
||||
dynamicPartials: false,
|
||||
strict_filters: false
|
||||
};
|
||||
|
||||
let options = Object.assign(defaults, this.liquidOptions || {});
|
||||
// debug("Liquid constructor options: %o", options);
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
addCustomTags(tags) {
|
||||
for (let name in tags) {
|
||||
this.addTag(name, tags[name]);
|
||||
}
|
||||
}
|
||||
|
||||
addFilters(filters) {
|
||||
for (let name in filters) {
|
||||
this.addFilter(name, filters[name]);
|
||||
}
|
||||
}
|
||||
|
||||
addFilter(name, filter) {
|
||||
this.liquidLib.registerFilter(name, filter);
|
||||
}
|
||||
|
||||
addTag(name, tagFn) {
|
||||
let tagObj;
|
||||
if (typeof tagFn === "function") {
|
||||
tagObj = tagFn(this.liquidLib);
|
||||
} else {
|
||||
throw new Error(
|
||||
"Liquid.addTag expects a callback function to be passed in: addTag(name, function(liquidEngine) { return { parse: …, render: … } })"
|
||||
);
|
||||
}
|
||||
this.liquidLib.registerTag(name, tagObj);
|
||||
}
|
||||
|
||||
addAllShortcodes(shortcodes) {
|
||||
for (let name in shortcodes) {
|
||||
this.addShortcode(name, shortcodes[name]);
|
||||
}
|
||||
}
|
||||
|
||||
addAllPairedShortcodes(shortcodes) {
|
||||
for (let name in shortcodes) {
|
||||
this.addPairedShortcode(name, shortcodes[name]);
|
||||
}
|
||||
}
|
||||
|
||||
static parseArguments(lexer, str, scope) {
|
||||
let argArray = [];
|
||||
|
||||
if (typeof str === "string") {
|
||||
// TODO key=value key2=value
|
||||
// TODO JSON?
|
||||
lexer.reset(str);
|
||||
let arg = lexer.next();
|
||||
while (arg) {
|
||||
/*{
|
||||
type: 'doubleQuoteString',
|
||||
value: '"test 2"',
|
||||
text: '"test 2"',
|
||||
toString: [Function: tokenToString],
|
||||
offset: 0,
|
||||
lineBreaks: 0,
|
||||
line: 1,
|
||||
col: 1 }*/
|
||||
if (arg.type.indexOf("ignore:") === -1) {
|
||||
argArray.push(LiquidLib.evalExp(arg.value, scope)); // or evalValue
|
||||
}
|
||||
arg = lexer.next();
|
||||
}
|
||||
}
|
||||
|
||||
return argArray;
|
||||
}
|
||||
|
||||
addShortcode(shortcodeName, shortcodeFn) {
|
||||
let _t = this;
|
||||
this.addTag(shortcodeName, function(liquidEngine) {
|
||||
return {
|
||||
parse: function(tagToken, remainTokens) {
|
||||
this.name = tagToken.name;
|
||||
this.args = tagToken.args;
|
||||
},
|
||||
render: function(scope, hash) {
|
||||
let argArray = Liquid.parseArguments(_t.argLexer, this.args, scope);
|
||||
|
||||
return Promise.resolve(shortcodeFn(...argArray));
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
addPairedShortcode(shortcodeName, shortcodeFn) {
|
||||
let _t = this;
|
||||
this.addTag(shortcodeName, function(liquidEngine) {
|
||||
return {
|
||||
parse: function(tagToken, remainTokens) {
|
||||
this.name = tagToken.name;
|
||||
this.args = tagToken.args;
|
||||
this.templates = [];
|
||||
|
||||
var stream = liquidEngine.parser
|
||||
.parseStream(remainTokens)
|
||||
.on("template", tpl => this.templates.push(tpl))
|
||||
.on("tag:end" + shortcodeName, token => stream.stop())
|
||||
.on("end", x => {
|
||||
throw new Error(`tag ${tagToken.raw} not closed`);
|
||||
});
|
||||
|
||||
stream.start();
|
||||
},
|
||||
render: function(scope, hash) {
|
||||
let argArray = Liquid.parseArguments(_t.argLexer, this.args, scope);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
liquidEngine.renderer
|
||||
.renderTemplates(this.templates, scope)
|
||||
.then(function(html) {
|
||||
resolve(shortcodeFn(html, ...argArray));
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
async compile(str, inputPath) {
|
||||
let engine = this.liquidLib;
|
||||
let tmpl = await engine.parse(str, inputPath);
|
||||
|
||||
// Required for relative includes
|
||||
let options = {};
|
||||
if (!inputPath || inputPath === "njk" || inputPath === "md") {
|
||||
// do nothing
|
||||
} else {
|
||||
options.root = [
|
||||
super.getIncludesDir(),
|
||||
TemplatePath.getDirFromFilePath(inputPath)
|
||||
];
|
||||
}
|
||||
return async function(data) {
|
||||
return engine.render(tmpl, data, options);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Liquid;
|
91
node_modules/@11ty/eleventy/src/Engines/Markdown.js
generated
vendored
Normal file
91
node_modules/@11ty/eleventy/src/Engines/Markdown.js
generated
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
const markdownIt = require("markdown-it");
|
||||
const TemplateEngine = require("./TemplateEngine");
|
||||
const config = require("../Config");
|
||||
// const debug = require("debug")("Eleventy:Markdown");
|
||||
|
||||
class Markdown extends TemplateEngine {
|
||||
constructor(name, includesDir) {
|
||||
super(name, includesDir);
|
||||
|
||||
this.markdownOptions = {};
|
||||
|
||||
this.setLibrary(this.config.libraryOverrides.md);
|
||||
}
|
||||
|
||||
setLibrary(mdLib) {
|
||||
this.mdLib = mdLib || markdownIt(this.getMarkdownOptions());
|
||||
|
||||
// Overrides a highlighter set in `markdownOptions`
|
||||
// This is separate so devs can pass in a new mdLib and still use the official eleventy plugin for markdown highlighting
|
||||
if (this.config.markdownHighlighter) {
|
||||
this.mdLib.set({
|
||||
highlight: this.config.markdownHighlighter
|
||||
});
|
||||
}
|
||||
|
||||
this.setEngineLib(this.mdLib);
|
||||
}
|
||||
|
||||
setMarkdownOptions(options) {
|
||||
this.markdownOptions = options;
|
||||
}
|
||||
|
||||
getMarkdownOptions() {
|
||||
// work with "mode" presets https://github.com/markdown-it/markdown-it#init-with-presets-and-options
|
||||
if (typeof this.markdownOptions === "string") {
|
||||
return this.markdownOptions;
|
||||
}
|
||||
|
||||
return Object.assign(
|
||||
{
|
||||
html: true
|
||||
},
|
||||
this.markdownOptions || {}
|
||||
);
|
||||
}
|
||||
|
||||
async compile(str, inputPath, preTemplateEngine, bypassMarkdown) {
|
||||
let mdlib = this.mdLib;
|
||||
|
||||
if (preTemplateEngine) {
|
||||
let fn;
|
||||
|
||||
let engine;
|
||||
if (typeof preTemplateEngine === "string") {
|
||||
engine = TemplateEngine.getEngine(
|
||||
preTemplateEngine,
|
||||
super.getIncludesDir()
|
||||
);
|
||||
} else {
|
||||
engine = preTemplateEngine;
|
||||
}
|
||||
|
||||
fn = await engine.compile(str, inputPath);
|
||||
|
||||
if (bypassMarkdown) {
|
||||
return async function(data) {
|
||||
return fn(data);
|
||||
};
|
||||
} else {
|
||||
return async function(data) {
|
||||
let preTemplateEngineRender = await fn(data);
|
||||
let finishedRender = mdlib.render(preTemplateEngineRender);
|
||||
return finishedRender;
|
||||
};
|
||||
}
|
||||
} else {
|
||||
if (bypassMarkdown) {
|
||||
return function() {
|
||||
return str;
|
||||
};
|
||||
} else {
|
||||
return function() {
|
||||
// throw away data if preTemplateEngine is falsy
|
||||
return mdlib.render(str);
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Markdown;
|
25
node_modules/@11ty/eleventy/src/Engines/Mustache.js
generated
vendored
Normal file
25
node_modules/@11ty/eleventy/src/Engines/Mustache.js
generated
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
const MustacheLib = require("mustache");
|
||||
const TemplateEngine = require("./TemplateEngine");
|
||||
|
||||
class Mustache extends TemplateEngine {
|
||||
constructor(name, includesDir) {
|
||||
super(name, includesDir);
|
||||
|
||||
this.setLibrary(this.config.libraryOverrides.mustache);
|
||||
}
|
||||
|
||||
setLibrary(lib) {
|
||||
this.mustacheLib = lib || MustacheLib;
|
||||
this.setEngineLib(this.mustacheLib);
|
||||
}
|
||||
|
||||
async compile(str, inputPath) {
|
||||
let partials = super.getPartials();
|
||||
|
||||
return function(data) {
|
||||
return this.render(str, data, partials).trim();
|
||||
}.bind(this.mustacheLib);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Mustache;
|
157
node_modules/@11ty/eleventy/src/Engines/Nunjucks.js
generated
vendored
Normal file
157
node_modules/@11ty/eleventy/src/Engines/Nunjucks.js
generated
vendored
Normal file
@@ -0,0 +1,157 @@
|
||||
const NunjucksLib = require("nunjucks");
|
||||
const TemplateEngine = require("./TemplateEngine");
|
||||
const TemplatePath = require("../TemplatePath");
|
||||
|
||||
class Nunjucks extends TemplateEngine {
|
||||
constructor(name, includesDir) {
|
||||
super(name, includesDir);
|
||||
|
||||
this.setLibrary(this.config.libraryOverrides.njk);
|
||||
}
|
||||
|
||||
setLibrary(env) {
|
||||
this.njkEnv =
|
||||
env ||
|
||||
new NunjucksLib.Environment(
|
||||
new NunjucksLib.FileSystemLoader([
|
||||
super.getIncludesDir(),
|
||||
TemplatePath.getWorkingDir()
|
||||
])
|
||||
);
|
||||
this.setEngineLib(this.njkEnv);
|
||||
|
||||
this.addFilters(this.config.nunjucksFilters);
|
||||
this.addFilters(this.config.nunjucksAsyncFilters, true);
|
||||
|
||||
// TODO these all go to the same place (addTag), add warnings for overwrites
|
||||
this.addCustomTags(this.config.nunjucksTags);
|
||||
this.addAllShortcodes(this.config.nunjucksShortcodes);
|
||||
this.addAllPairedShortcodes(this.config.nunjucksPairedShortcodes);
|
||||
}
|
||||
|
||||
addFilters(helpers, isAsync) {
|
||||
for (let name in helpers) {
|
||||
this.njkEnv.addFilter(name, helpers[name], isAsync);
|
||||
}
|
||||
}
|
||||
|
||||
addCustomTags(tags) {
|
||||
for (let name in tags) {
|
||||
this.addTag(name, tags[name]);
|
||||
}
|
||||
}
|
||||
|
||||
addTag(name, tagFn) {
|
||||
let tagObj;
|
||||
if (typeof tagFn === "function") {
|
||||
tagObj = tagFn(NunjucksLib, this.njkEnv);
|
||||
} else {
|
||||
throw new Error(
|
||||
"Nunjucks.addTag expects a callback function to be passed in: addTag(name, function(nunjucksEngine) {})"
|
||||
);
|
||||
}
|
||||
|
||||
this.njkEnv.addExtension(name, tagObj);
|
||||
}
|
||||
|
||||
addAllShortcodes(shortcodes) {
|
||||
for (let name in shortcodes) {
|
||||
this.addShortcode(name, shortcodes[name]);
|
||||
}
|
||||
}
|
||||
|
||||
addAllPairedShortcodes(shortcodes) {
|
||||
for (let name in shortcodes) {
|
||||
this.addPairedShortcode(name, shortcodes[name]);
|
||||
}
|
||||
}
|
||||
|
||||
addShortcode(shortcodeName, shortcodeFn) {
|
||||
function ShortcodeFunction() {
|
||||
this.tags = [shortcodeName];
|
||||
|
||||
this.parse = function(parser, nodes, lexer) {
|
||||
let args;
|
||||
let tok = parser.nextToken();
|
||||
|
||||
args = parser.parseSignature(true, true);
|
||||
|
||||
// Nunjucks bug with non-paired custom tags bug still exists even
|
||||
// though this issue is closed. Works fine for paired.
|
||||
// https://github.com/mozilla/nunjucks/issues/158
|
||||
if (args.children.length === 0) {
|
||||
args.addChild(new nodes.Literal(0, 0, ""));
|
||||
}
|
||||
|
||||
parser.advanceAfterBlockEnd(tok.value);
|
||||
|
||||
// return new nodes.CallExtensionAsync(this, "run", args);
|
||||
return new nodes.CallExtension(this, "run", args);
|
||||
};
|
||||
|
||||
this.run = function(...args) {
|
||||
// let callback = args.pop();
|
||||
let [context, ...argArray] = args;
|
||||
let ret = new NunjucksLib.runtime.SafeString(shortcodeFn(...argArray));
|
||||
// callback(null, ret);
|
||||
return ret;
|
||||
};
|
||||
}
|
||||
|
||||
this.njkEnv.addExtension(shortcodeName, new ShortcodeFunction());
|
||||
}
|
||||
|
||||
addPairedShortcode(shortcodeName, shortcodeFn) {
|
||||
function PairedShortcodeFunction() {
|
||||
this.tags = [shortcodeName];
|
||||
|
||||
this.parse = function(parser, nodes, lexer) {
|
||||
var tok = parser.nextToken();
|
||||
|
||||
var args = parser.parseSignature(true, true);
|
||||
parser.advanceAfterBlockEnd(tok.value);
|
||||
|
||||
var body = parser.parseUntilBlocks("end" + shortcodeName);
|
||||
parser.advanceAfterBlockEnd();
|
||||
|
||||
// return new nodes.CallExtensionAsync(this, "run", args, [body]);
|
||||
return new nodes.CallExtension(this, "run", args, [body]);
|
||||
};
|
||||
|
||||
this.run = function(...args) {
|
||||
// let callback = args.pop();
|
||||
let body = args.pop();
|
||||
let [context, ...argArray] = args;
|
||||
let ret = new NunjucksLib.runtime.SafeString(
|
||||
shortcodeFn(body(), ...argArray)
|
||||
);
|
||||
// callback(null, ret);
|
||||
return ret;
|
||||
};
|
||||
}
|
||||
|
||||
this.njkEnv.addExtension(shortcodeName, new PairedShortcodeFunction());
|
||||
}
|
||||
|
||||
async compile(str, inputPath) {
|
||||
let tmpl;
|
||||
if (!inputPath || inputPath === "njk" || inputPath === "md") {
|
||||
tmpl = NunjucksLib.compile(str, this.njkEnv);
|
||||
} else {
|
||||
tmpl = NunjucksLib.compile(str, this.njkEnv, inputPath);
|
||||
}
|
||||
return async function(data) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
tmpl.render(data, function(err, res) {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
resolve(res);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Nunjucks;
|
48
node_modules/@11ty/eleventy/src/Engines/Pug.js
generated
vendored
Normal file
48
node_modules/@11ty/eleventy/src/Engines/Pug.js
generated
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
const PugLib = require("pug");
|
||||
const TemplateEngine = require("./TemplateEngine");
|
||||
const TemplatePath = require("../TemplatePath");
|
||||
|
||||
class Pug extends TemplateEngine {
|
||||
constructor(name, includesDir) {
|
||||
super(name, includesDir);
|
||||
|
||||
this.pugOptions = {};
|
||||
|
||||
this.setLibrary(this.config.libraryOverrides.pug);
|
||||
this.setPugOptions(this.config.pugOptions);
|
||||
}
|
||||
|
||||
setLibrary(lib) {
|
||||
this.pugLib = lib || PugLib;
|
||||
this.setEngineLib(this.pugLib);
|
||||
}
|
||||
|
||||
setPugOptions(options) {
|
||||
this.pugOptions = options;
|
||||
}
|
||||
|
||||
getPugOptions() {
|
||||
let includesDir = super.getIncludesDir();
|
||||
|
||||
return Object.assign(
|
||||
{
|
||||
basedir: includesDir,
|
||||
filename: includesDir
|
||||
},
|
||||
this.pugOptions || {}
|
||||
);
|
||||
}
|
||||
|
||||
async compile(str, inputPath) {
|
||||
let options = this.getPugOptions();
|
||||
if (!inputPath || inputPath === "pug" || inputPath === "md") {
|
||||
// do nothing
|
||||
} else {
|
||||
options.filename = inputPath;
|
||||
}
|
||||
|
||||
return this.pugLib.compile(str, options);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Pug;
|
151
node_modules/@11ty/eleventy/src/Engines/TemplateEngine.js
generated
vendored
Normal file
151
node_modules/@11ty/eleventy/src/Engines/TemplateEngine.js
generated
vendored
Normal file
@@ -0,0 +1,151 @@
|
||||
const fastglob = require("fast-glob");
|
||||
const fs = require("fs-extra");
|
||||
const TemplatePath = require("../TemplatePath");
|
||||
const EleventyExtensionMap = require("../EleventyExtensionMap");
|
||||
const config = require("../Config");
|
||||
const debug = require("debug")("Eleventy:TemplateEngine");
|
||||
|
||||
class TemplateEngine {
|
||||
constructor(name, includesDir) {
|
||||
this.name = name;
|
||||
|
||||
this.extensionMap = new EleventyExtensionMap();
|
||||
this.extensions = this.extensionMap.getExtensionsFromKey(name);
|
||||
this.includesDir = includesDir;
|
||||
this.partialsHaveBeenCached = false;
|
||||
this.partials = [];
|
||||
this.engineLib = null;
|
||||
}
|
||||
|
||||
get config() {
|
||||
if (!this._config) {
|
||||
this._config = config.getConfig();
|
||||
}
|
||||
return this._config;
|
||||
}
|
||||
|
||||
set config(config) {
|
||||
this._config = config;
|
||||
}
|
||||
|
||||
getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
getIncludesDir() {
|
||||
return this.includesDir;
|
||||
}
|
||||
|
||||
// TODO make async
|
||||
getPartials() {
|
||||
if (!this.partialsHaveBeenCached) {
|
||||
this.partials = this.cachePartialFiles();
|
||||
}
|
||||
|
||||
return this.partials;
|
||||
}
|
||||
|
||||
// TODO make async
|
||||
cachePartialFiles() {
|
||||
// This only runs if getPartials() is called, which is only for Mustache/Handlebars
|
||||
this.partialsHaveBeenCached = true;
|
||||
let partials = {};
|
||||
let prefix = this.includesDir + "/**/*.";
|
||||
// TODO: reuse mustache partials in handlebars?
|
||||
let partialFiles = [];
|
||||
if (this.includesDir) {
|
||||
this.extensions.forEach(function(extension) {
|
||||
partialFiles = partialFiles.concat(
|
||||
fastglob.sync(prefix + extension, {
|
||||
caseSensitiveMatch: false,
|
||||
dot: true
|
||||
})
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
partialFiles = TemplatePath.addLeadingDotSlashArray(partialFiles);
|
||||
|
||||
for (let j = 0, k = partialFiles.length; j < k; j++) {
|
||||
let partialPath = TemplatePath.stripLeadingSubPath(
|
||||
partialFiles[j],
|
||||
this.includesDir
|
||||
);
|
||||
let partialPathNoExt = partialPath;
|
||||
this.extensions.forEach(function(extension) {
|
||||
partialPathNoExt = TemplatePath.removeExtension(
|
||||
partialPathNoExt,
|
||||
"." + extension
|
||||
);
|
||||
});
|
||||
partials[partialPathNoExt] = fs.readFileSync(partialFiles[j], "utf-8");
|
||||
}
|
||||
|
||||
debug(
|
||||
`${this.includesDir}/*.{${this.extensions}} found partials for: %o`,
|
||||
Object.keys(partials)
|
||||
);
|
||||
|
||||
return partials;
|
||||
}
|
||||
|
||||
setEngineLib(engineLib) {
|
||||
this.engineLib = engineLib;
|
||||
}
|
||||
|
||||
getEngineLib() {
|
||||
return this.engineLib;
|
||||
}
|
||||
|
||||
async render(str, data) {
|
||||
/* TODO compile needs to pass in inputPath? */
|
||||
let fn = await this.compile(str);
|
||||
return fn(data);
|
||||
}
|
||||
|
||||
// JavaScript files defer to the module loader rather than read the files to strings
|
||||
needsToReadFileContents() {
|
||||
return true;
|
||||
}
|
||||
|
||||
getExtraDataFromFile(inputPath) {
|
||||
return {};
|
||||
}
|
||||
|
||||
initRequireCache(inputPath) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
static get templateKeyMapToClassName() {
|
||||
return {
|
||||
ejs: "Ejs",
|
||||
md: "Markdown",
|
||||
jstl: "JavaScriptTemplateLiteral",
|
||||
html: "Html",
|
||||
hbs: "Handlebars",
|
||||
mustache: "Mustache",
|
||||
haml: "Haml",
|
||||
pug: "Pug",
|
||||
njk: "Nunjucks",
|
||||
liquid: "Liquid",
|
||||
"11ty.js": "JavaScript"
|
||||
};
|
||||
}
|
||||
|
||||
static hasEngine(name) {
|
||||
return name in TemplateEngine.templateKeyMapToClassName;
|
||||
}
|
||||
|
||||
static getEngine(name, includesDir) {
|
||||
if (!this.hasEngine(name)) {
|
||||
throw new Error(
|
||||
`Template Engine ${name} does not exist in getEngine (includes dir: ${includesDir})`
|
||||
);
|
||||
}
|
||||
|
||||
const cls = require("./" + TemplateEngine.templateKeyMapToClassName[name]);
|
||||
return new cls(name, includesDir);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = TemplateEngine;
|
4
node_modules/@11ty/eleventy/src/Errors/TemplateContentPrematureUseError.js
generated
vendored
Normal file
4
node_modules/@11ty/eleventy/src/Errors/TemplateContentPrematureUseError.js
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
const EleventyBaseError = require("../EleventyBaseError");
|
||||
class TemplateContentPrematureUseError extends EleventyBaseError {}
|
||||
|
||||
module.exports = TemplateContentPrematureUseError;
|
5
node_modules/@11ty/eleventy/src/Errors/UsingCircularTemplateContentReferenceError.js
generated
vendored
Normal file
5
node_modules/@11ty/eleventy/src/Errors/UsingCircularTemplateContentReferenceError.js
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
const EleventyBaseError = require("../EleventyBaseError");
|
||||
|
||||
class UsingCircularTemplateContentReferenceError extends EleventyBaseError {}
|
||||
|
||||
module.exports = UsingCircularTemplateContentReferenceError;
|
8
node_modules/@11ty/eleventy/src/Filters/Slug.js
generated
vendored
Normal file
8
node_modules/@11ty/eleventy/src/Filters/Slug.js
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
const slugify = require("slugify");
|
||||
|
||||
module.exports = function(str) {
|
||||
return slugify(str, {
|
||||
replacement: "-",
|
||||
lower: true
|
||||
});
|
||||
};
|
36
node_modules/@11ty/eleventy/src/Filters/Url.js
generated
vendored
Normal file
36
node_modules/@11ty/eleventy/src/Filters/Url.js
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
const validUrl = require("valid-url");
|
||||
const TemplatePath = require("../TemplatePath");
|
||||
|
||||
module.exports = function(url, pathPrefix) {
|
||||
// work with undefined
|
||||
url = url || "";
|
||||
|
||||
if (
|
||||
validUrl.isUri(url) ||
|
||||
url.indexOf("http://") === 0 ||
|
||||
url.indexOf("https://") === 0
|
||||
) {
|
||||
return url;
|
||||
}
|
||||
|
||||
if (pathPrefix === undefined || typeof pathPrefix !== "string") {
|
||||
let projectConfig = require("../Config").getConfig();
|
||||
pathPrefix = projectConfig.pathPrefix;
|
||||
}
|
||||
|
||||
let normUrl = TemplatePath.normalizeUrlPath(url);
|
||||
let normRootDir = TemplatePath.normalizeUrlPath("/", pathPrefix);
|
||||
let normFull = TemplatePath.normalizeUrlPath("/", pathPrefix, url);
|
||||
let isRootDirTrailingSlash =
|
||||
normRootDir.length && normRootDir.charAt(normRootDir.length - 1) === "/";
|
||||
|
||||
// minor difference with straight `normalize`, "" resolves to root dir and not "."
|
||||
// minor difference with straight `normalize`, "/" resolves to root dir
|
||||
if (normUrl === "/" || normUrl === normRootDir) {
|
||||
return normRootDir + (!isRootDirTrailingSlash ? "/" : "");
|
||||
} else if (normUrl.indexOf("/") === 0) {
|
||||
return normFull;
|
||||
}
|
||||
|
||||
return normUrl;
|
||||
};
|
253
node_modules/@11ty/eleventy/src/Plugins/Pagination.js
generated
vendored
Normal file
253
node_modules/@11ty/eleventy/src/Plugins/Pagination.js
generated
vendored
Normal file
@@ -0,0 +1,253 @@
|
||||
const lodashChunk = require("lodash/chunk");
|
||||
const lodashGet = require("lodash/get");
|
||||
const lodashSet = require("lodash/set");
|
||||
const EleventyBaseError = require("../EleventyBaseError");
|
||||
const config = require("../Config");
|
||||
|
||||
class PaginationError extends EleventyBaseError {}
|
||||
|
||||
class Pagination {
|
||||
constructor(data) {
|
||||
this.config = config.getConfig();
|
||||
|
||||
this.setData(data);
|
||||
}
|
||||
|
||||
static hasPagination(data) {
|
||||
return "pagination" in data;
|
||||
}
|
||||
|
||||
hasPagination() {
|
||||
if (!this.data) {
|
||||
throw new Error("Missing `setData` call for Pagination object.");
|
||||
}
|
||||
return Pagination.hasPagination(this.data);
|
||||
}
|
||||
|
||||
circularReferenceCheck(data) {
|
||||
if (data.eleventyExcludeFromCollections) {
|
||||
return;
|
||||
}
|
||||
|
||||
let key = data.pagination.data;
|
||||
let tags = data.tags || [];
|
||||
for (let tag of tags) {
|
||||
if (`collections.${tag}` === key) {
|
||||
throw new PaginationError(
|
||||
`Pagination circular reference${
|
||||
this.template ? ` on ${this.template.inputPath}` : ""
|
||||
}, data:\`${key}\` iterates over both the \`${tag}\` tag and also supplies pages to that tag.`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setData(data) {
|
||||
this.data = data || {};
|
||||
this.target = [];
|
||||
|
||||
if (!this.hasPagination()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!data.pagination) {
|
||||
throw new Error(
|
||||
"Misconfigured pagination data in template front matter (YAML front matter precaution: did you use tabs and not spaces for indentation?)."
|
||||
);
|
||||
} else if (!("size" in data.pagination)) {
|
||||
throw new Error("Missing pagination size in front matter data.");
|
||||
}
|
||||
this.circularReferenceCheck(data);
|
||||
|
||||
this.size = data.pagination.size;
|
||||
this.alias = data.pagination.alias;
|
||||
|
||||
this.target = this._resolveItems();
|
||||
this.items = this.getPagedItems();
|
||||
}
|
||||
|
||||
setTemplate(tmpl) {
|
||||
this.template = tmpl;
|
||||
}
|
||||
|
||||
_getDataKey() {
|
||||
return this.data.pagination.data;
|
||||
}
|
||||
|
||||
resolveObjectToValues() {
|
||||
if ("resolve" in this.data.pagination) {
|
||||
return this.data.pagination.resolve === "values";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
isFiltered(value) {
|
||||
if ("filter" in this.data.pagination) {
|
||||
let filtered = this.data.pagination.filter;
|
||||
if (Array.isArray(filtered)) {
|
||||
return filtered.indexOf(value) > -1;
|
||||
}
|
||||
|
||||
return filtered === value;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
_resolveItems() {
|
||||
let notFoundValue = "__NOT_FOUND_ERROR__";
|
||||
let key = this._getDataKey();
|
||||
let ret = lodashGet(this.data, key, notFoundValue);
|
||||
if (ret === notFoundValue) {
|
||||
throw new Error(
|
||||
`Could not resolve pagination key in template data: ${key}`
|
||||
);
|
||||
}
|
||||
|
||||
if (!Array.isArray(ret)) {
|
||||
if (this.resolveObjectToValues()) {
|
||||
ret = Object.values(ret);
|
||||
} else {
|
||||
ret = Object.keys(ret);
|
||||
}
|
||||
}
|
||||
|
||||
let result = ret.filter(
|
||||
function(value) {
|
||||
return !this.isFiltered(value);
|
||||
}.bind(this)
|
||||
);
|
||||
if (this.data.pagination.reverse === true) {
|
||||
return result.reverse();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
getPagedItems() {
|
||||
// TODO switch to a getter
|
||||
if (!this.data) {
|
||||
throw new Error("Missing `setData` call for Pagination object.");
|
||||
}
|
||||
|
||||
return lodashChunk(this.target, this.size);
|
||||
}
|
||||
|
||||
// TODO this name is not good
|
||||
// “To cancel” means to not write the original root template
|
||||
cancel() {
|
||||
return this.hasPagination();
|
||||
}
|
||||
|
||||
getPageCount() {
|
||||
if (!this.hasPagination()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return this.items.length;
|
||||
}
|
||||
|
||||
async getPageTemplates() {
|
||||
if (!this.data) {
|
||||
throw new Error("Missing `setData` call for Pagination object.");
|
||||
}
|
||||
|
||||
if (!this.hasPagination()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (this.pagesCache) {
|
||||
return this.pagesCache;
|
||||
}
|
||||
|
||||
let pages = [];
|
||||
let items = this.items;
|
||||
let tmpl = this.template;
|
||||
let templates = [];
|
||||
let links = [];
|
||||
let hrefs = [];
|
||||
let overrides = [];
|
||||
|
||||
for (let pageNumber = 0, k = items.length; pageNumber < k; pageNumber++) {
|
||||
let cloned = tmpl.clone();
|
||||
|
||||
// TODO maybe also move this permalink additions up into the pagination class
|
||||
if (pageNumber > 0 && !this.data[this.config.keys.permalink]) {
|
||||
cloned.setExtraOutputSubdirectory(pageNumber);
|
||||
}
|
||||
|
||||
templates.push(cloned);
|
||||
|
||||
let override = {
|
||||
pagination: {
|
||||
data: this.data.pagination.data,
|
||||
size: this.data.pagination.size,
|
||||
items: items[pageNumber],
|
||||
pageNumber: pageNumber
|
||||
}
|
||||
};
|
||||
|
||||
if (this.alias) {
|
||||
lodashSet(
|
||||
override,
|
||||
this.alias,
|
||||
this.size === 1 ? items[pageNumber][0] : items[pageNumber]
|
||||
);
|
||||
}
|
||||
|
||||
overrides.push(override);
|
||||
cloned.setPaginationData(override);
|
||||
|
||||
// TO DO subdirectory to links if the site doesn’t live at /
|
||||
links.push("/" + (await cloned.getOutputLink()));
|
||||
hrefs.push(await cloned.getOutputHref());
|
||||
}
|
||||
|
||||
// we loop twice to pass in the appropriate prev/next links (already full generated now)
|
||||
templates.forEach(
|
||||
function(cloned, pageNumber) {
|
||||
// links
|
||||
overrides[pageNumber].pagination.previousPageLink =
|
||||
pageNumber > 0 ? links[pageNumber - 1] : null;
|
||||
overrides[pageNumber].pagination.previous =
|
||||
overrides[pageNumber].pagination.previousPageLink;
|
||||
|
||||
overrides[pageNumber].pagination.nextPageLink =
|
||||
pageNumber < templates.length - 1 ? links[pageNumber + 1] : null;
|
||||
overrides[pageNumber].pagination.next =
|
||||
overrides[pageNumber].pagination.nextPageLink;
|
||||
|
||||
overrides[pageNumber].pagination.firstPageLink =
|
||||
links.length > 0 ? links[0] : null;
|
||||
overrides[pageNumber].pagination.lastPageLink =
|
||||
links.length > 0 ? links[links.length - 1] : null;
|
||||
|
||||
overrides[pageNumber].pagination.links = links;
|
||||
// todo deprecated, consistency with collections and use links instead
|
||||
overrides[pageNumber].pagination.pageLinks = links;
|
||||
|
||||
// hrefs
|
||||
overrides[pageNumber].pagination.previousPageHref =
|
||||
pageNumber > 0 ? hrefs[pageNumber - 1] : null;
|
||||
overrides[pageNumber].pagination.nextPageHref =
|
||||
pageNumber < templates.length - 1 ? hrefs[pageNumber + 1] : null;
|
||||
|
||||
overrides[pageNumber].pagination.firstPageHref =
|
||||
hrefs.length > 0 ? hrefs[0] : null;
|
||||
overrides[pageNumber].pagination.lastPageHref =
|
||||
hrefs.length > 0 ? hrefs[hrefs.length - 1] : null;
|
||||
|
||||
overrides[pageNumber].pagination.hrefs = hrefs;
|
||||
|
||||
cloned.setPaginationData(overrides[pageNumber]);
|
||||
|
||||
pages.push(cloned);
|
||||
}.bind(this)
|
||||
);
|
||||
|
||||
this.pagesCache = pages;
|
||||
|
||||
return pages;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Pagination;
|
698
node_modules/@11ty/eleventy/src/Template.js
generated
vendored
Normal file
698
node_modules/@11ty/eleventy/src/Template.js
generated
vendored
Normal file
@@ -0,0 +1,698 @@
|
||||
const fs = require("fs-extra");
|
||||
const parsePath = require("parse-filepath");
|
||||
const normalize = require("normalize-path");
|
||||
const lodashIsObject = require("lodash/isObject");
|
||||
const { DateTime } = require("luxon");
|
||||
|
||||
const EleventyExtensionMap = require("./EleventyExtensionMap");
|
||||
const TemplateData = require("./TemplateData");
|
||||
const TemplateContent = require("./TemplateContent");
|
||||
const TemplatePath = require("./TemplatePath");
|
||||
const TemplatePermalink = require("./TemplatePermalink");
|
||||
const TemplatePermalinkNoWrite = require("./TemplatePermalinkNoWrite");
|
||||
const TemplateLayout = require("./TemplateLayout");
|
||||
const TemplateFileSlug = require("./TemplateFileSlug");
|
||||
const Pagination = require("./Plugins/Pagination");
|
||||
const TemplateContentPrematureUseError = require("./Errors/TemplateContentPrematureUseError");
|
||||
const debug = require("debug")("Eleventy:Template");
|
||||
const debugDev = require("debug")("Dev:Eleventy:Template");
|
||||
|
||||
class Template extends TemplateContent {
|
||||
constructor(path, inputDir, outputDir, templateData) {
|
||||
debugDev("new Template(%o)", path);
|
||||
super(path, inputDir);
|
||||
|
||||
this.parsed = parsePath(path);
|
||||
|
||||
// for pagination
|
||||
this.extraOutputSubdirectory = "";
|
||||
|
||||
if (outputDir) {
|
||||
this.outputDir = normalize(outputDir);
|
||||
} else {
|
||||
this.outputDir = false;
|
||||
}
|
||||
|
||||
this.linters = [];
|
||||
this.transforms = [];
|
||||
this.plugins = {};
|
||||
this.templateData = templateData;
|
||||
if (this.templateData) {
|
||||
this.templateData.setInputDir(this.inputDir);
|
||||
}
|
||||
this.paginationData = {};
|
||||
|
||||
this.isVerbose = true;
|
||||
this.isDryRun = false;
|
||||
this.writeCount = 0;
|
||||
this.wrapWithLayouts = true;
|
||||
this.fileSlug = new TemplateFileSlug(this.inputPath, this.inputDir);
|
||||
this.fileSlugStr = this.fileSlug.getSlug();
|
||||
this.filePathStem = this.fileSlug.getFullPathWithoutExtension();
|
||||
}
|
||||
|
||||
setIsVerbose(isVerbose) {
|
||||
this.isVerbose = isVerbose;
|
||||
}
|
||||
|
||||
setDryRun(isDryRun) {
|
||||
this.isDryRun = !!isDryRun;
|
||||
}
|
||||
|
||||
setWrapWithLayouts(wrap) {
|
||||
this.wrapWithLayouts = wrap;
|
||||
}
|
||||
|
||||
setExtraOutputSubdirectory(dir) {
|
||||
this.extraOutputSubdirectory = dir + "/";
|
||||
}
|
||||
|
||||
getTemplateSubfolder() {
|
||||
return TemplatePath.stripLeadingSubPath(this.parsed.dir, this.inputDir);
|
||||
}
|
||||
|
||||
get baseFile() {
|
||||
return (this._extensionMap || EleventyExtensionMap).removeTemplateExtension(
|
||||
this.parsed.base
|
||||
);
|
||||
}
|
||||
|
||||
get htmlIOException() {
|
||||
// HTML output can’t overwrite the HTML input file.
|
||||
return (
|
||||
this.inputDir === this.outputDir &&
|
||||
this.templateRender.isEngine("html") &&
|
||||
this.baseFile === "index"
|
||||
);
|
||||
}
|
||||
|
||||
async _getLink(data) {
|
||||
if (!data) {
|
||||
data = await this.getData();
|
||||
}
|
||||
|
||||
let permalink = data[this.config.keys.permalink];
|
||||
if (permalink) {
|
||||
// render variables inside permalink front matter, bypass markdown
|
||||
let permalinkValue;
|
||||
if (!this.config.dynamicPermalinks || data.dynamicPermalink === false) {
|
||||
debugDev("Not using dynamicPermalinks, using %o", permalink);
|
||||
permalinkValue = permalink;
|
||||
} else {
|
||||
permalinkValue = await super.render(permalink, data, true);
|
||||
debug(
|
||||
"Rendering permalink for %o: %s becomes %o",
|
||||
this.inputPath,
|
||||
permalink,
|
||||
permalinkValue
|
||||
);
|
||||
debugDev("Permalink rendered with data: %o", data);
|
||||
}
|
||||
|
||||
let perm = new TemplatePermalink(
|
||||
permalinkValue,
|
||||
this.extraOutputSubdirectory
|
||||
);
|
||||
|
||||
return perm;
|
||||
} else if (permalink === false) {
|
||||
return new TemplatePermalinkNoWrite();
|
||||
}
|
||||
|
||||
return TemplatePermalink.generate(
|
||||
this.getTemplateSubfolder(),
|
||||
this.baseFile,
|
||||
this.extraOutputSubdirectory,
|
||||
this.htmlIOException ? this.config.htmlOutputSuffix : ""
|
||||
);
|
||||
}
|
||||
|
||||
// TODO instead of htmlIOException, do a global search to check if output path = input path and then add extra suffix
|
||||
async getOutputLink(data) {
|
||||
let link = await this._getLink(data);
|
||||
return link.toString();
|
||||
}
|
||||
|
||||
async getOutputHref(data) {
|
||||
let link = await this._getLink(data);
|
||||
return link.toHref();
|
||||
}
|
||||
|
||||
// TODO check for conflicts, see if file already exists?
|
||||
async getOutputPath(data) {
|
||||
let uri = await this.getOutputLink(data);
|
||||
|
||||
if (uri === false) {
|
||||
return false;
|
||||
} else if (
|
||||
(await this.getFrontMatterData())[this.config.keys.permalinkRoot]
|
||||
) {
|
||||
// TODO this only works with immediate front matter and not data files
|
||||
return normalize(uri);
|
||||
} else {
|
||||
return normalize(this.outputDir + "/" + uri);
|
||||
}
|
||||
}
|
||||
|
||||
setPaginationData(paginationData) {
|
||||
this.paginationData = paginationData;
|
||||
}
|
||||
|
||||
async mapDataAsRenderedTemplates(data, templateData) {
|
||||
// function supported in JavaScript type
|
||||
if (typeof data === "string" || typeof data === "function") {
|
||||
debug("rendering data.renderData for %o", this.inputPath);
|
||||
// bypassMarkdown
|
||||
let str = await super.render(data, templateData, true);
|
||||
return str;
|
||||
} else if (Array.isArray(data)) {
|
||||
let arr = [];
|
||||
for (let j = 0, k = data.length; j < k; j++) {
|
||||
arr.push(await this.mapDataAsRenderedTemplates(data[j], templateData));
|
||||
}
|
||||
return arr;
|
||||
} else if (lodashIsObject(data)) {
|
||||
let obj = {};
|
||||
for (let value in data) {
|
||||
obj[value] = await this.mapDataAsRenderedTemplates(
|
||||
data[value],
|
||||
templateData
|
||||
);
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
async _testGetAllLayoutFrontMatterData() {
|
||||
let frontMatterData = await this.getFrontMatterData();
|
||||
if (frontMatterData[this.config.keys.layout]) {
|
||||
let layout = TemplateLayout.getTemplate(
|
||||
frontMatterData[this.config.keys.layout],
|
||||
this.getInputDir(),
|
||||
this.config
|
||||
);
|
||||
return await layout.getData();
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
async getData() {
|
||||
if (!this.dataCache) {
|
||||
debugDev("%o getData()", this.inputPath);
|
||||
let localData = {};
|
||||
|
||||
if (this.templateData) {
|
||||
localData = await this.templateData.getLocalData(this.inputPath);
|
||||
debugDev("%o getData() getLocalData", this.inputPath);
|
||||
}
|
||||
|
||||
let frontMatterData = await this.getFrontMatterData();
|
||||
let foundLayout =
|
||||
frontMatterData[this.config.keys.layout] ||
|
||||
localData[this.config.keys.layout];
|
||||
|
||||
let mergedLayoutData = {};
|
||||
if (foundLayout) {
|
||||
let layout = TemplateLayout.getTemplate(
|
||||
foundLayout,
|
||||
this.getInputDir(),
|
||||
this.config
|
||||
);
|
||||
mergedLayoutData = await layout.getData();
|
||||
debugDev(
|
||||
"%o getData() get merged layout chain front matter",
|
||||
this.inputPath
|
||||
);
|
||||
}
|
||||
|
||||
let mergedData = TemplateData.mergeDeep(
|
||||
this.config,
|
||||
{},
|
||||
mergedLayoutData,
|
||||
localData,
|
||||
frontMatterData
|
||||
);
|
||||
mergedData = await this.addPageDate(mergedData);
|
||||
mergedData = this.addPageData(mergedData);
|
||||
debugDev("%o getData() mergedData", this.inputPath);
|
||||
|
||||
this.dataCache = mergedData;
|
||||
}
|
||||
|
||||
// Don’t deep merge pagination data! See https://github.com/11ty/eleventy/issues/147#issuecomment-440802454
|
||||
return Object.assign(
|
||||
TemplateData.mergeDeep(this.config, {}, this.dataCache),
|
||||
this.paginationData
|
||||
);
|
||||
}
|
||||
|
||||
async addPageDate(data) {
|
||||
if (!("page" in data)) {
|
||||
data.page = {};
|
||||
}
|
||||
|
||||
let newDate = await this.getMappedDate(data);
|
||||
|
||||
if ("page" in data && "date" in data.page) {
|
||||
debug(
|
||||
"Warning: data.page.date is in use (%o) will be overwritten with: %o",
|
||||
data.page.date,
|
||||
newDate
|
||||
);
|
||||
}
|
||||
|
||||
data.page.date = newDate;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
addPageData(data) {
|
||||
if (!("page" in data)) {
|
||||
data.page = {};
|
||||
}
|
||||
|
||||
data.page.inputPath = this.inputPath;
|
||||
data.page.fileSlug = this.fileSlugStr;
|
||||
data.page.filePathStem = this.filePathStem;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
async addPageRenderedData(data) {
|
||||
if (!("page" in data)) {
|
||||
data.page = {};
|
||||
}
|
||||
|
||||
let newUrl = await this.getOutputHref(data);
|
||||
if ("page" in data && "url" in data.page) {
|
||||
if (data.page.url !== newUrl) {
|
||||
debug(
|
||||
"Warning: data.page.url is in use (%o) will be overwritten with: %o",
|
||||
data.page.url,
|
||||
newUrl
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
data.page.url = newUrl;
|
||||
data.page.outputPath = await this.getOutputPath(data);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
// getData (with renderData and page.url added)
|
||||
async getRenderedData() {
|
||||
let data = await this.getData();
|
||||
data = await this.addPageRenderedData(data);
|
||||
|
||||
if (data.renderData) {
|
||||
data.renderData = await this.mapDataAsRenderedTemplates(
|
||||
data.renderData,
|
||||
data
|
||||
);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
async renderLayout(tmpl, tmplData) {
|
||||
let layoutKey = tmplData[tmpl.config.keys.layout];
|
||||
let layout = TemplateLayout.getTemplate(
|
||||
layoutKey,
|
||||
this.getInputDir(),
|
||||
this.config
|
||||
);
|
||||
debug("%o is using layout %o", this.inputPath, layoutKey);
|
||||
|
||||
// TODO reuse templateContent from templateMap
|
||||
let templateContent = await super.render(
|
||||
await this.getPreRender(),
|
||||
tmplData
|
||||
);
|
||||
return layout.render(tmplData, templateContent);
|
||||
}
|
||||
|
||||
async _testRenderWithoutLayouts(data) {
|
||||
this.setWrapWithLayouts(false);
|
||||
let ret = await this.render(data);
|
||||
this.setWrapWithLayouts(true);
|
||||
return ret;
|
||||
}
|
||||
|
||||
async renderContent(str, data, bypassMarkdown) {
|
||||
return super.render(str, data, bypassMarkdown);
|
||||
}
|
||||
|
||||
async render(data) {
|
||||
debugDev("%o render()", this.inputPath);
|
||||
if (!data) {
|
||||
data = await this.getRenderedData();
|
||||
}
|
||||
|
||||
if (!this.wrapWithLayouts && data[this.config.keys.layout]) {
|
||||
debugDev("Template.render is bypassing layouts for %o.", this.inputPath);
|
||||
}
|
||||
|
||||
if (this.wrapWithLayouts && data[this.config.keys.layout]) {
|
||||
debugDev(
|
||||
"Template.render found layout: %o",
|
||||
data[this.config.keys.layout]
|
||||
);
|
||||
return this.renderLayout(this, data);
|
||||
} else {
|
||||
debugDev("Template.render renderContent for %o", this.inputPath);
|
||||
return super.render(await this.getPreRender(), data);
|
||||
}
|
||||
}
|
||||
|
||||
addLinter(callback) {
|
||||
this.linters.push(callback);
|
||||
}
|
||||
|
||||
async runLinters(str, inputPath, outputPath) {
|
||||
this.linters.forEach(function(linter) {
|
||||
// these can be asynchronous but no guarantee of order when they run
|
||||
linter.call(this, str, inputPath, outputPath);
|
||||
});
|
||||
}
|
||||
|
||||
addTransform(callback) {
|
||||
this.transforms.push(callback);
|
||||
}
|
||||
|
||||
async runTransforms(str, outputPath, inputPath) {
|
||||
for (let transform of this.transforms) {
|
||||
str = await transform.call(this, str, outputPath, inputPath);
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
async getTemplates(data) {
|
||||
// TODO cache this
|
||||
let results = [];
|
||||
|
||||
if (!Pagination.hasPagination(data)) {
|
||||
data.page.url = await this.getOutputHref(data);
|
||||
data.page.outputPath = await this.getOutputPath(data);
|
||||
|
||||
results.push({
|
||||
template: this,
|
||||
inputPath: this.inputPath,
|
||||
fileSlug: this.fileSlugStr,
|
||||
filePathStem: this.filePathStem,
|
||||
data: data,
|
||||
date: data.page.date,
|
||||
outputPath: data.page.outputPath,
|
||||
url: data.page.url,
|
||||
set templateContent(content) {
|
||||
this._templateContent = content;
|
||||
},
|
||||
get templateContent() {
|
||||
if (this._templateContent === undefined) {
|
||||
// should at least warn here
|
||||
throw new TemplateContentPrematureUseError(
|
||||
`Tried to use templateContent too early (${this.inputPath})`
|
||||
);
|
||||
}
|
||||
return this._templateContent;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// needs collections for pagination items
|
||||
// but individual pagination entries won’t be part of a collection
|
||||
this.paging = new Pagination(data);
|
||||
this.paging.setTemplate(this);
|
||||
let templates = await this.paging.getPageTemplates();
|
||||
let pageNumber = 0;
|
||||
for (let page of templates) {
|
||||
// TODO try to reuse data instead of a new copy
|
||||
let pageData = await page.getRenderedData();
|
||||
|
||||
// Issue #115
|
||||
if (data.collections) {
|
||||
pageData.collections = data.collections;
|
||||
}
|
||||
|
||||
pageData.page.url = await page.getOutputHref(pageData);
|
||||
pageData.page.outputPath = await page.getOutputPath(pageData);
|
||||
|
||||
results.push({
|
||||
template: page,
|
||||
inputPath: this.inputPath,
|
||||
fileSlug: this.fileSlugStr,
|
||||
filePathStem: this.filePathStem,
|
||||
data: pageData,
|
||||
date: pageData.page.date,
|
||||
pageNumber: pageNumber++,
|
||||
outputPath: pageData.page.outputPath,
|
||||
url: pageData.page.url,
|
||||
set templateContent(content) {
|
||||
this._templateContent = content;
|
||||
},
|
||||
get templateContent() {
|
||||
if (this._templateContent === undefined) {
|
||||
throw new TemplateContentPrematureUseError(
|
||||
`Tried to use templateContent too early (${this.inputPath} page ${this.pageNumber})`
|
||||
);
|
||||
}
|
||||
return this._templateContent;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
async getRenderedTemplates(data) {
|
||||
let pages = await this.getTemplates(data);
|
||||
for (let page of pages) {
|
||||
let content = await page.template._getContent(page.outputPath, page.data);
|
||||
|
||||
page.templateContent = content;
|
||||
}
|
||||
return pages;
|
||||
}
|
||||
|
||||
async _getContent(outputPath, data) {
|
||||
return await this.render(data);
|
||||
}
|
||||
|
||||
async _write(outputPath, finalContent) {
|
||||
if (outputPath === false) {
|
||||
debug(
|
||||
"Ignored %o from %o (permalink: false).",
|
||||
outputPath,
|
||||
this.inputPath
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
this.writeCount++;
|
||||
|
||||
let lang = {
|
||||
start: "Writing",
|
||||
finished: "written."
|
||||
};
|
||||
|
||||
if (this.isDryRun) {
|
||||
lang = {
|
||||
start: "Pretending to write",
|
||||
finished: "" // not used
|
||||
};
|
||||
}
|
||||
|
||||
if (this.isVerbose) {
|
||||
console.log(`${lang.start} ${outputPath} from ${this.inputPath}.`);
|
||||
} else {
|
||||
debug(`${lang.start} %o from %o.`, outputPath, this.inputPath);
|
||||
}
|
||||
if (!this.isDryRun) {
|
||||
return fs.outputFile(outputPath, finalContent).then(() => {
|
||||
debug(`${outputPath} ${lang.finished}.`);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async renderPageEntry(mapEntry, page) {
|
||||
let content;
|
||||
let layoutKey = mapEntry.data[this.config.keys.layout];
|
||||
if (layoutKey) {
|
||||
let layout = TemplateLayout.getTemplate(
|
||||
layoutKey,
|
||||
this.getInputDir(),
|
||||
this.config
|
||||
);
|
||||
content = await layout.render(page.data, page.templateContent);
|
||||
await this.runLinters(content, page.inputPath, page.outputPath);
|
||||
content = await this.runTransforms(content, page.outputPath); // pass in page.inputPath?
|
||||
return content;
|
||||
} else {
|
||||
content = page.templateContent;
|
||||
await this.runLinters(
|
||||
page.templateContent,
|
||||
page.inputPath,
|
||||
page.outputPath
|
||||
);
|
||||
content = await this.runTransforms(content, page.outputPath); // pass in page.inputPath?
|
||||
}
|
||||
return content;
|
||||
}
|
||||
|
||||
async writeMapEntry(mapEntry) {
|
||||
let promises = [];
|
||||
for (let page of mapEntry._pages) {
|
||||
let content = await this.renderPageEntry(mapEntry, page);
|
||||
promises.push(this._write(page.outputPath, content));
|
||||
}
|
||||
|
||||
return Promise.all(promises);
|
||||
}
|
||||
|
||||
async write(outputPath, data) {
|
||||
let templates = await this.getRenderedTemplates(data);
|
||||
let promises = [];
|
||||
for (let tmpl of templates) {
|
||||
promises.push(this._write(tmpl.outputPath, tmpl.templateContent));
|
||||
}
|
||||
|
||||
return Promise.all(promises);
|
||||
}
|
||||
|
||||
// TODO this but better
|
||||
clone() {
|
||||
let tmpl = new Template(
|
||||
this.inputPath,
|
||||
this.inputDir,
|
||||
this.outputDir,
|
||||
this.templateData
|
||||
);
|
||||
tmpl.config = this.config;
|
||||
|
||||
for (let transform of this.transforms) {
|
||||
tmpl.addTransform(transform);
|
||||
}
|
||||
for (let linter of this.linters) {
|
||||
tmpl.addLinter(linter);
|
||||
}
|
||||
tmpl.setIsVerbose(this.isVerbose);
|
||||
tmpl.setDryRun(this.isDryRun);
|
||||
|
||||
return tmpl;
|
||||
}
|
||||
|
||||
getWriteCount() {
|
||||
return this.writeCount;
|
||||
}
|
||||
|
||||
async getMappedDate(data) {
|
||||
// should we use Luxon dates everywhere? Right now using built-in `Date`
|
||||
if ("date" in data) {
|
||||
debug(
|
||||
"getMappedDate: using a date in the data for %o of %o",
|
||||
this.inputPath,
|
||||
data.date
|
||||
);
|
||||
if (data.date instanceof Date) {
|
||||
// YAML does its own date parsing
|
||||
debug("getMappedDate: YAML parsed it: %o", data.date);
|
||||
return data.date;
|
||||
} else {
|
||||
let stat = await fs.stat(this.inputPath);
|
||||
// string
|
||||
if (data.date.toLowerCase() === "last modified") {
|
||||
return new Date(stat.ctimeMs);
|
||||
} else if (data.date.toLowerCase() === "created") {
|
||||
return new Date(stat.birthtimeMs);
|
||||
} else {
|
||||
// try to parse with Luxon
|
||||
let date = DateTime.fromISO(data.date, { zone: "utc" });
|
||||
if (!date.isValid) {
|
||||
throw new Error(
|
||||
`date front matter value (${data.date}) is invalid for ${this.inputPath}`
|
||||
);
|
||||
}
|
||||
debug(
|
||||
"getMappedDate: Luxon parsed %o: %o and %o",
|
||||
data.date,
|
||||
date,
|
||||
date.toJSDate()
|
||||
);
|
||||
|
||||
return date.toJSDate();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let filenameRegex = this.inputPath.match(/(\d{4}-\d{2}-\d{2})/);
|
||||
if (filenameRegex !== null) {
|
||||
let dateObj = DateTime.fromISO(filenameRegex[1]).toJSDate();
|
||||
debug(
|
||||
"getMappedDate: using filename regex time for %o of %o: %o",
|
||||
this.inputPath,
|
||||
filenameRegex[1],
|
||||
dateObj
|
||||
);
|
||||
return dateObj;
|
||||
}
|
||||
|
||||
let stat = await fs.stat(this.inputPath);
|
||||
let createdDate = new Date(stat.birthtimeMs);
|
||||
debug(
|
||||
"getMappedDate: using file created time for %o of %o (from %o)",
|
||||
this.inputPath,
|
||||
createdDate,
|
||||
stat.birthtimeMs
|
||||
);
|
||||
|
||||
// CREATED
|
||||
return createdDate;
|
||||
}
|
||||
}
|
||||
|
||||
async getTemplateMapContent(pageMapEntry) {
|
||||
pageMapEntry.template.setWrapWithLayouts(false);
|
||||
let content = await pageMapEntry.template._getContent(
|
||||
pageMapEntry.outputPath,
|
||||
pageMapEntry.data
|
||||
);
|
||||
pageMapEntry.template.setWrapWithLayouts(true);
|
||||
|
||||
return content;
|
||||
}
|
||||
|
||||
async getTemplateMapEntries() {
|
||||
debugDev("%o getMapped()", this.inputPath);
|
||||
|
||||
let data = await this.getData();
|
||||
let entries = [];
|
||||
// does not return outputPath or url, we don’t want to render permalinks yet
|
||||
entries.push({
|
||||
template: this,
|
||||
inputPath: this.inputPath,
|
||||
data: data
|
||||
});
|
||||
return entries;
|
||||
}
|
||||
|
||||
async _testCompleteRender() {
|
||||
let entries = await this.getTemplateMapEntries();
|
||||
let contents = [];
|
||||
|
||||
for (let entry of entries) {
|
||||
entry._pages = await entry.template.getTemplates(entry.data);
|
||||
|
||||
let page;
|
||||
for (page of entry._pages) {
|
||||
page.templateContent = await entry.template.getTemplateMapContent(page);
|
||||
}
|
||||
for (page of entry._pages) {
|
||||
contents.push(await this.renderPageEntry(entry, page));
|
||||
}
|
||||
}
|
||||
return contents;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Template;
|
35
node_modules/@11ty/eleventy/src/TemplateCache.js
generated
vendored
Normal file
35
node_modules/@11ty/eleventy/src/TemplateCache.js
generated
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
// Note: this is only used for TemplateLayout right now but could be used for more
|
||||
// Just be careful because right now the TemplateLayout cache keys are not directly mapped to paths
|
||||
// So you may get collisions if you use this for other things.
|
||||
class TemplateCache {
|
||||
constructor() {
|
||||
this.cache = {};
|
||||
}
|
||||
|
||||
clear() {
|
||||
this.cache = {};
|
||||
}
|
||||
|
||||
size() {
|
||||
return Object.keys(this.cache).length;
|
||||
}
|
||||
|
||||
add(key, template) {
|
||||
this.cache[key] = template;
|
||||
}
|
||||
|
||||
has(key) {
|
||||
return key in this.cache;
|
||||
}
|
||||
|
||||
get(key) {
|
||||
if (!this.has(key)) {
|
||||
throw new Error(`Could not find ${key} in TemplateCache.`);
|
||||
}
|
||||
|
||||
return this.cache[key];
|
||||
}
|
||||
}
|
||||
|
||||
// singleton
|
||||
module.exports = new TemplateCache();
|
69
node_modules/@11ty/eleventy/src/TemplateCollection.js
generated
vendored
Normal file
69
node_modules/@11ty/eleventy/src/TemplateCollection.js
generated
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
const multimatch = require("multimatch");
|
||||
const Sortable = require("./Util/Sortable");
|
||||
const TemplatePath = require("./TemplatePath");
|
||||
|
||||
class TemplateCollection extends Sortable {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
// right now this is only used by the tests
|
||||
async _testAddTemplate(template) {
|
||||
let data = await template.getData();
|
||||
for (let map of await template.getTemplates(data)) {
|
||||
this.add(map);
|
||||
}
|
||||
}
|
||||
|
||||
getAll() {
|
||||
return this.items.filter(() => true);
|
||||
}
|
||||
|
||||
getAllSorted() {
|
||||
return this.sort(Sortable.sortFunctionDateInputPath);
|
||||
}
|
||||
|
||||
getSortedByDate() {
|
||||
return this.sort(Sortable.sortFunctionDate);
|
||||
}
|
||||
|
||||
getGlobs(globs) {
|
||||
if (typeof globs === "string") {
|
||||
globs = [globs];
|
||||
}
|
||||
|
||||
globs = globs.map(glob => TemplatePath.addLeadingDotSlash(glob));
|
||||
|
||||
return globs;
|
||||
}
|
||||
|
||||
getFilteredByGlob(globs) {
|
||||
globs = this.getGlobs(globs);
|
||||
|
||||
return this.getAllSorted().filter(item => {
|
||||
if (multimatch([item.inputPath], globs).length) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
getFilteredByTag(tagName) {
|
||||
return this.getAllSorted().filter(function(item) {
|
||||
let match = false;
|
||||
if (!tagName) {
|
||||
return true;
|
||||
} else if (Array.isArray(item.data.tags)) {
|
||||
item.data.tags.forEach(tag => {
|
||||
if (tag === tagName) {
|
||||
match = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
return match;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = TemplateCollection;
|
140
node_modules/@11ty/eleventy/src/TemplateConfig.js
generated
vendored
Normal file
140
node_modules/@11ty/eleventy/src/TemplateConfig.js
generated
vendored
Normal file
@@ -0,0 +1,140 @@
|
||||
const fs = require("fs-extra");
|
||||
const chalk = require("chalk");
|
||||
const lodashMerge = require("lodash/merge");
|
||||
const TemplatePath = require("./TemplatePath");
|
||||
const EleventyBaseError = require("./EleventyBaseError");
|
||||
const dependencyTree = require("dependency-tree");
|
||||
const eleventyConfig = require("./EleventyConfig");
|
||||
const debug = require("debug")("Eleventy:TemplateConfig");
|
||||
|
||||
class EleventyConfigError extends EleventyBaseError {}
|
||||
|
||||
class TemplateConfig {
|
||||
constructor(customRootConfig, localProjectConfigPath) {
|
||||
this.overrides = {};
|
||||
this.localProjectConfigPath = localProjectConfigPath || ".eleventy.js";
|
||||
|
||||
if (customRootConfig) {
|
||||
this.customRootConfig = customRootConfig;
|
||||
debug("Warning: Using custom root config!");
|
||||
} else {
|
||||
this.customRootConfig = null;
|
||||
}
|
||||
this.initializeRootConfig();
|
||||
this.config = this.mergeConfig(this.localProjectConfigPath);
|
||||
}
|
||||
|
||||
getLocalProjectConfigFile() {
|
||||
return TemplatePath.addLeadingDotSlash(this.localProjectConfigPath);
|
||||
}
|
||||
|
||||
reset() {
|
||||
eleventyConfig.reset();
|
||||
this.initializeRootConfig();
|
||||
this.config = this.mergeConfig(this.localProjectConfigPath);
|
||||
}
|
||||
|
||||
resetOnWatch() {
|
||||
// nothing yet
|
||||
}
|
||||
|
||||
getConfig() {
|
||||
return this.config;
|
||||
}
|
||||
|
||||
setProjectConfigPath(path) {
|
||||
this.localProjectConfigPath = path;
|
||||
|
||||
this.config = this.mergeConfig(path);
|
||||
}
|
||||
|
||||
setPathPrefix(pathPrefix) {
|
||||
debug("Setting pathPrefix to %o", pathPrefix);
|
||||
this.overrides.pathPrefix = pathPrefix;
|
||||
this.config.pathPrefix = pathPrefix;
|
||||
}
|
||||
|
||||
initializeRootConfig() {
|
||||
this.rootConfig = this.customRootConfig || require("../config.js");
|
||||
|
||||
if (typeof this.rootConfig === "function") {
|
||||
this.rootConfig = this.rootConfig(eleventyConfig);
|
||||
// debug( "rootConfig is a function, after calling, eleventyConfig is %o", eleventyConfig );
|
||||
}
|
||||
debug("rootConfig %o", this.rootConfig);
|
||||
}
|
||||
|
||||
mergeConfig(localProjectConfigPath) {
|
||||
let overrides = ["templateFormats"];
|
||||
let localConfig = {};
|
||||
let path = TemplatePath.join(
|
||||
TemplatePath.getWorkingDir(),
|
||||
localProjectConfigPath
|
||||
);
|
||||
debug(`Merging config with ${path}`);
|
||||
|
||||
if (fs.existsSync(path)) {
|
||||
try {
|
||||
// remove from require cache so it will grab a fresh copy
|
||||
if (path in require.cache) {
|
||||
delete require.cache[path];
|
||||
}
|
||||
|
||||
localConfig = require(path);
|
||||
// debug( "localConfig require return value: %o", localConfig );
|
||||
} catch (err) {
|
||||
throw new EleventyConfigError(
|
||||
`Error in your Eleventy config file '${path}'.` +
|
||||
(err.message.includes("Cannot find module")
|
||||
? chalk.blueBright(" You may need to run `npm install`.")
|
||||
: ""),
|
||||
err
|
||||
);
|
||||
}
|
||||
} else {
|
||||
debug("Eleventy local project config file not found, skipping.");
|
||||
}
|
||||
|
||||
if (typeof localConfig === "function") {
|
||||
localConfig = localConfig(eleventyConfig);
|
||||
// debug( "localConfig is a function, after calling, eleventyConfig is %o", eleventyConfig );
|
||||
|
||||
if (
|
||||
typeof localConfig === "object" &&
|
||||
typeof localConfig.then === "function"
|
||||
) {
|
||||
throw new EleventyConfigError(
|
||||
`Error in your Eleventy config file '${path}': Returning a promise is not supported`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let eleventyConfigApiMergingObject = eleventyConfig.getMergingConfigObject();
|
||||
localConfig = lodashMerge(localConfig, eleventyConfigApiMergingObject);
|
||||
|
||||
// blow away any templateFormats set in config return object and prefer those set in config API.
|
||||
for (let localConfigKey of overrides) {
|
||||
localConfig[localConfigKey] =
|
||||
eleventyConfigApiMergingObject[localConfigKey] ||
|
||||
localConfig[localConfigKey];
|
||||
}
|
||||
|
||||
// debug("eleventyConfig.getMergingConfigObject: %o", eleventyConfig.getMergingConfigObject());
|
||||
debug("localConfig: %o", localConfig);
|
||||
debug("overrides: %o", this.overrides);
|
||||
|
||||
// Object assign overrides original values (good only for templateFormats) but not good for anything else
|
||||
let merged = lodashMerge({}, this.rootConfig, localConfig, this.overrides);
|
||||
|
||||
// blow away any templateFormats upstream (don’t merge)
|
||||
for (let key of overrides) {
|
||||
merged[key] = localConfig[key] || this.rootConfig[key];
|
||||
}
|
||||
|
||||
debug("Current configuration: %o", merged);
|
||||
|
||||
return merged;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = TemplateConfig;
|
206
node_modules/@11ty/eleventy/src/TemplateContent.js
generated
vendored
Normal file
206
node_modules/@11ty/eleventy/src/TemplateContent.js
generated
vendored
Normal file
@@ -0,0 +1,206 @@
|
||||
const os = require("os");
|
||||
const fs = require("fs-extra");
|
||||
const normalize = require("normalize-path");
|
||||
const matter = require("gray-matter");
|
||||
const lodashSet = require("lodash/set");
|
||||
|
||||
const TemplateData = require("./TemplateData");
|
||||
const TemplateRender = require("./TemplateRender");
|
||||
const EleventyBaseError = require("./EleventyBaseError");
|
||||
const EleventyErrorUtil = require("./EleventyErrorUtil");
|
||||
const config = require("./Config");
|
||||
const debug = require("debug")("Eleventy:TemplateContent");
|
||||
const debugDev = require("debug")("Dev:Eleventy:TemplateContent");
|
||||
|
||||
class TemplateContentCompileError extends EleventyBaseError {}
|
||||
class TemplateContentRenderError extends EleventyBaseError {}
|
||||
|
||||
class TemplateContent {
|
||||
constructor(inputPath, inputDir) {
|
||||
this.inputPath = inputPath;
|
||||
|
||||
if (inputDir) {
|
||||
this.inputDir = normalize(inputDir);
|
||||
} else {
|
||||
this.inputDir = false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Used by tests */
|
||||
_setExtensionMap(map) {
|
||||
this._extensionMap = map;
|
||||
}
|
||||
|
||||
set config(config) {
|
||||
this._config = config;
|
||||
}
|
||||
|
||||
get config() {
|
||||
if (!this._config) {
|
||||
this._config = config.getConfig();
|
||||
}
|
||||
|
||||
return this._config;
|
||||
}
|
||||
|
||||
get engine() {
|
||||
return this.templateRender.engine;
|
||||
}
|
||||
|
||||
get templateRender() {
|
||||
if (!this._templateRender) {
|
||||
this._templateRender = new TemplateRender(
|
||||
this.inputPath,
|
||||
this.inputDir,
|
||||
this._extensionMap
|
||||
);
|
||||
}
|
||||
|
||||
return this._templateRender;
|
||||
}
|
||||
|
||||
getInputPath() {
|
||||
return this.inputPath;
|
||||
}
|
||||
|
||||
getInputDir() {
|
||||
return this.inputDir;
|
||||
}
|
||||
|
||||
async read() {
|
||||
this.inputContent = await this.getInputContent();
|
||||
|
||||
if (this.inputContent) {
|
||||
let options = this.config.frontMatterParsingOptions || {};
|
||||
let fm = matter(this.inputContent, options);
|
||||
if (options.excerpt && fm.excerpt) {
|
||||
let excerptString = fm.excerpt + (options.excerpt_separator || "---");
|
||||
if (fm.content.startsWith(excerptString + os.EOL)) {
|
||||
// with a newline after excerpt separator
|
||||
fm.content =
|
||||
fm.excerpt.trim() +
|
||||
"\n" +
|
||||
fm.content.substr((excerptString + os.EOL).length);
|
||||
} else if (fm.content.startsWith(excerptString)) {
|
||||
// no newline after excerpt separator
|
||||
fm.content = fm.excerpt + fm.content.substr(excerptString.length);
|
||||
}
|
||||
|
||||
// alias, defaults to page.excerpt
|
||||
let alias = options.excerpt_alias || "page.excerpt";
|
||||
lodashSet(fm.data, alias, fm.excerpt);
|
||||
}
|
||||
this.frontMatter = fm;
|
||||
} else {
|
||||
this.frontMatter = {
|
||||
data: {},
|
||||
content: "",
|
||||
excerpt: ""
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
async getInputContent() {
|
||||
if (this.engine.needsToReadFileContents()) {
|
||||
return fs.readFile(this.inputPath, "utf-8");
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
async getFrontMatter() {
|
||||
if (!this.frontMatter) {
|
||||
await this.read();
|
||||
}
|
||||
|
||||
return this.frontMatter;
|
||||
}
|
||||
|
||||
async getPreRender() {
|
||||
if (!this.frontMatter) {
|
||||
await this.read();
|
||||
}
|
||||
|
||||
return this.frontMatter.content;
|
||||
}
|
||||
|
||||
async getFrontMatterData() {
|
||||
if (!this.frontMatter) {
|
||||
await this.read();
|
||||
}
|
||||
|
||||
let extraData = await this.engine.getExtraDataFromFile(this.inputPath);
|
||||
let data = TemplateData.mergeDeep({}, this.frontMatter.data, extraData);
|
||||
return TemplateData.cleanupData(data);
|
||||
}
|
||||
|
||||
async getEngineOverride() {
|
||||
let frontMatterData = await this.getFrontMatterData();
|
||||
return frontMatterData[this.config.keys.engineOverride];
|
||||
}
|
||||
|
||||
async setupTemplateRender(bypassMarkdown) {
|
||||
let engineOverride = await this.getEngineOverride();
|
||||
if (engineOverride !== undefined) {
|
||||
debugDev(
|
||||
"%o overriding template engine to use %o",
|
||||
this.inputPath,
|
||||
engineOverride
|
||||
);
|
||||
|
||||
this.templateRender.setEngineOverride(engineOverride, bypassMarkdown);
|
||||
} else {
|
||||
this.templateRender.setUseMarkdown(!bypassMarkdown);
|
||||
}
|
||||
}
|
||||
|
||||
async compile(str, bypassMarkdown) {
|
||||
await this.setupTemplateRender(bypassMarkdown);
|
||||
|
||||
debugDev(
|
||||
"%o compile() using engine: %o",
|
||||
this.inputPath,
|
||||
this.templateRender.engineName
|
||||
);
|
||||
|
||||
try {
|
||||
let fn = await this.templateRender.getCompiledTemplate(str);
|
||||
debugDev("%o getCompiledTemplate function created", this.inputPath);
|
||||
return fn;
|
||||
} catch (e) {
|
||||
debug(`Having trouble compiling template ${this.inputPath}: %O`, str);
|
||||
throw new TemplateContentCompileError(
|
||||
`Having trouble compiling template ${this.inputPath}`,
|
||||
e
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async render(str, data, bypassMarkdown) {
|
||||
try {
|
||||
let fn = await this.compile(str, bypassMarkdown);
|
||||
let rendered = await fn(data);
|
||||
debugDev(
|
||||
"%o getCompiledTemplate called, rendered content created",
|
||||
this.inputPath
|
||||
);
|
||||
return rendered;
|
||||
} catch (e) {
|
||||
if (EleventyErrorUtil.isPrematureTemplateContentError(e)) {
|
||||
throw e;
|
||||
} else {
|
||||
let engine = this.templateRender.getEnginesStr();
|
||||
debug(
|
||||
`Having trouble rendering ${engine} template ${this.inputPath}: %O`,
|
||||
str
|
||||
);
|
||||
throw new TemplateContentRenderError(
|
||||
`Having trouble rendering ${engine} template ${this.inputPath}`,
|
||||
e
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = TemplateContent;
|
352
node_modules/@11ty/eleventy/src/TemplateData.js
generated
vendored
Normal file
352
node_modules/@11ty/eleventy/src/TemplateData.js
generated
vendored
Normal file
@@ -0,0 +1,352 @@
|
||||
const fs = require("fs-extra");
|
||||
const fastglob = require("fast-glob");
|
||||
const parsePath = require("parse-filepath");
|
||||
const lodashset = require("lodash/set");
|
||||
const lodashUniq = require("lodash/uniq");
|
||||
const merge = require("./Util/Merge");
|
||||
const TemplateRender = require("./TemplateRender");
|
||||
const TemplatePath = require("./TemplatePath");
|
||||
const TemplateGlob = require("./TemplateGlob");
|
||||
const EleventyExtensionMap = require("./EleventyExtensionMap");
|
||||
const EleventyBaseError = require("./EleventyBaseError");
|
||||
const bench = require("./BenchmarkManager").get("Data");
|
||||
const config = require("./Config");
|
||||
const debugWarn = require("debug")("Eleventy:Warnings");
|
||||
const debug = require("debug")("Eleventy:TemplateData");
|
||||
const debugDev = require("debug")("Dev:Eleventy:TemplateData");
|
||||
|
||||
class TemplateDataParseError extends EleventyBaseError {}
|
||||
|
||||
class TemplateData {
|
||||
constructor(inputDir) {
|
||||
this.config = config.getConfig();
|
||||
this.dataTemplateEngine = this.config.dataTemplateEngine;
|
||||
|
||||
this.inputDirNeedsCheck = false;
|
||||
this.setInputDir(inputDir);
|
||||
|
||||
this.rawImports = {};
|
||||
this.globalData = null;
|
||||
}
|
||||
|
||||
/* Used by tests */
|
||||
_setConfig(config) {
|
||||
this.config = config;
|
||||
this.dataTemplateEngine = this.config.dataTemplateEngine;
|
||||
}
|
||||
|
||||
setInputDir(inputDir) {
|
||||
this.inputDirNeedsCheck = true;
|
||||
this.inputDir = inputDir;
|
||||
this.dataDir = this.config.dir.data
|
||||
? TemplatePath.join(inputDir, this.config.dir.data)
|
||||
: inputDir;
|
||||
}
|
||||
|
||||
setDataTemplateEngine(engineName) {
|
||||
this.dataTemplateEngine = engineName;
|
||||
}
|
||||
|
||||
getRawImports() {
|
||||
let pkgPath = TemplatePath.absolutePath("package.json");
|
||||
|
||||
try {
|
||||
this.rawImports[this.config.keys.package] = require(pkgPath);
|
||||
} catch (e) {
|
||||
debug(
|
||||
"Could not find and/or require package.json for data preprocessing at %o",
|
||||
pkgPath
|
||||
);
|
||||
}
|
||||
|
||||
return this.rawImports;
|
||||
}
|
||||
|
||||
getDataDir() {
|
||||
return this.dataDir;
|
||||
}
|
||||
|
||||
clearData() {
|
||||
this.globalData = null;
|
||||
}
|
||||
|
||||
async cacheData() {
|
||||
this.clearData();
|
||||
|
||||
return this.getData();
|
||||
}
|
||||
|
||||
_getGlobalDataGlobByExtension(dir, extension) {
|
||||
return TemplateGlob.normalizePath(
|
||||
dir,
|
||||
"/",
|
||||
this.config.dir.data !== "." ? this.config.dir.data : "",
|
||||
`/**/*.${extension}`
|
||||
);
|
||||
}
|
||||
|
||||
async _checkInputDir() {
|
||||
if (this.inputDirNeedsCheck) {
|
||||
let globalPathStat = await fs.stat(this.inputDir);
|
||||
|
||||
if (!globalPathStat.isDirectory()) {
|
||||
throw new Error("Could not find data path directory: " + this.inputDir);
|
||||
}
|
||||
|
||||
this.inputDirNeedsCheck = false;
|
||||
}
|
||||
}
|
||||
|
||||
async getInputDir() {
|
||||
let dir = ".";
|
||||
|
||||
if (this.inputDir) {
|
||||
await this._checkInputDir();
|
||||
dir = this.inputDir;
|
||||
}
|
||||
|
||||
return dir;
|
||||
}
|
||||
|
||||
async getTemplateDataFileGlob() {
|
||||
let dir = await this.getInputDir();
|
||||
return TemplatePath.addLeadingDotSlashArray([
|
||||
`${dir}/**/*.json`, // covers .11tydata.json too
|
||||
`${dir}/**/*${this.config.jsDataFileSuffix}.js`
|
||||
]);
|
||||
}
|
||||
|
||||
async getTemplateJavaScriptDataFileGlob() {
|
||||
let dir = await this.getInputDir();
|
||||
return TemplatePath.addLeadingDotSlashArray([
|
||||
`${dir}/**/*${this.config.jsDataFileSuffix}.js`
|
||||
]);
|
||||
}
|
||||
|
||||
async getGlobalDataGlob() {
|
||||
let dir = await this.getInputDir();
|
||||
return [this._getGlobalDataGlobByExtension(dir, "(json|js)")];
|
||||
}
|
||||
|
||||
getWatchPathCache() {
|
||||
return this.pathCache;
|
||||
}
|
||||
|
||||
async getGlobalDataFiles() {
|
||||
let paths = await fastglob(await this.getGlobalDataGlob(), {
|
||||
caseSensitiveMatch: false,
|
||||
dot: true
|
||||
});
|
||||
this.pathCache = paths;
|
||||
return paths;
|
||||
}
|
||||
|
||||
getObjectPathForDataFile(path) {
|
||||
let reducedPath = TemplatePath.stripLeadingSubPath(path, this.dataDir);
|
||||
let parsed = parsePath(reducedPath);
|
||||
let folders = parsed.dir ? parsed.dir.split("/") : [];
|
||||
folders.push(parsed.name);
|
||||
|
||||
return folders.join(".");
|
||||
}
|
||||
|
||||
async getAllGlobalData() {
|
||||
let rawImports = this.getRawImports();
|
||||
let globalData = {};
|
||||
let files = TemplatePath.addLeadingDotSlashArray(
|
||||
await this.getGlobalDataFiles()
|
||||
);
|
||||
let dataFileConflicts = {};
|
||||
|
||||
for (let j = 0, k = files.length; j < k; j++) {
|
||||
let folders = await this.getObjectPathForDataFile(files[j]);
|
||||
|
||||
// TODO maybe merge these two? (if both valid objects)
|
||||
if (dataFileConflicts[folders]) {
|
||||
debugWarn(
|
||||
`Warning: the key for a global data file (${files[j]}) will overwrite data from an already existing global data file (${dataFileConflicts[folders]})`
|
||||
);
|
||||
}
|
||||
dataFileConflicts[folders] = files[j];
|
||||
|
||||
debug(`Found global data file ${files[j]} and adding as: ${folders}`);
|
||||
let data = await this.getDataValue(files[j], rawImports);
|
||||
lodashset(globalData, folders, data);
|
||||
}
|
||||
|
||||
return globalData;
|
||||
}
|
||||
|
||||
async getData() {
|
||||
let rawImports = this.getRawImports();
|
||||
|
||||
if (!this.globalData) {
|
||||
let globalJson = await this.getAllGlobalData();
|
||||
|
||||
// OK: Shallow merge when combining rawImports (pkg) with global data files
|
||||
this.globalData = Object.assign({}, globalJson, rawImports);
|
||||
}
|
||||
|
||||
return this.globalData;
|
||||
}
|
||||
|
||||
/* Template and Directory data files */
|
||||
async combineLocalData(localDataPaths) {
|
||||
let localData = {};
|
||||
if (!Array.isArray(localDataPaths)) {
|
||||
localDataPaths = [localDataPaths];
|
||||
}
|
||||
for (let path of localDataPaths) {
|
||||
// clean up data for template/directory data files only.
|
||||
let dataForPath = await this.getDataValue(path, null, true);
|
||||
let cleanedDataForPath = TemplateData.cleanupData(dataForPath);
|
||||
TemplateData.mergeDeep(this.config, localData, cleanedDataForPath);
|
||||
// debug("`combineLocalData` (iterating) for %o: %O", path, localData);
|
||||
}
|
||||
return localData;
|
||||
}
|
||||
|
||||
async getLocalData(templatePath) {
|
||||
let localDataPaths = await this.getLocalDataPaths(templatePath);
|
||||
let importedData = await this.combineLocalData(localDataPaths);
|
||||
let globalData = await this.getData();
|
||||
|
||||
// OK-ish: shallow merge when combining template/data dir files with global data files
|
||||
let localData = Object.assign({}, globalData, importedData);
|
||||
// debug("`getLocalData` for %o: %O", templatePath, localData);
|
||||
return localData;
|
||||
}
|
||||
|
||||
async _getLocalJsonString(path) {
|
||||
let rawInput;
|
||||
try {
|
||||
rawInput = await fs.readFile(path, "utf-8");
|
||||
} catch (e) {
|
||||
// if file does not exist, return nothing
|
||||
}
|
||||
return rawInput;
|
||||
}
|
||||
|
||||
async getDataValue(path, rawImports, ignoreProcessing) {
|
||||
if (ignoreProcessing || TemplatePath.getExtension(path) === "js") {
|
||||
let localPath = TemplatePath.absolutePath(path);
|
||||
if (await fs.pathExists(localPath)) {
|
||||
let dataBench = bench.get(`\`${path}\``);
|
||||
dataBench.before();
|
||||
delete require.cache[localPath];
|
||||
let returnValue = require(localPath);
|
||||
if (typeof returnValue === "function") {
|
||||
returnValue = await returnValue();
|
||||
}
|
||||
|
||||
dataBench.after();
|
||||
return returnValue;
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
} else {
|
||||
let rawInput = await this._getLocalJsonString(path);
|
||||
let engineName = this.dataTemplateEngine;
|
||||
|
||||
if (rawInput) {
|
||||
if (ignoreProcessing || engineName === false) {
|
||||
try {
|
||||
return JSON.parse(rawInput);
|
||||
} catch (e) {
|
||||
throw new TemplateDataParseError(
|
||||
`Having trouble parsing data file ${path}`,
|
||||
e
|
||||
);
|
||||
}
|
||||
} else {
|
||||
let fn = await new TemplateRender(engineName).getCompiledTemplate(
|
||||
rawInput
|
||||
);
|
||||
|
||||
try {
|
||||
// pass in rawImports, don’t pass in global data, that’s what we’re parsing
|
||||
return JSON.parse(await fn(rawImports));
|
||||
} catch (e) {
|
||||
throw new TemplateDataParseError(
|
||||
`Having trouble parsing data file ${path}`,
|
||||
e
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
async getLocalDataPaths(templatePath) {
|
||||
let paths = [];
|
||||
let parsed = parsePath(templatePath);
|
||||
let inputDir = TemplatePath.addLeadingDotSlash(
|
||||
TemplatePath.normalize(this.inputDir)
|
||||
);
|
||||
debugDev("getLocalDataPaths(%o)", templatePath);
|
||||
debugDev("parsed.dir: %o", parsed.dir);
|
||||
|
||||
if (parsed.dir) {
|
||||
let fileNameNoExt = EleventyExtensionMap.removeTemplateExtension(
|
||||
parsed.base
|
||||
);
|
||||
let filePathNoExt = parsed.dir + "/" + fileNameNoExt;
|
||||
let dataSuffix = this.config.jsDataFileSuffix;
|
||||
debug("Using %o to find data files.", dataSuffix);
|
||||
paths.push(filePathNoExt + dataSuffix + ".js");
|
||||
paths.push(filePathNoExt + dataSuffix + ".json");
|
||||
paths.push(filePathNoExt + ".json");
|
||||
|
||||
let allDirs = TemplatePath.getAllDirs(parsed.dir);
|
||||
debugDev("allDirs: %o", allDirs);
|
||||
for (let dir of allDirs) {
|
||||
let lastDir = TemplatePath.getLastPathSegment(dir);
|
||||
let dirPathNoExt = dir + "/" + lastDir;
|
||||
|
||||
if (!inputDir) {
|
||||
paths.push(dirPathNoExt + dataSuffix + ".js");
|
||||
paths.push(dirPathNoExt + dataSuffix + ".json");
|
||||
paths.push(dirPathNoExt + ".json");
|
||||
} else {
|
||||
debugDev("dirStr: %o; inputDir: %o", dir, inputDir);
|
||||
if (dir.indexOf(inputDir) === 0 && dir !== inputDir) {
|
||||
paths.push(dirPathNoExt + dataSuffix + ".js");
|
||||
paths.push(dirPathNoExt + dataSuffix + ".json");
|
||||
paths.push(dirPathNoExt + ".json");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
debug("getLocalDataPaths(%o): %o", templatePath, paths);
|
||||
return lodashUniq(paths).reverse();
|
||||
}
|
||||
|
||||
static mergeDeep(config, target, ...source) {
|
||||
if (config.dataDeepMerge) {
|
||||
return TemplateData.merge(target, ...source);
|
||||
} else {
|
||||
return Object.assign(target, ...source);
|
||||
}
|
||||
}
|
||||
|
||||
static merge(target, ...source) {
|
||||
return merge(target, ...source);
|
||||
}
|
||||
|
||||
static cleanupData(data) {
|
||||
if ("tags" in data) {
|
||||
if (typeof data.tags === "string") {
|
||||
data.tags = data.tags ? [data.tags] : [];
|
||||
} else if (data.tags === null) {
|
||||
data.tags = [];
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = TemplateData;
|
49
node_modules/@11ty/eleventy/src/TemplateFileSlug.js
generated
vendored
Normal file
49
node_modules/@11ty/eleventy/src/TemplateFileSlug.js
generated
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
const parsePath = require("parse-filepath");
|
||||
const TemplatePath = require("./TemplatePath");
|
||||
const EleventyExtensionMap = require("./EleventyExtensionMap");
|
||||
|
||||
class TemplateFileSlug {
|
||||
constructor(inputPath, inputDir) {
|
||||
if (inputDir) {
|
||||
inputPath = TemplatePath.stripLeadingSubPath(inputPath, inputDir);
|
||||
}
|
||||
|
||||
this.inputPath = inputPath;
|
||||
this.cleanInputPath = inputPath.replace(/^.\//, "");
|
||||
|
||||
let dirs = this.cleanInputPath.split("/");
|
||||
this.dirs = dirs;
|
||||
this.dirs.pop();
|
||||
|
||||
this.parsed = parsePath(inputPath);
|
||||
// TODO update this after the fix for issue #117 merges
|
||||
this.filenameNoExt = EleventyExtensionMap.removeTemplateExtension(
|
||||
this.parsed.base
|
||||
);
|
||||
}
|
||||
|
||||
getFullPathWithoutExtension() {
|
||||
return "/" + TemplatePath.join(...this.dirs, this._getRawSlug());
|
||||
}
|
||||
|
||||
_getRawSlug() {
|
||||
let slug = this.filenameNoExt;
|
||||
let reg = slug.match(/\d{4}-\d{2}-\d{2}-(.*)/);
|
||||
if (reg) {
|
||||
return reg[1];
|
||||
}
|
||||
return slug;
|
||||
}
|
||||
|
||||
getSlug() {
|
||||
let rawSlug = this._getRawSlug();
|
||||
|
||||
if (rawSlug === "index") {
|
||||
return this.dirs.length ? this.dirs[this.dirs.length - 1] : "";
|
||||
}
|
||||
|
||||
return rawSlug;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = TemplateFileSlug;
|
37
node_modules/@11ty/eleventy/src/TemplateGlob.js
generated
vendored
Normal file
37
node_modules/@11ty/eleventy/src/TemplateGlob.js
generated
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
const TemplatePath = require("./TemplatePath");
|
||||
|
||||
class TemplateGlob {
|
||||
static normalizePath(...paths) {
|
||||
if (paths[0].charAt(0) === "!") {
|
||||
throw new Error(
|
||||
`TemplateGlob.normalizePath does not accept ! glob paths like: ${paths.join(
|
||||
""
|
||||
)}`
|
||||
);
|
||||
}
|
||||
return TemplatePath.addLeadingDotSlash(TemplatePath.join(...paths));
|
||||
}
|
||||
|
||||
static normalize(path) {
|
||||
path = path.trim();
|
||||
if (path.charAt(0) === "!") {
|
||||
return "!" + TemplateGlob.normalizePath(path.substr(1));
|
||||
} else {
|
||||
return TemplateGlob.normalizePath(path);
|
||||
}
|
||||
}
|
||||
|
||||
static map(files) {
|
||||
if (typeof files === "string") {
|
||||
return TemplateGlob.normalize(files);
|
||||
} else if (Array.isArray(files)) {
|
||||
return files.map(function(path) {
|
||||
return TemplateGlob.normalize(path);
|
||||
});
|
||||
} else {
|
||||
return files;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = TemplateGlob;
|
143
node_modules/@11ty/eleventy/src/TemplateLayout.js
generated
vendored
Normal file
143
node_modules/@11ty/eleventy/src/TemplateLayout.js
generated
vendored
Normal file
@@ -0,0 +1,143 @@
|
||||
const TemplateLayoutPathResolver = require("./TemplateLayoutPathResolver");
|
||||
const TemplateContent = require("./TemplateContent");
|
||||
const TemplateData = require("./TemplateData");
|
||||
const TemplatePath = require("./TemplatePath");
|
||||
|
||||
const templateCache = require("./TemplateCache");
|
||||
const config = require("./Config");
|
||||
const debug = require("debug")("Eleventy:TemplateLayout");
|
||||
const debugDev = require("debug")("Dev:Eleventy:TemplateLayout");
|
||||
|
||||
class TemplateLayout extends TemplateContent {
|
||||
constructor(key, inputDir) {
|
||||
// TODO getConfig() is duplicated in TemplateContent (super)
|
||||
let cfg = config.getConfig();
|
||||
let resolvedPath = new TemplateLayoutPathResolver(
|
||||
key,
|
||||
inputDir
|
||||
).getFullPath();
|
||||
super(resolvedPath, inputDir);
|
||||
|
||||
this.dataKeyLayoutPath = key;
|
||||
this.inputPath = resolvedPath;
|
||||
this.inputDir = inputDir;
|
||||
this.config = cfg;
|
||||
}
|
||||
|
||||
static resolveFullKey(key, inputDir) {
|
||||
return TemplatePath.join(inputDir, key);
|
||||
}
|
||||
|
||||
static getTemplate(key, inputDir, config) {
|
||||
let fullKey = TemplateLayout.resolveFullKey(key, inputDir);
|
||||
if (templateCache.has(fullKey)) {
|
||||
debugDev("Found %o in TemplateCache", key);
|
||||
return templateCache.get(fullKey);
|
||||
}
|
||||
|
||||
let tmpl = new TemplateLayout(key, inputDir);
|
||||
tmpl.config = config;
|
||||
templateCache.add(fullKey, tmpl);
|
||||
|
||||
return tmpl;
|
||||
}
|
||||
|
||||
async getTemplateLayoutMapEntry() {
|
||||
return {
|
||||
key: this.dataKeyLayoutPath,
|
||||
template: this,
|
||||
frontMatterData: await this.getFrontMatterData()
|
||||
};
|
||||
}
|
||||
|
||||
async getTemplateLayoutMap() {
|
||||
if (this.mapCache) {
|
||||
return this.mapCache;
|
||||
}
|
||||
|
||||
let cfgKey = this.config.keys.layout;
|
||||
let map = [];
|
||||
let mapEntry = await this.getTemplateLayoutMapEntry();
|
||||
map.push(mapEntry);
|
||||
|
||||
while (mapEntry.frontMatterData && cfgKey in mapEntry.frontMatterData) {
|
||||
let layout = TemplateLayout.getTemplate(
|
||||
mapEntry.frontMatterData[cfgKey],
|
||||
this.inputDir,
|
||||
this.config
|
||||
);
|
||||
mapEntry = await layout.getTemplateLayoutMapEntry();
|
||||
map.push(mapEntry);
|
||||
}
|
||||
|
||||
this.mapCache = map;
|
||||
return map;
|
||||
}
|
||||
|
||||
async getData() {
|
||||
if (this.dataCache) {
|
||||
return this.dataCache;
|
||||
}
|
||||
|
||||
let map = await this.getTemplateLayoutMap();
|
||||
let dataToMerge = [];
|
||||
for (let j = map.length - 1; j >= 0; j--) {
|
||||
dataToMerge.push(map[j].frontMatterData);
|
||||
}
|
||||
|
||||
// Deep merge of layout front matter
|
||||
let data = TemplateData.mergeDeep(this.config, {}, ...dataToMerge);
|
||||
delete data[this.config.keys.layout];
|
||||
|
||||
this.dataCache = data;
|
||||
return data;
|
||||
}
|
||||
|
||||
async getCompiledLayoutFunctions() {
|
||||
if (this.compileCache) {
|
||||
return this.compileCache;
|
||||
}
|
||||
|
||||
let map = await this.getTemplateLayoutMap();
|
||||
let fns = [];
|
||||
for (let layoutMap of map) {
|
||||
fns.push(
|
||||
await layoutMap.template.compile(
|
||||
await layoutMap.template.getPreRender()
|
||||
)
|
||||
);
|
||||
}
|
||||
this.compileCache = fns;
|
||||
return fns;
|
||||
}
|
||||
|
||||
static augmentDataWithContent(data, templateContent) {
|
||||
data = data || {};
|
||||
|
||||
if (templateContent !== undefined) {
|
||||
data.content = templateContent;
|
||||
data.layoutContent = templateContent;
|
||||
|
||||
// deprecated
|
||||
data._layoutContent = templateContent;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
// Inefficient? We want to compile all the templatelayouts into a single reusable callback?
|
||||
// Trouble: layouts may need data variables present downstream/upstream
|
||||
async render(data, templateContent) {
|
||||
data = TemplateLayout.augmentDataWithContent(data, templateContent);
|
||||
|
||||
let fns = await this.getCompiledLayoutFunctions();
|
||||
for (let fn of fns) {
|
||||
templateContent = await fn(data);
|
||||
data = TemplateLayout.augmentDataWithContent(data, templateContent);
|
||||
}
|
||||
|
||||
return templateContent;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = TemplateLayout;
|
128
node_modules/@11ty/eleventy/src/TemplateLayoutPathResolver.js
generated
vendored
Normal file
128
node_modules/@11ty/eleventy/src/TemplateLayoutPathResolver.js
generated
vendored
Normal file
@@ -0,0 +1,128 @@
|
||||
const fs = require("fs-extra");
|
||||
const config = require("./Config");
|
||||
const EleventyExtensionMap = require("./EleventyExtensionMap");
|
||||
const TemplatePath = require("./TemplatePath");
|
||||
const debug = require("debug")("Eleventy:TemplateLayoutPathResolver");
|
||||
|
||||
class TemplateLayoutPathResolver {
|
||||
constructor(path, inputDir) {
|
||||
this._config = config.getConfig();
|
||||
this.inputDir = inputDir;
|
||||
this.originalPath = path;
|
||||
this.path = path;
|
||||
this.aliases = {};
|
||||
|
||||
this.init();
|
||||
}
|
||||
|
||||
set inputDir(dir) {
|
||||
this._inputDir = dir;
|
||||
this.dir = this.getLayoutsDir();
|
||||
}
|
||||
|
||||
get inputDir() {
|
||||
return this._inputDir;
|
||||
}
|
||||
|
||||
// for testing
|
||||
set config(cfg) {
|
||||
this._config = cfg;
|
||||
this.dir = this.getLayoutsDir();
|
||||
this.init();
|
||||
}
|
||||
|
||||
get config() {
|
||||
return this._config;
|
||||
}
|
||||
|
||||
init() {
|
||||
// we might be able to move this into the constructor?
|
||||
this.aliases = Object.assign({}, this.config.layoutAliases, this.aliases);
|
||||
// debug("Current layout aliases: %o", this.aliases);
|
||||
|
||||
if (this.path in this.aliases) {
|
||||
// debug(
|
||||
// "Substituting layout: %o maps to %o",
|
||||
// this.path,
|
||||
// this.aliases[this.path]
|
||||
// );
|
||||
this.path = this.aliases[this.path];
|
||||
}
|
||||
|
||||
this.pathAlreadyHasExtension = this.dir + "/" + this.path;
|
||||
|
||||
if (
|
||||
this.path.split(".").length > 0 &&
|
||||
fs.existsSync(this.pathAlreadyHasExtension)
|
||||
) {
|
||||
this.filename = this.path;
|
||||
this.fullPath = this.pathAlreadyHasExtension;
|
||||
} else {
|
||||
this.filename = this.findFileName();
|
||||
this.fullPath = this.dir + "/" + this.filename;
|
||||
}
|
||||
}
|
||||
|
||||
addLayoutAlias(from, to) {
|
||||
this.aliases[from] = to;
|
||||
}
|
||||
|
||||
getFileName() {
|
||||
if (!this.filename) {
|
||||
throw new Error(
|
||||
`You’re trying to use a layout that does not exist: ${
|
||||
this.originalPath
|
||||
} (${this.filename})`
|
||||
);
|
||||
}
|
||||
|
||||
return this.filename;
|
||||
}
|
||||
|
||||
getFullPath() {
|
||||
if (!this.filename) {
|
||||
throw new Error(
|
||||
`You’re trying to use a layout that does not exist: ${
|
||||
this.originalPath
|
||||
} (${this.filename})`
|
||||
);
|
||||
}
|
||||
|
||||
return this.fullPath;
|
||||
}
|
||||
|
||||
findFileName() {
|
||||
if (!fs.existsSync(this.dir)) {
|
||||
throw Error(
|
||||
"TemplateLayoutPathResolver directory does not exist for " +
|
||||
this.path +
|
||||
": " +
|
||||
this.dir
|
||||
);
|
||||
}
|
||||
|
||||
let extensionMap = new EleventyExtensionMap(this.config.templateFormats);
|
||||
for (let filename of extensionMap.getFileList(this.path)) {
|
||||
// TODO async
|
||||
if (fs.existsSync(this.dir + "/" + filename)) {
|
||||
return filename;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getLayoutsDir() {
|
||||
let layoutsDir;
|
||||
if ("layouts" in this.config.dir) {
|
||||
layoutsDir = this.config.dir.layouts;
|
||||
} else if ("includes" in this.config.dir) {
|
||||
layoutsDir = this.config.dir.includes;
|
||||
} else {
|
||||
// Should this have a default?
|
||||
layoutsDir = "_includes";
|
||||
}
|
||||
|
||||
return TemplatePath.join(this.inputDir, layoutsDir);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = TemplateLayoutPathResolver;
|
546
node_modules/@11ty/eleventy/src/TemplateMap.js
generated
vendored
Normal file
546
node_modules/@11ty/eleventy/src/TemplateMap.js
generated
vendored
Normal file
@@ -0,0 +1,546 @@
|
||||
const isPlainObject = require("lodash/isPlainObject");
|
||||
const DependencyGraph = require("dependency-graph").DepGraph;
|
||||
const TemplateCollection = require("./TemplateCollection");
|
||||
const EleventyErrorUtil = require("./EleventyErrorUtil");
|
||||
const UsingCircularTemplateContentReferenceError = require("./Errors/UsingCircularTemplateContentReferenceError");
|
||||
const eleventyConfig = require("./EleventyConfig");
|
||||
const debug = require("debug")("Eleventy:TemplateMap");
|
||||
const debugDev = require("debug")("Dev:Eleventy:TemplateMap");
|
||||
|
||||
const EleventyBaseError = require("./EleventyBaseError");
|
||||
class DuplicatePermalinkOutputError extends EleventyBaseError {
|
||||
get removeDuplicateErrorStringFromOutput() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class TemplateMap {
|
||||
constructor() {
|
||||
this.map = [];
|
||||
this.graph = new DependencyGraph();
|
||||
this.collectionsData = null;
|
||||
this.cached = false;
|
||||
this.configCollections = null;
|
||||
this.verboseOutput = true;
|
||||
}
|
||||
|
||||
get tagPrefix() {
|
||||
return "___TAG___";
|
||||
}
|
||||
|
||||
async add(template) {
|
||||
for (let map of await template.getTemplateMapEntries()) {
|
||||
this.map.push(map);
|
||||
}
|
||||
}
|
||||
|
||||
getMap() {
|
||||
return this.map;
|
||||
}
|
||||
|
||||
get collection() {
|
||||
if (!this._collection) {
|
||||
this._collection = new TemplateCollection();
|
||||
}
|
||||
return this._collection;
|
||||
}
|
||||
|
||||
getTagTarget(str) {
|
||||
if (str.startsWith("collections.")) {
|
||||
return str.substr("collections.".length);
|
||||
}
|
||||
}
|
||||
|
||||
/* ---
|
||||
* pagination:
|
||||
* data: collections
|
||||
* ---
|
||||
*/
|
||||
isPaginationOverAllCollections(entry) {
|
||||
if (entry.data.pagination && entry.data.pagination.data) {
|
||||
return (
|
||||
entry.data.pagination.data === "collections" ||
|
||||
entry.data.pagination.data === "collections.all"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
getPaginationTagTarget(entry) {
|
||||
if (entry.data.pagination && entry.data.pagination.data) {
|
||||
return this.getTagTarget(entry.data.pagination.data);
|
||||
}
|
||||
}
|
||||
|
||||
getMappedDependencies() {
|
||||
let graph = new DependencyGraph();
|
||||
let tagPrefix = this.tagPrefix;
|
||||
|
||||
graph.addNode(tagPrefix + "all");
|
||||
|
||||
for (let entry of this.map) {
|
||||
if (this.isPaginationOverAllCollections(entry)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// using Pagination (but not targeting a user config collection)
|
||||
let paginationTagTarget = this.getPaginationTagTarget(entry);
|
||||
if (paginationTagTarget) {
|
||||
if (this.isUserConfigCollectionName(paginationTagTarget)) {
|
||||
// delay this one to the second stage
|
||||
continue;
|
||||
} else {
|
||||
// using pagination but over a tagged collection
|
||||
graph.addNode(entry.inputPath);
|
||||
if (!graph.hasNode(tagPrefix + paginationTagTarget)) {
|
||||
graph.addNode(tagPrefix + paginationTagTarget);
|
||||
}
|
||||
graph.addDependency(entry.inputPath, tagPrefix + paginationTagTarget);
|
||||
}
|
||||
} else {
|
||||
// not using pagination
|
||||
graph.addNode(entry.inputPath);
|
||||
}
|
||||
|
||||
if (!entry.data.eleventyExcludeFromCollections) {
|
||||
// collections.all
|
||||
graph.addDependency(tagPrefix + "all", entry.inputPath);
|
||||
|
||||
if (entry.data.tags) {
|
||||
for (let tag of entry.data.tags) {
|
||||
if (!graph.hasNode(tagPrefix + tag)) {
|
||||
graph.addNode(tagPrefix + tag);
|
||||
}
|
||||
|
||||
// collections.tagName
|
||||
// Dependency from tag to inputPath
|
||||
graph.addDependency(tagPrefix + tag, entry.inputPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return graph.overallOrder();
|
||||
}
|
||||
|
||||
getDelayedMappedDependencies() {
|
||||
let graph = new DependencyGraph();
|
||||
let tagPrefix = this.tagPrefix;
|
||||
|
||||
graph.addNode(tagPrefix + "all");
|
||||
|
||||
let userConfigCollections = this.getUserConfigCollectionNames();
|
||||
// Add tags from named user config collections
|
||||
for (let tag of userConfigCollections) {
|
||||
graph.addNode(tagPrefix + tag);
|
||||
// graph.addDependency( tagPrefix + tag, tagPrefix + "all" );
|
||||
}
|
||||
|
||||
for (let entry of this.map) {
|
||||
if (this.isPaginationOverAllCollections(entry)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let paginationTagTarget = this.getPaginationTagTarget(entry);
|
||||
if (
|
||||
paginationTagTarget &&
|
||||
this.isUserConfigCollectionName(paginationTagTarget)
|
||||
) {
|
||||
if (!graph.hasNode(entry.inputPath)) {
|
||||
graph.addNode(entry.inputPath);
|
||||
}
|
||||
graph.addDependency(entry.inputPath, tagPrefix + paginationTagTarget);
|
||||
|
||||
if (!entry.data.eleventyExcludeFromCollections) {
|
||||
// collections.all
|
||||
graph.addDependency(tagPrefix + "all", entry.inputPath);
|
||||
|
||||
if (entry.data.tags) {
|
||||
for (let tag of entry.data.tags) {
|
||||
if (!graph.hasNode(tagPrefix + tag)) {
|
||||
graph.addNode(tagPrefix + tag);
|
||||
}
|
||||
// collections.tagName
|
||||
// Dependency from tag to inputPath
|
||||
graph.addDependency(tagPrefix + tag, entry.inputPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return graph.overallOrder();
|
||||
}
|
||||
|
||||
getPaginatedOverCollectionsMappedDependencies() {
|
||||
let graph = new DependencyGraph();
|
||||
let tagPrefix = this.tagPrefix;
|
||||
let allNodeAdded = false;
|
||||
|
||||
for (let entry of this.map) {
|
||||
if (
|
||||
this.isPaginationOverAllCollections(entry) &&
|
||||
!this.getPaginationTagTarget(entry)
|
||||
) {
|
||||
if (!allNodeAdded) {
|
||||
graph.addNode(tagPrefix + "all");
|
||||
allNodeAdded = true;
|
||||
}
|
||||
|
||||
if (!graph.hasNode(entry.inputPath)) {
|
||||
graph.addNode(entry.inputPath);
|
||||
}
|
||||
|
||||
if (!entry.data.eleventyExcludeFromCollections) {
|
||||
// collections.all
|
||||
graph.addDependency(tagPrefix + "all", entry.inputPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return graph.overallOrder();
|
||||
}
|
||||
|
||||
getPaginatedOverAllCollectionMappedDependencies() {
|
||||
let graph = new DependencyGraph();
|
||||
let tagPrefix = this.tagPrefix;
|
||||
let allNodeAdded = false;
|
||||
|
||||
for (let entry of this.map) {
|
||||
if (
|
||||
this.isPaginationOverAllCollections(entry) &&
|
||||
this.getPaginationTagTarget(entry) === "all"
|
||||
) {
|
||||
if (!allNodeAdded) {
|
||||
graph.addNode(tagPrefix + "all");
|
||||
allNodeAdded = true;
|
||||
}
|
||||
|
||||
if (!graph.hasNode(entry.inputPath)) {
|
||||
graph.addNode(entry.inputPath);
|
||||
}
|
||||
|
||||
if (!entry.data.eleventyExcludeFromCollections) {
|
||||
// collections.all
|
||||
graph.addDependency(tagPrefix + "all", entry.inputPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return graph.overallOrder();
|
||||
}
|
||||
|
||||
async initDependencyMap(dependencyMap) {
|
||||
let tagPrefix = this.tagPrefix;
|
||||
for (let depEntry of dependencyMap) {
|
||||
if (depEntry.startsWith(tagPrefix)) {
|
||||
let tagName = depEntry.substr(tagPrefix.length);
|
||||
if (this.isUserConfigCollectionName(tagName)) {
|
||||
// async
|
||||
this.collectionsData[tagName] = await this.getUserConfigCollection(
|
||||
tagName
|
||||
);
|
||||
} else {
|
||||
this.collectionsData[tagName] = this.getTaggedCollection(tagName);
|
||||
}
|
||||
} else {
|
||||
let map = this.getMapEntryForInputPath(depEntry);
|
||||
map._pages = await map.template.getTemplates(map.data);
|
||||
|
||||
let counter = 0;
|
||||
for (let page of map._pages) {
|
||||
// TODO do we need this in map entries?
|
||||
if (!map.outputPath) {
|
||||
map.outputPath = page.outputPath;
|
||||
}
|
||||
if (
|
||||
counter === 0 ||
|
||||
(map.data.pagination &&
|
||||
map.data.pagination.addAllPagesToCollections)
|
||||
) {
|
||||
if (!map.data.eleventyExcludeFromCollections) {
|
||||
// TODO do we need .template in collection entries?
|
||||
this.collection.add(page);
|
||||
}
|
||||
}
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async cache() {
|
||||
debug("Caching collections objects.");
|
||||
this.collectionsData = {};
|
||||
|
||||
for (let entry of this.map) {
|
||||
entry.data.collections = this.collectionsData;
|
||||
}
|
||||
|
||||
let dependencyMap = this.getMappedDependencies();
|
||||
await this.initDependencyMap(dependencyMap);
|
||||
|
||||
let delayedDependencyMap = this.getDelayedMappedDependencies();
|
||||
await this.initDependencyMap(delayedDependencyMap);
|
||||
|
||||
let firstPaginatedDepMap = this.getPaginatedOverCollectionsMappedDependencies();
|
||||
await this.initDependencyMap(firstPaginatedDepMap);
|
||||
|
||||
let secondPaginatedDepMap = this.getPaginatedOverAllCollectionMappedDependencies();
|
||||
await this.initDependencyMap(secondPaginatedDepMap);
|
||||
|
||||
let orderedPaths = this.getOrderedInputPaths(
|
||||
dependencyMap,
|
||||
delayedDependencyMap,
|
||||
firstPaginatedDepMap,
|
||||
secondPaginatedDepMap
|
||||
);
|
||||
let orderedMap = orderedPaths.map(
|
||||
function(inputPath) {
|
||||
return this.getMapEntryForInputPath(inputPath);
|
||||
}.bind(this)
|
||||
);
|
||||
await this.populateContentDataInMap(orderedMap);
|
||||
|
||||
this.populateCollectionsWithContent();
|
||||
this.cached = true;
|
||||
|
||||
this.checkForDuplicatePermalinks();
|
||||
}
|
||||
|
||||
getMapEntryForInputPath(inputPath) {
|
||||
for (let map of this.map) {
|
||||
if (map.inputPath === inputPath) {
|
||||
return map;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getOrderedInputPaths(
|
||||
dependencyMap,
|
||||
delayedDependencyMap,
|
||||
firstPaginatedDepMap,
|
||||
secondPaginatedDepMap
|
||||
) {
|
||||
let orderedMap = [];
|
||||
let tagPrefix = this.tagPrefix;
|
||||
|
||||
for (let dep of dependencyMap) {
|
||||
if (!dep.startsWith(tagPrefix)) {
|
||||
orderedMap.push(dep);
|
||||
}
|
||||
}
|
||||
for (let dep of delayedDependencyMap) {
|
||||
if (!dep.startsWith(tagPrefix)) {
|
||||
orderedMap.push(dep);
|
||||
}
|
||||
}
|
||||
for (let dep of firstPaginatedDepMap) {
|
||||
if (!dep.startsWith(tagPrefix)) {
|
||||
orderedMap.push(dep);
|
||||
}
|
||||
}
|
||||
for (let dep of secondPaginatedDepMap) {
|
||||
if (!dep.startsWith(tagPrefix)) {
|
||||
orderedMap.push(dep);
|
||||
}
|
||||
}
|
||||
return orderedMap;
|
||||
}
|
||||
|
||||
async populateContentDataInMap(orderedMap) {
|
||||
let usedTemplateContentTooEarlyMap = [];
|
||||
for (let map of orderedMap) {
|
||||
if (!map._pages) {
|
||||
throw new Error(`Content pages not found for ${map.inputPath}`);
|
||||
}
|
||||
try {
|
||||
for (let pageEntry of map._pages) {
|
||||
pageEntry.templateContent = await map.template.getTemplateMapContent(
|
||||
pageEntry
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
if (EleventyErrorUtil.isPrematureTemplateContentError(e)) {
|
||||
usedTemplateContentTooEarlyMap.push(map);
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
debugDev(
|
||||
"Added this.map[...].templateContent, outputPath, et al for one map entry"
|
||||
);
|
||||
}
|
||||
|
||||
for (let map of usedTemplateContentTooEarlyMap) {
|
||||
try {
|
||||
for (let pageEntry of map._pages) {
|
||||
pageEntry.templateContent = await map.template.getTemplateMapContent(
|
||||
pageEntry
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
if (EleventyErrorUtil.isPrematureTemplateContentError(e)) {
|
||||
throw new UsingCircularTemplateContentReferenceError(
|
||||
`${map.inputPath} contains a circular reference (using collections) to its own templateContent.`
|
||||
);
|
||||
} else {
|
||||
// rethrow?
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_testGetAllTags() {
|
||||
let allTags = {};
|
||||
for (let map of this.map) {
|
||||
let tags = map.data.tags;
|
||||
if (Array.isArray(tags)) {
|
||||
for (let tag of tags) {
|
||||
allTags[tag] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return Object.keys(allTags);
|
||||
}
|
||||
|
||||
getTaggedCollection(tag) {
|
||||
let result;
|
||||
if (!tag || tag === "all") {
|
||||
result = this.collection.getAllSorted();
|
||||
} else {
|
||||
result = this.collection.getFilteredByTag(tag);
|
||||
}
|
||||
debug(`Collection: collections.${tag || "all"} size: ${result.length}`);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
async _testGetTaggedCollectionsData() {
|
||||
let collections = {};
|
||||
collections.all = this.collection.getAllSorted();
|
||||
debug(`Collection: collections.all size: ${collections.all.length}`);
|
||||
|
||||
let tags = this._testGetAllTags();
|
||||
for (let tag of tags) {
|
||||
collections[tag] = this.collection.getFilteredByTag(tag);
|
||||
debug(`Collection: collections.${tag} size: ${collections[tag].length}`);
|
||||
}
|
||||
return collections;
|
||||
}
|
||||
|
||||
setUserConfigCollections(configCollections) {
|
||||
return (this.configCollections = configCollections);
|
||||
}
|
||||
|
||||
isUserConfigCollectionName(name) {
|
||||
let collections = this.configCollections || eleventyConfig.getCollections();
|
||||
return name && !!collections[name];
|
||||
}
|
||||
|
||||
getUserConfigCollectionNames() {
|
||||
return Object.keys(
|
||||
this.configCollections || eleventyConfig.getCollections()
|
||||
);
|
||||
}
|
||||
|
||||
async getUserConfigCollection(name) {
|
||||
let configCollections =
|
||||
this.configCollections || eleventyConfig.getCollections();
|
||||
|
||||
// This works with async now
|
||||
let result = await configCollections[name](this.collection);
|
||||
|
||||
debug(`Collection: collections.${name} size: ${result.length}`);
|
||||
return result;
|
||||
}
|
||||
|
||||
async _testGetUserConfigCollectionsData() {
|
||||
let collections = {};
|
||||
let configCollections =
|
||||
this.configCollections || eleventyConfig.getCollections();
|
||||
|
||||
for (let name in configCollections) {
|
||||
collections[name] = configCollections[name](this.collection);
|
||||
|
||||
debug(
|
||||
`Collection: collections.${name} size: ${collections[name].length}`
|
||||
);
|
||||
}
|
||||
|
||||
return collections;
|
||||
}
|
||||
|
||||
async _testGetAllCollectionsData() {
|
||||
let collections = {};
|
||||
let taggedCollections = await this._testGetTaggedCollectionsData();
|
||||
Object.assign(collections, taggedCollections);
|
||||
|
||||
let userConfigCollections = await this._testGetUserConfigCollectionsData();
|
||||
Object.assign(collections, userConfigCollections);
|
||||
|
||||
return collections;
|
||||
}
|
||||
|
||||
populateCollectionsWithContent() {
|
||||
for (let collectionName in this.collectionsData) {
|
||||
if (!Array.isArray(this.collectionsData[collectionName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (let item of this.collectionsData[collectionName]) {
|
||||
if (!isPlainObject(item) || !("inputPath" in item)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let entry = this.getMapEntryForInputPath(item.inputPath);
|
||||
let index = item.pageNumber || 0;
|
||||
item.templateContent = entry._pages[index]._templateContent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
checkForDuplicatePermalinks() {
|
||||
let permalinks = {};
|
||||
let warnings = {};
|
||||
for (let entry of this.map) {
|
||||
for (let page of entry._pages) {
|
||||
if (page.url === false) {
|
||||
// do nothing
|
||||
} else if (!permalinks[page.url]) {
|
||||
permalinks[page.url] = [entry.inputPath];
|
||||
} else {
|
||||
warnings[
|
||||
page.outputPath
|
||||
] = `Output conflict: multiple input files are writing to \`${
|
||||
page.outputPath
|
||||
}\`. Use distinct \`permalink\` values to resolve this conflict.
|
||||
1. ${entry.inputPath}
|
||||
${permalinks[page.url]
|
||||
.map(function(inputPath, index) {
|
||||
return ` ${index + 2}. ${inputPath}\n`;
|
||||
})
|
||||
.join("")}
|
||||
`;
|
||||
|
||||
permalinks[page.url].push(entry.inputPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let warningList = Object.values(warnings);
|
||||
if (warningList.length) {
|
||||
// throw one at a time
|
||||
throw new DuplicatePermalinkOutputError(warningList[0]);
|
||||
}
|
||||
}
|
||||
|
||||
async getCollectionsData() {
|
||||
if (!this.cached) {
|
||||
await this.cache();
|
||||
}
|
||||
|
||||
return this.collectionsData;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = TemplateMap;
|
118
node_modules/@11ty/eleventy/src/TemplatePassthrough.js
generated
vendored
Normal file
118
node_modules/@11ty/eleventy/src/TemplatePassthrough.js
generated
vendored
Normal file
@@ -0,0 +1,118 @@
|
||||
const copy = require("recursive-copy");
|
||||
const fs = require("fs");
|
||||
const TemplatePath = require("./TemplatePath");
|
||||
const debug = require("debug")("Eleventy:TemplatePassthrough");
|
||||
const fastglob = require("fast-glob");
|
||||
const EleventyBaseError = require("./EleventyBaseError");
|
||||
|
||||
class TemplatePassthroughError extends EleventyBaseError {}
|
||||
|
||||
class TemplatePassthrough {
|
||||
constructor(path, outputDir, inputDir) {
|
||||
// inputPath is relative to the root of your project and not your Eleventy input directory.
|
||||
this.inputPath = path.inputPath;
|
||||
// inputDir is only used when stripping from output path in `getOutputPath`
|
||||
this.inputDir = inputDir;
|
||||
|
||||
this.outputPath = path.outputPath;
|
||||
this.outputDir = outputDir;
|
||||
|
||||
this.isDryRun = false;
|
||||
}
|
||||
|
||||
getOutputPath(inputFileFromGlob) {
|
||||
const { inputDir, outputDir, outputPath, inputPath } = this;
|
||||
|
||||
if (outputPath === true) {
|
||||
return TemplatePath.normalize(
|
||||
TemplatePath.join(
|
||||
outputDir,
|
||||
TemplatePath.stripLeadingSubPath(
|
||||
inputFileFromGlob || inputPath,
|
||||
inputDir
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (inputFileFromGlob) {
|
||||
return this.getOutputPathForGlobFile(inputFileFromGlob);
|
||||
}
|
||||
|
||||
return TemplatePath.normalize(TemplatePath.join(outputDir, outputPath));
|
||||
}
|
||||
|
||||
getOutputPathForGlobFile(inputFileFromGlob) {
|
||||
return TemplatePath.join(
|
||||
this.getOutputPath(),
|
||||
TemplatePath.getLastPathSegment(inputFileFromGlob)
|
||||
);
|
||||
}
|
||||
|
||||
setDryRun(isDryRun) {
|
||||
this.isDryRun = !!isDryRun;
|
||||
}
|
||||
|
||||
async getFiles(glob) {
|
||||
debug("Searching for: %o", glob);
|
||||
const files = TemplatePath.addLeadingDotSlashArray(
|
||||
await fastglob(glob, {
|
||||
caseSensitiveMatch: false,
|
||||
dot: true
|
||||
})
|
||||
);
|
||||
return files;
|
||||
}
|
||||
|
||||
copy(src, dest, copyOptions) {
|
||||
if (
|
||||
TemplatePath.stripLeadingDotSlash(dest).includes(
|
||||
TemplatePath.stripLeadingDotSlash(this.outputDir)
|
||||
)
|
||||
) {
|
||||
return copy(src, dest, copyOptions);
|
||||
}
|
||||
return Promise.reject(
|
||||
new TemplatePassthroughError(
|
||||
"Destination is not in the site output directory. Check your passthrough paths."
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
async write() {
|
||||
const copyOptions = {
|
||||
overwrite: true,
|
||||
dot: true,
|
||||
junk: false,
|
||||
results: false
|
||||
};
|
||||
|
||||
if (!this.isDryRun) {
|
||||
debug("Copying %o", this.inputPath);
|
||||
const isDirectory = TemplatePath.isDirectorySync(this.inputPath);
|
||||
const isFile = fs.existsSync(this.inputPath);
|
||||
|
||||
// If directory or file, recursive copy
|
||||
if (isDirectory || isFile) {
|
||||
// IMPORTANT: this returns a promise, does not await for promise to finish
|
||||
return this.copy(this.inputPath, this.getOutputPath(), copyOptions);
|
||||
}
|
||||
|
||||
// If not directory or file, attempt to get globs
|
||||
const files = await this.getFiles(this.inputPath);
|
||||
|
||||
const promises = files.map(inputFile =>
|
||||
this.copy(inputFile, this.getOutputPath(inputFile), copyOptions)
|
||||
);
|
||||
|
||||
return Promise.all(promises).catch(err => {
|
||||
throw new TemplatePassthroughError(
|
||||
`Error copying passthrough files: ${err.message}`,
|
||||
err
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = TemplatePassthrough;
|
141
node_modules/@11ty/eleventy/src/TemplatePassthroughManager.js
generated
vendored
Normal file
141
node_modules/@11ty/eleventy/src/TemplatePassthroughManager.js
generated
vendored
Normal file
@@ -0,0 +1,141 @@
|
||||
const config = require("./Config");
|
||||
const EleventyBaseError = require("./EleventyBaseError");
|
||||
const TemplatePassthrough = require("./TemplatePassthrough");
|
||||
const TemplateRender = require("./TemplateRender");
|
||||
const TemplatePath = require("./TemplatePath");
|
||||
const debug = require("debug")("Eleventy:TemplatePassthroughManager");
|
||||
|
||||
class TemplatePassthroughManagerCopyError extends EleventyBaseError {}
|
||||
|
||||
class TemplatePassthroughManager {
|
||||
constructor() {
|
||||
this.config = config.getConfig();
|
||||
this.reset();
|
||||
}
|
||||
|
||||
reset() {
|
||||
this.count = 0;
|
||||
debug("Resetting counts to 0");
|
||||
}
|
||||
|
||||
setConfig(configOverride) {
|
||||
this.config = configOverride || {};
|
||||
}
|
||||
|
||||
setOutputDir(outputDir) {
|
||||
this.outputDir = outputDir;
|
||||
}
|
||||
|
||||
setInputDir(inputDir) {
|
||||
this.inputDir = inputDir;
|
||||
}
|
||||
|
||||
setDryRun(isDryRun) {
|
||||
this.isDryRun = !!isDryRun;
|
||||
}
|
||||
|
||||
_normalizePaths(path, outputPath) {
|
||||
return {
|
||||
inputPath: TemplatePath.addLeadingDotSlash(path),
|
||||
outputPath: outputPath
|
||||
? TemplatePath.stripLeadingDotSlash(outputPath)
|
||||
: true
|
||||
};
|
||||
}
|
||||
|
||||
getConfigPaths() {
|
||||
if (!this.config.passthroughFileCopy) {
|
||||
debug("`passthroughFileCopy` is disabled in config, bypassing.");
|
||||
return [];
|
||||
}
|
||||
|
||||
let paths = [];
|
||||
let target = this.config.passthroughCopies || {};
|
||||
debug("`passthroughFileCopy` config paths: %o", target);
|
||||
for (let path in target) {
|
||||
paths.push(this._normalizePaths(path, target[path]));
|
||||
}
|
||||
debug("`passthroughFileCopy` config normalized paths: %o", paths);
|
||||
return paths;
|
||||
}
|
||||
|
||||
getConfigPathGlobs() {
|
||||
return this.getConfigPaths().map(path => {
|
||||
return TemplatePath.convertToRecursiveGlob(path.inputPath);
|
||||
});
|
||||
}
|
||||
|
||||
getFilePaths(paths) {
|
||||
if (!this.config.passthroughFileCopy) {
|
||||
debug("`passthroughFileCopy` is disabled in config, bypassing.");
|
||||
return [];
|
||||
}
|
||||
|
||||
let matches = [];
|
||||
for (let path of paths) {
|
||||
if (!TemplateRender.hasEngine(path)) {
|
||||
matches.push(path);
|
||||
}
|
||||
}
|
||||
|
||||
return matches;
|
||||
}
|
||||
|
||||
getCopyCount() {
|
||||
return this.count;
|
||||
}
|
||||
|
||||
async copyPath(path) {
|
||||
let pass = new TemplatePassthrough(path, this.outputDir, this.inputDir);
|
||||
pass.setDryRun(this.isDryRun);
|
||||
|
||||
return pass
|
||||
.write()
|
||||
.then(
|
||||
function() {
|
||||
this.count++;
|
||||
debug("Copied %o", path.inputPath);
|
||||
}.bind(this)
|
||||
)
|
||||
.catch(function(e) {
|
||||
return Promise.reject(
|
||||
new TemplatePassthroughManagerCopyError(
|
||||
`Having trouble copying '${path.inputPath}'`,
|
||||
e
|
||||
)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// Performance note: these can actually take a fair bit of time, but aren’t a
|
||||
// bottleneck to eleventy. The copies are performed asynchronously and don’t affect eleventy
|
||||
// write times in a significant way.
|
||||
async copyAll(paths) {
|
||||
if (!this.config.passthroughFileCopy) {
|
||||
debug("`passthroughFileCopy` is disabled in config, bypassing.");
|
||||
return;
|
||||
}
|
||||
|
||||
let promises = [];
|
||||
debug("TemplatePassthrough copy started.");
|
||||
for (let path of this.getConfigPaths()) {
|
||||
debug(`TemplatePassthrough copying from config: ${path}`);
|
||||
promises.push(this.copyPath(path));
|
||||
}
|
||||
|
||||
let passthroughPaths = this.getFilePaths(paths);
|
||||
for (let path of passthroughPaths) {
|
||||
let normalizedPath = this._normalizePaths(path);
|
||||
debug(
|
||||
`TemplatePassthrough copying from non-matching file extension: ${normalizedPath}`
|
||||
);
|
||||
promises.push(this.copyPath(normalizedPath));
|
||||
}
|
||||
|
||||
return Promise.all(promises).then(() => {
|
||||
debug(`TemplatePassthrough copy finished. Current count: ${this.count}`);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = TemplatePassthroughManager;
|
285
node_modules/@11ty/eleventy/src/TemplatePath.js
generated
vendored
Normal file
285
node_modules/@11ty/eleventy/src/TemplatePath.js
generated
vendored
Normal file
@@ -0,0 +1,285 @@
|
||||
const path = require("path");
|
||||
const normalize = require("normalize-path");
|
||||
const parsePath = require("parse-filepath");
|
||||
const fs = require("fs-extra");
|
||||
|
||||
function TemplatePath() {}
|
||||
|
||||
/**
|
||||
* @returns {String} the absolute path to Eleventy’s project directory.
|
||||
*/
|
||||
TemplatePath.getWorkingDir = function() {
|
||||
return TemplatePath.normalize(path.resolve("."));
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the directory portion of a path.
|
||||
* Works for directory and file paths and paths ending in a glob pattern.
|
||||
*
|
||||
* @param {String} path A path
|
||||
* @returns {String} the directory portion of a path.
|
||||
*/
|
||||
TemplatePath.getDir = function(path) {
|
||||
if (TemplatePath.isDirectorySync(path)) {
|
||||
return path;
|
||||
}
|
||||
|
||||
return TemplatePath.getDirFromFilePath(path);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the directory portion of a path that either points to a file
|
||||
* or ends in a glob pattern. If `path` points to a directory,
|
||||
* the returned value will have its last path segment stripped
|
||||
* due to how [`parsePath`][1] works.
|
||||
*
|
||||
* [1]: https://www.npmjs.com/package/parse-filepath
|
||||
*
|
||||
* @param {String} path A path
|
||||
* @returns {String} the directory portion of a path.
|
||||
*/
|
||||
TemplatePath.getDirFromFilePath = function(path) {
|
||||
return parsePath(path).dir || ".";
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the last path segment in a path (no leading/trailing slashes).
|
||||
*
|
||||
* Assumes [`parsePath`][1] was called on `path` before.
|
||||
*
|
||||
* [1]: https://www.npmjs.com/package/parse-filepath
|
||||
*
|
||||
* @param {String} path A path
|
||||
* @returns {String} the last path segment in a path
|
||||
*/
|
||||
TemplatePath.getLastPathSegment = function(path) {
|
||||
if (!path.includes("/")) {
|
||||
return path;
|
||||
}
|
||||
|
||||
// Trim a trailing slash if there is one
|
||||
path = path.replace(/\/$/, "");
|
||||
|
||||
return path.substr(path.lastIndexOf("/") + 1);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {String} path A path
|
||||
* @returns {String[]} an array of paths pointing to each path segment of the
|
||||
* provided `path`.
|
||||
*/
|
||||
TemplatePath.getAllDirs = function(path) {
|
||||
// Trim a trailing slash if there is one
|
||||
path = path.replace(/\/$/, "");
|
||||
|
||||
if (!path.includes("/")) {
|
||||
return [path];
|
||||
}
|
||||
|
||||
return path
|
||||
.split("/")
|
||||
.map((segment, index, array) => array.slice(0, index + 1).join("/"))
|
||||
.filter(path => path !== ".")
|
||||
.reverse();
|
||||
};
|
||||
|
||||
/**
|
||||
* Normalizes a path, resolving single-dot and double-dot segments.
|
||||
*
|
||||
* Node.js’ [`path.normalize`][1] is called to strip a possible leading `"./"` segment.
|
||||
*
|
||||
* [1]: https://nodejs.org/api/path.html#path_path_normalize_path
|
||||
*
|
||||
* @param {String} thePath The path that should be normalized.
|
||||
* @returns {String} the normalized path.
|
||||
*/
|
||||
TemplatePath.normalize = function(thePath) {
|
||||
return normalize(path.normalize(thePath));
|
||||
};
|
||||
|
||||
/**
|
||||
* Joins all given path segments together.
|
||||
*
|
||||
* It uses Node.js’ [`path.join`][1] method and the [normalize-path][2] package.
|
||||
*
|
||||
* [1]: https://nodejs.org/api/path.html#path_path_join_paths
|
||||
* [2]: https://www.npmjs.com/package/normalize-path
|
||||
*
|
||||
* @param {String[]} paths An arbitrary amount of path segments.
|
||||
* @returns {String} the normalized and joined path.
|
||||
*/
|
||||
TemplatePath.join = function(...paths) {
|
||||
return normalize(path.join(...paths));
|
||||
};
|
||||
|
||||
/**
|
||||
* Joins the given URL path segments and normalizes the resulting path.
|
||||
* Maintains traling a single trailing slash if the last URL path argument
|
||||
* had atleast one.
|
||||
*
|
||||
* @param {String[]} urlPaths
|
||||
* @returns {String} a normalized URL path described by the given URL path segments.
|
||||
*/
|
||||
TemplatePath.normalizeUrlPath = function(...urlPaths) {
|
||||
const urlPath = path.posix.join(...urlPaths);
|
||||
return urlPath.replace(/\/+$/, "/");
|
||||
};
|
||||
|
||||
/**
|
||||
* Joins the given path segments. Since the first path is absolute,
|
||||
* the resulting path will be absolute as well.
|
||||
*
|
||||
* @param {String[]} paths
|
||||
* @returns {String} the absolute path described by the given path segments.
|
||||
*/
|
||||
TemplatePath.absolutePath = function(...paths) {
|
||||
return TemplatePath.join(TemplatePath.getWorkingDir(), ...paths);
|
||||
};
|
||||
|
||||
/**
|
||||
* Turns an absolute path into a path relative Eleventy’s project directory.
|
||||
*
|
||||
* @param {String} absolutePath
|
||||
* @returns {String} the relative path.
|
||||
*/
|
||||
TemplatePath.relativePath = function(absolutePath) {
|
||||
return TemplatePath.stripLeadingSubPath(
|
||||
absolutePath,
|
||||
TemplatePath.getWorkingDir()
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds a leading dot-slash segment to each path in the `paths` array.
|
||||
*
|
||||
* @param {String[]} paths
|
||||
* @returns {String[]}
|
||||
*/
|
||||
TemplatePath.addLeadingDotSlashArray = function(paths) {
|
||||
return paths.map(path => TemplatePath.addLeadingDotSlash(path));
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds a leading dot-slash segment to `path`.
|
||||
*
|
||||
* @param {String} path
|
||||
* @returns {String}
|
||||
*/
|
||||
TemplatePath.addLeadingDotSlash = function(path) {
|
||||
if (path === "." || path === "..") {
|
||||
return path + "/";
|
||||
}
|
||||
|
||||
if (path.startsWith("/") || path.startsWith("./") || path.startsWith("../")) {
|
||||
return path;
|
||||
}
|
||||
|
||||
return "./" + path;
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes a leading dot-slash segment.
|
||||
*
|
||||
* @param {String} path
|
||||
* @returns {String} the `path` without a leading dot-slash segment.
|
||||
*/
|
||||
TemplatePath.stripLeadingDotSlash = function(path) {
|
||||
return typeof path === "string" ? path.replace(/^\.\//, "") : path;
|
||||
};
|
||||
|
||||
/**
|
||||
* Determines whether a path starts with a given sub path.
|
||||
*
|
||||
* @param {String} path A path
|
||||
* @param {String} subPath A path
|
||||
* @returns {Boolean} whether `path` starts with `subPath`.
|
||||
*/
|
||||
TemplatePath.startsWithSubPath = function(path, subPath) {
|
||||
path = TemplatePath.normalize(path);
|
||||
subPath = TemplatePath.normalize(subPath);
|
||||
|
||||
return path.startsWith(subPath);
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes the `subPath` at the start of `path` if present
|
||||
* and returns the remainding path.
|
||||
*
|
||||
* @param {String} path A path
|
||||
* @param {String} subPath A path
|
||||
* @returns {String} the `path` without `subPath` at the start of it.
|
||||
*/
|
||||
TemplatePath.stripLeadingSubPath = function(path, subPath) {
|
||||
path = TemplatePath.normalize(path);
|
||||
subPath = TemplatePath.normalize(subPath);
|
||||
|
||||
if (subPath !== "." && path.startsWith(subPath)) {
|
||||
return path.substr(subPath.length + 1);
|
||||
}
|
||||
|
||||
return path;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {String} path A path
|
||||
* @returns {Boolean} whether `path` points to an existing directory.
|
||||
*/
|
||||
TemplatePath.isDirectorySync = function(path) {
|
||||
return fs.existsSync(path) && fs.statSync(path).isDirectory();
|
||||
};
|
||||
|
||||
/**
|
||||
* Appends a recursive wildcard glob pattern to `path`
|
||||
* unless `path` is not a directory; then, `path` is assumed to be a file path
|
||||
* and is left unchaged.
|
||||
*
|
||||
* @param {String} path
|
||||
* @returns {String}
|
||||
*/
|
||||
TemplatePath.convertToRecursiveGlob = function(path) {
|
||||
if (path === "") {
|
||||
return "./**";
|
||||
}
|
||||
|
||||
path = TemplatePath.addLeadingDotSlash(path);
|
||||
|
||||
if (TemplatePath.isDirectorySync(path)) {
|
||||
return path + (!path.endsWith("/") ? "/" : "") + "**";
|
||||
}
|
||||
|
||||
return path;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the extension of the path without the leading dot.
|
||||
* If the path has no extensions, the empty string is returned.
|
||||
*
|
||||
* @param {String} thePath
|
||||
* @returns {String} the path’s extension if it exists;
|
||||
* otherwise, the empty string.
|
||||
*/
|
||||
TemplatePath.getExtension = function(thePath) {
|
||||
return path.extname(thePath).replace(/^\./, "");
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes the extension from a path.
|
||||
*
|
||||
* @param {String} path
|
||||
* @param {String} extension
|
||||
* @returns {String}
|
||||
*/
|
||||
TemplatePath.removeExtension = function(path, extension = undefined) {
|
||||
if (extension === undefined) {
|
||||
return path;
|
||||
}
|
||||
|
||||
const pathExtension = TemplatePath.getExtension(path);
|
||||
if (pathExtension !== "" && extension.endsWith(pathExtension)) {
|
||||
return path.substring(0, path.lastIndexOf(pathExtension) - 1);
|
||||
}
|
||||
|
||||
return path;
|
||||
};
|
||||
|
||||
module.exports = TemplatePath;
|
58
node_modules/@11ty/eleventy/src/TemplatePermalink.js
generated
vendored
Normal file
58
node_modules/@11ty/eleventy/src/TemplatePermalink.js
generated
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
const parsePath = require("parse-filepath");
|
||||
const TemplatePath = require("./TemplatePath");
|
||||
|
||||
function TemplatePermalink(link, extraSubdir) {
|
||||
this.link = this._cleanLink(link);
|
||||
this.extraSubdir = extraSubdir || "";
|
||||
}
|
||||
|
||||
TemplatePermalink.prototype._cleanLink = function(link) {
|
||||
return link + (link.substr(-1) === "/" ? "index.html" : "");
|
||||
};
|
||||
|
||||
TemplatePermalink.prototype.resolve = function() {
|
||||
let parsed = parsePath(this.link);
|
||||
|
||||
return TemplatePath.join(parsed.dir, this.extraSubdir, parsed.base);
|
||||
};
|
||||
|
||||
TemplatePermalink.prototype.toString = function() {
|
||||
return this.resolve();
|
||||
};
|
||||
|
||||
// remove all index.html’s from links
|
||||
// index.html becomes /
|
||||
// test/index.html becomes test/
|
||||
TemplatePermalink.prototype.toHref = function() {
|
||||
let str = this.toString();
|
||||
let original = (str.charAt(0) !== "/" ? "/" : "") + this.toString();
|
||||
let needle = "/index.html";
|
||||
if (original === needle) {
|
||||
return "/";
|
||||
} else if (original.substr(-1 * needle.length) === needle) {
|
||||
return original.substr(0, original.length - needle.length) + "/";
|
||||
}
|
||||
return original;
|
||||
};
|
||||
|
||||
TemplatePermalink._hasDuplicateFolder = function(dir, base) {
|
||||
let folders = dir.split("/");
|
||||
if (!folders[folders.length - 1]) {
|
||||
folders.pop();
|
||||
}
|
||||
return folders[folders.length - 1] === base;
|
||||
};
|
||||
|
||||
TemplatePermalink.generate = function(dir, filenameNoExt, extraSubdir, suffix) {
|
||||
let hasDupeFolder = TemplatePermalink._hasDuplicateFolder(dir, filenameNoExt);
|
||||
let path =
|
||||
(dir ? dir + "/" : "") +
|
||||
(filenameNoExt !== "index" && !hasDupeFolder ? filenameNoExt + "/" : "") +
|
||||
"index" +
|
||||
(suffix || "") +
|
||||
".html";
|
||||
|
||||
return new TemplatePermalink(path, extraSubdir);
|
||||
};
|
||||
|
||||
module.exports = TemplatePermalink;
|
11
node_modules/@11ty/eleventy/src/TemplatePermalinkNoWrite.js
generated
vendored
Normal file
11
node_modules/@11ty/eleventy/src/TemplatePermalinkNoWrite.js
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
class TemplatePermalinkNoWrite {
|
||||
toString() {
|
||||
return false;
|
||||
}
|
||||
|
||||
toHref() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = TemplatePermalinkNoWrite;
|
206
node_modules/@11ty/eleventy/src/TemplateRender.js
generated
vendored
Normal file
206
node_modules/@11ty/eleventy/src/TemplateRender.js
generated
vendored
Normal file
@@ -0,0 +1,206 @@
|
||||
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;
|
220
node_modules/@11ty/eleventy/src/TemplateWriter.js
generated
vendored
Normal file
220
node_modules/@11ty/eleventy/src/TemplateWriter.js
generated
vendored
Normal file
@@ -0,0 +1,220 @@
|
||||
const Template = require("./Template");
|
||||
const TemplatePath = require("./TemplatePath");
|
||||
const TemplateMap = require("./TemplateMap");
|
||||
const TemplateRender = require("./TemplateRender");
|
||||
const EleventyFiles = require("./EleventyFiles");
|
||||
const EleventyBaseError = require("./EleventyBaseError");
|
||||
const EleventyErrorHandler = require("./EleventyErrorHandler");
|
||||
const EleventyErrorUtil = require("./EleventyErrorUtil");
|
||||
|
||||
const config = require("./Config");
|
||||
const debug = require("debug")("Eleventy:TemplateWriter");
|
||||
const debugDev = require("debug")("Dev:Eleventy:TemplateWriter");
|
||||
|
||||
class TemplateWriterWriteError extends EleventyBaseError {}
|
||||
|
||||
function TemplateWriter(
|
||||
inputPath,
|
||||
outputDir,
|
||||
templateFormats, // TODO remove this, see `.getFileManager()` first
|
||||
templateData,
|
||||
isPassthroughAll
|
||||
) {
|
||||
this.config = config.getConfig();
|
||||
this.input = inputPath;
|
||||
this.inputDir = TemplatePath.getDir(inputPath);
|
||||
this.outputDir = outputDir;
|
||||
this.templateFormats = templateFormats;
|
||||
this.templateData = templateData;
|
||||
this.isVerbose = true;
|
||||
this.isDryRun = false;
|
||||
this.writeCount = 0;
|
||||
|
||||
// TODO can we get rid of this? It’s only used for tests in getFileManager()
|
||||
this.passthroughAll = isPassthroughAll;
|
||||
}
|
||||
|
||||
/* For testing */
|
||||
TemplateWriter.prototype.overrideConfig = function(config) {
|
||||
this.config = config;
|
||||
};
|
||||
|
||||
TemplateWriter.prototype.restart = function() {
|
||||
this.writeCount = 0;
|
||||
debugDev("Resetting counts to 0");
|
||||
};
|
||||
|
||||
TemplateWriter.prototype.setEleventyFiles = function(eleventyFiles) {
|
||||
this.eleventyFiles = eleventyFiles;
|
||||
};
|
||||
|
||||
TemplateWriter.prototype.getFileManager = function() {
|
||||
// usually Eleventy.js will setEleventyFiles with the EleventyFiles manager
|
||||
if (!this.eleventyFiles) {
|
||||
// if not, we can create one (used only by tests)
|
||||
this.eleventyFiles = new EleventyFiles(
|
||||
this.input,
|
||||
this.outputDir,
|
||||
this.templateFormats,
|
||||
this.passthroughAll
|
||||
);
|
||||
this.eleventyFiles.init();
|
||||
}
|
||||
|
||||
return this.eleventyFiles;
|
||||
};
|
||||
|
||||
TemplateWriter.prototype._getAllPaths = async function() {
|
||||
return await this.getFileManager().getFiles();
|
||||
};
|
||||
|
||||
TemplateWriter.prototype._createTemplate = function(path) {
|
||||
let tmpl = new Template(
|
||||
path,
|
||||
this.inputDir,
|
||||
this.outputDir,
|
||||
this.templateData
|
||||
);
|
||||
|
||||
tmpl.setIsVerbose(this.isVerbose);
|
||||
tmpl.setDryRun(this.isDryRun);
|
||||
|
||||
/*
|
||||
* Sample filter: arg str, return pretty HTML string
|
||||
* function(str) {
|
||||
* return pretty(str, { ocd: true });
|
||||
* }
|
||||
*/
|
||||
for (let transformName in this.config.filters) {
|
||||
let transform = this.config.filters[transformName];
|
||||
if (typeof transform === "function") {
|
||||
tmpl.addTransform(transform);
|
||||
}
|
||||
}
|
||||
|
||||
for (let linterName in this.config.linters) {
|
||||
let linter = this.config.linters[linterName];
|
||||
if (typeof linter === "function") {
|
||||
tmpl.addLinter(linter);
|
||||
}
|
||||
}
|
||||
|
||||
return tmpl;
|
||||
};
|
||||
|
||||
TemplateWriter.prototype._addToTemplateMap = async function(paths) {
|
||||
let promises = [];
|
||||
for (let path of paths) {
|
||||
if (TemplateRender.hasEngine(path)) {
|
||||
promises.push(
|
||||
this.templateMap.add(this._createTemplate(path)).then(() => {
|
||||
debug(`${path} added to map.`);
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return Promise.all(promises);
|
||||
};
|
||||
|
||||
TemplateWriter.prototype._createTemplateMap = async function(paths) {
|
||||
this.templateMap = new TemplateMap();
|
||||
|
||||
await this._addToTemplateMap(paths);
|
||||
await this.templateMap.cache();
|
||||
|
||||
debugDev("TemplateMap cache complete.");
|
||||
return this.templateMap;
|
||||
};
|
||||
|
||||
TemplateWriter.prototype._writeTemplate = async function(mapEntry) {
|
||||
let tmpl = mapEntry.template;
|
||||
// we don’t re-use the map templateContent because it doesn’t include layouts
|
||||
return tmpl.writeMapEntry(mapEntry).then(() => {
|
||||
this.writeCount += tmpl.getWriteCount();
|
||||
});
|
||||
};
|
||||
|
||||
TemplateWriter.prototype.write = async function() {
|
||||
let promises = [];
|
||||
let paths = await this._getAllPaths();
|
||||
debug("Found: %o", paths);
|
||||
promises.push(
|
||||
this.getFileManager()
|
||||
.getPassthroughManager()
|
||||
.copyAll(paths)
|
||||
.catch(e => {
|
||||
EleventyErrorHandler.warn(e, "Error with passthrough copy");
|
||||
return Promise.reject(
|
||||
new TemplateWriterWriteError(`Having trouble copying`, e)
|
||||
);
|
||||
})
|
||||
);
|
||||
|
||||
// TODO optimize await here
|
||||
await this._createTemplateMap(paths);
|
||||
debug("Template map created.");
|
||||
|
||||
let mapEntry;
|
||||
let usedTemplateContentTooEarlyMap = [];
|
||||
for (mapEntry of this.templateMap.getMap()) {
|
||||
promises.push(
|
||||
this._writeTemplate(mapEntry).catch(function(e) {
|
||||
// Premature templateContent in layout render, this also happens in
|
||||
// TemplateMap.populateContentDataInMap for non-layout content
|
||||
if (EleventyErrorUtil.isPrematureTemplateContentError(e)) {
|
||||
usedTemplateContentTooEarlyMap.push(mapEntry);
|
||||
} else {
|
||||
return Promise.reject(
|
||||
new TemplateWriterWriteError(
|
||||
`Having trouble writing template: ${mapEntry.outputPath}`,
|
||||
e
|
||||
)
|
||||
);
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
for (mapEntry of usedTemplateContentTooEarlyMap) {
|
||||
promises.push(
|
||||
this._writeTemplate(mapEntry).catch(function(e) {
|
||||
return Promise.reject(
|
||||
new TemplateWriterWriteError(
|
||||
`Having trouble writing template (second pass): ${mapEntry.outputPath}`,
|
||||
e
|
||||
)
|
||||
);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
return Promise.all(promises).catch(e => {
|
||||
EleventyErrorHandler.error(e, "Error writing templates");
|
||||
throw e;
|
||||
});
|
||||
};
|
||||
|
||||
TemplateWriter.prototype.setVerboseOutput = function(isVerbose) {
|
||||
this.isVerbose = isVerbose;
|
||||
};
|
||||
|
||||
TemplateWriter.prototype.setDryRun = function(isDryRun) {
|
||||
this.isDryRun = !!isDryRun;
|
||||
|
||||
this.getFileManager()
|
||||
.getPassthroughManager()
|
||||
.setDryRun(this.isDryRun);
|
||||
};
|
||||
|
||||
TemplateWriter.prototype.getCopyCount = function() {
|
||||
return this.getFileManager()
|
||||
.getPassthroughManager()
|
||||
.getCopyCount();
|
||||
};
|
||||
|
||||
TemplateWriter.prototype.getWriteCount = function() {
|
||||
return this.writeCount;
|
||||
};
|
||||
|
||||
module.exports = TemplateWriter;
|
545
node_modules/@11ty/eleventy/src/UserConfig.js
generated
vendored
Normal file
545
node_modules/@11ty/eleventy/src/UserConfig.js
generated
vendored
Normal file
@@ -0,0 +1,545 @@
|
||||
const EventEmitter = require("events");
|
||||
const chalk = require("chalk");
|
||||
const semver = require("semver");
|
||||
const { DateTime } = require("luxon");
|
||||
const EleventyBaseError = require("./EleventyBaseError");
|
||||
const bench = require("./BenchmarkManager").get("Configuration");
|
||||
const debug = require("debug")("Eleventy:UserConfig");
|
||||
const pkg = require("../package.json");
|
||||
|
||||
class UserConfigError extends EleventyBaseError {}
|
||||
|
||||
// API to expose configuration options in config file
|
||||
class UserConfig {
|
||||
constructor() {
|
||||
this.reset();
|
||||
}
|
||||
|
||||
reset() {
|
||||
debug("Resetting EleventyConfig to initial values.");
|
||||
this.events = new EventEmitter();
|
||||
this.collections = {};
|
||||
|
||||
this.liquidOptions = {};
|
||||
this.liquidTags = {};
|
||||
this.liquidFilters = {};
|
||||
this.liquidShortcodes = {};
|
||||
this.liquidPairedShortcodes = {};
|
||||
this.nunjucksFilters = {};
|
||||
this.nunjucksAsyncFilters = {};
|
||||
this.nunjucksTags = {};
|
||||
this.nunjucksShortcodes = {};
|
||||
this.nunjucksPairedShortcodes = {};
|
||||
this.handlebarsHelpers = {};
|
||||
this.handlebarsShortcodes = {};
|
||||
this.handlebarsPairedShortcodes = {};
|
||||
this.javascriptFunctions = {};
|
||||
this.pugOptions = {};
|
||||
this.ejsOptions = {};
|
||||
this.markdownHighlighter = null;
|
||||
this.libraryOverrides = {};
|
||||
|
||||
this.passthroughCopies = {};
|
||||
this.layoutAliases = {};
|
||||
this.linters = {};
|
||||
// now named `transforms` in API
|
||||
this.filters = {};
|
||||
this.activeNamespace = "";
|
||||
this.DateTime = DateTime;
|
||||
this.dynamicPermalinks = true;
|
||||
this.useGitIgnore = true;
|
||||
this.dataDeepMerge = false;
|
||||
this.experiments = new Set();
|
||||
// this.userExtensionMap = {};
|
||||
// this.templateExtensionAliases = {};
|
||||
this.watchJavaScriptDependencies = true;
|
||||
this.browserSyncConfig = {};
|
||||
}
|
||||
|
||||
versionCheck(expected) {
|
||||
if (!semver.satisfies(pkg.version, expected)) {
|
||||
throw new UserConfigError(
|
||||
`This project requires the eleventy version to match '${expected}' but found ${pkg.version}. Use \`npm update @11ty/eleventy -g\` to upgrade the eleventy global or \`npm update @11ty/eleventy --save\` to upgrade your local project version.`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
on(eventName, callback) {
|
||||
return this.events.on(eventName, callback);
|
||||
}
|
||||
|
||||
emit(eventName, ...args) {
|
||||
return this.events.emit(eventName, ...args);
|
||||
}
|
||||
|
||||
// This is a method for plugins, probably shouldn’t use this in projects.
|
||||
// Projects should use `setLibrary` as documented here:
|
||||
// https://github.com/11ty/eleventy/blob/master/docs/engines/markdown.md#use-your-own-options
|
||||
addMarkdownHighlighter(highlightFn) {
|
||||
this.markdownHighlighter = highlightFn;
|
||||
}
|
||||
|
||||
// tagCallback: function(liquidEngine) { return { parse: …, render: … }} };
|
||||
addLiquidTag(name, tagFn) {
|
||||
name = this.getNamespacedName(name);
|
||||
|
||||
if (typeof tagFn !== "function") {
|
||||
throw new UserConfigError(
|
||||
`EleventyConfig.addLiquidTag expects a callback function to be passed in for ${name}: addLiquidTag(name, function(liquidEngine) { return { parse: …, render: … } })`
|
||||
);
|
||||
}
|
||||
|
||||
if (this.liquidTags[name]) {
|
||||
debug(
|
||||
chalk.yellow(
|
||||
"Warning, overwriting a Liquid tag with `addLiquidTag(%o)`"
|
||||
),
|
||||
name
|
||||
);
|
||||
}
|
||||
this.liquidTags[name] = bench.add(`"${name}" Liquid Custom Tag`, tagFn);
|
||||
}
|
||||
|
||||
addLiquidFilter(name, callback) {
|
||||
name = this.getNamespacedName(name);
|
||||
|
||||
if (this.liquidFilters[name]) {
|
||||
debug(
|
||||
chalk.yellow(
|
||||
"Warning, overwriting a Liquid filter with `addLiquidFilter(%o)`"
|
||||
),
|
||||
name
|
||||
);
|
||||
}
|
||||
|
||||
this.liquidFilters[name] = bench.add(`"${name}" Liquid Filter`, callback);
|
||||
}
|
||||
|
||||
addNunjucksAsyncFilter(name, callback) {
|
||||
name = this.getNamespacedName(name);
|
||||
|
||||
if (this.nunjucksAsyncFilters[name]) {
|
||||
debug(
|
||||
chalk.yellow(
|
||||
"Warning, overwriting a Nunjucks filter with `addNunjucksAsyncFilter(%o)`"
|
||||
),
|
||||
name
|
||||
);
|
||||
}
|
||||
|
||||
this.nunjucksAsyncFilters[name] = bench.add(
|
||||
`"${name}" Nunjucks Async Filter`,
|
||||
callback
|
||||
);
|
||||
}
|
||||
|
||||
// Support the nunjucks style syntax for asynchronous filter add
|
||||
addNunjucksFilter(name, callback, isAsync) {
|
||||
if (isAsync) {
|
||||
// namespacing happens downstream
|
||||
this.addNunjucksAsyncFilter(name, callback);
|
||||
} else {
|
||||
name = this.getNamespacedName(name);
|
||||
|
||||
if (this.nunjucksFilters[name]) {
|
||||
debug(
|
||||
chalk.yellow(
|
||||
"Warning, overwriting a Nunjucks filter with `addNunjucksFilter(%o)`"
|
||||
),
|
||||
name
|
||||
);
|
||||
}
|
||||
|
||||
this.nunjucksFilters[name] = bench.add(
|
||||
`"${name}" Nunjucks Filter`,
|
||||
callback
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
addHandlebarsHelper(name, callback) {
|
||||
name = this.getNamespacedName(name);
|
||||
|
||||
if (this.handlebarsHelpers[name]) {
|
||||
debug(
|
||||
chalk.yellow(
|
||||
"Warning, overwriting a Handlebars helper with `addHandlebarsHelper(%o)`."
|
||||
),
|
||||
name
|
||||
);
|
||||
}
|
||||
|
||||
this.handlebarsHelpers[name] = bench.add(
|
||||
`"${name}" Handlebars Helper`,
|
||||
callback
|
||||
);
|
||||
}
|
||||
|
||||
addFilter(name, callback) {
|
||||
debug("Adding universal filter %o", this.getNamespacedName(name));
|
||||
|
||||
// namespacing happens downstream
|
||||
this.addLiquidFilter(name, callback);
|
||||
this.addNunjucksFilter(name, callback);
|
||||
this.addJavaScriptFunction(name, callback);
|
||||
|
||||
// TODO remove Handlebars helpers in Universal Filters. Use shortcodes instead (the Handlebars template syntax is the same).
|
||||
this.addHandlebarsHelper(name, callback);
|
||||
}
|
||||
|
||||
addNunjucksTag(name, tagFn) {
|
||||
name = this.getNamespacedName(name);
|
||||
|
||||
if (typeof tagFn !== "function") {
|
||||
throw new UserConfigError(
|
||||
`EleventyConfig.addNunjucksTag expects a callback function to be passed in for ${name}: addNunjucksTag(name, function(nunjucksEngine) {})`
|
||||
);
|
||||
}
|
||||
|
||||
if (this.nunjucksTags[name]) {
|
||||
debug(
|
||||
chalk.yellow(
|
||||
"Warning, overwriting a Nunjucks tag with `addNunjucksTag(%o)`"
|
||||
),
|
||||
name
|
||||
);
|
||||
}
|
||||
|
||||
this.nunjucksTags[name] = bench.add(`"${name}" Nunjucks Custom Tag`, tagFn);
|
||||
}
|
||||
|
||||
addTransform(name, callback) {
|
||||
name = this.getNamespacedName(name);
|
||||
|
||||
// these are now called transforms
|
||||
// this naming is kept here for backwards compatibility
|
||||
// TODO major version change
|
||||
this.filters[name] = callback;
|
||||
}
|
||||
|
||||
addLinter(name, callback) {
|
||||
name = this.getNamespacedName(name);
|
||||
|
||||
this.linters[name] = callback;
|
||||
}
|
||||
|
||||
addLayoutAlias(from, to) {
|
||||
this.layoutAliases[from] = to;
|
||||
}
|
||||
|
||||
// get config defined collections
|
||||
getCollections() {
|
||||
return this.collections;
|
||||
}
|
||||
|
||||
addCollection(name, callback) {
|
||||
name = this.getNamespacedName(name);
|
||||
|
||||
if (this.collections[name]) {
|
||||
throw new UserConfigError(
|
||||
`config.addCollection(${name}) already exists. Try a different name for your collection.`
|
||||
);
|
||||
}
|
||||
|
||||
this.collections[name] = callback;
|
||||
}
|
||||
|
||||
addPlugin(plugin, options) {
|
||||
debug("Adding plugin (unknown name: check your config file).");
|
||||
if (typeof plugin === "function") {
|
||||
plugin(this);
|
||||
} else if (plugin && plugin.configFunction) {
|
||||
if (options && typeof options.init === "function") {
|
||||
options.init.call(this, plugin.initArguments || {});
|
||||
}
|
||||
|
||||
plugin.configFunction(this, options);
|
||||
} else {
|
||||
throw new UserConfigError(
|
||||
"Invalid EleventyConfig.addPlugin signature. Should be a function or a valid Eleventy plugin object."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
getNamespacedName(name) {
|
||||
return this.activeNamespace + name;
|
||||
}
|
||||
|
||||
namespace(pluginNamespace, callback) {
|
||||
let validNamespace = pluginNamespace && typeof pluginNamespace === "string";
|
||||
if (validNamespace) {
|
||||
this.activeNamespace = pluginNamespace || "";
|
||||
}
|
||||
|
||||
callback();
|
||||
|
||||
if (validNamespace) {
|
||||
this.activeNamespace = "";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a path to a file or directory to the list of pass-through copies
|
||||
* which are copied as-is to the output.
|
||||
*
|
||||
* @param {string|object} fileOrDir The path to the file or directory that should
|
||||
* be copied. OR an object where the key is the input glob and the property is the output directory
|
||||
* @returns {any} a reference to the `EleventyConfig` object.
|
||||
* @memberof EleventyConfig
|
||||
*/
|
||||
addPassthroughCopy(fileOrDir) {
|
||||
if (typeof fileOrDir === "string") {
|
||||
this.passthroughCopies[fileOrDir] = true;
|
||||
} else {
|
||||
Object.assign(this.passthroughCopies, fileOrDir);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
setTemplateFormats(templateFormats) {
|
||||
if (typeof templateFormats === "string") {
|
||||
templateFormats = templateFormats.split(",").map(format => format.trim());
|
||||
}
|
||||
|
||||
this.templateFormats = templateFormats;
|
||||
}
|
||||
|
||||
setLibrary(engineName, libraryInstance) {
|
||||
// Pug options are passed to `compile` and not in the library constructor so we don’t need to warn
|
||||
if (engineName === "liquid" && this.mdOptions) {
|
||||
debug(
|
||||
"WARNING: using `eleventyConfig.setLibrary` will override any configuration set using `.setLiquidOptions` or with the `liquidOptions` key in the config object. You’ll need to pass these options to the library yourself."
|
||||
);
|
||||
}
|
||||
|
||||
this.libraryOverrides[engineName.toLowerCase()] = libraryInstance;
|
||||
}
|
||||
|
||||
setPugOptions(options) {
|
||||
this.pugOptions = options;
|
||||
}
|
||||
|
||||
setLiquidOptions(options) {
|
||||
this.liquidOptions = options;
|
||||
}
|
||||
|
||||
setEjsOptions(options) {
|
||||
this.ejsOptions = options;
|
||||
}
|
||||
|
||||
setDynamicPermalinks(enabled) {
|
||||
this.dynamicPermalinks = !!enabled;
|
||||
}
|
||||
|
||||
setUseGitIgnore(enabled) {
|
||||
this.useGitIgnore = !!enabled;
|
||||
}
|
||||
|
||||
addShortcode(name, callback) {
|
||||
debug("Adding universal shortcode %o", this.getNamespacedName(name));
|
||||
this.addNunjucksShortcode(name, callback);
|
||||
this.addLiquidShortcode(name, callback);
|
||||
this.addHandlebarsShortcode(name, callback);
|
||||
this.addJavaScriptFunction(name, callback);
|
||||
}
|
||||
|
||||
addNunjucksShortcode(name, callback) {
|
||||
name = this.getNamespacedName(name);
|
||||
|
||||
if (this.nunjucksShortcodes[name]) {
|
||||
debug(
|
||||
chalk.yellow(
|
||||
"Warning, overwriting a Nunjucks Shortcode with `addNunjucksShortcode(%o)`"
|
||||
),
|
||||
name
|
||||
);
|
||||
}
|
||||
|
||||
this.nunjucksShortcodes[name] = bench.add(
|
||||
`"${name}" Nunjucks Shortcode`,
|
||||
callback
|
||||
);
|
||||
}
|
||||
|
||||
addLiquidShortcode(name, callback) {
|
||||
name = this.getNamespacedName(name);
|
||||
|
||||
if (this.liquidShortcodes[name]) {
|
||||
debug(
|
||||
chalk.yellow(
|
||||
"Warning, overwriting a Liquid Shortcode with `addLiquidShortcode(%o)`"
|
||||
),
|
||||
name
|
||||
);
|
||||
}
|
||||
|
||||
this.liquidShortcodes[name] = bench.add(
|
||||
`"${name}" Liquid Shortcode`,
|
||||
callback
|
||||
);
|
||||
}
|
||||
|
||||
addHandlebarsShortcode(name, callback) {
|
||||
name = this.getNamespacedName(name);
|
||||
|
||||
if (this.handlebarsShortcodes[name]) {
|
||||
debug(
|
||||
chalk.yellow(
|
||||
"Warning, overwriting a Handlebars Shortcode with `addHandlebarsShortcode(%o)`"
|
||||
),
|
||||
name
|
||||
);
|
||||
}
|
||||
|
||||
this.handlebarsShortcodes[name] = bench.add(
|
||||
`"${name}" Handlebars Shortcode`,
|
||||
callback
|
||||
);
|
||||
}
|
||||
|
||||
addPairedShortcode(name, callback) {
|
||||
this.addPairedNunjucksShortcode(name, callback);
|
||||
this.addPairedLiquidShortcode(name, callback);
|
||||
this.addPairedHandlebarsShortcode(name, callback);
|
||||
this.addJavaScriptFunction(name, callback);
|
||||
}
|
||||
|
||||
addPairedNunjucksShortcode(name, callback) {
|
||||
name = this.getNamespacedName(name);
|
||||
|
||||
if (this.nunjucksPairedShortcodes[name]) {
|
||||
debug(
|
||||
chalk.yellow(
|
||||
"Warning, overwriting a Nunjucks Paired Shortcode with `addPairedNunjucksShortcode(%o)`"
|
||||
),
|
||||
name
|
||||
);
|
||||
}
|
||||
|
||||
this.nunjucksPairedShortcodes[name] = bench.add(
|
||||
`"${name}" Nunjucks Paired Shortcode`,
|
||||
callback
|
||||
);
|
||||
}
|
||||
|
||||
addPairedLiquidShortcode(name, callback) {
|
||||
name = this.getNamespacedName(name);
|
||||
|
||||
if (this.liquidPairedShortcodes[name]) {
|
||||
debug(
|
||||
chalk.yellow(
|
||||
"Warning, overwriting a Liquid Paired Shortcode with `addPairedLiquidShortcode(%o)`"
|
||||
),
|
||||
name
|
||||
);
|
||||
}
|
||||
|
||||
this.liquidPairedShortcodes[name] = bench.add(
|
||||
`"${name}" Liquid Paired Shortcode`,
|
||||
callback
|
||||
);
|
||||
}
|
||||
|
||||
addPairedHandlebarsShortcode(name, callback) {
|
||||
name = this.getNamespacedName(name);
|
||||
|
||||
if (this.handlebarsPairedShortcodes[name]) {
|
||||
debug(
|
||||
chalk.yellow(
|
||||
"Warning, overwriting a Handlebars Paired Shortcode with `addPairedHandlebarsShortcode(%o)`"
|
||||
),
|
||||
name
|
||||
);
|
||||
}
|
||||
|
||||
this.handlebarsPairedShortcodes[name] = bench.add(
|
||||
`"${name}" Handlebars Paired Shortcode`,
|
||||
callback
|
||||
);
|
||||
}
|
||||
|
||||
addJavaScriptFunction(name, callback) {
|
||||
name = this.getNamespacedName(name);
|
||||
|
||||
if (this.javascriptFunctions[name]) {
|
||||
debug(
|
||||
chalk.yellow(
|
||||
"Warning, overwriting a JavaScript template function with `addJavaScriptFunction(%o)`"
|
||||
),
|
||||
name
|
||||
);
|
||||
}
|
||||
|
||||
this.javascriptFunctions[name] = bench.add(
|
||||
`"${name}" JavaScript Function`,
|
||||
callback
|
||||
);
|
||||
}
|
||||
|
||||
addExperiment(key) {
|
||||
this.experiments.add(key);
|
||||
}
|
||||
|
||||
setDataDeepMerge(deepMerge) {
|
||||
this.dataDeepMerge = !!deepMerge;
|
||||
}
|
||||
|
||||
// addTemplateExtensionAlias(targetKey, extension) {
|
||||
// this.templateExtensionAliases[extension] = targetKey;
|
||||
// }
|
||||
|
||||
setWatchJavaScriptDependencies(watchEnabled) {
|
||||
this.watchJavaScriptDependencies = !!watchEnabled;
|
||||
}
|
||||
|
||||
setBrowserSyncConfig(options = {}) {
|
||||
this.browserSyncConfig = options;
|
||||
}
|
||||
|
||||
setFrontMatterParsingOptions(options = {}) {
|
||||
this.frontMatterParsingOptions = options;
|
||||
}
|
||||
|
||||
getMergingConfigObject() {
|
||||
return {
|
||||
templateFormats: this.templateFormats,
|
||||
filters: this.filters, // now called transforms
|
||||
linters: this.linters,
|
||||
layoutAliases: this.layoutAliases,
|
||||
passthroughCopies: this.passthroughCopies,
|
||||
liquidOptions: this.liquidOptions,
|
||||
liquidTags: this.liquidTags,
|
||||
liquidFilters: this.liquidFilters,
|
||||
liquidShortcodes: this.liquidShortcodes,
|
||||
liquidPairedShortcodes: this.liquidPairedShortcodes,
|
||||
nunjucksFilters: this.nunjucksFilters,
|
||||
nunjucksAsyncFilters: this.nunjucksAsyncFilters,
|
||||
nunjucksTags: this.nunjucksTags,
|
||||
nunjucksShortcodes: this.nunjucksShortcodes,
|
||||
nunjucksPairedShortcodes: this.nunjucksPairedShortcodes,
|
||||
handlebarsHelpers: this.handlebarsHelpers,
|
||||
handlebarsShortcodes: this.handlebarsShortcodes,
|
||||
handlebarsPairedShortcodes: this.handlebarsPairedShortcodes,
|
||||
javascriptFunctions: this.javascriptFunctions,
|
||||
pugOptions: this.pugOptions,
|
||||
ejsOptions: this.ejsOptions,
|
||||
markdownHighlighter: this.markdownHighlighter,
|
||||
libraryOverrides: this.libraryOverrides,
|
||||
dynamicPermalinks: this.dynamicPermalinks,
|
||||
useGitIgnore: this.useGitIgnore,
|
||||
dataDeepMerge: this.dataDeepMerge,
|
||||
experiments: this.experiments,
|
||||
// templateExtensionAliases: this.templateExtensionAliases,
|
||||
watchJavaScriptDependencies: this.watchJavaScriptDependencies,
|
||||
browserSyncConfig: this.browserSyncConfig,
|
||||
frontMatterParsingOptions: this.frontMatterParsingOptions
|
||||
};
|
||||
}
|
||||
|
||||
// addExtension(fileExtension, userClass) {
|
||||
// this.userExtensionMap[ fileExtension ] = userClass;
|
||||
// }
|
||||
}
|
||||
|
||||
module.exports = UserConfig;
|
20
node_modules/@11ty/eleventy/src/Util/Capitalize.js
generated
vendored
Normal file
20
node_modules/@11ty/eleventy/src/Util/Capitalize.js
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
module.exports = function(str, options) {
|
||||
options = Object.assign(
|
||||
{
|
||||
lowercaseRestOfWord: false
|
||||
},
|
||||
options
|
||||
);
|
||||
|
||||
return str
|
||||
.split(" ")
|
||||
.map(function(word) {
|
||||
return (
|
||||
word.substr(0, 1).toUpperCase() +
|
||||
(options.lowercaseRestOfWord
|
||||
? word.substr(1).toLowerCase()
|
||||
: word.substr(1))
|
||||
);
|
||||
})
|
||||
.join(" ");
|
||||
};
|
51
node_modules/@11ty/eleventy/src/Util/Merge.js
generated
vendored
Normal file
51
node_modules/@11ty/eleventy/src/Util/Merge.js
generated
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
const isPlainObject = require("lodash/isPlainObject");
|
||||
const OVERRIDE_PREFIX = "override:";
|
||||
|
||||
function getMergedItem(target, source, parentKey) {
|
||||
// if key is prefixed with OVERRIDE_PREFIX, it just keeps the new source value (no merging)
|
||||
if (parentKey && parentKey.indexOf(OVERRIDE_PREFIX) === 0) {
|
||||
return source;
|
||||
}
|
||||
|
||||
if (!target) {
|
||||
return source;
|
||||
} else if (Array.isArray(target) && Array.isArray(source)) {
|
||||
return target.concat(source);
|
||||
} else if (isPlainObject(target)) {
|
||||
if (isPlainObject(source)) {
|
||||
for (var key in source) {
|
||||
let newKey = key;
|
||||
if (key.indexOf(OVERRIDE_PREFIX) === 0) {
|
||||
newKey = key.substr(OVERRIDE_PREFIX.length);
|
||||
}
|
||||
target[newKey] = getMergedItem(target[key], source[key], newKey);
|
||||
}
|
||||
}
|
||||
return target;
|
||||
} else {
|
||||
// number, string, class instance, etc
|
||||
return source;
|
||||
}
|
||||
}
|
||||
function Merge(target, ...sources) {
|
||||
// Remove override prefixes from root target.
|
||||
if (isPlainObject(target)) {
|
||||
for (var key in target) {
|
||||
if (key.indexOf(OVERRIDE_PREFIX) === 0) {
|
||||
target[key.substr(OVERRIDE_PREFIX.length)] = target[key];
|
||||
delete target[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (var source of sources) {
|
||||
if (!source) {
|
||||
continue;
|
||||
}
|
||||
target = getMergedItem(target, source);
|
||||
}
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
module.exports = Merge;
|
3
node_modules/@11ty/eleventy/src/Util/Pluralize.js
generated
vendored
Normal file
3
node_modules/@11ty/eleventy/src/Util/Pluralize.js
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
module.exports = function(count, singleWord, pluralWord) {
|
||||
return count === 1 ? singleWord : pluralWord;
|
||||
};
|
144
node_modules/@11ty/eleventy/src/Util/Sortable.js
generated
vendored
Normal file
144
node_modules/@11ty/eleventy/src/Util/Sortable.js
generated
vendored
Normal file
@@ -0,0 +1,144 @@
|
||||
const capitalize = require("./Capitalize");
|
||||
|
||||
class Sortable {
|
||||
constructor() {
|
||||
this.sortAscending = true;
|
||||
this.sortNumeric = false;
|
||||
this.items = [];
|
||||
|
||||
this.sortFunctionStringMap = {
|
||||
"A-Z": "Ascending",
|
||||
"Z-A": "Descending",
|
||||
"0-9": "NumericAscending",
|
||||
"9-0": "NumericDescending"
|
||||
};
|
||||
}
|
||||
|
||||
get length() {
|
||||
return this.items.length;
|
||||
}
|
||||
|
||||
add(item) {
|
||||
this.items.push(item);
|
||||
}
|
||||
|
||||
sort(sortFunction) {
|
||||
if (!sortFunction) {
|
||||
sortFunction = this.getSortFunction();
|
||||
} else if (typeof sortFunction === "string") {
|
||||
if (sortFunction in this.sortFunctionStringMap) {
|
||||
sortFunction = this.sortFunctionStringMap[sortFunction];
|
||||
}
|
||||
|
||||
sortFunction = Sortable["sortFunction" + capitalize(sortFunction)];
|
||||
}
|
||||
|
||||
return this.items.filter(() => true).sort(sortFunction);
|
||||
}
|
||||
|
||||
sortAscending() {
|
||||
return this.sort(this.getSortFunctionAscending);
|
||||
}
|
||||
|
||||
sortDescending() {
|
||||
return this.sort(this.getSortFunctionDescending);
|
||||
}
|
||||
|
||||
isSortAscending() {
|
||||
return this.sortAscending;
|
||||
}
|
||||
|
||||
isSortNumeric() {
|
||||
return this.sortNumeric;
|
||||
}
|
||||
|
||||
setSortDescending() {
|
||||
this.sortAscending = false;
|
||||
}
|
||||
|
||||
setSortAscending(isAscending) {
|
||||
this.sortAscending = isAscending;
|
||||
}
|
||||
|
||||
setSortNumeric(isNumeric) {
|
||||
this.sortNumeric = isNumeric;
|
||||
}
|
||||
|
||||
/* Sort functions */
|
||||
static sortFunctionNumericAscending(a, b) {
|
||||
return a - b;
|
||||
}
|
||||
|
||||
static sortFunctionNumericDescending(a, b) {
|
||||
return b - a;
|
||||
}
|
||||
|
||||
static sortFunctionAscending(a, b) {
|
||||
if (a > b) {
|
||||
return 1;
|
||||
} else if (a < b) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static sortFunctionDescending(a, b) {
|
||||
return Sortable.sortFunctionAscending(b, a);
|
||||
}
|
||||
|
||||
static sortFunctionAlphabeticAscending(a, b) {
|
||||
return Sortable.sortFunctionAscending(a, b);
|
||||
}
|
||||
|
||||
static sortFunctionAlphabeticDescending(a, b) {
|
||||
return Sortable.sortFunctionAscending(b, a);
|
||||
}
|
||||
|
||||
static sortFunctionDate(mapA, mapB) {
|
||||
return Sortable.sortFunctionNumericAscending(
|
||||
mapA.date.getTime(),
|
||||
mapB.date.getTime()
|
||||
);
|
||||
}
|
||||
|
||||
static sortFunctionDateInputPath(mapA, mapB) {
|
||||
let sortDate = Sortable.sortFunctionNumericAscending(
|
||||
mapA.date.getTime(),
|
||||
mapB.date.getTime()
|
||||
);
|
||||
if (sortDate === 0) {
|
||||
return Sortable.sortFunctionAlphabeticAscending(
|
||||
mapA.inputPath,
|
||||
mapB.inputPath
|
||||
);
|
||||
}
|
||||
return sortDate;
|
||||
}
|
||||
/* End sort functions */
|
||||
|
||||
getSortFunction() {
|
||||
if (this.sortAscending) {
|
||||
return this.getSortFunctionAscending();
|
||||
} else {
|
||||
return this.getSortFunctionDescending();
|
||||
}
|
||||
}
|
||||
|
||||
getSortFunctionAscending() {
|
||||
if (this.sortNumeric) {
|
||||
return Sortable.sortFunctionNumericAscending;
|
||||
} else {
|
||||
return Sortable.sortFunctionAlphabeticAscending;
|
||||
}
|
||||
}
|
||||
|
||||
getSortFunctionDescending() {
|
||||
if (this.sortNumeric) {
|
||||
return Sortable.sortFunctionNumericDescending;
|
||||
} else {
|
||||
return Sortable.sortFunctionAlphabeticDescending;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Sortable;
|
Reference in New Issue
Block a user