@11ty/eleventy
Advanced tools
+1
-1
@@ -7,3 +7,3 @@ #!/usr/bin/env node | ||
| const pkg = require("./package.json"); | ||
| require("please-upgrade-node")(pkg, { | ||
| require("@11ty/node-version-check")(pkg, { | ||
| message: function (requiredVersion) { | ||
@@ -10,0 +10,0 @@ return ( |
+6
-9
| { | ||
| "name": "@11ty/eleventy", | ||
| "version": "4.0.0-alpha.5", | ||
| "version": "4.0.0-alpha.6", | ||
| "description": "A simpler static site generator.", | ||
@@ -138,3 +138,3 @@ "publishConfig": { | ||
| "@11ty/dependency-tree-esm": "^2.0.3", | ||
| "@11ty/eleventy-dev-server": "^3.0.0-alpha.5", | ||
| "@11ty/eleventy-dev-server": "^3.0.0-alpha.6", | ||
| "@11ty/eleventy-plugin-bundle": "^3.0.7", | ||
@@ -144,5 +144,7 @@ "@11ty/eleventy-utils": "^2.0.7", | ||
| "@11ty/lodash-custom": "^4.17.21", | ||
| "@11ty/node-version-check": "^1.0.1", | ||
| "@11ty/nunjucks": "^4.0.0-alpha.1", | ||
| "@11ty/parse-date-strings": "^2.0.6", | ||
| "@11ty/posthtml-urls": "^1.0.2", | ||
| "@11ty/recursive-copy": "^4.0.3", | ||
| "@11ty/recursive-copy": "^5.0.0", | ||
| "@sindresorhus/slugify": "^3.0.0", | ||
@@ -162,5 +164,3 @@ "bcp-47-normalize": "^2.3.0", | ||
| "node-retrieve-globals": "^6.0.1", | ||
| "nunjucks": "^3.2.4", | ||
| "picomatch": "^4.0.3", | ||
| "please-upgrade-node": "^3.2.0", | ||
| "posthtml": "^0.16.7", | ||
@@ -172,7 +172,4 @@ "posthtml-match-helper": "^2.0.3", | ||
| "overrides": { | ||
| "commander": "^14", | ||
| "chokidar": "$chokidar", | ||
| "fdir": "6.4.6", | ||
| "posthtml-parser": "^0.12" | ||
| "fdir": "6.4.6" | ||
| } | ||
| } |
@@ -1,2 +0,2 @@ | ||
| class Benchmark { | ||
| export default class Benchmark { | ||
| constructor() { | ||
@@ -52,3 +52,1 @@ // TypeScript slop | ||
| } | ||
| export default Benchmark; |
@@ -15,2 +15,3 @@ import path from "node:path"; | ||
| import { coerce } from "../Util/SemverCoerce.js"; | ||
| import ReservedData from "../Util/ReservedData.js"; | ||
@@ -315,2 +316,6 @@ const { set: lodashSet, get: lodashGet } = lodash; | ||
| lodashSet(globalData, objectPathTarget, data); | ||
| if (this.config.freezeReservedData) { | ||
| ReservedData.check(globalData, files[j]); | ||
| } | ||
| } | ||
@@ -317,0 +322,0 @@ |
| import lodash from "@11ty/lodash-custom"; | ||
| import ReservedData from "../Util/ReservedData.js"; | ||
| import EleventyBaseError from "../Errors/EleventyBaseError.js"; | ||
@@ -36,2 +37,7 @@ | ||
| if (this.config.freezeReservedData) { | ||
| // TODO-ish might come from the `config` callback too | ||
| ReservedData.check(globalData, this.templateConfig.getActiveConfigPath()); | ||
| } | ||
| return globalData; | ||
@@ -38,0 +44,0 @@ } |
@@ -73,2 +73,24 @@ import { TemplatePath, isPlainObject } from "@11ty/eleventy-utils"; | ||
| } else { | ||
| // JavaScript lol | ||
| if (mod.toString().trimStart().startsWith("class ")) { | ||
| // we already know that mod.prototype.data and mod.prototype.render do not exist (per above) | ||
| // now we look for instance properties for `data` or `render`, issue #1645 | ||
| let modInstance = new mod(); | ||
| if (Object.hasOwn(modInstance, "data") || Object.hasOwn(modInstance, "render")) { | ||
| if (!Object.hasOwn(modInstance, "render")) { | ||
| mod.prototype.render = noop; | ||
| } | ||
| if (!Object.hasOwn(modInstance, "data") && !mod.data && originalModData) { | ||
| mod.prototype.data = originalModData; | ||
| } | ||
| return modInstance; | ||
| } else { | ||
| throw new Error( | ||
| "Invalid class signature for an 11ty.js template: needs a render or data instance property.", | ||
| ); | ||
| } | ||
| } | ||
| return { | ||
@@ -75,0 +97,0 @@ ...(originalModData ? { data: originalModData } : undefined), |
@@ -315,2 +315,3 @@ import moo from "moo"; | ||
| let engine = this.liquidLib; | ||
| let liquidOptions = this.liquidOptions; | ||
| let tmplReady = engine.parse(str, inputPath); | ||
@@ -329,7 +330,10 @@ | ||
| options.globals = { | ||
| page: data?.page, | ||
| eleventy: data?.eleventy, | ||
| collections: data?.collections, | ||
| }; | ||
| options.globals = Object.assign( | ||
| { | ||
| page: data?.page, | ||
| eleventy: data?.eleventy, | ||
| collections: data?.collections, | ||
| }, | ||
| liquidOptions?.globals, | ||
| ); | ||
@@ -336,0 +340,0 @@ return engine.render(tmpl, data, options); |
@@ -5,3 +5,8 @@ import debugUtil from "debug"; | ||
| // Direct reference to avoid use of `browser` Nunjucks variant in bundles | ||
| import { default as NunjucksLib, Environment, FileSystemLoader, Template } from "nunjucks/index.js"; | ||
| import { | ||
| default as NunjucksLib, | ||
| Environment, | ||
| FileSystemLoader, | ||
| Template, | ||
| } from "@11ty/nunjucks/index.js"; | ||
| import TemplateEngine from "./TemplateEngine.js"; | ||
@@ -8,0 +13,0 @@ import EleventyBaseError from "../Errors/EleventyBaseError.js"; |
@@ -7,3 +7,4 @@ import matchHelper from "posthtml-match-helper"; | ||
| function getTextNodeContent(node) { | ||
| if (node.attrs?.["eleventy:id-ignore"] === "") { | ||
| let ignoredAttr = node.attrs?.["eleventy:id-ignore"]; | ||
| if (ignoredAttr === "" || ignoredAttr === true) { | ||
| delete node.attrs["eleventy:id-ignore"]; | ||
@@ -10,0 +11,0 @@ return ""; |
+6
-14
@@ -389,3 +389,3 @@ import { parse } from "node:path"; | ||
| localData = await this.templateData.getTemplateDirectoryData(this.inputPath); | ||
| globalData = await this.templateData.getGlobalData(this.inputPath); | ||
| globalData = await this.templateData.getGlobalData(); | ||
| debugDev("%o getData getTemplateDirectoryData and getGlobalData", this.inputPath); | ||
@@ -417,3 +417,3 @@ } | ||
| if (this.config.freezeReservedData) { | ||
| ReservedData.check(mergedData); | ||
| ReservedData.checkSubset(mergedData); | ||
| } | ||
@@ -427,14 +427,6 @@ | ||
| } catch (e) { | ||
| if ( | ||
| ReservedData.isReservedDataError(e) || | ||
| (e instanceof TypeError && | ||
| e.message.startsWith("Cannot add property") && | ||
| e.message.endsWith("not extensible")) | ||
| ) { | ||
| throw new EleventyBaseError( | ||
| `You attempted to set one of Eleventy’s reserved data property names${e.reservedNames ? `: ${e.reservedNames.join(", ")}` : ""}. You can opt-out of this behavior with \`eleventyConfig.setFreezeReservedData(false)\` or rename/remove the property in your data cascade that conflicts with Eleventy’s reserved property names (e.g. \`eleventy\`, \`pkg\`, and others). Learn more: https://v3.11ty.dev/docs/data-eleventy-supplied/`, | ||
| e, | ||
| ); | ||
| // if ReservedDataError, defer to that (from ReservedData.checkSubset above) | ||
| if (!ReservedData.isReservedDataError(e) && ReservedData.isFrozenError(e)) { | ||
| throw ReservedData.getError({ cause: e }); | ||
| } | ||
| throw e; | ||
@@ -634,3 +626,3 @@ } | ||
| if (this.config.freezeReservedData) { | ||
| ReservedData.check(data[this.config.keys.computed]); | ||
| ReservedData.checkSubset(data[this.config.keys.computed]); | ||
| } | ||
@@ -637,0 +629,0 @@ |
@@ -16,9 +16,11 @@ import { Merge, TemplatePath } from "@11ty/eleventy-utils"; | ||
| constructor(templateSyntax) { | ||
| this.isEligible = CdataWrapper.isEligible(templateSyntax); | ||
| constructor(pageTemplateSyntax = "", layoutTemplateSyntax = "") { | ||
| this.isEligible = CdataWrapper.isEligible(pageTemplateSyntax, layoutTemplateSyntax); | ||
| } | ||
| // Markdown only | ||
| static isEligible(templateSyntax) { | ||
| return templateSyntax.split(",").includes("md"); | ||
| // Markdown in Markdown layout only | ||
| static isEligible(templateSyntax, layoutTemplateSyntax) { | ||
| return ( | ||
| templateSyntax.split(",").includes("md") && layoutTemplateSyntax.split(",").includes("md") | ||
| ); | ||
| } | ||
@@ -248,12 +250,16 @@ | ||
| async renderPageEntry(pageEntry) { | ||
| let pageTemplateSyntax = pageEntry.template?.getEngineNames( | ||
| pageEntry.data[this.config.keys.engineOverride], | ||
| ); | ||
| let templateContent = pageEntry.templateContent; | ||
| let compiledFunctions = await this.getCompiledLayoutFunctions(); | ||
| for (let { render, template } of compiledFunctions) { | ||
| let templateSyntax = template.getEngineNames(pageEntry.data[this.config.keys.engineOverride]); | ||
| let layoutTemplateSyntax = template.getEngineNames(); // templateEngineOverride not supported in layouts | ||
| let cdata = new CdataWrapper(pageTemplateSyntax, layoutTemplateSyntax); | ||
| let cdata = new CdataWrapper(templateSyntax); | ||
| let data = { | ||
| ...pageEntry.data, | ||
| // This should come *after* data, so `content` have override `content` props set in data cascade | ||
| content: cdata.wrap(templateContent), | ||
| ...pageEntry.data, | ||
| }; | ||
@@ -260,0 +266,0 @@ |
@@ -73,3 +73,5 @@ import { TemplatePath } from "@11ty/eleventy-utils"; | ||
| let fullPath = this.templateConfig.directories.getLayoutPath(layoutPath); | ||
| if (this.templateConfig.existsCache.exists(fullPath)) { | ||
| let existsCache = this.templateConfig.existsCache; | ||
| if (existsCache.exists(fullPath) && !existsCache.isDirectory(fullPath)) { | ||
| // #4191 | ||
| return true; | ||
@@ -76,0 +78,0 @@ } |
@@ -7,3 +7,3 @@ import posthtml from "posthtml"; | ||
| class HtmlTransformer { | ||
| export class HtmlTransformer { | ||
| // feature test for Eleventy Bundle Plugin | ||
@@ -17,3 +17,5 @@ static SUPPORTS_PLUGINS_ENABLED_CALLBACK = true; | ||
| this.callbacks = {}; | ||
| this.posthtmlProcessOptions = {}; | ||
| this.posthtmlProcessOptions = { | ||
| recognizeNoValueAttribute: true, | ||
| }; | ||
| this.plugins = {}; | ||
@@ -173,3 +175,1 @@ } | ||
| } | ||
| export { HtmlTransformer }; |
+48
-11
| class EleventyReservedDataError extends TypeError {} | ||
| class ReservedData { | ||
| static fullProperties = [ | ||
| "pkg", // Object.freeze’d upstream | ||
| "eleventy", // Object.freeze’d upstream | ||
| // "page" is only frozen for specific subproperties below | ||
| "content", | ||
| "collections", | ||
| ]; | ||
| static properties = [ | ||
| // "pkg", // Object.freeze’d upstream | ||
| // "eleventy", // Object.freeze’d upstream | ||
| // "page" is only frozen for specific subproperties below | ||
@@ -25,3 +31,3 @@ "content", | ||
| // Check in the data cascade for reserved data properties. | ||
| static getReservedKeys(data) { | ||
| static getReservedKeys(data, globalProperties = this.fullProperties) { | ||
| if (!data) { | ||
@@ -31,3 +37,3 @@ return []; | ||
| let keys = this.properties.filter((key) => { | ||
| let keys = globalProperties.filter((key) => { | ||
| return key in data; | ||
@@ -51,15 +57,46 @@ }); | ||
| static check(data) { | ||
| let reserved = ReservedData.getReservedKeys(data); | ||
| if (reserved.length === 0) { | ||
| static #check(data, sourceLocation, propertiesList) { | ||
| let reservedNames = ReservedData.getReservedKeys(data, propertiesList); | ||
| if (reservedNames.length === 0) { | ||
| return; | ||
| } | ||
| throw this.getError({ | ||
| reservedNames, | ||
| sourceLocation, | ||
| }); | ||
| } | ||
| let error = new EleventyReservedDataError( | ||
| `Cannot override reserved Eleventy properties: ${reserved.join(", ")}`, | ||
| // check for frozen objects too | ||
| static check(data, sourceLocation) { | ||
| this.#check(data, sourceLocation, this.fullProperties); | ||
| } | ||
| static checkSubset(data, sourceLocation) { | ||
| this.#check(data, sourceLocation, this.properties); | ||
| } | ||
| static getError(options = {}) { | ||
| let { reservedNames, cause, sourceLocation } = options || {}; | ||
| if (cause) { | ||
| reservedNames ??= cause.reservedNames; | ||
| } | ||
| let e = new EleventyReservedDataError( | ||
| `You attempted to set one of Eleventy’s reserved data property names${reservedNames ? `: ${reservedNames.join(", ")}` : ""}${sourceLocation ? ` (source: ${sourceLocation})` : ""}. You can opt-out of this behavior with \`eleventyConfig.setFreezeReservedData(false)\` or rename/remove the property in your data cascade that conflicts with Eleventy’s reserved property names (e.g. \`eleventy\`, \`pkg\`, and others). Learn more: https://v3.11ty.dev/docs/data-eleventy-supplied/`, | ||
| { cause }, | ||
| ); | ||
| error.reservedNames = reserved; | ||
| if (reservedNames) { | ||
| e.reservedNames = reservedNames; | ||
| } | ||
| return e; | ||
| } | ||
| throw error; | ||
| static isFrozenError(e) { | ||
| return ( | ||
| e instanceof TypeError && | ||
| e.message.startsWith("Cannot add property") && | ||
| e.message.endsWith("not extensible") | ||
| ); | ||
| } | ||
@@ -66,0 +103,0 @@ |
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
567403
0.46%16837
0.42%+ Added
+ Added
+ Added
+ Added
+ Added
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
Updated