Initial commit: 11ty website with Fire/Frost branding
This commit is contained in:
24
node_modules/@11ty/eleventy/src/Util/ArrayUtil.js
generated
vendored
Normal file
24
node_modules/@11ty/eleventy/src/Util/ArrayUtil.js
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
export function arrayDelete(arr, match) {
|
||||
if (!Array.isArray(arr)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (!match) {
|
||||
return arr;
|
||||
}
|
||||
|
||||
// only mutates if found
|
||||
if (typeof match === "function") {
|
||||
if (arr.find(match)) {
|
||||
return arr.filter((entry) => {
|
||||
return !match(entry);
|
||||
});
|
||||
}
|
||||
} else if (arr.includes(match)) {
|
||||
return arr.filter((entry) => {
|
||||
return entry !== match;
|
||||
});
|
||||
}
|
||||
|
||||
return arr;
|
||||
}
|
||||
88
node_modules/@11ty/eleventy/src/Util/AsyncEventEmitter.js
generated
vendored
Normal file
88
node_modules/@11ty/eleventy/src/Util/AsyncEventEmitter.js
generated
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
import { EventEmitter } from "node:events";
|
||||
|
||||
/**
|
||||
* This class emits events asynchronously.
|
||||
*
|
||||
* Note that Eleventy has two separate event emitter instances it uses:
|
||||
* 1. a userland one (UserConfig.js)
|
||||
* 2. a global one for internals (EventBus.js)
|
||||
*/
|
||||
class AsyncEventEmitter extends EventEmitter {
|
||||
#handlerMode = "parallel";
|
||||
|
||||
// TypeScript slop
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
}
|
||||
|
||||
reset() {
|
||||
// `eleventy#` event type listeners are removed at the start of each build (singletons)
|
||||
for (let type of this.eventNames()) {
|
||||
if (typeof type === "string" && type.startsWith("eleventy#")) {
|
||||
this.removeAllListeners(type);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} type - The event name to emit.
|
||||
* @param {...*} args - Additional arguments that get passed to listeners.
|
||||
* @returns {Promise} - Promise resolves once all listeners were invoked
|
||||
*/
|
||||
/** @ts-expect-error */
|
||||
async emit(type, ...args) {
|
||||
let listeners = this.listeners(type);
|
||||
if (listeners.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (this.#handlerMode == "sequential") {
|
||||
const result = [];
|
||||
for (const listener of listeners) {
|
||||
const returnValue = await listener.apply(this, args);
|
||||
result.push(returnValue);
|
||||
}
|
||||
return result;
|
||||
} else {
|
||||
return Promise.all(
|
||||
listeners.map((listener) => {
|
||||
return listener.apply(this, args);
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} type - The event name to emit.
|
||||
* @param {...*} args - Additional lazy-executed function arguments that get passed to listeners.
|
||||
* @returns {Promise} - Promise resolves once all listeners were invoked
|
||||
*/
|
||||
async emitLazy(type, ...args) {
|
||||
let listeners = this.listeners(type);
|
||||
if (listeners.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
let argsMap = [];
|
||||
for (let arg of args) {
|
||||
if (typeof arg === "function") {
|
||||
let r = arg();
|
||||
if (r instanceof Promise) {
|
||||
r = await r;
|
||||
}
|
||||
argsMap.push(r);
|
||||
} else {
|
||||
argsMap.push(arg);
|
||||
}
|
||||
}
|
||||
|
||||
return this.emit.call(this, type, ...argsMap);
|
||||
}
|
||||
|
||||
setHandlerMode(mode) {
|
||||
this.#handlerMode = mode;
|
||||
}
|
||||
}
|
||||
|
||||
export default AsyncEventEmitter;
|
||||
59
node_modules/@11ty/eleventy/src/Util/Compatibility.js
generated
vendored
Normal file
59
node_modules/@11ty/eleventy/src/Util/Compatibility.js
generated
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
import semver from "semver";
|
||||
|
||||
import { getEleventyPackageJson, getWorkingProjectPackageJson } from "./ImportJsonSync.js";
|
||||
|
||||
const pkg = getEleventyPackageJson();
|
||||
|
||||
// Used in user config versionCheck method.
|
||||
class Compatibility {
|
||||
static NORMALIZE_PRERELEASE_REGEX = /-canary\b/g;
|
||||
|
||||
static #projectPackageJson;
|
||||
|
||||
constructor(compatibleRange) {
|
||||
this.compatibleRange = Compatibility.getCompatibilityValue(compatibleRange);
|
||||
}
|
||||
|
||||
static get projectPackageJson() {
|
||||
if (!this.#projectPackageJson) {
|
||||
this.#projectPackageJson = getWorkingProjectPackageJson();
|
||||
}
|
||||
|
||||
return this.#projectPackageJson;
|
||||
}
|
||||
|
||||
static normalizeIdentifier(identifier) {
|
||||
return identifier.replace(Compatibility.NORMALIZE_PRERELEASE_REGEX, "-alpha");
|
||||
}
|
||||
|
||||
static getCompatibilityValue(compatibleRange) {
|
||||
if (compatibleRange) {
|
||||
return compatibleRange;
|
||||
}
|
||||
|
||||
// fetch from project’s package.json
|
||||
if (this.projectPackageJson?.["11ty"]?.compatibility) {
|
||||
return this.projectPackageJson["11ty"].compatibility;
|
||||
}
|
||||
}
|
||||
|
||||
isCompatible() {
|
||||
return Compatibility.satisfies(pkg.version, this.compatibleRange);
|
||||
}
|
||||
|
||||
static satisfies(version, compatibleRange) {
|
||||
return semver.satisfies(
|
||||
Compatibility.normalizeIdentifier(version),
|
||||
Compatibility.normalizeIdentifier(compatibleRange),
|
||||
{
|
||||
includePrerelease: true,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
getErrorMessage() {
|
||||
return `We found Eleventy version '${pkg.version}' which does not meet the required version range: '${this.compatibleRange}'. Use \`npm install @11ty/eleventy\` to upgrade your local project to the latest Eleventy version (or \`npm install @11ty/eleventy -g\` to upgrade the globally installed version).`;
|
||||
}
|
||||
}
|
||||
|
||||
export default Compatibility;
|
||||
140
node_modules/@11ty/eleventy/src/Util/ConsoleLogger.js
generated
vendored
Normal file
140
node_modules/@11ty/eleventy/src/Util/ConsoleLogger.js
generated
vendored
Normal file
@@ -0,0 +1,140 @@
|
||||
import { Readable } from "node:stream";
|
||||
import chalk from "kleur";
|
||||
import debugUtil from "debug";
|
||||
|
||||
const debug = debugUtil("Eleventy:Logger");
|
||||
|
||||
/**
|
||||
* Logger implementation that logs to STDOUT.
|
||||
* @typedef {'error'|'log'|'warn'|'info'} LogType
|
||||
*/
|
||||
class ConsoleLogger {
|
||||
/** @type {boolean} */
|
||||
#isVerbose = true;
|
||||
/** @type {boolean} */
|
||||
#isChalkEnabled = true;
|
||||
/** @type {object|boolean|undefined} */
|
||||
#logger;
|
||||
/** @type {Readable|undefined} */
|
||||
#outputStream;
|
||||
|
||||
constructor() {}
|
||||
|
||||
isLoggingEnabled() {
|
||||
if (!this.isVerbose || process.env.DEBUG) {
|
||||
return true;
|
||||
}
|
||||
return this.#logger !== false;
|
||||
}
|
||||
|
||||
get isVerbose() {
|
||||
return this.#isVerbose;
|
||||
}
|
||||
|
||||
set isVerbose(verbose) {
|
||||
this.#isVerbose = !!verbose;
|
||||
}
|
||||
|
||||
get isChalkEnabled() {
|
||||
return this.#isChalkEnabled;
|
||||
}
|
||||
|
||||
set isChalkEnabled(enabled) {
|
||||
this.#isChalkEnabled = !!enabled;
|
||||
}
|
||||
|
||||
overrideLogger(logger) {
|
||||
this.#logger = logger;
|
||||
}
|
||||
|
||||
get logger() {
|
||||
return this.#logger || console;
|
||||
}
|
||||
|
||||
/** @param {string} msg */
|
||||
log(msg) {
|
||||
this.message(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef LogOptions
|
||||
* @property {string} message
|
||||
* @property {string=} prefix
|
||||
* @property {LogType=} type
|
||||
* @property {string=} color
|
||||
* @property {boolean=} force
|
||||
* @param {LogOptions} options
|
||||
*/
|
||||
logWithOptions({ message, type, prefix, color, force }) {
|
||||
this.message(message, type, color, force, prefix);
|
||||
}
|
||||
|
||||
/** @param {string} msg */
|
||||
forceLog(msg) {
|
||||
this.message(msg, undefined, undefined, true);
|
||||
}
|
||||
|
||||
/** @param {string} msg */
|
||||
info(msg) {
|
||||
this.message(msg, "warn", "blue");
|
||||
}
|
||||
|
||||
/** @param {string} msg */
|
||||
warn(msg) {
|
||||
this.message(msg, "warn", "yellow");
|
||||
}
|
||||
|
||||
/** @param {string} msg */
|
||||
error(msg) {
|
||||
this.message(msg, "error", "red");
|
||||
}
|
||||
|
||||
get outputStream() {
|
||||
if (!this.#outputStream) {
|
||||
this.#outputStream = new Readable({
|
||||
read() {},
|
||||
});
|
||||
}
|
||||
return this.#outputStream;
|
||||
}
|
||||
|
||||
/** @param {string} msg */
|
||||
toStream(msg) {
|
||||
this.outputStream.push(msg);
|
||||
}
|
||||
|
||||
closeStream() {
|
||||
this.outputStream.push(null);
|
||||
return this.outputStream;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the message to log.
|
||||
*
|
||||
* @param {string} message - The raw message to log.
|
||||
* @param {LogType} [type='log'] - The error level to log.
|
||||
* @param {string|undefined} [chalkColor=undefined] - Color name or falsy to disable
|
||||
* @param {boolean} [forceToConsole=false] - Enforce a log on console instead of specified target.
|
||||
*/
|
||||
message(
|
||||
message,
|
||||
type = "log",
|
||||
chalkColor = undefined,
|
||||
forceToConsole = false,
|
||||
prefix = "[11ty]",
|
||||
) {
|
||||
if (!forceToConsole && (!this.isVerbose || process.env.DEBUG)) {
|
||||
debug(message);
|
||||
} else if (this.#logger !== false) {
|
||||
message = `${chalk.gray(prefix)} ${message.split("\n").join(`\n${chalk.gray(prefix)} `)}`;
|
||||
|
||||
if (chalkColor && this.isChalkEnabled) {
|
||||
this.logger[type](chalk[chalkColor](message));
|
||||
} else {
|
||||
this.logger[type](message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default ConsoleLogger;
|
||||
23
node_modules/@11ty/eleventy/src/Util/DateGitFirstAdded.js
generated
vendored
Normal file
23
node_modules/@11ty/eleventy/src/Util/DateGitFirstAdded.js
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
import { spawnAsync } from "./SpawnAsync.js";
|
||||
|
||||
async function getGitFirstAddedTimeStamp(filePath) {
|
||||
try {
|
||||
let timestamp = await spawnAsync(
|
||||
"git",
|
||||
// Formats https://www.git-scm.com/docs/git-log#_pretty_formats
|
||||
// %at author date, UNIX timestamp
|
||||
["log", "--diff-filter=A", "--follow", "-1", "--format=%at", filePath],
|
||||
);
|
||||
return parseInt(timestamp, 10) * 1000;
|
||||
} catch (e) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
||||
// return a Date
|
||||
export default async function (inputPath) {
|
||||
let timestamp = await getGitFirstAddedTimeStamp(inputPath);
|
||||
if (timestamp) {
|
||||
return new Date(timestamp);
|
||||
}
|
||||
}
|
||||
23
node_modules/@11ty/eleventy/src/Util/DateGitLastUpdated.js
generated
vendored
Normal file
23
node_modules/@11ty/eleventy/src/Util/DateGitLastUpdated.js
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
import { spawnAsync } from "./SpawnAsync.js";
|
||||
|
||||
async function getGitLastUpdatedTimeStamp(filePath) {
|
||||
try {
|
||||
let timestamp = await spawnAsync(
|
||||
"git",
|
||||
// Formats https://www.git-scm.com/docs/git-log#_pretty_formats
|
||||
// %at author date, UNIX timestamp
|
||||
["log", "-1", "--format=%at", filePath],
|
||||
);
|
||||
return parseInt(timestamp, 10) * 1000;
|
||||
} catch (e) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
||||
// return a Date
|
||||
export default async function (inputPath) {
|
||||
let timestamp = await getGitLastUpdatedTimeStamp(inputPath);
|
||||
if (timestamp) {
|
||||
return new Date(timestamp);
|
||||
}
|
||||
}
|
||||
10
node_modules/@11ty/eleventy/src/Util/DirContains.js
generated
vendored
Normal file
10
node_modules/@11ty/eleventy/src/Util/DirContains.js
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
import path from "node:path";
|
||||
|
||||
// Returns true if subfolder is in parent (accepts absolute or relative paths for both)
|
||||
export default function (parentFolder, subFolder) {
|
||||
// path.resolve returns an absolute path
|
||||
if (path.resolve(subFolder).startsWith(path.resolve(parentFolder))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
53
node_modules/@11ty/eleventy/src/Util/EsmResolver.js
generated
vendored
Normal file
53
node_modules/@11ty/eleventy/src/Util/EsmResolver.js
generated
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
import debugUtil from "debug";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import PathNormalizer from "./PathNormalizer.js";
|
||||
|
||||
const debug = debugUtil("Eleventy:EsmResolver");
|
||||
|
||||
let lastModifiedPaths = new Map();
|
||||
export async function initialize({ port }) {
|
||||
// From `eleventy.importCacheReset` event in Require.js
|
||||
port.on("message", ({ path, newDate }) => {
|
||||
lastModifiedPaths.set(path, newDate);
|
||||
});
|
||||
}
|
||||
|
||||
// Fixes issue https://github.com/11ty/eleventy/issues/3270
|
||||
// Docs: https://nodejs.org/docs/latest/api/module.html#resolvespecifier-context-nextresolve
|
||||
export async function resolve(specifier, context, nextResolve) {
|
||||
try {
|
||||
// Not a relative import and not a file import
|
||||
// Or from node_modules (perhaps better to check if the specifier is in the project directory instead)
|
||||
if (
|
||||
(!specifier.startsWith("../") &&
|
||||
!specifier.startsWith("./") &&
|
||||
!specifier.startsWith("file:")) ||
|
||||
context.parentURL.includes("/node_modules/")
|
||||
) {
|
||||
return nextResolve(specifier);
|
||||
}
|
||||
|
||||
let fileUrl = new URL(specifier, context.parentURL);
|
||||
if (fileUrl.searchParams.has("_cache_bust")) {
|
||||
// already is cache busted outside resolver (wider compat, url was changed prior to import, probably in Require.js)
|
||||
return nextResolve(specifier);
|
||||
}
|
||||
|
||||
let absolutePath = PathNormalizer.normalizeSeperator(fileURLToPath(fileUrl));
|
||||
// Bust the import cache if this is a recently modified file
|
||||
if (lastModifiedPaths.has(absolutePath)) {
|
||||
fileUrl.search = ""; // delete existing searchparams
|
||||
fileUrl.searchParams.set("_cache_bust", lastModifiedPaths.get(absolutePath));
|
||||
debug("Cache busting %o to %o", specifier, fileUrl.toString());
|
||||
|
||||
return nextResolve(fileUrl.toString());
|
||||
}
|
||||
} catch (e) {
|
||||
debug("EsmResolver Error parsing specifier (%o): %o", specifier, e);
|
||||
}
|
||||
|
||||
return nextResolve(specifier);
|
||||
}
|
||||
|
||||
// export async function load(url, context, nextLoad) {
|
||||
// }
|
||||
14
node_modules/@11ty/eleventy/src/Util/EventBusUtil.js
generated
vendored
Normal file
14
node_modules/@11ty/eleventy/src/Util/EventBusUtil.js
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
import eventBus from "../EventBus.js";
|
||||
import debugUtil from "debug";
|
||||
|
||||
const debug = debugUtil("Eleventy:EventBus");
|
||||
|
||||
class EventBusUtil {
|
||||
static debugCurrentListenerCounts() {
|
||||
for (let name of eventBus.eventNames()) {
|
||||
debug("Listeners for %o: %o", name, eventBus.listenerCount(name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default EventBusUtil;
|
||||
62
node_modules/@11ty/eleventy/src/Util/ExistsCache.js
generated
vendored
Normal file
62
node_modules/@11ty/eleventy/src/Util/ExistsCache.js
generated
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
import fs from "node:fs";
|
||||
import { TemplatePath } from "@11ty/eleventy-utils";
|
||||
|
||||
// Checks both files and directories
|
||||
class ExistsCache {
|
||||
#exists = new Map();
|
||||
#dirs = new Map();
|
||||
|
||||
constructor() {
|
||||
this.lookupCount = 0;
|
||||
}
|
||||
|
||||
get size() {
|
||||
return this.#exists.size;
|
||||
}
|
||||
|
||||
has(path) {
|
||||
return this.#exists.has(path);
|
||||
}
|
||||
|
||||
set(path, isExist) {
|
||||
this.#exists.set(TemplatePath.addLeadingDotSlash(path), Boolean(isExist));
|
||||
}
|
||||
|
||||
// Not yet needed
|
||||
// setDirectory(path, isExist) {}
|
||||
|
||||
// Relative paths (to root directory) expected (but not enforced due to perf costs)
|
||||
exists(path) {
|
||||
if (!this.#exists.has(path)) {
|
||||
let exists = fs.existsSync(path);
|
||||
this.lookupCount++;
|
||||
|
||||
// mark for next time
|
||||
this.#exists.set(path, Boolean(exists));
|
||||
|
||||
return exists;
|
||||
}
|
||||
|
||||
return this.#exists.get(path);
|
||||
}
|
||||
|
||||
isDirectory(path) {
|
||||
if (!this.exists(path)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!this.#dirs.has(path)) {
|
||||
let isDir = fs.statSync(path).isDirectory();
|
||||
this.lookupCount++;
|
||||
|
||||
// mark for next time
|
||||
this.#dirs.set(path, isDir);
|
||||
|
||||
return isDir;
|
||||
}
|
||||
|
||||
return this.#dirs.get(path);
|
||||
}
|
||||
}
|
||||
|
||||
export default ExistsCache;
|
||||
19
node_modules/@11ty/eleventy/src/Util/FilePathUtil.js
generated
vendored
Normal file
19
node_modules/@11ty/eleventy/src/Util/FilePathUtil.js
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
class FilePathUtil {
|
||||
static isMatchingExtension(filepath, fileExtension) {
|
||||
if (!fileExtension) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(fileExtension || "").startsWith(".")) {
|
||||
fileExtension = "." + fileExtension;
|
||||
}
|
||||
|
||||
return filepath.endsWith(fileExtension);
|
||||
}
|
||||
|
||||
static getFileExtension(filepath) {
|
||||
return (filepath || "").split(".").pop();
|
||||
}
|
||||
}
|
||||
|
||||
export { FilePathUtil };
|
||||
48
node_modules/@11ty/eleventy/src/Util/FileSystemManager.js
generated
vendored
Normal file
48
node_modules/@11ty/eleventy/src/Util/FileSystemManager.js
generated
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
import path from "node:path";
|
||||
import fs from "node:fs";
|
||||
import { mkdir, writeFile } from "node:fs/promises";
|
||||
|
||||
class FileSystemManager {
|
||||
constructor(templateConfig) {
|
||||
if (!templateConfig || templateConfig.constructor.name !== "TemplateConfig") {
|
||||
throw new Error(
|
||||
"Internal error: Missing `templateConfig` or was not an instance of `TemplateConfig`.",
|
||||
);
|
||||
}
|
||||
this.templateConfig = templateConfig;
|
||||
}
|
||||
|
||||
exists(pathname) {
|
||||
return this.templateConfig.existsCache.exists(pathname);
|
||||
}
|
||||
|
||||
async createDirectoryForFile(filePath) {
|
||||
let dir = path.parse(filePath).dir;
|
||||
if (!dir || this.exists(dir)) {
|
||||
return;
|
||||
}
|
||||
|
||||
return mkdir(dir, { recursive: true });
|
||||
}
|
||||
|
||||
createDirectoryForFileSync(filePath) {
|
||||
let dir = path.parse(filePath).dir;
|
||||
if (!dir || this.exists(dir)) {
|
||||
return;
|
||||
}
|
||||
|
||||
fs.mkdirSync(dir, { recursive: true });
|
||||
}
|
||||
|
||||
async writeFile(filePath, content) {
|
||||
return writeFile(filePath, content);
|
||||
}
|
||||
|
||||
writeFileSync(filePath, content) {
|
||||
// Note: This deliberately uses the synchronous version to avoid
|
||||
// unbounded concurrency: https://github.com/11ty/eleventy/issues/3271
|
||||
fs.writeFileSync(filePath, content);
|
||||
}
|
||||
}
|
||||
|
||||
export { FileSystemManager };
|
||||
30
node_modules/@11ty/eleventy/src/Util/GetJavaScriptData.js
generated
vendored
Normal file
30
node_modules/@11ty/eleventy/src/Util/GetJavaScriptData.js
generated
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
import EleventyBaseError from "../Errors/EleventyBaseError.js";
|
||||
|
||||
class JavaScriptInvalidDataFormatError extends EleventyBaseError {}
|
||||
|
||||
export default async function (inst, inputPath, key = "data", options = {}) {
|
||||
let { mixins, isObjectRequired } = Object.assign(
|
||||
{
|
||||
mixins: {},
|
||||
isObjectRequired: true,
|
||||
},
|
||||
options,
|
||||
);
|
||||
|
||||
if (inst && key in inst) {
|
||||
// get extra data from `data` method,
|
||||
// either as a function or getter or object literal
|
||||
let result = await (typeof inst[key] === "function"
|
||||
? Object.keys(mixins).length > 0
|
||||
? inst[key].call(mixins)
|
||||
: inst[key]()
|
||||
: inst[key]);
|
||||
|
||||
if (isObjectRequired && typeof result !== "object") {
|
||||
throw new JavaScriptInvalidDataFormatError(
|
||||
`Invalid data format returned from ${inputPath}: typeof ${typeof result}`,
|
||||
);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
22
node_modules/@11ty/eleventy/src/Util/GlobMatcher.js
generated
vendored
Normal file
22
node_modules/@11ty/eleventy/src/Util/GlobMatcher.js
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
import picomatch from "picomatch";
|
||||
import { TemplatePath } from "@11ty/eleventy-utils";
|
||||
|
||||
function isGlobMatch(filepath, globs = [], options = undefined) {
|
||||
if (!filepath || !Array.isArray(globs) || globs.length === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let inputPath = TemplatePath.stripLeadingDotSlash(filepath);
|
||||
let opts = Object.assign(
|
||||
{
|
||||
dot: true,
|
||||
nocase: true, // insensitive
|
||||
},
|
||||
options,
|
||||
);
|
||||
|
||||
// globs: string or array of strings
|
||||
return picomatch.isMatch(inputPath, globs, opts);
|
||||
}
|
||||
|
||||
export { isGlobMatch };
|
||||
85
node_modules/@11ty/eleventy/src/Util/GlobRemap.js
generated
vendored
Normal file
85
node_modules/@11ty/eleventy/src/Util/GlobRemap.js
generated
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
import path from "node:path";
|
||||
import ProjectDirectories from "./ProjectDirectories.js";
|
||||
import PathNormalizer from "./PathNormalizer.js";
|
||||
|
||||
// even on Windows (in cmd.exe) these paths are normalized to forward slashes
|
||||
// tinyglobby expects forward slashes on Windows
|
||||
const SEP = "/";
|
||||
|
||||
class GlobRemap {
|
||||
constructor(paths = []) {
|
||||
this.paths = paths;
|
||||
this.cwd = GlobRemap.getCwd(paths);
|
||||
}
|
||||
|
||||
getCwd() {
|
||||
return this.cwd;
|
||||
}
|
||||
|
||||
getRemapped(paths) {
|
||||
return paths.map((entry) => GlobRemap.remapInput(entry, this.cwd));
|
||||
}
|
||||
|
||||
getInput() {
|
||||
return this.getRemapped(this.paths);
|
||||
}
|
||||
|
||||
getOutput(paths = []) {
|
||||
return paths.map((entry) => GlobRemap.remapOutput(entry, this.cwd));
|
||||
}
|
||||
|
||||
static getParentDirPrefix(filePath = "") {
|
||||
let count = [];
|
||||
for (let p of filePath.split(SEP)) {
|
||||
if (p === "..") {
|
||||
count.push("..");
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (count.length > 0) {
|
||||
// trailing slash
|
||||
return count.join(SEP) + SEP;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
static getLongestParentDirPrefix(filePaths) {
|
||||
let longest = "";
|
||||
filePaths
|
||||
.map((entry) => {
|
||||
return this.getParentDirPrefix(entry);
|
||||
})
|
||||
.filter((entry) => Boolean(entry))
|
||||
.forEach((prefix) => {
|
||||
if (!longest || prefix.length > longest.length) {
|
||||
longest = prefix;
|
||||
}
|
||||
});
|
||||
return longest;
|
||||
}
|
||||
|
||||
// alias
|
||||
static getCwd(filePaths) {
|
||||
return this.getLongestParentDirPrefix(filePaths);
|
||||
}
|
||||
|
||||
static remapInput(entry, cwd) {
|
||||
if (cwd) {
|
||||
if (!entry.startsWith("**" + SEP) && !entry.startsWith(`.git${SEP}**`)) {
|
||||
return PathNormalizer.normalizeSeperator(ProjectDirectories.getRelativeTo(entry, cwd));
|
||||
}
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
|
||||
static remapOutput(entry, cwd) {
|
||||
if (cwd) {
|
||||
return PathNormalizer.normalizeSeperator(path.join(cwd, entry));
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
|
||||
export default GlobRemap;
|
||||
149
node_modules/@11ty/eleventy/src/Util/HtmlRelativeCopy.js
generated
vendored
Normal file
149
node_modules/@11ty/eleventy/src/Util/HtmlRelativeCopy.js
generated
vendored
Normal file
@@ -0,0 +1,149 @@
|
||||
import path from "node:path";
|
||||
import { TemplatePath } from "@11ty/eleventy-utils";
|
||||
import isValidUrl from "./ValidUrl.js";
|
||||
import { isGlobMatch } from "./GlobMatcher.js";
|
||||
|
||||
class HtmlRelativeCopy {
|
||||
#userConfig;
|
||||
#matchingGlobs = new Set();
|
||||
#matchingGlobsArray;
|
||||
#dirty = false;
|
||||
#paths = new Set();
|
||||
#failOnError = true;
|
||||
#copyOptions = {
|
||||
dot: false, // differs from standard passthrough copy
|
||||
};
|
||||
|
||||
isEnabled() {
|
||||
return this.#matchingGlobs.size > 0;
|
||||
}
|
||||
|
||||
setFailOnError(failOnError) {
|
||||
this.#failOnError = Boolean(failOnError);
|
||||
}
|
||||
|
||||
setCopyOptions(opts) {
|
||||
if (opts) {
|
||||
Object.assign(this.#copyOptions, opts);
|
||||
}
|
||||
}
|
||||
|
||||
setUserConfig(userConfig) {
|
||||
if (!userConfig || userConfig.constructor.name !== "UserConfig") {
|
||||
throw new Error(
|
||||
"Internal error: Missing `userConfig` or was not an instance of `UserConfig`.",
|
||||
);
|
||||
}
|
||||
this.#userConfig = userConfig;
|
||||
}
|
||||
|
||||
addPaths(paths = []) {
|
||||
for (let path of paths) {
|
||||
this.#paths.add(TemplatePath.getDir(path));
|
||||
}
|
||||
}
|
||||
|
||||
get matchingGlobs() {
|
||||
if (this.#dirty || !this.#matchingGlobsArray) {
|
||||
this.#matchingGlobsArray = Array.from(this.#matchingGlobs);
|
||||
this.#dirty = false;
|
||||
}
|
||||
|
||||
return this.#matchingGlobsArray;
|
||||
}
|
||||
|
||||
addMatchingGlob(glob) {
|
||||
if (glob) {
|
||||
if (Array.isArray(glob)) {
|
||||
for (let g of glob) {
|
||||
this.#matchingGlobs.add(g);
|
||||
}
|
||||
} else {
|
||||
this.#matchingGlobs.add(glob);
|
||||
}
|
||||
this.#dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
isSkippableHref(rawRef) {
|
||||
if (
|
||||
this.#matchingGlobs.size === 0 ||
|
||||
!rawRef ||
|
||||
path.isAbsolute(rawRef) ||
|
||||
isValidUrl(rawRef)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
isCopyableTarget(target) {
|
||||
if (!isGlobMatch(target, this.matchingGlobs)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
exists(filePath) {
|
||||
return this.#userConfig.exists(filePath);
|
||||
}
|
||||
|
||||
getAliasedPath(ref) {
|
||||
for (let dir of this.#paths) {
|
||||
let found = TemplatePath.join(dir, ref);
|
||||
if (this.isCopyableTarget(found) && this.exists(found)) {
|
||||
return found;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getFilePathRelativeToProjectRoot(ref, contextFilePath) {
|
||||
let dir = TemplatePath.getDirFromFilePath(contextFilePath);
|
||||
return TemplatePath.join(dir, ref);
|
||||
}
|
||||
|
||||
copy(fileRef, tmplInputPath, tmplOutputPath) {
|
||||
// original ref is a full URL or no globs exist
|
||||
if (this.isSkippableHref(fileRef)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Relative to source file’s input path
|
||||
let source = this.getFilePathRelativeToProjectRoot(fileRef, tmplInputPath);
|
||||
if (!this.isCopyableTarget(source)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.exists(source)) {
|
||||
// Try to alias using `options.paths`
|
||||
let alias = this.getAliasedPath(fileRef);
|
||||
if (!alias) {
|
||||
if (this.#failOnError) {
|
||||
throw new Error(
|
||||
"Missing input file for `html-relative` Passthrough Copy file: " +
|
||||
TemplatePath.absolutePath(source),
|
||||
);
|
||||
}
|
||||
|
||||
// don’t fail on error
|
||||
return;
|
||||
}
|
||||
|
||||
source = alias;
|
||||
}
|
||||
|
||||
let target = this.getFilePathRelativeToProjectRoot(fileRef, tmplOutputPath);
|
||||
|
||||
// We use a Set here to allow passthrough copy manager to properly error on conflicts upstream
|
||||
// Only errors when different inputs write to the same output
|
||||
// Also errors if attempts to write outside the output folder.
|
||||
this.#userConfig.emit("eleventy#copy", {
|
||||
source,
|
||||
target,
|
||||
options: this.#copyOptions,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export { HtmlRelativeCopy };
|
||||
172
node_modules/@11ty/eleventy/src/Util/HtmlTransformer.js
generated
vendored
Normal file
172
node_modules/@11ty/eleventy/src/Util/HtmlTransformer.js
generated
vendored
Normal file
@@ -0,0 +1,172 @@
|
||||
import posthtml from "posthtml";
|
||||
import urls from "@11ty/posthtml-urls";
|
||||
import { FilePathUtil } from "./FilePathUtil.js";
|
||||
|
||||
import { arrayDelete } from "./ArrayUtil.js";
|
||||
|
||||
class HtmlTransformer {
|
||||
// feature test for Eleventy Bundle Plugin
|
||||
static SUPPORTS_PLUGINS_ENABLED_CALLBACK = true;
|
||||
|
||||
static TYPES = ["callbacks", "plugins"];
|
||||
|
||||
constructor() {
|
||||
// execution order is important (not order of addition/object key order)
|
||||
this.callbacks = {};
|
||||
this.posthtmlProcessOptions = {};
|
||||
this.plugins = {};
|
||||
}
|
||||
|
||||
get aggregateBench() {
|
||||
if (!this.userConfig) {
|
||||
throw new Error("Internal error: Missing `userConfig` in HtmlTransformer.");
|
||||
}
|
||||
return this.userConfig.benchmarkManager.get("Aggregate");
|
||||
}
|
||||
|
||||
setUserConfig(config) {
|
||||
this.userConfig = config;
|
||||
}
|
||||
|
||||
static prioritySort(a, b) {
|
||||
if (b.priority > a.priority) {
|
||||
return 1;
|
||||
}
|
||||
if (a.priority > b.priority) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// context is important as it is used in html base plugin for page specific URL
|
||||
static _getPosthtmlInstance(callbacks = [], plugins = [], context = {}) {
|
||||
let inst = posthtml();
|
||||
|
||||
// already sorted by priority when added
|
||||
for (let { fn: plugin, options } of plugins) {
|
||||
inst.use(plugin(Object.assign({}, context, options)));
|
||||
}
|
||||
|
||||
// Run the built-ins last
|
||||
if (callbacks.length > 0) {
|
||||
inst.use(
|
||||
urls({
|
||||
eachURL: (url, attrName, tagName) => {
|
||||
for (let { fn: callback } of callbacks) {
|
||||
// already sorted by priority when added
|
||||
url = callback.call(context, url, { attribute: attrName, tag: tagName });
|
||||
}
|
||||
|
||||
return url;
|
||||
},
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
return inst;
|
||||
}
|
||||
|
||||
_add(extensions, addType, value, options = {}) {
|
||||
options = Object.assign(
|
||||
{
|
||||
priority: 0,
|
||||
},
|
||||
options,
|
||||
);
|
||||
|
||||
let extensionsArray = (extensions || "").split(",");
|
||||
for (let ext of extensionsArray) {
|
||||
let target = this[addType];
|
||||
if (!target[ext]) {
|
||||
target[ext] = [];
|
||||
}
|
||||
|
||||
target[ext].push({
|
||||
// *could* fallback to function name, `value.name`
|
||||
name: options.name, // for `remove` and debugging
|
||||
fn: value, // callback or plugin
|
||||
priority: options.priority, // sorted in descending order
|
||||
enabled: options.enabled || (() => true),
|
||||
options: options.pluginOptions,
|
||||
});
|
||||
|
||||
target[ext].sort(HtmlTransformer.prioritySort);
|
||||
}
|
||||
}
|
||||
|
||||
addPosthtmlPlugin(extensions, plugin, options = {}) {
|
||||
this._add(extensions, "plugins", plugin, options);
|
||||
}
|
||||
|
||||
// match can be a plugin function or a filter callback(plugin => true);
|
||||
remove(extensions, match) {
|
||||
for (let removeType of HtmlTransformer.TYPES) {
|
||||
for (let ext of (extensions || "").split(",")) {
|
||||
this[removeType][ext] = arrayDelete(this[removeType][ext], match);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
addUrlTransform(extensions, callback, options = {}) {
|
||||
this._add(extensions, "callbacks", callback, options);
|
||||
}
|
||||
|
||||
setPosthtmlProcessOptions(options) {
|
||||
Object.assign(this.posthtmlProcessOptions, options);
|
||||
}
|
||||
|
||||
isTransformable(extension, context) {
|
||||
return (
|
||||
this.getCallbacks(extension, context).length > 0 || this.getPlugins(extension).length > 0
|
||||
);
|
||||
}
|
||||
|
||||
getCallbacks(extension, context) {
|
||||
let callbacks = this.callbacks[extension] || [];
|
||||
return callbacks.filter(({ enabled }) => {
|
||||
if (!enabled || typeof enabled !== "function") {
|
||||
return true;
|
||||
}
|
||||
return enabled(context);
|
||||
});
|
||||
}
|
||||
|
||||
getPlugins(extension) {
|
||||
let plugins = this.plugins[extension] || [];
|
||||
return plugins.filter(({ enabled }) => {
|
||||
if (!enabled || typeof enabled !== "function") {
|
||||
return true;
|
||||
}
|
||||
return enabled();
|
||||
});
|
||||
}
|
||||
|
||||
static async transformStandalone(content, callback, posthtmlProcessOptions = {}) {
|
||||
let posthtmlInstance = this._getPosthtmlInstance([
|
||||
{
|
||||
fn: callback,
|
||||
enabled: () => true,
|
||||
},
|
||||
]);
|
||||
let result = await posthtmlInstance.process(content, posthtmlProcessOptions);
|
||||
return result.html;
|
||||
}
|
||||
|
||||
async transformContent(outputPath, content, context) {
|
||||
let extension = FilePathUtil.getFileExtension(outputPath);
|
||||
if (!this.isTransformable(extension, context)) {
|
||||
return content;
|
||||
}
|
||||
|
||||
let bench = this.aggregateBench.get(`Transforming \`${extension}\` with posthtml`);
|
||||
bench.before();
|
||||
let callbacks = this.getCallbacks(extension, context);
|
||||
let plugins = this.getPlugins(extension);
|
||||
let posthtmlInstance = HtmlTransformer._getPosthtmlInstance(callbacks, plugins, context);
|
||||
let result = await posthtmlInstance.process(content, this.posthtmlProcessOptions);
|
||||
bench.after();
|
||||
return result.html;
|
||||
}
|
||||
}
|
||||
|
||||
export { HtmlTransformer };
|
||||
77
node_modules/@11ty/eleventy/src/Util/ImportJsonSync.js
generated
vendored
Normal file
77
node_modules/@11ty/eleventy/src/Util/ImportJsonSync.js
generated
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
import fs from "node:fs";
|
||||
import { createRequire } from "node:module";
|
||||
import debugUtil from "debug";
|
||||
|
||||
import { TemplatePath } from "@11ty/eleventy-utils";
|
||||
|
||||
import { normalizeFilePathInEleventyPackage } from "./Require.js";
|
||||
|
||||
const debug = debugUtil("Eleventy:ImportJsonSync");
|
||||
const require = createRequire(import.meta.url);
|
||||
|
||||
function findFilePathInParentDirs(dir, filename) {
|
||||
// `package.json` searches look in parent dirs:
|
||||
// https://docs.npmjs.com/cli/v7/configuring-npm/folders#more-information
|
||||
// Fixes issue #3178, limited to working dir paths only
|
||||
let workingDir = TemplatePath.getWorkingDir();
|
||||
// TODO use DirContains
|
||||
let allDirs = TemplatePath.getAllDirs(dir).filter((entry) => entry.startsWith(workingDir));
|
||||
|
||||
for (let dir of allDirs) {
|
||||
let newPath = TemplatePath.join(dir, filename);
|
||||
if (fs.existsSync(newPath)) {
|
||||
debug("Found %o searching parent directories at: %o", filename, dir);
|
||||
return newPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function importJsonSync(filePath) {
|
||||
if (!filePath || !filePath.endsWith(".json")) {
|
||||
throw new Error(`importJsonSync expects a .json file extension (received: ${filePath})`);
|
||||
}
|
||||
|
||||
return require(filePath);
|
||||
}
|
||||
|
||||
function getEleventyPackageJson() {
|
||||
let filePath = normalizeFilePathInEleventyPackage("package.json");
|
||||
return importJsonSync(filePath);
|
||||
}
|
||||
|
||||
function getModulePackageJson(dir) {
|
||||
let filePath = findFilePathInParentDirs(TemplatePath.absolutePath(dir), "package.json");
|
||||
|
||||
// optional!
|
||||
if (!filePath) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return importJsonSync(filePath);
|
||||
}
|
||||
|
||||
// This will *not* find a package.json in a parent directory above root
|
||||
function getWorkingProjectPackageJsonPath() {
|
||||
let dir = TemplatePath.absolutePath(TemplatePath.getWorkingDir());
|
||||
return findFilePathInParentDirs(dir, "package.json");
|
||||
}
|
||||
|
||||
function getWorkingProjectPackageJson() {
|
||||
let filePath = getWorkingProjectPackageJsonPath();
|
||||
|
||||
// optional!
|
||||
if (!filePath) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return importJsonSync(filePath);
|
||||
}
|
||||
|
||||
export {
|
||||
importJsonSync,
|
||||
findFilePathInParentDirs,
|
||||
getEleventyPackageJson,
|
||||
getModulePackageJson,
|
||||
getWorkingProjectPackageJson,
|
||||
getWorkingProjectPackageJsonPath,
|
||||
};
|
||||
5
node_modules/@11ty/eleventy/src/Util/IsAsyncFunction.js
generated
vendored
Normal file
5
node_modules/@11ty/eleventy/src/Util/IsAsyncFunction.js
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
const ComparisonAsyncFunction = (async () => {}).constructor;
|
||||
|
||||
export default function isAsyncFunction(fn) {
|
||||
return fn instanceof ComparisonAsyncFunction;
|
||||
}
|
||||
55
node_modules/@11ty/eleventy/src/Util/JavaScriptDependencies.js
generated
vendored
Normal file
55
node_modules/@11ty/eleventy/src/Util/JavaScriptDependencies.js
generated
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
import dependencyTree from "@11ty/dependency-tree";
|
||||
import { find } from "@11ty/dependency-tree-esm";
|
||||
import { TemplatePath } from "@11ty/eleventy-utils";
|
||||
|
||||
import EleventyBaseError from "../Errors/EleventyBaseError.js";
|
||||
|
||||
class JavaScriptDependencies {
|
||||
static getErrorMessage(file, type) {
|
||||
return `A problem was encountered looking for JavaScript dependencies in ${type} file: ${file}. This only affects --watch and --serve behavior and does not affect your build.`;
|
||||
}
|
||||
|
||||
static async getDependencies(inputFiles, isProjectUsingEsm) {
|
||||
let depSet = new Set();
|
||||
|
||||
// TODO does this need to work with aliasing? what other JS extensions will have deps?
|
||||
let commonJsFiles = inputFiles.filter(
|
||||
(file) => (!isProjectUsingEsm && file.endsWith(".js")) || file.endsWith(".cjs"),
|
||||
);
|
||||
|
||||
for (let file of commonJsFiles) {
|
||||
try {
|
||||
let modules = dependencyTree(file, {
|
||||
nodeModuleNames: "exclude",
|
||||
allowNotFound: true,
|
||||
}).map((dependency) => {
|
||||
return TemplatePath.addLeadingDotSlash(TemplatePath.relativePath(dependency));
|
||||
});
|
||||
|
||||
for (let dep of modules) {
|
||||
depSet.add(dep);
|
||||
}
|
||||
} catch (e) {
|
||||
throw new EleventyBaseError(this.getErrorMessage(file, "CommonJS"), e);
|
||||
}
|
||||
}
|
||||
|
||||
let esmFiles = inputFiles.filter(
|
||||
(file) => (isProjectUsingEsm && file.endsWith(".js")) || file.endsWith(".mjs"),
|
||||
);
|
||||
for (let file of esmFiles) {
|
||||
try {
|
||||
let modules = await find(file);
|
||||
for (let dep of modules) {
|
||||
depSet.add(dep);
|
||||
}
|
||||
} catch (e) {
|
||||
throw new EleventyBaseError(this.getErrorMessage(file, "ESM"), e);
|
||||
}
|
||||
}
|
||||
|
||||
return Array.from(depSet).sort();
|
||||
}
|
||||
}
|
||||
|
||||
export default JavaScriptDependencies;
|
||||
26
node_modules/@11ty/eleventy/src/Util/MemoizeFunction.js
generated
vendored
Normal file
26
node_modules/@11ty/eleventy/src/Util/MemoizeFunction.js
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
export default function (callback, options = {}) {
|
||||
let { bench, name } = options;
|
||||
let cache = new Map();
|
||||
|
||||
return (...args) => {
|
||||
// Only supports single-arg functions for now.
|
||||
if (args.filter(Boolean).length > 1) {
|
||||
bench?.get(`(count) ${name} Not valid for memoize`).incrementCount();
|
||||
return callback(...args);
|
||||
}
|
||||
|
||||
let [cacheKey] = args;
|
||||
|
||||
if (!cache.has(cacheKey)) {
|
||||
cache.set(cacheKey, callback(...args));
|
||||
|
||||
bench?.get(`(count) ${name} memoize miss`).incrementCount();
|
||||
|
||||
return cache.get(cacheKey);
|
||||
}
|
||||
|
||||
bench?.get(`(count) ${name} memoize hit`).incrementCount();
|
||||
|
||||
return cache.get(cacheKey);
|
||||
};
|
||||
}
|
||||
20
node_modules/@11ty/eleventy/src/Util/Objects/DeepFreeze.js
generated
vendored
Normal file
20
node_modules/@11ty/eleventy/src/Util/Objects/DeepFreeze.js
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
import { isPlainObject } from "@11ty/eleventy-utils";
|
||||
|
||||
// via https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze
|
||||
|
||||
function DeepFreeze(obj, topLevelExceptions) {
|
||||
for (let name of Reflect.ownKeys(obj)) {
|
||||
if ((topLevelExceptions || []).find((key) => key === name)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const value = obj[name];
|
||||
if (isPlainObject(value)) {
|
||||
DeepFreeze(value);
|
||||
}
|
||||
}
|
||||
|
||||
return Object.freeze(obj);
|
||||
}
|
||||
|
||||
export { DeepFreeze };
|
||||
9
node_modules/@11ty/eleventy/src/Util/Objects/ObjectFilter.js
generated
vendored
Normal file
9
node_modules/@11ty/eleventy/src/Util/Objects/ObjectFilter.js
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
export default function objectFilter(obj, callback) {
|
||||
let newObject = {};
|
||||
for (let [key, value] of Object.entries(obj || {})) {
|
||||
if (callback(value, key)) {
|
||||
newObject[key] = value;
|
||||
}
|
||||
}
|
||||
return newObject;
|
||||
}
|
||||
118
node_modules/@11ty/eleventy/src/Util/Objects/ProxyWrap.js
generated
vendored
Normal file
118
node_modules/@11ty/eleventy/src/Util/Objects/ProxyWrap.js
generated
vendored
Normal file
@@ -0,0 +1,118 @@
|
||||
import types from "node:util/types";
|
||||
import debugUtil from "debug";
|
||||
import { isPlainObject } from "@11ty/eleventy-utils";
|
||||
|
||||
const debug = debugUtil("Dev:Eleventy:Proxy");
|
||||
|
||||
function wrapObject(target, fallback) {
|
||||
if (Object.isFrozen(target)) {
|
||||
return target;
|
||||
}
|
||||
|
||||
return new Proxy(target, {
|
||||
getOwnPropertyDescriptor(target, prop) {
|
||||
let ret;
|
||||
|
||||
if (Reflect.has(target, prop)) {
|
||||
ret = Reflect.getOwnPropertyDescriptor(target, prop);
|
||||
} else if (Reflect.has(fallback, prop)) {
|
||||
ret = Reflect.getOwnPropertyDescriptor(fallback, prop);
|
||||
}
|
||||
|
||||
return ret;
|
||||
},
|
||||
has(target, prop) {
|
||||
if (Reflect.has(target, prop)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return Reflect.has(fallback, prop);
|
||||
},
|
||||
ownKeys(target) {
|
||||
let s = new Set();
|
||||
// The fallback keys need to come first to preserve proper key order
|
||||
// https://github.com/11ty/eleventy/issues/3849
|
||||
if (isPlainObject(fallback)) {
|
||||
for (let k of Reflect.ownKeys(fallback)) {
|
||||
s.add(k);
|
||||
}
|
||||
}
|
||||
for (let k of Reflect.ownKeys(target)) {
|
||||
if (!s.has(k)) {
|
||||
s.add(k);
|
||||
}
|
||||
}
|
||||
return Array.from(s);
|
||||
},
|
||||
get(target, prop) {
|
||||
debug("handler:get", prop);
|
||||
|
||||
let value = Reflect.get(target, prop);
|
||||
|
||||
if (Reflect.has(target, prop)) {
|
||||
// Already proxied
|
||||
if (types.isProxy(value)) {
|
||||
return value;
|
||||
}
|
||||
|
||||
if (isPlainObject(value) && Reflect.has(fallback, prop)) {
|
||||
if (Object.isFrozen(value)) {
|
||||
return value;
|
||||
}
|
||||
|
||||
let ret = wrapObject(value, Reflect.get(fallback, prop));
|
||||
debug("handler:get (primary, object)", prop);
|
||||
return ret;
|
||||
}
|
||||
|
||||
debug("handler:get (primary)", prop);
|
||||
return value;
|
||||
}
|
||||
|
||||
// Does not exist in primary
|
||||
if (
|
||||
(typeof fallback === "object" || typeof fallback === "function") &&
|
||||
Reflect.has(fallback, prop)
|
||||
) {
|
||||
// fallback has prop
|
||||
let fallbackValue = Reflect.get(fallback, prop);
|
||||
|
||||
if (isPlainObject(fallbackValue)) {
|
||||
if (Object.isFrozen(fallbackValue)) {
|
||||
return fallbackValue;
|
||||
}
|
||||
|
||||
debug("handler:get (fallback, object)", prop);
|
||||
// set empty object on primary
|
||||
let emptyObject = {};
|
||||
Reflect.set(target, prop, emptyObject);
|
||||
|
||||
return wrapObject(emptyObject, fallbackValue);
|
||||
}
|
||||
|
||||
debug("handler:get (fallback)", prop);
|
||||
return fallbackValue;
|
||||
}
|
||||
|
||||
// primary *and* fallback do _not_ have prop
|
||||
debug("handler:get (not on primary or fallback)", prop);
|
||||
|
||||
return value;
|
||||
},
|
||||
set(target, prop, value) {
|
||||
debug("handler:set", prop);
|
||||
|
||||
return Reflect.set(target, prop, value);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function ProxyWrap(target, fallback) {
|
||||
if (!isPlainObject(target) || !isPlainObject(fallback)) {
|
||||
throw new Error("ProxyWrap expects objects for both the target and fallback");
|
||||
}
|
||||
|
||||
return wrapObject(target, fallback);
|
||||
}
|
||||
|
||||
export { ProxyWrap };
|
||||
1
node_modules/@11ty/eleventy/src/Util/Objects/SampleModule.mjs
generated
vendored
Normal file
1
node_modules/@11ty/eleventy/src/Util/Objects/SampleModule.mjs
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export default {};
|
||||
136
node_modules/@11ty/eleventy/src/Util/Objects/Sortable.js
generated
vendored
Normal file
136
node_modules/@11ty/eleventy/src/Util/Objects/Sortable.js
generated
vendored
Normal file
@@ -0,0 +1,136 @@
|
||||
class Sortable {
|
||||
constructor() {
|
||||
this.isSortAscending = true;
|
||||
this.isSortNumeric = false;
|
||||
this.items = [];
|
||||
this._dirty = true;
|
||||
|
||||
this.sortFunctionStringMap = {
|
||||
"A-Z": "sortFunctionAscending",
|
||||
"Z-A": "sortFunctionDescending",
|
||||
"0-9": "sortFunctionNumericAscending",
|
||||
"9-0": "sortFunctionNumericDescending",
|
||||
};
|
||||
}
|
||||
|
||||
get length() {
|
||||
return this.items.length;
|
||||
}
|
||||
|
||||
add(item) {
|
||||
this._dirty = true;
|
||||
this.items.push(item);
|
||||
}
|
||||
|
||||
sort(sortFunction) {
|
||||
if (!sortFunction) {
|
||||
sortFunction = this.getSortFunction();
|
||||
} else if (typeof sortFunction === "string") {
|
||||
let key = sortFunction;
|
||||
let name;
|
||||
if (key in this.sortFunctionStringMap) {
|
||||
name = this.sortFunctionStringMap[key];
|
||||
}
|
||||
if (Sortable[name]) {
|
||||
sortFunction = Sortable[name];
|
||||
} else {
|
||||
throw new Error(
|
||||
`Invalid String argument for sort(). Received \`${key}\`. Valid values: ${Object.keys(
|
||||
this.sortFunctionStringMap,
|
||||
)}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return this.items.slice().sort(sortFunction);
|
||||
}
|
||||
|
||||
sortAscending() {
|
||||
return this.sort(this.getSortFunctionAscending());
|
||||
}
|
||||
|
||||
sortDescending() {
|
||||
return this.sort(this.getSortFunctionDescending());
|
||||
}
|
||||
|
||||
setSortDescending(isDescending = true) {
|
||||
this.isSortAscending = !isDescending;
|
||||
}
|
||||
|
||||
setSortAscending(isAscending = true) {
|
||||
this.isSortAscending = isAscending;
|
||||
}
|
||||
|
||||
setSortNumeric(isNumeric) {
|
||||
this.isSortNumeric = 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.isSortAscending) {
|
||||
return this.getSortFunctionAscending();
|
||||
} else {
|
||||
return this.getSortFunctionDescending();
|
||||
}
|
||||
}
|
||||
|
||||
getSortFunctionAscending() {
|
||||
if (this.isSortNumeric) {
|
||||
return Sortable.sortFunctionNumericAscending;
|
||||
} else {
|
||||
return Sortable.sortFunctionAlphabeticAscending;
|
||||
}
|
||||
}
|
||||
|
||||
getSortFunctionDescending() {
|
||||
if (this.isSortNumeric) {
|
||||
return Sortable.sortFunctionNumericDescending;
|
||||
} else {
|
||||
return Sortable.sortFunctionAlphabeticDescending;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default Sortable;
|
||||
3
node_modules/@11ty/eleventy/src/Util/Objects/Unique.js
generated
vendored
Normal file
3
node_modules/@11ty/eleventy/src/Util/Objects/Unique.js
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
export default function Unique(arr) {
|
||||
return Array.from(new Set(arr));
|
||||
}
|
||||
16
node_modules/@11ty/eleventy/src/Util/PassthroughCopyBehaviorCheck.js
generated
vendored
Normal file
16
node_modules/@11ty/eleventy/src/Util/PassthroughCopyBehaviorCheck.js
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
function isUsingEleventyDevServer(config) {
|
||||
return (
|
||||
!config.serverOptions.module || config.serverOptions.module === "@11ty/eleventy-dev-server"
|
||||
);
|
||||
}
|
||||
|
||||
// Config opt-out via serverPassthroughCopyBehavior
|
||||
// False when other server is used
|
||||
// False when runMode is "build" or "watch"
|
||||
export default function (config, runMode) {
|
||||
return (
|
||||
config.serverPassthroughCopyBehavior === "passthrough" &&
|
||||
isUsingEleventyDevServer(config) &&
|
||||
runMode === "serve"
|
||||
);
|
||||
}
|
||||
58
node_modules/@11ty/eleventy/src/Util/PathNormalizer.js
generated
vendored
Normal file
58
node_modules/@11ty/eleventy/src/Util/PathNormalizer.js
generated
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { TemplatePath } from "@11ty/eleventy-utils";
|
||||
|
||||
export default class PathNormalizer {
|
||||
static getParts(inputPath) {
|
||||
if (!inputPath) {
|
||||
return [];
|
||||
}
|
||||
|
||||
let separator = "/";
|
||||
if (inputPath.includes(path.sep)) {
|
||||
separator = path.sep;
|
||||
}
|
||||
|
||||
return inputPath.split(separator).filter((entry) => entry !== ".");
|
||||
}
|
||||
|
||||
// order is important here: the top-most directory returns first
|
||||
// array of file and all parent directories
|
||||
static getAllPaths(inputPath) {
|
||||
let parts = this.getParts(inputPath);
|
||||
let allPaths = [];
|
||||
|
||||
let fullpath = "";
|
||||
for (let part of parts) {
|
||||
fullpath += (fullpath.length > 0 ? "/" : "") + part;
|
||||
allPaths.push(fullpath);
|
||||
}
|
||||
|
||||
return allPaths;
|
||||
}
|
||||
|
||||
static normalizeSeperator(inputPath) {
|
||||
if (!inputPath) {
|
||||
return inputPath;
|
||||
}
|
||||
return inputPath.split(path.sep).join("/");
|
||||
}
|
||||
|
||||
static fullNormalization(inputPath) {
|
||||
if (typeof inputPath !== "string") {
|
||||
return inputPath;
|
||||
}
|
||||
|
||||
// Fix file:///Users/ or file:///C:/ paths passed in
|
||||
if (inputPath.startsWith("file://")) {
|
||||
inputPath = fileURLToPath(inputPath);
|
||||
}
|
||||
|
||||
// Paths should not be absolute (we convert absolute paths to relative)
|
||||
// Paths should not have a leading dot slash
|
||||
// Paths should always be `/` independent of OS path separator
|
||||
return TemplatePath.stripLeadingDotSlash(
|
||||
this.normalizeSeperator(TemplatePath.relativePath(inputPath)),
|
||||
);
|
||||
}
|
||||
}
|
||||
21
node_modules/@11ty/eleventy/src/Util/PathPrefixer.js
generated
vendored
Normal file
21
node_modules/@11ty/eleventy/src/Util/PathPrefixer.js
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
import path from "node:path";
|
||||
|
||||
import PathNormalizer from "./PathNormalizer.js";
|
||||
|
||||
class PathPrefixer {
|
||||
static normalizePathPrefix(pathPrefix) {
|
||||
if (pathPrefix) {
|
||||
// add leading / (for browsersync), see #1454
|
||||
// path.join uses \\ for Windows so we split and rejoin
|
||||
return PathPrefixer.joinUrlParts("/", pathPrefix);
|
||||
}
|
||||
|
||||
return "/";
|
||||
}
|
||||
|
||||
static joinUrlParts(...parts) {
|
||||
return PathNormalizer.normalizeSeperator(path.join(...parts));
|
||||
}
|
||||
}
|
||||
|
||||
export default PathPrefixer;
|
||||
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 @@
|
||||
export default function (count, singleWord, pluralWord) {
|
||||
return count === 1 ? singleWord : pluralWord;
|
||||
}
|
||||
369
node_modules/@11ty/eleventy/src/Util/ProjectDirectories.js
generated
vendored
Normal file
369
node_modules/@11ty/eleventy/src/Util/ProjectDirectories.js
generated
vendored
Normal file
@@ -0,0 +1,369 @@
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { TemplatePath } from "@11ty/eleventy-utils";
|
||||
import { isDynamicPattern } from "tinyglobby";
|
||||
|
||||
import DirContains from "./DirContains.js";
|
||||
|
||||
/* Directories internally should always use *nix forward slashes */
|
||||
class ProjectDirectories {
|
||||
static defaults = {
|
||||
input: "./",
|
||||
data: "./_data/", // Relative to input directory
|
||||
includes: "./_includes/", // Relative to input directory
|
||||
layouts: "./_layouts/", // Relative to input directory
|
||||
output: "./_site/",
|
||||
};
|
||||
|
||||
// no updates allowed, input/output set via CLI
|
||||
#frozen = false;
|
||||
|
||||
#raw = {};
|
||||
|
||||
#dirs = {};
|
||||
|
||||
inputFile = undefined;
|
||||
inputGlob = undefined;
|
||||
|
||||
// Add leading dot slash
|
||||
// Use forward slashes
|
||||
static normalizePath(fileOrDir) {
|
||||
return TemplatePath.standardizeFilePath(fileOrDir);
|
||||
}
|
||||
|
||||
// Must be a directory
|
||||
// Always include a trailing slash
|
||||
static normalizeDirectory(dir) {
|
||||
return this.addTrailingSlash(this.normalizePath(dir));
|
||||
}
|
||||
|
||||
normalizeDirectoryPathRelativeToInputDirectory(filePath) {
|
||||
return ProjectDirectories.normalizeDirectory(path.join(this.input, filePath));
|
||||
}
|
||||
|
||||
static addTrailingSlash(path) {
|
||||
if (path.slice(-1) === "/") {
|
||||
return path;
|
||||
}
|
||||
return path + "/";
|
||||
}
|
||||
|
||||
// If input/output are set via CLI, they take precedence over all other configuration values.
|
||||
freeze() {
|
||||
this.#frozen = true;
|
||||
}
|
||||
|
||||
setViaConfigObject(configDirs = {}) {
|
||||
// input must come last
|
||||
let inputChanged = false;
|
||||
if (
|
||||
configDirs.input &&
|
||||
ProjectDirectories.normalizeDirectory(configDirs.input) !== this.input
|
||||
) {
|
||||
this.#setInputRaw(configDirs.input);
|
||||
inputChanged = true;
|
||||
}
|
||||
|
||||
// If falsy or an empty string, the current directory is used.
|
||||
if (configDirs.output !== undefined) {
|
||||
if (ProjectDirectories.normalizeDirectory(configDirs.output) !== this.output) {
|
||||
this.setOutput(configDirs.output);
|
||||
}
|
||||
}
|
||||
|
||||
// Input relative directory, if falsy or an empty string, inputDir is used!
|
||||
// Always set if input changed, e.g. input is `src` and data is `../_data` (resulting in `./_data`) we still want to set data to this new value
|
||||
if (configDirs.data !== undefined) {
|
||||
if (
|
||||
inputChanged ||
|
||||
this.normalizeDirectoryPathRelativeToInputDirectory(configDirs.data || "") !== this.data
|
||||
) {
|
||||
this.setData(configDirs.data);
|
||||
}
|
||||
}
|
||||
|
||||
// Input relative directory, if falsy or an empty string, inputDir is used!
|
||||
if (configDirs.includes !== undefined) {
|
||||
if (
|
||||
inputChanged ||
|
||||
this.normalizeDirectoryPathRelativeToInputDirectory(configDirs.includes || "") !==
|
||||
this.includes
|
||||
) {
|
||||
this.setIncludes(configDirs.includes);
|
||||
}
|
||||
}
|
||||
|
||||
// Input relative directory, if falsy or an empty string, inputDir is used!
|
||||
if (configDirs.layouts !== undefined) {
|
||||
if (
|
||||
inputChanged ||
|
||||
this.normalizeDirectoryPathRelativeToInputDirectory(configDirs.layouts || "") !==
|
||||
this.layouts
|
||||
) {
|
||||
this.setLayouts(configDirs.layouts);
|
||||
}
|
||||
}
|
||||
|
||||
if (inputChanged) {
|
||||
this.updateInputDependencies();
|
||||
}
|
||||
}
|
||||
|
||||
updateInputDependencies() {
|
||||
// raw first, fall back to Eleventy defaults if not yet set
|
||||
this.setData(this.#raw.data ?? ProjectDirectories.defaults.data);
|
||||
this.setIncludes(this.#raw.includes ?? ProjectDirectories.defaults.includes);
|
||||
|
||||
// Should not include this if not explicitly opted-in
|
||||
if (this.#raw.layouts !== undefined) {
|
||||
this.setLayouts(this.#raw.layouts ?? ProjectDirectories.defaults.layouts);
|
||||
}
|
||||
}
|
||||
|
||||
/* Relative to project root, must exist */
|
||||
#setInputRaw(dirOrFile, inputDir = undefined) {
|
||||
// is frozen and was defined previously
|
||||
if (this.#frozen && this.#raw.input !== undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.#raw.input = dirOrFile;
|
||||
|
||||
if (!dirOrFile) {
|
||||
// input must exist if inputDir is not set.
|
||||
return;
|
||||
}
|
||||
|
||||
// Normalize absolute paths to relative, #3805
|
||||
// if(path.isAbsolute(dirOrFile)) {
|
||||
// dirOrFile = path.relative(".", dirOrFile);
|
||||
// }
|
||||
|
||||
// Input has to exist (assumed glob if it does not exist)
|
||||
let inputExists = fs.existsSync(dirOrFile);
|
||||
let inputExistsAndIsDirectory = inputExists && fs.statSync(dirOrFile).isDirectory();
|
||||
|
||||
if (inputExistsAndIsDirectory) {
|
||||
// is not a file or glob
|
||||
this.#dirs.input = ProjectDirectories.normalizeDirectory(dirOrFile);
|
||||
} else {
|
||||
if (inputExists) {
|
||||
this.inputFile = ProjectDirectories.normalizePath(dirOrFile);
|
||||
} else {
|
||||
if (!isDynamicPattern(dirOrFile)) {
|
||||
throw new Error(
|
||||
`The "${dirOrFile}" \`input\` parameter (directory or file path) must exist on the file system (unless detected as a glob by the \`tinyglobby\` package)`,
|
||||
);
|
||||
}
|
||||
|
||||
this.inputGlob = dirOrFile;
|
||||
}
|
||||
|
||||
// Explicit Eleventy option for inputDir
|
||||
if (inputDir) {
|
||||
// Changed in 3.0: must exist
|
||||
if (!fs.existsSync(inputDir)) {
|
||||
throw new Error("Directory must exist (via inputDir option to Eleventy constructor).");
|
||||
}
|
||||
|
||||
this.#dirs.input = ProjectDirectories.normalizeDirectory(inputDir);
|
||||
} else {
|
||||
// the input directory is implied to be the parent directory of the
|
||||
// file, unless inputDir is explicitly specified (via Eleventy constructor `options`)
|
||||
this.#dirs.input = ProjectDirectories.normalizeDirectory(
|
||||
TemplatePath.getDirFromFilePath(dirOrFile), // works with globs
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setInput(dirOrFile, inputDir = undefined) {
|
||||
this.#setInputRaw(dirOrFile, inputDir); // does not update
|
||||
this.updateInputDependencies();
|
||||
}
|
||||
|
||||
/* Relative to input dir */
|
||||
setIncludes(dir) {
|
||||
if (dir !== undefined) {
|
||||
// falsy or an empty string is valid (falls back to input dir)
|
||||
this.#raw.includes = dir;
|
||||
this.#dirs.includes = ProjectDirectories.normalizeDirectory(
|
||||
TemplatePath.join(this.input, dir || ""),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/* Relative to input dir */
|
||||
/* Optional */
|
||||
setLayouts(dir) {
|
||||
if (dir !== undefined) {
|
||||
// falsy or an empty string is valid (falls back to input dir)
|
||||
this.#raw.layouts = dir;
|
||||
this.#dirs.layouts = ProjectDirectories.normalizeDirectory(
|
||||
TemplatePath.join(this.input, dir || ""),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/* Relative to input dir */
|
||||
setData(dir) {
|
||||
if (dir !== undefined) {
|
||||
// falsy or an empty string is valid (falls back to input dir)
|
||||
// TODO must exist if specified
|
||||
this.#raw.data = dir;
|
||||
this.#dirs.data = ProjectDirectories.normalizeDirectory(
|
||||
TemplatePath.join(this.input, dir || ""),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/* Relative to project root */
|
||||
setOutput(dir) {
|
||||
// is frozen and was defined previously
|
||||
if (this.#frozen && this.#raw.output !== undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (dir !== undefined) {
|
||||
this.#raw.output = dir;
|
||||
this.#dirs.output = ProjectDirectories.normalizeDirectory(dir || "");
|
||||
}
|
||||
}
|
||||
|
||||
get input() {
|
||||
return this.#dirs.input || ProjectDirectories.defaults.input;
|
||||
}
|
||||
|
||||
get data() {
|
||||
return this.#dirs.data || ProjectDirectories.defaults.data;
|
||||
}
|
||||
|
||||
get includes() {
|
||||
return this.#dirs.includes || ProjectDirectories.defaults.includes;
|
||||
}
|
||||
|
||||
get layouts() {
|
||||
// explicit opt-in, no fallback.
|
||||
return this.#dirs.layouts;
|
||||
}
|
||||
|
||||
get output() {
|
||||
return this.#dirs.output || ProjectDirectories.defaults.output;
|
||||
}
|
||||
|
||||
isTemplateFile(filePath) {
|
||||
let inputPath = this.getInputPath(filePath);
|
||||
// TODO use DirContains
|
||||
if (this.layouts && inputPath.startsWith(this.layouts)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// if this.includes is "" (and thus is the same directory as this.input)
|
||||
// we don’t actually know if this is a template file, so defer
|
||||
if (this.includes && this.includes !== this.input) {
|
||||
if (inputPath.startsWith(this.includes)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO use DirContains
|
||||
return inputPath.startsWith(this.input);
|
||||
}
|
||||
|
||||
// for a hypothetical template file
|
||||
getInputPath(filePathRelativeToInputDir) {
|
||||
// TODO change ~/ to project root dir
|
||||
return TemplatePath.addLeadingDotSlash(
|
||||
TemplatePath.join(this.input, TemplatePath.standardizeFilePath(filePathRelativeToInputDir)),
|
||||
);
|
||||
}
|
||||
|
||||
// Inverse of getInputPath
|
||||
// Removes input dir from path
|
||||
getInputPathRelativeToInputDirectory(filePathRelativeToInputDir) {
|
||||
let inputDir = TemplatePath.addLeadingDotSlash(TemplatePath.join(this.input));
|
||||
|
||||
// No leading dot slash
|
||||
return TemplatePath.stripLeadingSubPath(filePathRelativeToInputDir, inputDir);
|
||||
}
|
||||
|
||||
// for a hypothetical Eleventy layout file
|
||||
getLayoutPath(filePathRelativeToLayoutDir) {
|
||||
return TemplatePath.addLeadingDotSlash(
|
||||
TemplatePath.join(
|
||||
this.layouts || this.includes,
|
||||
TemplatePath.standardizeFilePath(filePathRelativeToLayoutDir),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Removes layout dir from path
|
||||
getLayoutPathRelativeToInputDirectory(filePathRelativeToLayoutDir) {
|
||||
let layoutPath = this.getLayoutPath(filePathRelativeToLayoutDir);
|
||||
let inputDir = TemplatePath.addLeadingDotSlash(TemplatePath.join(this.input));
|
||||
|
||||
// No leading dot slash
|
||||
return TemplatePath.stripLeadingSubPath(layoutPath, inputDir);
|
||||
}
|
||||
|
||||
getProjectPath(filePath) {
|
||||
return TemplatePath.addLeadingDotSlash(
|
||||
TemplatePath.join(".", TemplatePath.standardizeFilePath(filePath)),
|
||||
);
|
||||
}
|
||||
|
||||
isFileInProjectFolder(filePath) {
|
||||
return DirContains(TemplatePath.getWorkingDir(), filePath);
|
||||
}
|
||||
|
||||
isFileInOutputFolder(filePath) {
|
||||
return DirContains(this.output, filePath);
|
||||
}
|
||||
|
||||
static getRelativeTo(targetPath, cwd) {
|
||||
return path.relative(cwd, path.join(path.resolve("."), targetPath));
|
||||
}
|
||||
|
||||
// Access the data without being able to set the data.
|
||||
getUserspaceInstance() {
|
||||
let d = this;
|
||||
|
||||
return {
|
||||
get input() {
|
||||
return d.input;
|
||||
},
|
||||
get inputFile() {
|
||||
return d.inputFile;
|
||||
},
|
||||
get inputGlob() {
|
||||
return d.inputGlob;
|
||||
},
|
||||
get data() {
|
||||
return d.data;
|
||||
},
|
||||
get includes() {
|
||||
return d.includes;
|
||||
},
|
||||
get layouts() {
|
||||
return d.layouts;
|
||||
},
|
||||
get output() {
|
||||
return d.output;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
toString() {
|
||||
return {
|
||||
input: this.input,
|
||||
inputFile: this.inputFile,
|
||||
inputGlob: this.inputGlob,
|
||||
data: this.data,
|
||||
includes: this.includes,
|
||||
layouts: this.layouts,
|
||||
output: this.output,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export default ProjectDirectories;
|
||||
134
node_modules/@11ty/eleventy/src/Util/ProjectTemplateFormats.js
generated
vendored
Normal file
134
node_modules/@11ty/eleventy/src/Util/ProjectTemplateFormats.js
generated
vendored
Normal file
@@ -0,0 +1,134 @@
|
||||
import debugUtil from "debug";
|
||||
const debug = debugUtil("Eleventy:Util:ProjectTemplateFormats");
|
||||
|
||||
class ProjectTemplateFormats {
|
||||
#useAll = {};
|
||||
#raw = {};
|
||||
|
||||
#values = {}; // Set objects
|
||||
|
||||
static union(...sets) {
|
||||
let s = new Set();
|
||||
|
||||
for (let set of sets) {
|
||||
if (!set || typeof set[Symbol.iterator] !== "function") {
|
||||
continue;
|
||||
}
|
||||
for (let v of set) {
|
||||
s.add(v);
|
||||
}
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
#normalize(formats) {
|
||||
if (Array.isArray(formats)) {
|
||||
formats = "" + formats.join(",");
|
||||
}
|
||||
|
||||
if (typeof formats !== "string") {
|
||||
throw new Error(
|
||||
`Invalid formats (expect String, Array) passed to ProjectTemplateFormats->normalize: ${formats}`,
|
||||
);
|
||||
}
|
||||
|
||||
let final = new Set();
|
||||
for (let format of formats.split(",")) {
|
||||
format = format.trim();
|
||||
if (format && format !== "*") {
|
||||
final.add(format);
|
||||
}
|
||||
}
|
||||
|
||||
return final;
|
||||
}
|
||||
|
||||
isWildcard() {
|
||||
return this.#useAll.cli || this.#useAll.config || false;
|
||||
}
|
||||
|
||||
/** @returns {boolean} */
|
||||
#isUseAll(rawFormats) {
|
||||
if (rawFormats === "") {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (typeof rawFormats === "string") {
|
||||
rawFormats = rawFormats.split(",");
|
||||
}
|
||||
|
||||
if (Array.isArray(rawFormats)) {
|
||||
return rawFormats.find((entry) => entry === "*") !== undefined;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// 3.x Breaking: "" now means no formats. In 2.x and prior it meant "*"
|
||||
setViaCommandLine(formats) {
|
||||
if (formats === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.#useAll.cli = this.#isUseAll(formats);
|
||||
this.#raw.cli = formats;
|
||||
this.#values.cli = this.#normalize(formats);
|
||||
}
|
||||
|
||||
// 3.x Breaking: "" now means no formats—in 2.x and prior it meant "*"
|
||||
// 3.x Adds support for comma separated string—in 2.x this required an Array
|
||||
setViaConfig(formats) {
|
||||
if (formats === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
// "*" is supported
|
||||
this.#useAll.config = this.#isUseAll(formats);
|
||||
this.#raw.config = formats;
|
||||
this.#values.config = this.#normalize(formats);
|
||||
}
|
||||
|
||||
addViaConfig(formats) {
|
||||
if (!formats) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.#isUseAll(formats)) {
|
||||
throw new Error(
|
||||
`\`addTemplateFormats("*")\` is not supported for project template syntaxes.`,
|
||||
);
|
||||
}
|
||||
|
||||
// "*" not supported here
|
||||
this.#raw.configAdd = formats;
|
||||
this.#values.configAdd = this.#normalize(formats);
|
||||
}
|
||||
|
||||
getAllTemplateFormats() {
|
||||
return Array.from(ProjectTemplateFormats.union(this.#values.config, this.#values.configAdd));
|
||||
}
|
||||
|
||||
getTemplateFormats() {
|
||||
if (this.#useAll.cli) {
|
||||
let v = this.getAllTemplateFormats();
|
||||
debug("Using CLI --formats='*': %o", v);
|
||||
return v;
|
||||
}
|
||||
|
||||
if (this.#raw.cli !== undefined) {
|
||||
let v = Array.from(this.#values.cli);
|
||||
debug("Using CLI --formats: %o", v);
|
||||
return v;
|
||||
}
|
||||
|
||||
let v = this.getAllTemplateFormats();
|
||||
debug(
|
||||
"Using configuration `templateFormats`, `setTemplateFormats()`, `addTemplateFormats()`: %o",
|
||||
v,
|
||||
);
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
||||
export default ProjectTemplateFormats;
|
||||
15
node_modules/@11ty/eleventy/src/Util/PromiseUtil.js
generated
vendored
Normal file
15
node_modules/@11ty/eleventy/src/Util/PromiseUtil.js
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
function withResolvers() {
|
||||
if ("withResolvers" in Promise) {
|
||||
return Promise.withResolvers();
|
||||
}
|
||||
|
||||
let resolve;
|
||||
let reject;
|
||||
let promise = new Promise((res, rej) => {
|
||||
resolve = res;
|
||||
reject = rej;
|
||||
});
|
||||
return { promise, resolve, reject };
|
||||
}
|
||||
|
||||
export { withResolvers };
|
||||
258
node_modules/@11ty/eleventy/src/Util/Require.js
generated
vendored
Normal file
258
node_modules/@11ty/eleventy/src/Util/Require.js
generated
vendored
Normal file
@@ -0,0 +1,258 @@
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import module from "node:module";
|
||||
import { MessageChannel } from "node:worker_threads";
|
||||
|
||||
import { TemplatePath } from "@11ty/eleventy-utils";
|
||||
|
||||
import EleventyBaseError from "../Errors/EleventyBaseError.js";
|
||||
import eventBus from "../EventBus.js";
|
||||
|
||||
class EleventyImportError extends EleventyBaseError {}
|
||||
|
||||
const { port1, port2 } = new MessageChannel();
|
||||
|
||||
// ESM Cache Buster is an enhancement that works in Node 18.19+
|
||||
// https://nodejs.org/docs/latest/api/module.html#moduleregisterspecifier-parenturl-options
|
||||
// Fixes https://github.com/11ty/eleventy/issues/3270
|
||||
// ENV variable for https://github.com/11ty/eleventy/issues/3371
|
||||
if ("register" in module && !process?.env?.ELEVENTY_SKIP_ESM_RESOLVER) {
|
||||
module.register("./EsmResolver.js", import.meta.url, {
|
||||
parentURL: import.meta.url,
|
||||
data: {
|
||||
port: port2,
|
||||
},
|
||||
transferList: [port2],
|
||||
});
|
||||
}
|
||||
|
||||
// important to clear the require.cache in CJS projects
|
||||
const require = module.createRequire(import.meta.url);
|
||||
|
||||
const requestPromiseCache = new Map();
|
||||
|
||||
function getImportErrorMessage(filePath, type) {
|
||||
return `There was a problem importing '${path.relative(".", filePath)}' via ${type}`;
|
||||
}
|
||||
|
||||
// Used for JSON imports, suffering from Node warning that import assertions experimental but also
|
||||
// throwing an error if you try to import() a JSON file without an import assertion.
|
||||
/**
|
||||
*
|
||||
* @returns {string|undefined}
|
||||
*/
|
||||
function loadContents(path, options = {}) {
|
||||
let rawInput;
|
||||
/** @type {string} */
|
||||
let encoding = "utf8"; // JSON is utf8
|
||||
if (options?.encoding || options?.encoding === null) {
|
||||
encoding = options.encoding;
|
||||
}
|
||||
|
||||
try {
|
||||
// @ts-expect-error This is an error in the upstream types
|
||||
rawInput = fs.readFileSync(path, encoding);
|
||||
} catch (error) {
|
||||
// @ts-expect-error Temporary
|
||||
if (error?.code === "ENOENT") {
|
||||
// if file does not exist, return nothing
|
||||
return;
|
||||
}
|
||||
|
||||
throw error;
|
||||
}
|
||||
|
||||
// Can return a buffer, string, etc
|
||||
if (typeof rawInput === "string") {
|
||||
rawInput = rawInput.trim();
|
||||
}
|
||||
|
||||
return rawInput;
|
||||
}
|
||||
|
||||
let lastModifiedPaths = new Map();
|
||||
eventBus.on("eleventy.importCacheReset", (fileQueue) => {
|
||||
for (let filePath of fileQueue) {
|
||||
let absolutePath = TemplatePath.absolutePath(filePath);
|
||||
let newDate = Date.now();
|
||||
lastModifiedPaths.set(absolutePath, newDate);
|
||||
|
||||
// post to EsmResolver worker thread
|
||||
if (port1) {
|
||||
port1.postMessage({ path: absolutePath, newDate });
|
||||
}
|
||||
|
||||
// ESM Eleventy when using `import()` on a CJS project file still adds to require.cache
|
||||
if (absolutePath in (require?.cache || {})) {
|
||||
delete require.cache[absolutePath];
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// raw means we don’t normalize away the `default` export
|
||||
async function dynamicImportAbsolutePath(absolutePath, options = {}) {
|
||||
let { type, returnRaw, cacheBust } = Object.assign(
|
||||
{
|
||||
type: undefined,
|
||||
returnRaw: false,
|
||||
cacheBust: false, // force cache bust
|
||||
},
|
||||
options,
|
||||
);
|
||||
|
||||
// Short circuit for JSON files (that are optional and can be empty)
|
||||
if (absolutePath.endsWith(".json") || type === "json") {
|
||||
try {
|
||||
// https://v8.dev/features/import-assertions#dynamic-import() is still experimental in Node 20
|
||||
let rawInput = loadContents(absolutePath);
|
||||
if (!rawInput) {
|
||||
// should not error when file exists but is _empty_
|
||||
return;
|
||||
}
|
||||
return JSON.parse(rawInput);
|
||||
} catch (e) {
|
||||
return Promise.reject(
|
||||
new EleventyImportError(getImportErrorMessage(absolutePath, "fs.readFile(json)"), e),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Removed a `require` short circuit from this piece originally added
|
||||
// in https://github.com/11ty/eleventy/pull/3493 Was a bit faster but
|
||||
// error messaging was worse for require(esm)
|
||||
|
||||
let urlPath;
|
||||
try {
|
||||
let u = new URL(`file:${absolutePath}`);
|
||||
|
||||
// Bust the import cache if this is the last modified file (or cache busting is forced)
|
||||
if (cacheBust) {
|
||||
lastModifiedPaths.set(absolutePath, Date.now());
|
||||
}
|
||||
|
||||
if (cacheBust || lastModifiedPaths.has(absolutePath)) {
|
||||
u.searchParams.set("_cache_bust", lastModifiedPaths.get(absolutePath));
|
||||
}
|
||||
|
||||
urlPath = u.toString();
|
||||
} catch (e) {
|
||||
urlPath = absolutePath;
|
||||
}
|
||||
|
||||
let promise;
|
||||
if (requestPromiseCache.has(urlPath)) {
|
||||
promise = requestPromiseCache.get(urlPath);
|
||||
} else {
|
||||
promise = import(urlPath);
|
||||
requestPromiseCache.set(urlPath, promise);
|
||||
}
|
||||
|
||||
return promise.then(
|
||||
(target) => {
|
||||
if (returnRaw) {
|
||||
return target;
|
||||
}
|
||||
|
||||
// If the only export is `default`, elevate to top (for ESM and CJS)
|
||||
if (Object.keys(target).length === 1 && "default" in target) {
|
||||
return target.default;
|
||||
}
|
||||
|
||||
// When using import() on a CommonJS file that exports an object sometimes it
|
||||
// returns duplicated values in `default` key, e.g. `{ default: {key: value}, key: value }`
|
||||
|
||||
// A few examples:
|
||||
// module.exports = { key: false };
|
||||
// returns `{ default: {key: false}, key: false }` as not expected.
|
||||
// module.exports = { key: true };
|
||||
// module.exports = { key: null };
|
||||
// module.exports = { key: undefined };
|
||||
// module.exports = { key: class {} };
|
||||
|
||||
// A few examples where it does not duplicate:
|
||||
// module.exports = { key: 1 };
|
||||
// returns `{ default: {key: 1} }` as expected.
|
||||
// module.exports = { key: "value" };
|
||||
// module.exports = { key: {} };
|
||||
// module.exports = { key: [] };
|
||||
|
||||
if (type === "cjs" && "default" in target) {
|
||||
let match = true;
|
||||
for (let key in target) {
|
||||
if (key === "default") {
|
||||
continue;
|
||||
}
|
||||
if (key === "module.exports") {
|
||||
continue;
|
||||
}
|
||||
if (target[key] !== target.default[key]) {
|
||||
match = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (match) {
|
||||
return target.default;
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise return { default: value, named: value }
|
||||
// Object.assign here so we can add things to it in JavaScript.js
|
||||
return Object.assign({}, target);
|
||||
},
|
||||
(error) => {
|
||||
return Promise.reject(
|
||||
new EleventyImportError(getImportErrorMessage(absolutePath, `import(${type})`), error),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
function normalizeFilePathInEleventyPackage(file) {
|
||||
// Back up relative paths from ./src/Util/Require.js
|
||||
return path.resolve(fileURLToPath(import.meta.url), "../../../", file);
|
||||
}
|
||||
|
||||
async function dynamicImportFromEleventyPackage(file) {
|
||||
// points to files relative to the top level Eleventy directory
|
||||
let filePath = normalizeFilePathInEleventyPackage(file);
|
||||
|
||||
// Returns promise
|
||||
return dynamicImportAbsolutePath(filePath, { type: "esm" });
|
||||
}
|
||||
|
||||
async function dynamicImport(localPath, type, options = {}) {
|
||||
let absolutePath = TemplatePath.absolutePath(localPath);
|
||||
options.type = type;
|
||||
|
||||
// Returns promise
|
||||
return dynamicImportAbsolutePath(absolutePath, options);
|
||||
}
|
||||
|
||||
/* Used to import default Eleventy configuration file, raw means we don’t normalize away the `default` export */
|
||||
async function dynamicImportRawFromEleventyPackage(file) {
|
||||
// points to files relative to the top level Eleventy directory
|
||||
let filePath = normalizeFilePathInEleventyPackage(file);
|
||||
|
||||
// Returns promise
|
||||
return dynamicImportAbsolutePath(filePath, { type: "esm", returnRaw: true });
|
||||
}
|
||||
|
||||
/* Used to import app configuration files, raw means we don’t normalize away the `default` export */
|
||||
async function dynamicImportRaw(localPath, type) {
|
||||
let absolutePath = TemplatePath.absolutePath(localPath);
|
||||
|
||||
// Returns promise
|
||||
return dynamicImportAbsolutePath(absolutePath, { type, returnRaw: true });
|
||||
}
|
||||
|
||||
export {
|
||||
loadContents as EleventyLoadContent,
|
||||
dynamicImport as EleventyImport,
|
||||
dynamicImportRaw as EleventyImportRaw,
|
||||
normalizeFilePathInEleventyPackage,
|
||||
|
||||
// no longer used in core
|
||||
dynamicImportFromEleventyPackage as EleventyImportFromEleventy,
|
||||
dynamicImportRawFromEleventyPackage as EleventyImportRawFromEleventy,
|
||||
};
|
||||
69
node_modules/@11ty/eleventy/src/Util/ReservedData.js
generated
vendored
Normal file
69
node_modules/@11ty/eleventy/src/Util/ReservedData.js
generated
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
class EleventyReservedDataError extends TypeError {}
|
||||
|
||||
class ReservedData {
|
||||
static properties = [
|
||||
// "pkg", // Object.freeze’d upstream
|
||||
// "eleventy", // Object.freeze’d upstream
|
||||
// "page" is only frozen for specific subproperties below
|
||||
"content",
|
||||
"collections",
|
||||
];
|
||||
|
||||
static pageProperties = [
|
||||
"date",
|
||||
"inputPath",
|
||||
"fileSlug",
|
||||
"filePathStem",
|
||||
"outputFileExtension",
|
||||
"templateSyntax",
|
||||
"url",
|
||||
"outputPath",
|
||||
// not yet `excerpt` or `lang` set via front matter and computed data
|
||||
];
|
||||
|
||||
// Check in the data cascade for reserved data properties.
|
||||
static getReservedKeys(data) {
|
||||
if (!data) {
|
||||
return [];
|
||||
}
|
||||
|
||||
let keys = this.properties.filter((key) => {
|
||||
return key in data;
|
||||
});
|
||||
|
||||
if ("page" in data) {
|
||||
if (typeof data.page === "object") {
|
||||
for (let key of this.pageProperties) {
|
||||
if (key in data.page) {
|
||||
keys.push(`page.${key}`);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// fail `page` when set to non-object values.
|
||||
keys.push("page");
|
||||
}
|
||||
}
|
||||
return keys;
|
||||
}
|
||||
|
||||
static check(data) {
|
||||
let reserved = ReservedData.getReservedKeys(data);
|
||||
if (reserved.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
let error = new EleventyReservedDataError(
|
||||
`Cannot override reserved Eleventy properties: ${reserved.join(", ")}`,
|
||||
);
|
||||
|
||||
error.reservedNames = reserved;
|
||||
|
||||
throw error;
|
||||
}
|
||||
|
||||
static isReservedDataError(e) {
|
||||
return e instanceof EleventyReservedDataError;
|
||||
}
|
||||
}
|
||||
|
||||
export default ReservedData;
|
||||
11
node_modules/@11ty/eleventy/src/Util/SetUnion.js
generated
vendored
Normal file
11
node_modules/@11ty/eleventy/src/Util/SetUnion.js
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
function setUnion(...sets) {
|
||||
let root = new Set();
|
||||
for (let set of sets) {
|
||||
for (let entry of set) {
|
||||
root.add(entry);
|
||||
}
|
||||
}
|
||||
return root;
|
||||
}
|
||||
|
||||
export { setUnion };
|
||||
29
node_modules/@11ty/eleventy/src/Util/SpawnAsync.js
generated
vendored
Normal file
29
node_modules/@11ty/eleventy/src/Util/SpawnAsync.js
generated
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
import { spawn } from "node:child_process";
|
||||
import { withResolvers } from "./PromiseUtil.js";
|
||||
|
||||
export function spawnAsync(command, args, options) {
|
||||
let { promise, resolve, reject } = withResolvers();
|
||||
|
||||
const cmd = spawn(command, args, options);
|
||||
let res = [];
|
||||
cmd.stdout.on("data", (data) => {
|
||||
res.push(data.toString("utf8"));
|
||||
});
|
||||
|
||||
let err = [];
|
||||
cmd.stderr.on("data", (data) => {
|
||||
err.push(data.toString("utf8"));
|
||||
});
|
||||
|
||||
cmd.on("close", (code) => {
|
||||
if (err.length > 0) {
|
||||
reject(err.join("\n"));
|
||||
} else if (code === 1) {
|
||||
reject("Internal error: process closed with error exit code.");
|
||||
} else {
|
||||
resolve(res.join("\n"));
|
||||
}
|
||||
});
|
||||
|
||||
return promise;
|
||||
}
|
||||
160
node_modules/@11ty/eleventy/src/Util/TemplateDepGraph.js
generated
vendored
Normal file
160
node_modules/@11ty/eleventy/src/Util/TemplateDepGraph.js
generated
vendored
Normal file
@@ -0,0 +1,160 @@
|
||||
import { DepGraph as DependencyGraph } from "dependency-graph";
|
||||
import debugUtil from "debug";
|
||||
|
||||
const debug = debugUtil("Eleventy:TemplateDepGraph");
|
||||
|
||||
const COLLECTION_PREFIX = "__collection:";
|
||||
|
||||
export class TemplateDepGraph extends DependencyGraph {
|
||||
static STAGES = ["[basic]", "[userconfig]", "[keys]", "all"];
|
||||
|
||||
#configCollectionNames = new Set();
|
||||
|
||||
constructor() {
|
||||
// BREAKING TODO move this back to non-circular with errors
|
||||
super({ circular: true });
|
||||
|
||||
let previous;
|
||||
// establish stage relationships, all uses keys, keys uses userconfig, userconfig uses tags
|
||||
for (let stageName of TemplateDepGraph.STAGES.filter(Boolean).reverse()) {
|
||||
let stageKey = `${COLLECTION_PREFIX}${stageName}`;
|
||||
if (previous) {
|
||||
this.uses(previous, stageKey);
|
||||
}
|
||||
previous = stageKey;
|
||||
}
|
||||
}
|
||||
|
||||
uses(from, to) {
|
||||
this.addDependency(from, to);
|
||||
}
|
||||
|
||||
addTag(tagName, type) {
|
||||
if (
|
||||
tagName === "all" ||
|
||||
(tagName.startsWith("[") && tagName.endsWith("]")) ||
|
||||
this.#configCollectionNames.has(tagName)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
if (!type) {
|
||||
throw new Error(
|
||||
`Missing tag type for addTag. Expecting one of ${TemplateDepGraph.STAGES.map((entry) => entry.slice(1, -1)).join(" or ")}. Received: ${type}`,
|
||||
);
|
||||
}
|
||||
|
||||
debug("collection type %o uses tag %o", tagName, type);
|
||||
|
||||
this.uses(`${COLLECTION_PREFIX}[${type}]`, `${COLLECTION_PREFIX}${tagName}`);
|
||||
}
|
||||
|
||||
addConfigCollectionName(collectionName) {
|
||||
if (collectionName === "all") {
|
||||
return;
|
||||
}
|
||||
|
||||
this.#configCollectionNames.add(collectionName);
|
||||
// Collection relationships to `[userconfig]` are added last, in unfilteredOrder()
|
||||
}
|
||||
|
||||
cleanupCollectionNames(collectionNames = []) {
|
||||
let s = new Set(collectionNames);
|
||||
if (s.has("[userconfig]")) {
|
||||
return collectionNames;
|
||||
}
|
||||
|
||||
let hasAnyConfigCollections = collectionNames.find((name) => {
|
||||
if (this.#configCollectionNames.has(name)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
if (hasAnyConfigCollections) {
|
||||
s.add("[userconfig]");
|
||||
}
|
||||
|
||||
return Array.from(s);
|
||||
}
|
||||
|
||||
addTemplate(filePath, consumes = [], publishesTo = []) {
|
||||
// Move to the beginning if it doesn’t consume anything
|
||||
if (consumes.length === 0) {
|
||||
this.uses(`${COLLECTION_PREFIX}[basic]`, filePath);
|
||||
}
|
||||
|
||||
consumes = this.cleanupCollectionNames(consumes);
|
||||
publishesTo = this.cleanupCollectionNames(publishesTo);
|
||||
// Can’t consume AND publish to `all` simultaneously
|
||||
let consumesAll = consumes.includes("all");
|
||||
if (consumesAll) {
|
||||
publishesTo = publishesTo.filter((entry) => entry !== "all");
|
||||
}
|
||||
|
||||
debug("%o consumes %o and publishes to %o", filePath, consumes, publishesTo);
|
||||
|
||||
for (let collectionName of publishesTo) {
|
||||
if (!consumesAll) {
|
||||
let tagType = "basic";
|
||||
|
||||
let consumesUserConfigCollection = consumes.includes("[userconfig]");
|
||||
if (consumesUserConfigCollection) {
|
||||
// must finish before [keys]
|
||||
tagType = "keys";
|
||||
}
|
||||
|
||||
this.addTag(collectionName, tagType);
|
||||
}
|
||||
|
||||
this.uses(`${COLLECTION_PREFIX}${collectionName}`, filePath);
|
||||
}
|
||||
|
||||
for (let collectionName of consumes) {
|
||||
this.uses(filePath, `${COLLECTION_PREFIX}${collectionName}`);
|
||||
|
||||
let stageIndex = TemplateDepGraph.STAGES.indexOf(collectionName);
|
||||
let nextStage = stageIndex > 0 ? TemplateDepGraph.STAGES[stageIndex + 1] : undefined;
|
||||
if (nextStage) {
|
||||
this.uses(`${COLLECTION_PREFIX}${nextStage}`, filePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
addDependency(from, to) {
|
||||
if (!this.hasNode(from)) {
|
||||
this.addNode(from);
|
||||
}
|
||||
if (!this.hasNode(to)) {
|
||||
this.addNode(to);
|
||||
}
|
||||
super.addDependency(from, to);
|
||||
}
|
||||
|
||||
unfilteredOrder() {
|
||||
// these need to be added last, after the template map has been added (see addConfigCollectionName)
|
||||
for (let collectionName of this.#configCollectionNames) {
|
||||
this.uses(`${COLLECTION_PREFIX}[keys]`, `${COLLECTION_PREFIX}${collectionName}`);
|
||||
}
|
||||
|
||||
return super.overallOrder();
|
||||
}
|
||||
|
||||
overallOrder() {
|
||||
let unfiltered = this.unfilteredOrder();
|
||||
|
||||
let filtered = unfiltered.filter((entry) => {
|
||||
if (entry === `${COLLECTION_PREFIX}[keys]`) {
|
||||
return true;
|
||||
}
|
||||
return !entry.startsWith(`${COLLECTION_PREFIX}[`) && !entry.endsWith("]");
|
||||
});
|
||||
|
||||
let allKey = `${COLLECTION_PREFIX}all`;
|
||||
// Add another collections.all entry to the end (if not already the last one)
|
||||
if (filtered[filtered.length - 1] !== allKey) {
|
||||
filtered.push(allKey);
|
||||
}
|
||||
|
||||
return filtered;
|
||||
}
|
||||
}
|
||||
70
node_modules/@11ty/eleventy/src/Util/TransformsUtil.js
generated
vendored
Normal file
70
node_modules/@11ty/eleventy/src/Util/TransformsUtil.js
generated
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
import EleventyBaseError from "../Errors/EleventyBaseError.js";
|
||||
import { isPlainObject } from "@11ty/eleventy-utils";
|
||||
import debugUtil from "debug";
|
||||
|
||||
const debug = debugUtil("Eleventy:Transforms");
|
||||
|
||||
class EleventyTransformError extends EleventyBaseError {}
|
||||
|
||||
class TransformsUtil {
|
||||
static changeTransformsToArray(transformsObj) {
|
||||
let transforms = [];
|
||||
for (let name in transformsObj) {
|
||||
transforms.push({
|
||||
name: name,
|
||||
callback: transformsObj[name],
|
||||
});
|
||||
}
|
||||
return transforms;
|
||||
}
|
||||
|
||||
static async runAll(content, pageData, transforms = {}, options = {}) {
|
||||
let { baseHrefOverride, logger } = options;
|
||||
let { inputPath, outputPath, url } = pageData;
|
||||
|
||||
if (!isPlainObject(transforms)) {
|
||||
throw new Error("Object of transforms expected.");
|
||||
}
|
||||
|
||||
let transformsArray = this.changeTransformsToArray(transforms);
|
||||
|
||||
for (let { callback, name } of transformsArray) {
|
||||
debug("Running %o transform on %o: %o", name, inputPath, outputPath);
|
||||
|
||||
try {
|
||||
let hadContentBefore = !!content;
|
||||
|
||||
content = await callback.call(
|
||||
{
|
||||
inputPath,
|
||||
outputPath,
|
||||
url,
|
||||
page: pageData,
|
||||
baseHref: baseHrefOverride,
|
||||
},
|
||||
content,
|
||||
outputPath,
|
||||
);
|
||||
|
||||
if (hadContentBefore && !content) {
|
||||
if (!logger || !logger.warn) {
|
||||
throw new Error("Internal error: missing `logger` instance.");
|
||||
}
|
||||
|
||||
logger.warn(
|
||||
`Warning: Transform \`${name}\` returned empty when writing ${outputPath} from ${inputPath}.`,
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
throw new EleventyTransformError(
|
||||
`Transform \`${name}\` encountered an error when transforming ${inputPath}.`,
|
||||
e,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return content;
|
||||
}
|
||||
}
|
||||
|
||||
export default TransformsUtil;
|
||||
9
node_modules/@11ty/eleventy/src/Util/ValidUrl.js
generated
vendored
Normal file
9
node_modules/@11ty/eleventy/src/Util/ValidUrl.js
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
export default function isValidUrl(url) {
|
||||
try {
|
||||
new URL(url);
|
||||
return true;
|
||||
} catch (e) {
|
||||
// invalid url OR local path
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user