eleventy-plugin-vento 4.0.1 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,10 +1,27 @@
1
1
  # eleventy-plugin-vento
2
2
 
3
+ ## 4.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - eb33d79: Expose Vento's `FilterThis` on Eleventy-declared filters. (fixes #72)
8
+
9
+ > [!IMPORTANT]
10
+ > Using this feature incurs the same performance regression that [`eleventyComputed` template strings](https://www.11ty.dev/docs/data-computed/#using-a-template-string) do. Caching can assist with this, see [README](https://github.com/noelforte/eleventy-plugin-vento/blob/main/readme.md) for more information.
11
+
12
+ Vento binds its own `this` object when executing filter functions. The `this` object contains 2 keys, `this.env` and `this.data`, for getting access to both the Vento environment and the template data respectively.
13
+
14
+ In addition to Vento's object, `this.page` and `this.eleventy` are also cloned to the top level from `this.data` to maintain feature-parity with Eleventy.
15
+
16
+ With this change, you can now create filters that leverage the Vento environment. See [README](https://github.com/noelforte/eleventy-plugin-vento/blob/main/readme.md) for more info.
17
+
18
+ - eb33d79: Update vento to 1.12.12
19
+
3
20
  ## 4.0.1
4
21
 
5
22
  ### Patch Changes
6
23
 
7
- - - hotfix - include `types` field in package.json to declare bundled types
24
+ - hotfix - include `types` field in package.json to declare bundled types
8
25
 
9
26
  ## 4.0.0
10
27
 
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
  import path from "node:path";
3
3
  import autotrimPlugin, { defaultTags as autotrimDefaultTags } from "ventojs/plugins/auto_trim.js";
4
4
 
5
- // src/create-vento-interface.ts
5
+ // src/engine.ts
6
6
  import { default as ventojs } from "ventojs";
7
7
 
8
8
  // src/create-vento-tag.ts
@@ -10,8 +10,12 @@ function createVentoTag(spec) {
10
10
  const IS_PAIRED = spec.group === "pairedShortcodes";
11
11
  const tag = (env, code, output, tokens) => {
12
12
  if (!code.startsWith(spec.name)) return;
13
- const fn = `__env.utils._11tyFns.${spec.group}.${spec.name}`;
14
- const ctx = "__env.utils._11tyCtx";
13
+ const { dataVarname } = env.options;
14
+ const thisArg = `{
15
+ page: ${dataVarname}.page,
16
+ eleventy: ${dataVarname}.eleventy
17
+ }`;
18
+ const fn = `__env.utils.eleventyFunctions.${spec.group}.${spec.name}`;
15
19
  const args = [code.replace(spec.name, "").trim()];
16
20
  const varname = output.startsWith("__shortcode_content") ? `${output}_precomp` : "__shortcode_content";
17
21
  const compiled = [];
@@ -27,7 +31,7 @@ function createVentoTag(spec) {
27
31
  }
28
32
  tokens.shift();
29
33
  }
30
- args.unshift(ctx);
34
+ args.unshift(thisArg);
31
35
  compiled.push(
32
36
  "{",
33
37
  `const __shortcode_result = await ${fn}.call(${args.filter(Boolean).join(", ")});`,
@@ -49,7 +53,7 @@ function createVentoTag(spec) {
49
53
  import createDebugger from "debug";
50
54
  var debugBaseNamespace = "Eleventy:Vento";
51
55
  var DEBUG = {
52
- setup: createDebugger(`${debugBaseNamespace}:Setup`),
56
+ main: createDebugger(debugBaseNamespace),
53
57
  cache: createDebugger(`${debugBaseNamespace}:Cache`),
54
58
  render: createDebugger(`${debugBaseNamespace}:Render`)
55
59
  };
@@ -59,9 +63,8 @@ var REQUIRED_API_METHODS = [
59
63
  ["getFilters", "v3.0.0-alpha.15"],
60
64
  ["addExtension", "v1.0.0"]
61
65
  ];
62
- var CONTEXT_DATA_KEYS = ["page", "eleventy"];
63
66
  function runCompatibilityCheck(config) {
64
- DEBUG.setup("Run compatibility check");
67
+ DEBUG.main("Run compatibility check");
65
68
  for (const [method, version] of REQUIRED_API_METHODS) {
66
69
  if (!(method in config)) {
67
70
  console.error(
@@ -75,20 +78,11 @@ function runCompatibilityCheck(config) {
75
78
  }
76
79
  }
77
80
 
78
- // src/create-vento-interface.ts
79
- function createVentoInterface(options) {
81
+ // src/engine.ts
82
+ function createVentoEngine(options) {
80
83
  const env = ventojs(options);
81
- env.utils._11tyFns = { shortcodes: {}, pairedShortcodes: {} };
84
+ env.utils.eleventyFunctions = { shortcodes: {}, pairedShortcodes: {} };
82
85
  env.utils._11tyCtx = {};
83
- function setContext(newContext) {
84
- if (env.utils._11tyCtx?.page?.inputPath === newContext?.page?.inputPath) {
85
- return;
86
- }
87
- for (const K of CONTEXT_DATA_KEYS) {
88
- env.utils._11tyCtx[K] = newContext[K];
89
- }
90
- DEBUG.setup("Reload context, new context is: %o", env.utils._11tyCtx);
91
- }
92
86
  function loadPlugins(plugins) {
93
87
  for (const plugin of plugins) {
94
88
  env.use(plugin);
@@ -96,18 +90,21 @@ function createVentoInterface(options) {
96
90
  }
97
91
  function loadFilters(filters) {
98
92
  for (const [name, fn] of Object.entries(filters)) {
99
- env.filters[name] = fn.bind(env.utils._11tyCtx);
93
+ env.filters[name] = async function(...args) {
94
+ Object.assign(this, { page: this.data.page, eleventy: this.data.eleventy });
95
+ return await fn.apply(this, args);
96
+ };
100
97
  }
101
98
  }
102
99
  function loadShortcodes(shortcodes) {
103
100
  for (const [name, fn] of Object.entries(shortcodes)) {
104
- env.utils._11tyFns.shortcodes[name] = fn;
101
+ env.utils.eleventyFunctions.shortcodes[name] = fn;
105
102
  env.tags.push(createVentoTag({ name, group: "shortcodes" }));
106
103
  }
107
104
  }
108
105
  function loadPairedShortcodes(pairedShortcodes) {
109
106
  for (const [name, fn] of Object.entries(pairedShortcodes)) {
110
- env.utils._11tyFns.pairedShortcodes[name] = fn;
107
+ env.utils.eleventyFunctions.pairedShortcodes[name] = fn;
111
108
  env.tags.push(createVentoTag({ name, group: "pairedShortcodes" }));
112
109
  }
113
110
  }
@@ -131,26 +128,24 @@ ${template}`,
131
128
  }
132
129
  return template;
133
130
  }
134
- async function render(template, data, from) {
135
- setContext(data);
136
- DEBUG.render("Rendering `%s`", from);
137
- const { content } = await template(data);
138
- return content;
139
- }
140
131
  return {
141
132
  cache: env.cache,
142
133
  loadPlugins,
143
134
  loadFilters,
144
135
  loadShortcodes,
145
136
  loadPairedShortcodes,
146
- getTemplateFunction,
147
- render
137
+ getTemplateFunction
148
138
  };
149
139
  }
140
+ async function renderVentoTemplate(template, data, from) {
141
+ DEBUG.render("Rendering `%s`", from);
142
+ const { content } = await template(data);
143
+ return content;
144
+ }
150
145
 
151
146
  // src/index.ts
152
147
  function VentoPlugin(eleventyConfig, userOptions) {
153
- DEBUG.setup("Initializing eleventy-plugin-vento");
148
+ DEBUG.main("Initializing eleventy-plugin-vento");
154
149
  runCompatibilityCheck(eleventyConfig);
155
150
  const options = {
156
151
  // Define defaults
@@ -165,13 +160,13 @@ function VentoPlugin(eleventyConfig, userOptions) {
165
160
  // Merge in user-provided options
166
161
  ...userOptions
167
162
  };
168
- DEBUG.setup("Merged default and user config: %O", options);
163
+ DEBUG.main("Merged default and user config: %O", options);
169
164
  const filters = eleventyConfig.getFilters();
170
- DEBUG.setup("Reading filters from Eleventy: %o", filters);
165
+ DEBUG.main("Reading filters from Eleventy: %o", filters);
171
166
  const shortcodes = eleventyConfig.getShortcodes();
172
- DEBUG.setup("Reading shortcodes from Eleventy: %o", shortcodes);
167
+ DEBUG.main("Reading shortcodes from Eleventy: %o", shortcodes);
173
168
  const pairedShortcodes = eleventyConfig.getPairedShortcodes();
174
- DEBUG.setup("Reading paired shortcodes from Eleventy: %o", pairedShortcodes);
169
+ DEBUG.main("Reading paired shortcodes from Eleventy: %o", pairedShortcodes);
175
170
  if (options.autotrim) {
176
171
  const defaults = ["@vento", "@11ty"];
177
172
  const tagSet = new Set(options.autotrim === true ? defaults : options.autotrim);
@@ -187,26 +182,26 @@ function VentoPlugin(eleventyConfig, userOptions) {
187
182
  tagSet.add(name);
188
183
  }
189
184
  }
190
- DEBUG.setup("Enabled autotrim for tags: %o", tagSet);
185
+ DEBUG.main("Enabled autotrim for tags: %o", tagSet);
191
186
  options.plugins.push(autotrimPlugin({ tags: [...tagSet] }));
192
187
  }
193
- DEBUG.setup("Initializing Vento environment");
194
- const engine = createVentoInterface(options.ventoOptions);
195
- DEBUG.setup("Loading plugins: %o", options.plugins);
188
+ DEBUG.main("Initializing Vento environment");
189
+ const engine = createVentoEngine(options.ventoOptions);
190
+ DEBUG.main("Loading plugins: %o", options.plugins);
196
191
  engine.loadPlugins(options.plugins);
197
192
  if (options.filters) {
198
- DEBUG.setup("Loading filters: %o", filters);
193
+ DEBUG.main("Loading filters: %o", filters);
199
194
  engine.loadFilters(filters);
200
195
  }
201
196
  if (options.shortcodes) {
202
- DEBUG.setup("Loading shortcodes: %o", shortcodes);
197
+ DEBUG.main("Loading shortcodes: %o", shortcodes);
203
198
  engine.loadShortcodes(shortcodes);
204
199
  }
205
200
  if (options.pairedShortcodes) {
206
- DEBUG.setup("Loading paired shortcodes: %o", pairedShortcodes);
201
+ DEBUG.main("Loading paired shortcodes: %o", pairedShortcodes);
207
202
  engine.loadPairedShortcodes(pairedShortcodes);
208
203
  }
209
- DEBUG.setup("Registering Vento cache handler on eleventy.beforeWatch event");
204
+ DEBUG.main("Registering Vento cache handler on eleventy.beforeWatch event");
210
205
  eleventyConfig.on("eleventy.beforeWatch", async (updatedFiles) => {
211
206
  for (let file of updatedFiles) {
212
207
  file = path.normalize(file);
@@ -214,30 +209,32 @@ function VentoPlugin(eleventyConfig, userOptions) {
214
209
  engine.cache.delete(file);
215
210
  }
216
211
  });
217
- DEBUG.setup("Registering .vto as a template format");
212
+ DEBUG.main("Registering .vto as a template format");
218
213
  eleventyConfig.addTemplateFormats("vto");
219
- DEBUG.setup("Registering .vto extension with eleventy");
214
+ DEBUG.main("Registering .vto extension with eleventy");
220
215
  eleventyConfig.addExtension("vto", {
221
216
  outputFileExtension: "html",
222
217
  read: true,
223
218
  compile(inputContent, inputPath) {
224
219
  inputPath = path.normalize(inputPath);
220
+ DEBUG.main("Getting template function for `%s`", inputPath);
225
221
  const template = engine.getTemplateFunction(inputContent, inputPath, false);
226
- return async (data) => await engine.render(template, data, inputPath);
222
+ return async (data) => await renderVentoTemplate(template, data, inputPath);
227
223
  },
228
224
  compileOptions: {
229
225
  // Custom permalink compilation
230
226
  permalink(permalinkContent, inputPath) {
231
- if (typeof permalinkContent === "string" && /\{\{\s+.+\s+\}\}/.test(permalinkContent)) {
232
- inputPath = "Permalink::" + path.normalize(inputPath);
233
- const template = engine.getTemplateFunction(permalinkContent, inputPath);
234
- return async (data) => await engine.render(template, data, inputPath);
227
+ if (typeof permalinkContent !== "string" || !/\{\{\s+.+\s+\}\}/.test(permalinkContent)) {
228
+ return permalinkContent;
235
229
  }
236
- return permalinkContent;
230
+ inputPath = "Permalink::" + path.normalize(inputPath);
231
+ DEBUG.main("Getting template function for `%s`", inputPath);
232
+ const template = engine.getTemplateFunction(permalinkContent, inputPath);
233
+ return async (data) => await renderVentoTemplate(template, data, inputPath);
237
234
  }
238
235
  }
239
236
  });
240
- DEBUG.setup("eleventy-plugin-vento initialized");
237
+ DEBUG.main("eleventy-plugin-vento initialized");
241
238
  }
242
239
  export {
243
240
  VentoPlugin
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eleventy-plugin-vento",
3
- "version": "4.0.1",
3
+ "version": "4.1.0",
4
4
  "description": "Adds support for the Vento templating language to Eleventy.",
5
5
  "type": "module",
6
6
  "engines": {
@@ -37,24 +37,24 @@
37
37
  "license": "MIT",
38
38
  "dependencies": {
39
39
  "debug": "4.3.7",
40
- "ventojs": "1.12.11"
40
+ "ventojs": "1.12.12"
41
41
  },
42
42
  "devDependencies": {
43
43
  "11ty.ts": "0.0.5",
44
44
  "@11ty/eleventy": "3.0.0",
45
- "@changesets/cli": "2.27.9",
46
- "@eslint/js": "9.14.0",
45
+ "@changesets/cli": "2.27.10",
46
+ "@eslint/js": "9.15.0",
47
47
  "@types/debug": "4.1.12",
48
48
  "@types/eslint-config-prettier": "6.11.3",
49
49
  "@types/eslint__js": "8.42.3",
50
- "@types/node": "22.8.4",
51
- "eslint": "9.14.0",
50
+ "@types/node": "22.9.3",
51
+ "eslint": "9.15.0",
52
52
  "eslint-config-prettier": "9.1.0",
53
- "eslint-plugin-unicorn": "56.0.0",
53
+ "eslint-plugin-unicorn": "56.0.1",
54
54
  "tsup": "8.3.5",
55
- "typescript": "5.6.3",
56
- "typescript-eslint": "8.12.2",
57
- "vitest": "2.1.4"
55
+ "typescript": "5.7.2",
56
+ "typescript-eslint": "8.15.0",
57
+ "vitest": "2.1.5"
58
58
  },
59
59
  "prettier": {
60
60
  "bracketSameLine": true,
@@ -68,6 +68,7 @@
68
68
  "lint": "eslint '.'",
69
69
  "ts-check": "tsc --noEmit",
70
70
  "build": "tsup",
71
+ "dev": "tsup --watch ./src",
71
72
  "ci:version": "changeset version && pnpm install --no-frozen-lockfile",
72
73
  "ci:publish": "changeset publish",
73
74
  "ci:generate-changesets": "node ./scripts/generate-changesets.js",
package/readme.md CHANGED
@@ -90,6 +90,42 @@ Filters that are added via Eleventy's `.addFilter()` or `.addAsyncFilter()` meth
90
90
 
91
91
  If you'd prefer to set filters yourself (via a plugin or other method) or prevent Eleventy from loading filters into Vento, set `filters: false` in the plugin options.
92
92
 
93
+ ### Filters and `this`
94
+
95
+ This plugin merges the keys normally expected from `this` with the `FilterThis` object Vento provides to filters. The final bound `this` object for filters is as follows:
96
+
97
+ ```ts
98
+ {
99
+ env, // Vento environment
100
+ data, // all template global data
101
+ page, // this.page
102
+ eleventy, // this.eleventy
103
+ }
104
+ ```
105
+
106
+ This feature enables re-use of the Vento environment this plugin provides, within Eleventy filters. As an example use case, you could create a filter that compiles dynamic data and cache it with Vento's own cache:
107
+
108
+ ```js
109
+ eleventyConfig.addFilter('vento', function (content) {
110
+ const res = this.env.runString(content, this.data);
111
+ return res.content;
112
+ });
113
+ ```
114
+
115
+ Because re-compilation introduces some overhead, you may want to cache your template strings compiled via a filter. With access to `this.env` you can use Vento's own cache:
116
+
117
+ ```js
118
+ import 'hash' from 'node:crypto'; // since Node v20.12.0
119
+
120
+ const sha1Hash(str) => hash('sha1', str, 'hex');
121
+
122
+ eleventyConfig.addFilter('vento', function (content) {
123
+ const file = `dynamicString:${sha1Hash(content)}`;
124
+ const res = this.env.runString(content, this.data, file);
125
+ return res.content;
126
+ });
127
+ ```
128
+
93
129
  ### Relevant documentation
94
130
 
95
131
  Vento: See [Filters](https://vento.js.org/configuration/#filters) and [Pipes](https://vento.js.org/syntax/pipes/)
@@ -202,7 +238,7 @@ Vento: See [Auto Trim Plugin](https://vento.js.org/plugins/auto-trim/).
202
238
 
203
239
  Like Eleventy, this plugin uses the [`debug`](https://www.npmjs.com/package/debug) package to handle verbose logging. The following `DEBUG` namespaces are implemented:
204
240
 
205
- - `Eleventy:Vento:Setup` - Logs initial setup of the plugin, loading features, pre-page compile setup steps (like changing `page` and `eleventy` objects)
241
+ - `Eleventy:Vento` - Logs initial setup of the plugin, loading features, pre-page compile setup steps (like changing `page` and `eleventy` objects)
206
242
  - `Eleventy:Vento:Cache` - Logs updates to Vento's own internal cache, which is used in tandem with Eleventy's cache.
207
243
  - `Eleventy:Vento:Render` - Logs when templates are rendered
208
244
 
@@ -215,7 +251,7 @@ $ DEBUG='Eleventy:*' npx @11ty/eleventy
215
251
  Alternatively, use a finer grained namespace to see only the output generated by `eleventy-plugin-vento`.
216
252
 
217
253
  ```sh
218
- $ DEBUG='Eleventy:Vento:*' npx @11ty/eleventy
254
+ $ DEBUG='Eleventy:Vento*' npx @11ty/eleventy
219
255
  ```
220
256
 
221
257
  ```sh