Initial commit: 11ty website with Fire/Frost branding
This commit is contained in:
75
node_modules/@11ty/eleventy-plugin-bundle/src/BundleFileOutput.js
generated
vendored
Normal file
75
node_modules/@11ty/eleventy-plugin-bundle/src/BundleFileOutput.js
generated
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import debugUtil from "debug";
|
||||
|
||||
import { createHash } from "@11ty/eleventy-utils";
|
||||
|
||||
const debug = debugUtil("Eleventy:Bundle");
|
||||
|
||||
const hashCache = {};
|
||||
const directoryExistsCache = {};
|
||||
const writingCache = new Set();
|
||||
|
||||
class BundleFileOutput {
|
||||
constructor(outputDirectory, bundleDirectory) {
|
||||
this.outputDirectory = outputDirectory;
|
||||
this.bundleDirectory = bundleDirectory || "";
|
||||
this.hashLength = 10;
|
||||
this.fileExtension = undefined;
|
||||
}
|
||||
|
||||
setFileExtension(ext) {
|
||||
this.fileExtension = ext;
|
||||
}
|
||||
|
||||
async getFilenameHash(content) {
|
||||
if(hashCache[content]) {
|
||||
return hashCache[content];
|
||||
}
|
||||
|
||||
let base64hash = await createHash(content);
|
||||
let filenameHash = base64hash.substring(0, this.hashLength);
|
||||
hashCache[content] = filenameHash;
|
||||
return filenameHash;
|
||||
}
|
||||
|
||||
getFilename(filename, extension) {
|
||||
return filename + (extension && !extension.startsWith(".") ? `.${extension}` : "");
|
||||
}
|
||||
|
||||
modifyPathToUrl(dir, filename) {
|
||||
return "/" + path.join(dir, filename).split(path.sep).join("/");
|
||||
}
|
||||
|
||||
async writeBundle(content, type, writeToFileSystem) {
|
||||
// do not write a bundle, do not return a file name is content is empty
|
||||
if(!content) {
|
||||
return;
|
||||
}
|
||||
|
||||
let dir = path.join(this.outputDirectory, this.bundleDirectory);
|
||||
let filenameHash = await this.getFilenameHash(content);
|
||||
let filename = this.getFilename(filenameHash, this.fileExtension || type);
|
||||
|
||||
if(writeToFileSystem) {
|
||||
let fullPath = path.join(dir, filename);
|
||||
|
||||
// no duplicate writes, this may be improved with a fs exists check, but it would only save the first write
|
||||
if(!writingCache.has(fullPath)) {
|
||||
writingCache.add(fullPath);
|
||||
|
||||
if(!directoryExistsCache[dir]) {
|
||||
fs.mkdirSync(dir, { recursive: true });
|
||||
directoryExistsCache[dir] = true;
|
||||
}
|
||||
|
||||
debug("Writing bundle %o", fullPath);
|
||||
fs.writeFileSync(fullPath, content);
|
||||
}
|
||||
}
|
||||
|
||||
return this.modifyPathToUrl(this.bundleDirectory, filename);
|
||||
}
|
||||
}
|
||||
|
||||
export { BundleFileOutput };
|
||||
231
node_modules/@11ty/eleventy-plugin-bundle/src/CodeManager.js
generated
vendored
Normal file
231
node_modules/@11ty/eleventy-plugin-bundle/src/CodeManager.js
generated
vendored
Normal file
@@ -0,0 +1,231 @@
|
||||
import { BundleFileOutput } from "./BundleFileOutput.js";
|
||||
import debugUtil from "debug";
|
||||
|
||||
const debug = debugUtil("Eleventy:Bundle");
|
||||
const DEBUG_LOG_TRUNCATION_SIZE = 200;
|
||||
|
||||
class CodeManager {
|
||||
// code is placed in this bucket by default
|
||||
static DEFAULT_BUCKET_NAME = "default";
|
||||
|
||||
// code is hoisted to this bucket when necessary
|
||||
static HOISTED_BUCKET_NAME = "default";
|
||||
|
||||
constructor(name) {
|
||||
this.name = name;
|
||||
this.trimOnAdd = true;
|
||||
// TODO unindent on add
|
||||
this.reset();
|
||||
this.transforms = [];
|
||||
this.isHoisting = true;
|
||||
this.fileExtension = undefined;
|
||||
this.toFileDirectory = undefined;
|
||||
this.bundleExportKey = "bundle";
|
||||
this.runsAfterHtmlTransformer = false;
|
||||
this.pluckedSelector = undefined;
|
||||
}
|
||||
|
||||
setDelayed(isDelayed) {
|
||||
this.runsAfterHtmlTransformer = Boolean(isDelayed);
|
||||
}
|
||||
|
||||
isDelayed() {
|
||||
return this.runsAfterHtmlTransformer;
|
||||
}
|
||||
|
||||
// posthtml-match-selector friendly
|
||||
setPluckedSelector(selector) {
|
||||
this.pluckedSelector = selector;
|
||||
}
|
||||
|
||||
getPluckedSelector() {
|
||||
return this.pluckedSelector;
|
||||
}
|
||||
|
||||
setFileExtension(ext) {
|
||||
this.fileExtension = ext;
|
||||
}
|
||||
|
||||
setHoisting(enabled) {
|
||||
this.isHoisting = !!enabled;
|
||||
}
|
||||
|
||||
setBundleDirectory(dir) {
|
||||
this.toFileDirectory = dir;
|
||||
}
|
||||
|
||||
setBundleExportKey(key) {
|
||||
this.bundleExportKey = key;
|
||||
}
|
||||
|
||||
getBundleExportKey() {
|
||||
return this.bundleExportKey;
|
||||
}
|
||||
|
||||
reset() {
|
||||
this.pages = {};
|
||||
}
|
||||
|
||||
static normalizeBuckets(bucket) {
|
||||
if(Array.isArray(bucket)) {
|
||||
return bucket;
|
||||
} else if(typeof bucket === "string") {
|
||||
return bucket.split(",");
|
||||
}
|
||||
return [CodeManager.DEFAULT_BUCKET_NAME];
|
||||
}
|
||||
|
||||
setTransforms(transforms) {
|
||||
if(!Array.isArray(transforms)) {
|
||||
throw new Error("Array expected to setTransforms");
|
||||
}
|
||||
|
||||
this.transforms = transforms;
|
||||
}
|
||||
|
||||
_initBucket(pageUrl, bucket) {
|
||||
if(!this.pages[pageUrl][bucket]) {
|
||||
this.pages[pageUrl][bucket] = new Set();
|
||||
}
|
||||
}
|
||||
|
||||
addToPage(pageUrl, code = [], bucket) {
|
||||
if(!Array.isArray(code) && code) {
|
||||
code = [code];
|
||||
}
|
||||
if(code.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(!this.pages[pageUrl]) {
|
||||
this.pages[pageUrl] = {};
|
||||
}
|
||||
|
||||
let buckets = CodeManager.normalizeBuckets(bucket);
|
||||
|
||||
let codeContent = code.map(entry => {
|
||||
if(this.trimOnAdd) {
|
||||
return entry.trim();
|
||||
}
|
||||
return entry;
|
||||
});
|
||||
|
||||
|
||||
for(let b of buckets) {
|
||||
this._initBucket(pageUrl, b);
|
||||
|
||||
for(let content of codeContent) {
|
||||
if(content) {
|
||||
if(!this.pages[pageUrl][b].has(content)) {
|
||||
debug("Adding code to bundle %o for %o (bucket: %o, size: %o): %o", this.name, pageUrl, b, content.length, content.length > DEBUG_LOG_TRUNCATION_SIZE ? content.slice(0, DEBUG_LOG_TRUNCATION_SIZE) + "…" : content);
|
||||
this.pages[pageUrl][b].add(content);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async runTransforms(str, pageData, buckets) {
|
||||
for (let callback of this.transforms) {
|
||||
str = await callback.call(
|
||||
{
|
||||
page: pageData,
|
||||
type: this.name,
|
||||
buckets: buckets
|
||||
},
|
||||
str
|
||||
);
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
getBucketsForPage(pageData) {
|
||||
let pageUrl = pageData.url;
|
||||
if(!this.pages[pageUrl]) {
|
||||
return [];
|
||||
}
|
||||
return Object.keys(this.pages[pageUrl]);
|
||||
}
|
||||
|
||||
getRawForPage(pageData, buckets = undefined) {
|
||||
let url = pageData.url;
|
||||
if(!this.pages[url]) {
|
||||
debug("No bundle code found for %o on %o, %O", this.name, url, this.pages);
|
||||
return new Set();
|
||||
}
|
||||
|
||||
buckets = CodeManager.normalizeBuckets(buckets);
|
||||
|
||||
let set = new Set();
|
||||
let size = 0;
|
||||
for(let b of buckets) {
|
||||
if(!this.pages[url][b]) {
|
||||
// Just continue, if you retrieve code from a bucket that doesn’t exist or has no code, it will return an empty set
|
||||
continue;
|
||||
}
|
||||
|
||||
for(let entry of this.pages[url][b]) {
|
||||
size += entry.length;
|
||||
set.add(entry);
|
||||
}
|
||||
}
|
||||
|
||||
debug("Retrieving %o for %o (buckets: %o, entries: %o, size: %o)", this.name, url, buckets, set.size, size);
|
||||
return set;
|
||||
}
|
||||
|
||||
async getForPage(pageData, buckets = undefined) {
|
||||
let set = this.getRawForPage(pageData, buckets);
|
||||
let bundleContent = Array.from(set).join("\n");
|
||||
|
||||
// returns promise
|
||||
return this.runTransforms(bundleContent, pageData, buckets);
|
||||
}
|
||||
|
||||
async writeBundle(pageData, buckets, options = {}) {
|
||||
let url = pageData.url;
|
||||
if(!this.pages[url]) {
|
||||
debug("No bundle code found for %o on %o, %O", this.name, url, this.pages);
|
||||
return "";
|
||||
}
|
||||
|
||||
let { output, write } = options;
|
||||
|
||||
buckets = CodeManager.normalizeBuckets(buckets);
|
||||
|
||||
// TODO the bundle output URL might be useful in the transforms for sourcemaps
|
||||
let content = await this.getForPage(pageData, buckets);
|
||||
let writer = new BundleFileOutput(output, this.toFileDirectory);
|
||||
writer.setFileExtension(this.fileExtension);
|
||||
return writer.writeBundle(content, this.name, write);
|
||||
}
|
||||
|
||||
// Used when a bucket is output multiple times on a page and needs to be hoisted
|
||||
hoistBucket(pageData, bucketName) {
|
||||
let newTargetBucketName = CodeManager.HOISTED_BUCKET_NAME;
|
||||
if(!this.isHoisting || bucketName === newTargetBucketName) {
|
||||
return;
|
||||
}
|
||||
|
||||
let url = pageData.url;
|
||||
if(!this.pages[url] || !this.pages[url][bucketName]) {
|
||||
debug("No bundle code found for %o on %o, %O", this.name, url, this.pages);
|
||||
return;
|
||||
}
|
||||
|
||||
debug("Code in bucket (%o) is being hoisted to a new bucket (%o)", bucketName, newTargetBucketName);
|
||||
|
||||
this._initBucket(url, newTargetBucketName);
|
||||
|
||||
for(let codeEntry of this.pages[url][bucketName]) {
|
||||
this.pages[url][bucketName].delete(codeEntry);
|
||||
this.pages[url][newTargetBucketName].add(codeEntry);
|
||||
}
|
||||
|
||||
// delete the bucket
|
||||
delete this.pages[url][bucketName];
|
||||
}
|
||||
}
|
||||
|
||||
export { CodeManager };
|
||||
158
node_modules/@11ty/eleventy-plugin-bundle/src/OutOfOrderRender.js
generated
vendored
Normal file
158
node_modules/@11ty/eleventy-plugin-bundle/src/OutOfOrderRender.js
generated
vendored
Normal file
@@ -0,0 +1,158 @@
|
||||
import debugUtil from "debug";
|
||||
|
||||
const debug = debugUtil("Eleventy:Bundle");
|
||||
|
||||
/* This class defers any `bundleGet` calls to a post-build transform step,
|
||||
* to allow `getBundle` to be called before all of the `css` additions have been processed
|
||||
*/
|
||||
class OutOfOrderRender {
|
||||
static SPLIT_REGEX = /(\/\*__EleventyBundle:[^:]*:[^:]*:[^:]*:EleventyBundle__\*\/)/;
|
||||
static SEPARATOR = ":";
|
||||
|
||||
constructor(content) {
|
||||
this.content = content;
|
||||
this.managers = {};
|
||||
}
|
||||
|
||||
// type if `get` (return string) or `file` (bundle writes to file, returns file url)
|
||||
static getAssetKey(type, name, bucket) {
|
||||
if(Array.isArray(bucket)) {
|
||||
bucket = bucket.join(",");
|
||||
} else if(typeof bucket === "string") {
|
||||
} else {
|
||||
bucket = "";
|
||||
}
|
||||
return `/*__EleventyBundle:${type}:${name}:${bucket || "default"}:EleventyBundle__*/`
|
||||
}
|
||||
|
||||
static parseAssetKey(str) {
|
||||
if(str.startsWith("/*__EleventyBundle:")) {
|
||||
let [prefix, type, name, bucket, suffix] = str.split(OutOfOrderRender.SEPARATOR);
|
||||
return { type, name, bucket };
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
setAssetManager(name, assetManager) {
|
||||
this.managers[name] = assetManager;
|
||||
}
|
||||
|
||||
setOutputDirectory(dir) {
|
||||
this.outputDirectory = dir;
|
||||
}
|
||||
|
||||
normalizeMatch(match) {
|
||||
let ret = OutOfOrderRender.parseAssetKey(match)
|
||||
return ret || match;
|
||||
}
|
||||
|
||||
findAll() {
|
||||
let matches = this.content.split(OutOfOrderRender.SPLIT_REGEX);
|
||||
let ret = [];
|
||||
for(let match of matches) {
|
||||
ret.push(this.normalizeMatch(match));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
setWriteToFileSystem(isWrite) {
|
||||
this.writeToFileSystem = isWrite;
|
||||
}
|
||||
|
||||
getAllBucketsForPage(pageData) {
|
||||
let availableBucketsForPage = new Set();
|
||||
for(let name in this.managers) {
|
||||
for(let bucket of this.managers[name].getBucketsForPage(pageData)) {
|
||||
availableBucketsForPage.add(`${name}::${bucket}`);
|
||||
}
|
||||
}
|
||||
return availableBucketsForPage;
|
||||
}
|
||||
|
||||
getManager(name) {
|
||||
if(!this.managers[name]) {
|
||||
throw new Error(`No asset manager found for ${name}. Known names: ${Object.keys(this.managers)}`);
|
||||
}
|
||||
return this.managers[name];
|
||||
}
|
||||
|
||||
async replaceAll(pageData, stage = 0) {
|
||||
let matches = this.findAll();
|
||||
let availableBucketsForPage = this.getAllBucketsForPage(pageData);
|
||||
let usedBucketsOnPage = new Set();
|
||||
let bucketsOutputStringCount = {};
|
||||
let bucketsFileCount = {};
|
||||
|
||||
for(let match of matches) {
|
||||
if(typeof match === "string") {
|
||||
continue;
|
||||
}
|
||||
|
||||
// type is `file` or `get`
|
||||
let {type, name, bucket} = match;
|
||||
let key = `${name}::${bucket}`;
|
||||
if(!usedBucketsOnPage.has(key)) {
|
||||
usedBucketsOnPage.add(key);
|
||||
}
|
||||
|
||||
if(type === "get") {
|
||||
if(!bucketsOutputStringCount[key]) {
|
||||
bucketsOutputStringCount[key] = 0;
|
||||
}
|
||||
bucketsOutputStringCount[key]++;
|
||||
} else if(type === "file") {
|
||||
if(!bucketsFileCount[key]) {
|
||||
bucketsFileCount[key] = 0;
|
||||
}
|
||||
bucketsFileCount[key]++;
|
||||
}
|
||||
}
|
||||
|
||||
// Hoist code in non-default buckets that are output multiple times
|
||||
// Only hoist if 2+ `get` OR 1+ `get` and 1+ `file`
|
||||
for(let bucketInfo in bucketsOutputStringCount) {
|
||||
let stringOutputCount = bucketsOutputStringCount[bucketInfo];
|
||||
if(stringOutputCount > 1 || stringOutputCount === 1 && bucketsFileCount[bucketInfo] > 0) {
|
||||
let [name, bucketName] = bucketInfo.split("::");
|
||||
this.getManager(name).hoistBucket(pageData, bucketName);
|
||||
}
|
||||
}
|
||||
|
||||
let content = await Promise.all(matches.map(match => {
|
||||
if(typeof match === "string") {
|
||||
return match;
|
||||
}
|
||||
|
||||
let {type, name, bucket} = match;
|
||||
let manager = this.getManager(name);
|
||||
|
||||
// Quit early if in stage 0, run delayed replacements if in stage 1+
|
||||
if(typeof manager.isDelayed === "function" && manager.isDelayed() && stage === 0) {
|
||||
return OutOfOrderRender.getAssetKey(type, name, bucket);
|
||||
}
|
||||
|
||||
if(type === "get") {
|
||||
// returns promise
|
||||
return manager.getForPage(pageData, bucket);
|
||||
} else if(type === "file") {
|
||||
// returns promise
|
||||
return manager.writeBundle(pageData, bucket, {
|
||||
output: this.outputDirectory,
|
||||
write: this.writeToFileSystem,
|
||||
});
|
||||
}
|
||||
return "";
|
||||
}));
|
||||
|
||||
for(let bucketInfo of availableBucketsForPage) {
|
||||
if(!usedBucketsOnPage.has(bucketInfo)) {
|
||||
let [name, bucketName] = bucketInfo.split("::");
|
||||
debug(`WARNING! \`${pageData.inputPath}\` has unbundled \`${name}\` assets (in the '${bucketName}' bucket) that were not written to or used on the page. You might want to add a call to \`getBundle('${name}', '${bucketName}')\` to your content! Learn more: https://github.com/11ty/eleventy-plugin-bundle#asset-bucketing`);
|
||||
}
|
||||
}
|
||||
|
||||
return content.join("");
|
||||
}
|
||||
}
|
||||
|
||||
export { OutOfOrderRender };
|
||||
69
node_modules/@11ty/eleventy-plugin-bundle/src/bundlePlucker.js
generated
vendored
Normal file
69
node_modules/@11ty/eleventy-plugin-bundle/src/bundlePlucker.js
generated
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
import debugUtil from "debug";
|
||||
import matchHelper from "posthtml-match-helper";
|
||||
|
||||
const debug = debugUtil("Eleventy:Bundle");
|
||||
|
||||
const ATTRS = {
|
||||
ignore: "eleventy:ignore",
|
||||
bucket: "eleventy:bucket",
|
||||
};
|
||||
|
||||
const POSTHTML_PLUGIN_NAME = "11ty/eleventy/html-bundle-plucker";
|
||||
|
||||
function hasAttribute(node, name) {
|
||||
return node?.attrs?.[name] !== undefined;
|
||||
}
|
||||
|
||||
function addHtmlPlucker(eleventyConfig, bundleManager) {
|
||||
let matchSelector = bundleManager.getPluckedSelector();
|
||||
|
||||
if(!matchSelector) {
|
||||
throw new Error("Internal error: missing plucked selector on bundle manager.");
|
||||
}
|
||||
|
||||
eleventyConfig.htmlTransformer.addPosthtmlPlugin(
|
||||
"html",
|
||||
function (context = {}) {
|
||||
let pageUrl = context?.url;
|
||||
if(!pageUrl) {
|
||||
throw new Error("Internal error: missing `url` property from context.");
|
||||
}
|
||||
|
||||
return function (tree, ...args) {
|
||||
tree.match(matchHelper(matchSelector), function (node) {
|
||||
try {
|
||||
// ignore
|
||||
if(hasAttribute(node, ATTRS.ignore)) {
|
||||
delete node.attrs[ATTRS.ignore];
|
||||
return node;
|
||||
}
|
||||
|
||||
if(Array.isArray(node?.content) && node.content.length > 0) {
|
||||
// TODO make this better decoupled
|
||||
if(node?.content.find(entry => entry.includes(`/*__EleventyBundle:`))) {
|
||||
// preserve {% getBundle %} calls as-is
|
||||
return node;
|
||||
}
|
||||
|
||||
let bucketName = node?.attrs?.[ATTRS.bucket];
|
||||
bundleManager.addToPage(pageUrl, [ ...node.content ], bucketName);
|
||||
|
||||
return { attrs: [], content: [], tag: false };
|
||||
}
|
||||
} catch(e) {
|
||||
debug(`Bundle plucker: error adding content to bundle in HTML Assets: %o`, e);
|
||||
return node;
|
||||
}
|
||||
|
||||
return node;
|
||||
});
|
||||
};
|
||||
},
|
||||
{
|
||||
// pluginOptions
|
||||
name: POSTHTML_PLUGIN_NAME,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
export { addHtmlPlucker };
|
||||
85
node_modules/@11ty/eleventy-plugin-bundle/src/eleventy.bundleManagers.js
generated
vendored
Normal file
85
node_modules/@11ty/eleventy-plugin-bundle/src/eleventy.bundleManagers.js
generated
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
import debugUtil from "debug";
|
||||
import { CodeManager } from "./CodeManager.js";
|
||||
import { addHtmlPlucker } from "./bundlePlucker.js"
|
||||
|
||||
const debug = debugUtil("Eleventy:Bundle");
|
||||
|
||||
function eleventyBundleManagers(eleventyConfig, pluginOptions = {}) {
|
||||
if(pluginOptions.force) {
|
||||
// no errors
|
||||
} else if(("getBundleManagers" in eleventyConfig || "addBundle" in eleventyConfig)) {
|
||||
throw new Error("Duplicate addPlugin calls for @11ty/eleventy-plugin-bundle");
|
||||
}
|
||||
|
||||
let managers = {};
|
||||
|
||||
function addBundle(name, bundleOptions = {}) {
|
||||
if(name in managers) {
|
||||
// note: shortcode must still be added
|
||||
debug("Bundle exists %o, skipping.", name);
|
||||
} else {
|
||||
debug("Creating new bundle %o", name);
|
||||
managers[name] = new CodeManager(name);
|
||||
|
||||
if(bundleOptions.delayed !== undefined) {
|
||||
managers[name].setDelayed(bundleOptions.delayed);
|
||||
}
|
||||
|
||||
if(bundleOptions.hoist !== undefined) {
|
||||
managers[name].setHoisting(bundleOptions.hoist);
|
||||
}
|
||||
|
||||
if(bundleOptions.bundleHtmlContentFromSelector !== undefined) {
|
||||
managers[name].setPluckedSelector(bundleOptions.bundleHtmlContentFromSelector);
|
||||
managers[name].setDelayed(true); // must override `delayed` above
|
||||
|
||||
addHtmlPlucker(eleventyConfig, managers[name]);
|
||||
}
|
||||
|
||||
if(bundleOptions.bundleExportKey !== undefined) {
|
||||
managers[name].setBundleExportKey(bundleOptions.bundleExportKey);
|
||||
}
|
||||
|
||||
if(bundleOptions.outputFileExtension) {
|
||||
managers[name].setFileExtension(bundleOptions.outputFileExtension);
|
||||
}
|
||||
|
||||
if(bundleOptions.toFileDirectory) {
|
||||
managers[name].setBundleDirectory(bundleOptions.toFileDirectory);
|
||||
}
|
||||
|
||||
if(bundleOptions.transforms) {
|
||||
managers[name].setTransforms(bundleOptions.transforms);
|
||||
}
|
||||
}
|
||||
|
||||
// if undefined, defaults to `name`
|
||||
if(bundleOptions.shortcodeName !== false) {
|
||||
let shortcodeName = bundleOptions.shortcodeName || name;
|
||||
|
||||
// e.g. `css` shortcode to add code to page bundle
|
||||
// These shortcode names are not configurable on purpose (for wider plugin compatibility)
|
||||
eleventyConfig.addPairedShortcode(shortcodeName, function addContent(content, bucket, explicitUrl) {
|
||||
let url = explicitUrl || this.page?.url;
|
||||
if(url) { // don’t add if a file doesn’t have an output URL
|
||||
managers[name].addToPage(url, content, bucket);
|
||||
}
|
||||
return "";
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
eleventyConfig.addBundle = addBundle;
|
||||
|
||||
eleventyConfig.getBundleManagers = function() {
|
||||
return managers;
|
||||
};
|
||||
|
||||
eleventyConfig.on("eleventy.before", async () => {
|
||||
for(let key in managers) {
|
||||
managers[key].reset();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default eleventyBundleManagers;
|
||||
105
node_modules/@11ty/eleventy-plugin-bundle/src/eleventy.pruneEmptyBundles.js
generated
vendored
Normal file
105
node_modules/@11ty/eleventy-plugin-bundle/src/eleventy.pruneEmptyBundles.js
generated
vendored
Normal file
@@ -0,0 +1,105 @@
|
||||
import matchHelper from "posthtml-match-helper";
|
||||
import debugUtil from "debug";
|
||||
|
||||
const debug = debugUtil("Eleventy:Bundle");
|
||||
|
||||
const ATTRS = {
|
||||
keep: "eleventy:keep"
|
||||
};
|
||||
|
||||
const POSTHTML_PLUGIN_NAME = "11ty/eleventy-bundle/prune-empty";
|
||||
|
||||
function getTextNodeContent(node) {
|
||||
if (!node.content) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return node.content
|
||||
.map((entry) => {
|
||||
if (typeof entry === "string") {
|
||||
return entry;
|
||||
}
|
||||
if (Array.isArray(entry.content)) {
|
||||
return getTextNodeContent(entry);
|
||||
}
|
||||
return "";
|
||||
})
|
||||
.join("");
|
||||
}
|
||||
|
||||
function eleventyPruneEmptyBundles(eleventyConfig, options = {}) {
|
||||
// Right now script[src],link[rel="stylesheet"] nodes are removed if the final bundles are empty.
|
||||
// `false` to disable
|
||||
options.pruneEmptySelector = options.pruneEmptySelector ?? `style,script,link[rel="stylesheet"]`;
|
||||
|
||||
// Subsequent call can remove a previously added `addPosthtmlPlugin` entry
|
||||
// htmlTransformer.remove is v3.0.1-alpha.4+
|
||||
if(typeof eleventyConfig.htmlTransformer.remove === "function") {
|
||||
eleventyConfig.htmlTransformer.remove("html", entry => {
|
||||
if(entry.name === POSTHTML_PLUGIN_NAME) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Temporary workaround for missing `name` property.
|
||||
let fnStr = entry.fn.toString();
|
||||
return !entry.name && fnStr.startsWith("function (pluginOptions = {}) {") && fnStr.includes(`tree.match(matchHelper(options.pruneEmptySelector), function (node)`);
|
||||
});
|
||||
}
|
||||
|
||||
// `false` disables this plugin
|
||||
if(options.pruneEmptySelector === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(!eleventyConfig.htmlTransformer || !eleventyConfig.htmlTransformer?.constructor?.SUPPORTS_PLUGINS_ENABLED_CALLBACK) {
|
||||
debug("You will need to upgrade your version of Eleventy core to remove empty bundle tags automatically (v3 or newer).");
|
||||
return;
|
||||
}
|
||||
|
||||
eleventyConfig.htmlTransformer.addPosthtmlPlugin(
|
||||
"html",
|
||||
function bundlePruneEmptyPosthtmlPlugin(pluginOptions = {}) {
|
||||
return function (tree) {
|
||||
tree.match(matchHelper(options.pruneEmptySelector), function (node) {
|
||||
if(node.attrs && node.attrs[ATTRS.keep] !== undefined) {
|
||||
delete node.attrs[ATTRS.keep];
|
||||
return node;
|
||||
}
|
||||
|
||||
// <link rel="stylesheet" href="">
|
||||
if(node.tag === "link") {
|
||||
if(node.attrs?.rel === "stylesheet" && (node.attrs?.href || "").trim().length === 0) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
let content = getTextNodeContent(node);
|
||||
|
||||
if(!content) {
|
||||
// <script></script> or <script src=""></script>
|
||||
if(node.tag === "script" && (node.attrs?.src || "").trim().length === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// <style></style>
|
||||
if(node.tag === "style") {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return node;
|
||||
});
|
||||
};
|
||||
},
|
||||
{
|
||||
name: POSTHTML_PLUGIN_NAME,
|
||||
// the `enabled` callback for plugins is available on v3.0.0-alpha.20+ and v3.0.0-beta.2+
|
||||
enabled: () => {
|
||||
return Object.keys(eleventyConfig.getBundleManagers()).length > 0;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
export default eleventyPruneEmptyBundles;
|
||||
83
node_modules/@11ty/eleventy-plugin-bundle/src/eleventy.shortcodes.js
generated
vendored
Normal file
83
node_modules/@11ty/eleventy-plugin-bundle/src/eleventy.shortcodes.js
generated
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
import { OutOfOrderRender } from "./OutOfOrderRender.js";
|
||||
import debugUtil from "debug";
|
||||
|
||||
const debug = debugUtil("Eleventy:Bundle");
|
||||
|
||||
export default function(eleventyConfig, pluginOptions = {}) {
|
||||
let managers = eleventyConfig.getBundleManagers();
|
||||
let writeToFileSystem = true;
|
||||
|
||||
function bundleTransform(content, stage = 0) {
|
||||
// Only run if content is string
|
||||
// Only run if managers are in play
|
||||
if(typeof content !== "string" || Object.keys(managers).length === 0) {
|
||||
return content;
|
||||
}
|
||||
|
||||
debug("Processing %o", this.page.url);
|
||||
let render = new OutOfOrderRender(content);
|
||||
for(let key in managers) {
|
||||
render.setAssetManager(key, managers[key]);
|
||||
}
|
||||
|
||||
render.setOutputDirectory(eleventyConfig.directories.output);
|
||||
render.setWriteToFileSystem(writeToFileSystem);
|
||||
|
||||
return render.replaceAll(this.page, stage);
|
||||
}
|
||||
|
||||
eleventyConfig.on("eleventy.before", async ({ outputMode }) => {
|
||||
if(Object.keys(managers).length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(outputMode !== "fs") {
|
||||
writeToFileSystem = false;
|
||||
debug("Skipping writing to the file system due to output mode: %o", outputMode);
|
||||
}
|
||||
});
|
||||
|
||||
// e.g. `getBundle` shortcode to get code in current page bundle
|
||||
// bucket can be an array
|
||||
// This shortcode name is not configurable on purpose (for wider plugin compatibility)
|
||||
eleventyConfig.addShortcode("getBundle", function getContent(type, bucket, explicitUrl) {
|
||||
if(!type || !(type in managers) || Object.keys(managers).length === 0) {
|
||||
throw new Error(`Invalid bundle type: ${type}. Available options: ${Object.keys(managers)}`);
|
||||
}
|
||||
|
||||
return OutOfOrderRender.getAssetKey("get", type, bucket);
|
||||
});
|
||||
|
||||
// write a bundle to the file system
|
||||
// This shortcode name is not configurable on purpose (for wider plugin compatibility)
|
||||
eleventyConfig.addShortcode("getBundleFileUrl", function(type, bucket, explicitUrl) {
|
||||
if(!type || !(type in managers) || Object.keys(managers).length === 0) {
|
||||
throw new Error(`Invalid bundle type: ${type}. Available options: ${Object.keys(managers)}`);
|
||||
}
|
||||
|
||||
return OutOfOrderRender.getAssetKey("file", type, bucket);
|
||||
});
|
||||
|
||||
eleventyConfig.addTransform("@11ty/eleventy-bundle", function (content) {
|
||||
let hasNonDelayedManagers = Boolean(Object.values(eleventyConfig.getBundleManagers()).find(manager => {
|
||||
return typeof manager.isDelayed !== "function" || !manager.isDelayed();
|
||||
}));
|
||||
if(hasNonDelayedManagers) {
|
||||
return bundleTransform.call(this, content, 0);
|
||||
}
|
||||
return content;
|
||||
});
|
||||
|
||||
eleventyConfig.addPlugin((eleventyConfig) => {
|
||||
// Delayed bundles *MUST* not alter URLs
|
||||
eleventyConfig.addTransform("@11ty/eleventy-bundle/delayed", function (content) {
|
||||
let hasDelayedManagers = Boolean(Object.values(eleventyConfig.getBundleManagers()).find(manager => {
|
||||
return typeof manager.isDelayed === "function" && manager.isDelayed();
|
||||
}));
|
||||
if(hasDelayedManagers) {
|
||||
return bundleTransform.call(this, content, 1);
|
||||
}
|
||||
return content;
|
||||
});
|
||||
});
|
||||
};
|
||||
Reference in New Issue
Block a user