eleventy-plugin-vento 4.0.1 → 4.1.1-beta.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 +40 -1
- package/dist/{index.d.ts → plugin.d.ts} +10 -14
- package/dist/plugin.js +243 -0
- package/package.json +20 -18
- package/readme.md +22 -6
- package/dist/index.js +0 -244
package/CHANGELOG.md
CHANGED
|
@@ -1,10 +1,49 @@
|
|
|
1
1
|
# eleventy-plugin-vento
|
|
2
2
|
|
|
3
|
+
## 4.1.1-beta.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 335f21e: Select type updates (shouldn't affect compilation, however should improve DX)
|
|
8
|
+
|
|
9
|
+
Changes are:
|
|
10
|
+
|
|
11
|
+
- split types into separate files
|
|
12
|
+
- namespace `ventojs` type imports
|
|
13
|
+
- make `PluginOptions` optional by default
|
|
14
|
+
- make Eleventy types more readable
|
|
15
|
+
- declare a special (`EleventyVentoEnvironment`) for this plugin to replace Vento's own `Environment`
|
|
16
|
+
|
|
17
|
+
- 9eaa059: Update `debug` to v4.4.0
|
|
18
|
+
- f387b5e: Update `ventojs` to v1.12.13
|
|
19
|
+
- 070109a: Refactored files and functions internally that shouldn't have any impact on usage or performance:
|
|
20
|
+
|
|
21
|
+
- Split `debug` functions into separate exports, renamed `runCompatiblityCheck -> compatibilityCheck` (dd4c379b)
|
|
22
|
+
- Utilities are now split into separate files (e06a83ab)
|
|
23
|
+
- Main file renamed from `index.ts` to `plugin.ts` (1b122d2a)
|
|
24
|
+
|
|
25
|
+
## 4.1.0
|
|
26
|
+
|
|
27
|
+
### Minor Changes
|
|
28
|
+
|
|
29
|
+
- eb33d79: Expose Vento's `FilterThis` on Eleventy-declared filters. (fixes #72)
|
|
30
|
+
|
|
31
|
+
> [!IMPORTANT]
|
|
32
|
+
> 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.
|
|
33
|
+
|
|
34
|
+
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.
|
|
35
|
+
|
|
36
|
+
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.
|
|
37
|
+
|
|
38
|
+
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.
|
|
39
|
+
|
|
40
|
+
- eb33d79: Update vento to 1.12.12
|
|
41
|
+
|
|
3
42
|
## 4.0.1
|
|
4
43
|
|
|
5
44
|
### Patch Changes
|
|
6
45
|
|
|
7
|
-
-
|
|
46
|
+
- hotfix - include `types` field in package.json to declare bundled types
|
|
8
47
|
|
|
9
48
|
## 4.0.0
|
|
10
49
|
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { UserConfig } from '@11ty/eleventy';
|
|
2
|
-
import {
|
|
2
|
+
import { LiteralUnion } from 'type-fest';
|
|
3
|
+
import * as ventojs from 'ventojs';
|
|
3
4
|
import { Plugin } from 'ventojs/src/environment.js';
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
interface VentoPluginOptions {
|
|
6
|
+
interface PluginOptions {
|
|
7
7
|
/**
|
|
8
8
|
* An array of Vento plugins
|
|
9
9
|
*/
|
|
10
|
-
plugins
|
|
10
|
+
plugins?: Plugin[];
|
|
11
11
|
/**
|
|
12
12
|
* Enables Vento's autotrim plugin.
|
|
13
13
|
* ```js
|
|
@@ -20,13 +20,13 @@ interface VentoPluginOptions {
|
|
|
20
20
|
* autotrim: true
|
|
21
21
|
* ```
|
|
22
22
|
*/
|
|
23
|
-
autotrim
|
|
23
|
+
autotrim?: LiteralUnion<'@11ty' | '@vento', string>[] | boolean;
|
|
24
24
|
/** Enable use of Eleventy filters */
|
|
25
|
-
filters
|
|
25
|
+
filters?: boolean;
|
|
26
26
|
/** Enable use of Eleventy shortcodes */
|
|
27
|
-
shortcodes
|
|
27
|
+
shortcodes?: boolean;
|
|
28
28
|
/** Enable use of Eleventy paired shortcodes */
|
|
29
|
-
pairedShortcodes
|
|
29
|
+
pairedShortcodes?: boolean;
|
|
30
30
|
/**
|
|
31
31
|
* A Vento configuration object.
|
|
32
32
|
*
|
|
@@ -34,13 +34,9 @@ interface VentoPluginOptions {
|
|
|
34
34
|
* Eleventy's own `dir.includes` location.**
|
|
35
35
|
* @see {@link https://vento.js.org/configuration/}
|
|
36
36
|
*/
|
|
37
|
-
ventoOptions
|
|
37
|
+
ventoOptions?: ventojs.Options;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
|
|
41
|
-
* @file Main plugin declaration
|
|
42
|
-
*/
|
|
43
|
-
|
|
44
|
-
declare function VentoPlugin(eleventyConfig: UserConfig, userOptions: Partial<VentoPluginOptions>): void;
|
|
40
|
+
declare function VentoPlugin(eleventyConfig: UserConfig, userOptions: PluginOptions): void;
|
|
45
41
|
|
|
46
42
|
export { VentoPlugin };
|
package/dist/plugin.js
ADDED
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
// src/plugin.ts
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import autotrimPlugin, { defaultTags as autotrimDefaultTags } from "ventojs/plugins/auto_trim.js";
|
|
4
|
+
|
|
5
|
+
// src/engine.ts
|
|
6
|
+
import createVentoEnv from "ventojs";
|
|
7
|
+
|
|
8
|
+
// src/utils/create-vento-tag.ts
|
|
9
|
+
function createVentoTag(tagInfo) {
|
|
10
|
+
const IS_PAIRED = tagInfo.group === "pairedShortcodes";
|
|
11
|
+
let INT = 0;
|
|
12
|
+
const tag = (env, code, output, tokens) => {
|
|
13
|
+
if (!code.startsWith(tagInfo.name)) return;
|
|
14
|
+
const { dataVarname } = env.options;
|
|
15
|
+
const thisArg = `{
|
|
16
|
+
page: ${dataVarname}.page,
|
|
17
|
+
eleventy: ${dataVarname}.eleventy
|
|
18
|
+
}`;
|
|
19
|
+
const fn = `__env.utils.eleventyFunctions.${tagInfo.group}.${tagInfo.name}`;
|
|
20
|
+
const args = [code.replace(tagInfo.name, "").trim()];
|
|
21
|
+
const compiled = [];
|
|
22
|
+
if (IS_PAIRED) {
|
|
23
|
+
const nestedVarname = `__arg${INT++}`;
|
|
24
|
+
args.unshift(env.compileFilters(tokens, nestedVarname, env.options.autoescape));
|
|
25
|
+
compiled.push(
|
|
26
|
+
"{",
|
|
27
|
+
`let ${nestedVarname} = "";`,
|
|
28
|
+
...env.compileTokens(tokens, nestedVarname, [`/${tagInfo.name}`])
|
|
29
|
+
);
|
|
30
|
+
if (tokens.length > 0 && (tokens[0][0] !== "tag" || tokens[0][1] !== `/${tagInfo.name}`)) {
|
|
31
|
+
throw new Error(`Vento: Missing closing tag for ${tagInfo.name} tag: ${code}`);
|
|
32
|
+
}
|
|
33
|
+
tokens.shift();
|
|
34
|
+
}
|
|
35
|
+
args.unshift(thisArg);
|
|
36
|
+
compiled.push(
|
|
37
|
+
"{",
|
|
38
|
+
`const __result = await ${fn}.call(${args.filter(Boolean).join(", ")});`,
|
|
39
|
+
`${output} += ${env.compileFilters(tokens, "__result", env.options.autoescape)}`,
|
|
40
|
+
"}"
|
|
41
|
+
);
|
|
42
|
+
if (IS_PAIRED) {
|
|
43
|
+
compiled.push("}");
|
|
44
|
+
}
|
|
45
|
+
return compiled.join("\n");
|
|
46
|
+
};
|
|
47
|
+
return Object.defineProperty(tag, "name", {
|
|
48
|
+
value: tagInfo.name + IS_PAIRED ? `PairedTag` : `Tag`
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// src/utils/debuggers.ts
|
|
53
|
+
import createDebugger from "debug";
|
|
54
|
+
var debugBaseNamespace = "Eleventy:Vento";
|
|
55
|
+
var debugMain = createDebugger(debugBaseNamespace);
|
|
56
|
+
var debugCache = createDebugger(`${debugBaseNamespace}:Cache`);
|
|
57
|
+
var debugRender = createDebugger(`${debugBaseNamespace}:Render`);
|
|
58
|
+
|
|
59
|
+
// src/engine.ts
|
|
60
|
+
function createVentoEngine(options) {
|
|
61
|
+
const env = createVentoEnv(options);
|
|
62
|
+
env.utils.eleventyFunctions = { shortcodes: {}, pairedShortcodes: {} };
|
|
63
|
+
function loadPlugins(plugins) {
|
|
64
|
+
for (const plugin of plugins) {
|
|
65
|
+
env.use(plugin);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
function loadFilters(filters) {
|
|
69
|
+
for (const [name, fn] of Object.entries(filters)) {
|
|
70
|
+
env.filters[name] = async function(...args) {
|
|
71
|
+
const { page, eleventy } = this.data;
|
|
72
|
+
const filterResult = await fn.apply({ ...this, page, eleventy }, args);
|
|
73
|
+
return filterResult;
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
function loadShortcodes(shortcodes) {
|
|
78
|
+
for (const [name, fn] of Object.entries(shortcodes)) {
|
|
79
|
+
env.utils.eleventyFunctions.shortcodes[name] = fn;
|
|
80
|
+
const shortcodeTag = createVentoTag({ name, group: "shortcodes" });
|
|
81
|
+
env.tags.push(shortcodeTag);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
function loadPairedShortcodes(pairedShortcodes) {
|
|
85
|
+
for (const [name, fn] of Object.entries(pairedShortcodes)) {
|
|
86
|
+
env.utils.eleventyFunctions.pairedShortcodes[name] = fn;
|
|
87
|
+
const shortcodeTag = createVentoTag({ name, group: "pairedShortcodes" });
|
|
88
|
+
env.tags.push(shortcodeTag);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
function getTemplateFunction(source, file, useVentoCache = true) {
|
|
92
|
+
let template = env.cache.get(file);
|
|
93
|
+
if ((template == null ? void 0 : template.source) === source) {
|
|
94
|
+
debugCache("Cache HIT for `%s`, used precompiled template", file);
|
|
95
|
+
} else {
|
|
96
|
+
template = env.compile(source, file);
|
|
97
|
+
debugCache(
|
|
98
|
+
`Cache MISS for \`%s\`, compiled new template:
|
|
99
|
+
Use Vento cache: %o
|
|
100
|
+
|
|
101
|
+
${template}`,
|
|
102
|
+
file,
|
|
103
|
+
useVentoCache
|
|
104
|
+
);
|
|
105
|
+
if (useVentoCache) {
|
|
106
|
+
env.cache.set(file, template);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return template;
|
|
110
|
+
}
|
|
111
|
+
return {
|
|
112
|
+
cache: env.cache,
|
|
113
|
+
loadPlugins,
|
|
114
|
+
loadFilters,
|
|
115
|
+
loadShortcodes,
|
|
116
|
+
loadPairedShortcodes,
|
|
117
|
+
getTemplateFunction
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
async function renderVentoTemplate(template, data, from) {
|
|
121
|
+
debugRender("Rendering `%s`", from);
|
|
122
|
+
const { content } = await template(data);
|
|
123
|
+
return content;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// src/utils/compat-check.ts
|
|
127
|
+
var REQUIRED_API_METHODS = [
|
|
128
|
+
["getShortcodes", "v3.0.0-alpha.15"],
|
|
129
|
+
["getPairedShortcodes", "v3.0.0-alpha.15"],
|
|
130
|
+
["getFilters", "v3.0.0-alpha.15"],
|
|
131
|
+
["addExtension", "v1.0.0"]
|
|
132
|
+
];
|
|
133
|
+
function compatibilityCheck(config) {
|
|
134
|
+
debugMain("Run compatibility check");
|
|
135
|
+
for (const [method, version] of REQUIRED_API_METHODS) {
|
|
136
|
+
if (!(method in config)) {
|
|
137
|
+
console.error(
|
|
138
|
+
"[eleventy-plugin-vento] Plugin compatibility error:",
|
|
139
|
+
`\`${method}\``,
|
|
140
|
+
"not found. Please use Eleventy",
|
|
141
|
+
version,
|
|
142
|
+
"or later."
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// src/plugin.ts
|
|
149
|
+
function VentoPlugin(eleventyConfig, userOptions) {
|
|
150
|
+
debugMain("Initializing eleventy-plugin-vento");
|
|
151
|
+
compatibilityCheck(eleventyConfig);
|
|
152
|
+
const options = {
|
|
153
|
+
// Define defaults
|
|
154
|
+
autotrim: false,
|
|
155
|
+
plugins: [],
|
|
156
|
+
filters: true,
|
|
157
|
+
shortcodes: true,
|
|
158
|
+
pairedShortcodes: true,
|
|
159
|
+
ventoOptions: {
|
|
160
|
+
includes: eleventyConfig.directories.includes
|
|
161
|
+
},
|
|
162
|
+
// Merge in user-provided options
|
|
163
|
+
...userOptions
|
|
164
|
+
};
|
|
165
|
+
debugMain("Merged default and user config: %O", options);
|
|
166
|
+
const filters = eleventyConfig.getFilters();
|
|
167
|
+
debugMain("Reading filters from Eleventy: %o", filters);
|
|
168
|
+
const shortcodes = eleventyConfig.getShortcodes();
|
|
169
|
+
debugMain("Reading shortcodes from Eleventy: %o", shortcodes);
|
|
170
|
+
const pairedShortcodes = eleventyConfig.getPairedShortcodes();
|
|
171
|
+
debugMain("Reading paired shortcodes from Eleventy: %o", pairedShortcodes);
|
|
172
|
+
if (options.autotrim) {
|
|
173
|
+
const defaults = ["@vento", "@11ty"];
|
|
174
|
+
const tagSet = new Set(options.autotrim === true ? defaults : options.autotrim);
|
|
175
|
+
if (tagSet.has("@vento")) {
|
|
176
|
+
tagSet.delete("@vento");
|
|
177
|
+
for (const name of autotrimDefaultTags) {
|
|
178
|
+
tagSet.add(name);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
if (tagSet.has("@11ty")) {
|
|
182
|
+
tagSet.delete("@11ty");
|
|
183
|
+
for (const name in pairedShortcodes) {
|
|
184
|
+
tagSet.add(name);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
debugMain("Enabled autotrim for tags: %o", tagSet);
|
|
188
|
+
options.plugins.push(autotrimPlugin({ tags: [...tagSet] }));
|
|
189
|
+
}
|
|
190
|
+
debugMain("Initializing Vento environment");
|
|
191
|
+
const engine = createVentoEngine(options.ventoOptions);
|
|
192
|
+
debugMain("Loading plugins: %o", options.plugins);
|
|
193
|
+
engine.loadPlugins(options.plugins);
|
|
194
|
+
if (options.filters) {
|
|
195
|
+
debugMain("Loading filters: %o", filters);
|
|
196
|
+
engine.loadFilters(filters);
|
|
197
|
+
}
|
|
198
|
+
if (options.shortcodes) {
|
|
199
|
+
debugMain("Loading shortcodes: %o", shortcodes);
|
|
200
|
+
engine.loadShortcodes(shortcodes);
|
|
201
|
+
}
|
|
202
|
+
if (options.pairedShortcodes) {
|
|
203
|
+
debugMain("Loading paired shortcodes: %o", pairedShortcodes);
|
|
204
|
+
engine.loadPairedShortcodes(pairedShortcodes);
|
|
205
|
+
}
|
|
206
|
+
debugMain("Registering Vento cache handler on eleventy.beforeWatch event");
|
|
207
|
+
eleventyConfig.on("eleventy.beforeWatch", async (updatedFiles) => {
|
|
208
|
+
for (let file of updatedFiles) {
|
|
209
|
+
file = path.normalize(file);
|
|
210
|
+
debugCache("Delete cache entry for %s", file);
|
|
211
|
+
engine.cache.delete(file);
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
debugMain("Registering .vto as a template format");
|
|
215
|
+
eleventyConfig.addTemplateFormats("vto");
|
|
216
|
+
debugMain("Registering .vto extension with eleventy");
|
|
217
|
+
eleventyConfig.addExtension("vto", {
|
|
218
|
+
outputFileExtension: "html",
|
|
219
|
+
read: true,
|
|
220
|
+
compile(inputContent, inputPath) {
|
|
221
|
+
inputPath = path.normalize(inputPath);
|
|
222
|
+
debugMain("Getting template function for `%s`", inputPath);
|
|
223
|
+
const template = engine.getTemplateFunction(inputContent, inputPath, false);
|
|
224
|
+
return async (data) => await renderVentoTemplate(template, data, inputPath);
|
|
225
|
+
},
|
|
226
|
+
compileOptions: {
|
|
227
|
+
// Custom permalink compilation
|
|
228
|
+
permalink(permalinkContent, inputPath) {
|
|
229
|
+
if (typeof permalinkContent !== "string" || !/\{\{\s+.+\s+\}\}/.test(permalinkContent)) {
|
|
230
|
+
return permalinkContent;
|
|
231
|
+
}
|
|
232
|
+
inputPath = "Permalink::" + path.normalize(inputPath);
|
|
233
|
+
debugMain("Getting template function for `%s`", inputPath);
|
|
234
|
+
const template = engine.getTemplateFunction(permalinkContent, inputPath);
|
|
235
|
+
return async (data) => await renderVentoTemplate(template, data, inputPath);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
});
|
|
239
|
+
debugMain("eleventy-plugin-vento initialized");
|
|
240
|
+
}
|
|
241
|
+
export {
|
|
242
|
+
VentoPlugin
|
|
243
|
+
};
|
package/package.json
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eleventy-plugin-vento",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.1.1-beta.0",
|
|
4
4
|
"description": "Adds support for the Vento templating language to Eleventy.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
7
7
|
"node": ">=18"
|
|
8
8
|
},
|
|
9
|
-
"types": "./dist/
|
|
9
|
+
"types": "./dist/plugin.d.ts",
|
|
10
10
|
"exports": {
|
|
11
11
|
".": {
|
|
12
|
-
"import": "./dist/
|
|
13
|
-
"types": "./dist/
|
|
12
|
+
"import": "./dist/plugin.js",
|
|
13
|
+
"types": "./dist/plugin.d.ts"
|
|
14
14
|
}
|
|
15
15
|
},
|
|
16
16
|
"files": [
|
|
@@ -36,25 +36,27 @@
|
|
|
36
36
|
},
|
|
37
37
|
"license": "MIT",
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"debug": "4.
|
|
40
|
-
"ventojs": "1.12.
|
|
39
|
+
"debug": "4.4.0",
|
|
40
|
+
"ventojs": "1.12.13"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"11ty.ts": "0.0.5",
|
|
44
44
|
"@11ty/eleventy": "3.0.0",
|
|
45
|
-
"@changesets/cli": "2.27.
|
|
46
|
-
"@eslint/js": "9.
|
|
45
|
+
"@changesets/cli": "2.27.10",
|
|
46
|
+
"@eslint/js": "9.16.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.
|
|
51
|
-
"eslint": "9.
|
|
50
|
+
"@types/node": "22.10.1",
|
|
51
|
+
"eslint": "9.16.0",
|
|
52
52
|
"eslint-config-prettier": "9.1.0",
|
|
53
|
-
"eslint-plugin-unicorn": "56.0.
|
|
53
|
+
"eslint-plugin-unicorn": "56.0.1",
|
|
54
|
+
"globals": "15.13.0",
|
|
54
55
|
"tsup": "8.3.5",
|
|
55
|
-
"
|
|
56
|
-
"typescript
|
|
57
|
-
"
|
|
56
|
+
"type-fest": "4.30.0",
|
|
57
|
+
"typescript": "5.7.2",
|
|
58
|
+
"typescript-eslint": "8.18.0",
|
|
59
|
+
"vitest": "2.1.8"
|
|
58
60
|
},
|
|
59
61
|
"prettier": {
|
|
60
62
|
"bracketSameLine": true,
|
|
@@ -64,13 +66,13 @@
|
|
|
64
66
|
},
|
|
65
67
|
"scripts": {
|
|
66
68
|
"test": "vitest --run",
|
|
67
|
-
"check": "pnpm --color run '
|
|
68
|
-
"lint": "eslint '.'",
|
|
69
|
-
"
|
|
69
|
+
"check": "pnpm --color run '/^check:/'",
|
|
70
|
+
"check:lint": "eslint '.'",
|
|
71
|
+
"check:types": "tsc --noEmit",
|
|
70
72
|
"build": "tsup",
|
|
73
|
+
"dev": "tsup --watch ./src",
|
|
71
74
|
"ci:version": "changeset version && pnpm install --no-frozen-lockfile",
|
|
72
75
|
"ci:publish": "changeset publish",
|
|
73
|
-
"ci:generate-changesets": "node ./scripts/generate-changesets.js",
|
|
74
76
|
"format": "pnpm dlx prettier --config ./package.json --write ."
|
|
75
77
|
}
|
|
76
78
|
}
|
package/readme.md
CHANGED
|
@@ -62,9 +62,6 @@ export default function (eleventyConfig) {
|
|
|
62
62
|
// to trim the default tags (see section on Auto-trimming)
|
|
63
63
|
autotrim: false,
|
|
64
64
|
|
|
65
|
-
// Enable/disable ignore tag syntax (see section on ignoring tags)
|
|
66
|
-
ignoreTag: false,
|
|
67
|
-
|
|
68
65
|
// A Vento configuration object
|
|
69
66
|
ventoOptions: {
|
|
70
67
|
includes: eleventyConfig.directories.includes,
|
|
@@ -90,6 +87,24 @@ Filters that are added via Eleventy's `.addFilter()` or `.addAsyncFilter()` meth
|
|
|
90
87
|
|
|
91
88
|
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
89
|
|
|
90
|
+
### Filters and `this`
|
|
91
|
+
|
|
92
|
+
Eleventy provides filters with scoped data via the `this.page` and `this.eleventy` objects (see [Filters#Scoped data in Filters](https://www.11ty.dev/docs/filters/#scoped-data-in-filters) in Eleventy's docs for more details). Likewise, Vento provides filters with `this.env` and `this.data` representing the Vento environment and the current template data. This plugin merges both objects together to make `this.page` (and `eleventy`/`env`/`data`) available on all filters processed by Vento.
|
|
93
|
+
|
|
94
|
+
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 to improve performance:
|
|
95
|
+
|
|
96
|
+
```js
|
|
97
|
+
import 'hash' from 'node:crypto'; // since Node v20.12.0
|
|
98
|
+
|
|
99
|
+
const sha1Hash(str) => hash('sha1', str, 'hex');
|
|
100
|
+
|
|
101
|
+
eleventyConfig.addFilter('vento', function (content) {
|
|
102
|
+
const file = `dynamicString:${sha1Hash(content)}`;
|
|
103
|
+
const res = this.env.runString(content, this.data, file);
|
|
104
|
+
return res.content;
|
|
105
|
+
});
|
|
106
|
+
```
|
|
107
|
+
|
|
93
108
|
### Relevant documentation
|
|
94
109
|
|
|
95
110
|
Vento: See [Filters](https://vento.js.org/configuration/#filters) and [Pipes](https://vento.js.org/syntax/pipes/)
|
|
@@ -144,7 +159,8 @@ Eleventy: See [Shortcodes](https://www.11ty.dev/docs/shortcodes/) and the sub-se
|
|
|
144
159
|
|
|
145
160
|
## Vento Plugins
|
|
146
161
|
|
|
147
|
-
|
|
162
|
+
> [!NOTE]
|
|
163
|
+
> The `auto_trim` plugin that ships with Vento has a specific implementation in the scope of this plugin. See [Auto-Trimming Tags](#auto-trimming-tags) for more details.\_
|
|
148
164
|
|
|
149
165
|
If you'd like to extend the Vento library with any plugins, include them in an array passed to the `plugins` option.
|
|
150
166
|
|
|
@@ -202,7 +218,7 @@ Vento: See [Auto Trim Plugin](https://vento.js.org/plugins/auto-trim/).
|
|
|
202
218
|
|
|
203
219
|
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
220
|
|
|
205
|
-
- `Eleventy:Vento
|
|
221
|
+
- `Eleventy:Vento` - Logs initial setup of the plugin, loading features, pre-page compile setup steps (like changing `page` and `eleventy` objects)
|
|
206
222
|
- `Eleventy:Vento:Cache` - Logs updates to Vento's own internal cache, which is used in tandem with Eleventy's cache.
|
|
207
223
|
- `Eleventy:Vento:Render` - Logs when templates are rendered
|
|
208
224
|
|
|
@@ -215,7 +231,7 @@ $ DEBUG='Eleventy:*' npx @11ty/eleventy
|
|
|
215
231
|
Alternatively, use a finer grained namespace to see only the output generated by `eleventy-plugin-vento`.
|
|
216
232
|
|
|
217
233
|
```sh
|
|
218
|
-
$ DEBUG='Eleventy:Vento
|
|
234
|
+
$ DEBUG='Eleventy:Vento*' npx @11ty/eleventy
|
|
219
235
|
```
|
|
220
236
|
|
|
221
237
|
```sh
|
package/dist/index.js
DELETED
|
@@ -1,244 +0,0 @@
|
|
|
1
|
-
// src/index.ts
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
import autotrimPlugin, { defaultTags as autotrimDefaultTags } from "ventojs/plugins/auto_trim.js";
|
|
4
|
-
|
|
5
|
-
// src/create-vento-interface.ts
|
|
6
|
-
import { default as ventojs } from "ventojs";
|
|
7
|
-
|
|
8
|
-
// src/create-vento-tag.ts
|
|
9
|
-
function createVentoTag(spec) {
|
|
10
|
-
const IS_PAIRED = spec.group === "pairedShortcodes";
|
|
11
|
-
const tag = (env, code, output, tokens) => {
|
|
12
|
-
if (!code.startsWith(spec.name)) return;
|
|
13
|
-
const fn = `__env.utils._11tyFns.${spec.group}.${spec.name}`;
|
|
14
|
-
const ctx = "__env.utils._11tyCtx";
|
|
15
|
-
const args = [code.replace(spec.name, "").trim()];
|
|
16
|
-
const varname = output.startsWith("__shortcode_content") ? `${output}_precomp` : "__shortcode_content";
|
|
17
|
-
const compiled = [];
|
|
18
|
-
if (IS_PAIRED) {
|
|
19
|
-
args.unshift(env.compileFilters(tokens, varname, env.options.autoescape));
|
|
20
|
-
compiled.push(
|
|
21
|
-
"{",
|
|
22
|
-
`let ${varname} = "";`,
|
|
23
|
-
...env.compileTokens(tokens, varname, [`/${spec.name}`])
|
|
24
|
-
);
|
|
25
|
-
if (tokens.length > 0 && (tokens[0][0] !== "tag" || tokens[0][1] !== `/${spec.name}`)) {
|
|
26
|
-
throw new Error(`Vento: Missing closing tag for ${spec.name} tag: ${code}`);
|
|
27
|
-
}
|
|
28
|
-
tokens.shift();
|
|
29
|
-
}
|
|
30
|
-
args.unshift(ctx);
|
|
31
|
-
compiled.push(
|
|
32
|
-
"{",
|
|
33
|
-
`const __shortcode_result = await ${fn}.call(${args.filter(Boolean).join(", ")});`,
|
|
34
|
-
`${output} += ${env.compileFilters(tokens, "__shortcode_result", env.options.autoescape)}`,
|
|
35
|
-
"}"
|
|
36
|
-
);
|
|
37
|
-
if (IS_PAIRED) {
|
|
38
|
-
compiled.push("}");
|
|
39
|
-
}
|
|
40
|
-
const compiledTag = compiled.join("\n");
|
|
41
|
-
return compiledTag;
|
|
42
|
-
};
|
|
43
|
-
return Object.defineProperty(tag, "name", {
|
|
44
|
-
value: spec.name + IS_PAIRED ? `PairedTag` : `Tag`
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// src/utils.ts
|
|
49
|
-
import createDebugger from "debug";
|
|
50
|
-
var debugBaseNamespace = "Eleventy:Vento";
|
|
51
|
-
var DEBUG = {
|
|
52
|
-
setup: createDebugger(`${debugBaseNamespace}:Setup`),
|
|
53
|
-
cache: createDebugger(`${debugBaseNamespace}:Cache`),
|
|
54
|
-
render: createDebugger(`${debugBaseNamespace}:Render`)
|
|
55
|
-
};
|
|
56
|
-
var REQUIRED_API_METHODS = [
|
|
57
|
-
["getShortcodes", "v3.0.0-alpha.15"],
|
|
58
|
-
["getPairedShortcodes", "v3.0.0-alpha.15"],
|
|
59
|
-
["getFilters", "v3.0.0-alpha.15"],
|
|
60
|
-
["addExtension", "v1.0.0"]
|
|
61
|
-
];
|
|
62
|
-
var CONTEXT_DATA_KEYS = ["page", "eleventy"];
|
|
63
|
-
function runCompatibilityCheck(config) {
|
|
64
|
-
DEBUG.setup("Run compatibility check");
|
|
65
|
-
for (const [method, version] of REQUIRED_API_METHODS) {
|
|
66
|
-
if (!(method in config)) {
|
|
67
|
-
console.error(
|
|
68
|
-
"[eleventy-plugin-vento] Plugin compatibility error:",
|
|
69
|
-
`\`${method}\``,
|
|
70
|
-
"not found. Please use Eleventy",
|
|
71
|
-
version,
|
|
72
|
-
"or later."
|
|
73
|
-
);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// src/create-vento-interface.ts
|
|
79
|
-
function createVentoInterface(options) {
|
|
80
|
-
const env = ventojs(options);
|
|
81
|
-
env.utils._11tyFns = { shortcodes: {}, pairedShortcodes: {} };
|
|
82
|
-
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
|
-
function loadPlugins(plugins) {
|
|
93
|
-
for (const plugin of plugins) {
|
|
94
|
-
env.use(plugin);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
function loadFilters(filters) {
|
|
98
|
-
for (const [name, fn] of Object.entries(filters)) {
|
|
99
|
-
env.filters[name] = fn.bind(env.utils._11tyCtx);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
function loadShortcodes(shortcodes) {
|
|
103
|
-
for (const [name, fn] of Object.entries(shortcodes)) {
|
|
104
|
-
env.utils._11tyFns.shortcodes[name] = fn;
|
|
105
|
-
env.tags.push(createVentoTag({ name, group: "shortcodes" }));
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
function loadPairedShortcodes(pairedShortcodes) {
|
|
109
|
-
for (const [name, fn] of Object.entries(pairedShortcodes)) {
|
|
110
|
-
env.utils._11tyFns.pairedShortcodes[name] = fn;
|
|
111
|
-
env.tags.push(createVentoTag({ name, group: "pairedShortcodes" }));
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
function getTemplateFunction(source, file, useVentoCache = true) {
|
|
115
|
-
let template = env.cache.get(file);
|
|
116
|
-
if (template?.source === source) {
|
|
117
|
-
DEBUG.cache("Cache HIT for `%s`, used precompiled template", file);
|
|
118
|
-
} else {
|
|
119
|
-
template = env.compile(source, file);
|
|
120
|
-
DEBUG.cache(
|
|
121
|
-
`Cache MISS for \`%s\`, compiled new template:
|
|
122
|
-
Use Vento cache: %o
|
|
123
|
-
|
|
124
|
-
${template}`,
|
|
125
|
-
file,
|
|
126
|
-
useVentoCache
|
|
127
|
-
);
|
|
128
|
-
if (useVentoCache) {
|
|
129
|
-
env.cache.set(file, template);
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
return template;
|
|
133
|
-
}
|
|
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
|
-
return {
|
|
141
|
-
cache: env.cache,
|
|
142
|
-
loadPlugins,
|
|
143
|
-
loadFilters,
|
|
144
|
-
loadShortcodes,
|
|
145
|
-
loadPairedShortcodes,
|
|
146
|
-
getTemplateFunction,
|
|
147
|
-
render
|
|
148
|
-
};
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
// src/index.ts
|
|
152
|
-
function VentoPlugin(eleventyConfig, userOptions) {
|
|
153
|
-
DEBUG.setup("Initializing eleventy-plugin-vento");
|
|
154
|
-
runCompatibilityCheck(eleventyConfig);
|
|
155
|
-
const options = {
|
|
156
|
-
// Define defaults
|
|
157
|
-
autotrim: false,
|
|
158
|
-
plugins: [],
|
|
159
|
-
filters: true,
|
|
160
|
-
shortcodes: true,
|
|
161
|
-
pairedShortcodes: true,
|
|
162
|
-
ventoOptions: {
|
|
163
|
-
includes: eleventyConfig.directories.includes
|
|
164
|
-
},
|
|
165
|
-
// Merge in user-provided options
|
|
166
|
-
...userOptions
|
|
167
|
-
};
|
|
168
|
-
DEBUG.setup("Merged default and user config: %O", options);
|
|
169
|
-
const filters = eleventyConfig.getFilters();
|
|
170
|
-
DEBUG.setup("Reading filters from Eleventy: %o", filters);
|
|
171
|
-
const shortcodes = eleventyConfig.getShortcodes();
|
|
172
|
-
DEBUG.setup("Reading shortcodes from Eleventy: %o", shortcodes);
|
|
173
|
-
const pairedShortcodes = eleventyConfig.getPairedShortcodes();
|
|
174
|
-
DEBUG.setup("Reading paired shortcodes from Eleventy: %o", pairedShortcodes);
|
|
175
|
-
if (options.autotrim) {
|
|
176
|
-
const defaults = ["@vento", "@11ty"];
|
|
177
|
-
const tagSet = new Set(options.autotrim === true ? defaults : options.autotrim);
|
|
178
|
-
if (tagSet.has("@vento")) {
|
|
179
|
-
tagSet.delete("@vento");
|
|
180
|
-
for (const name of autotrimDefaultTags) {
|
|
181
|
-
tagSet.add(name);
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
if (tagSet.has("@11ty")) {
|
|
185
|
-
tagSet.delete("@11ty");
|
|
186
|
-
for (const name in pairedShortcodes) {
|
|
187
|
-
tagSet.add(name);
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
DEBUG.setup("Enabled autotrim for tags: %o", tagSet);
|
|
191
|
-
options.plugins.push(autotrimPlugin({ tags: [...tagSet] }));
|
|
192
|
-
}
|
|
193
|
-
DEBUG.setup("Initializing Vento environment");
|
|
194
|
-
const engine = createVentoInterface(options.ventoOptions);
|
|
195
|
-
DEBUG.setup("Loading plugins: %o", options.plugins);
|
|
196
|
-
engine.loadPlugins(options.plugins);
|
|
197
|
-
if (options.filters) {
|
|
198
|
-
DEBUG.setup("Loading filters: %o", filters);
|
|
199
|
-
engine.loadFilters(filters);
|
|
200
|
-
}
|
|
201
|
-
if (options.shortcodes) {
|
|
202
|
-
DEBUG.setup("Loading shortcodes: %o", shortcodes);
|
|
203
|
-
engine.loadShortcodes(shortcodes);
|
|
204
|
-
}
|
|
205
|
-
if (options.pairedShortcodes) {
|
|
206
|
-
DEBUG.setup("Loading paired shortcodes: %o", pairedShortcodes);
|
|
207
|
-
engine.loadPairedShortcodes(pairedShortcodes);
|
|
208
|
-
}
|
|
209
|
-
DEBUG.setup("Registering Vento cache handler on eleventy.beforeWatch event");
|
|
210
|
-
eleventyConfig.on("eleventy.beforeWatch", async (updatedFiles) => {
|
|
211
|
-
for (let file of updatedFiles) {
|
|
212
|
-
file = path.normalize(file);
|
|
213
|
-
DEBUG.cache("Delete cache entry for %s", file);
|
|
214
|
-
engine.cache.delete(file);
|
|
215
|
-
}
|
|
216
|
-
});
|
|
217
|
-
DEBUG.setup("Registering .vto as a template format");
|
|
218
|
-
eleventyConfig.addTemplateFormats("vto");
|
|
219
|
-
DEBUG.setup("Registering .vto extension with eleventy");
|
|
220
|
-
eleventyConfig.addExtension("vto", {
|
|
221
|
-
outputFileExtension: "html",
|
|
222
|
-
read: true,
|
|
223
|
-
compile(inputContent, inputPath) {
|
|
224
|
-
inputPath = path.normalize(inputPath);
|
|
225
|
-
const template = engine.getTemplateFunction(inputContent, inputPath, false);
|
|
226
|
-
return async (data) => await engine.render(template, data, inputPath);
|
|
227
|
-
},
|
|
228
|
-
compileOptions: {
|
|
229
|
-
// Custom permalink compilation
|
|
230
|
-
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);
|
|
235
|
-
}
|
|
236
|
-
return permalinkContent;
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
});
|
|
240
|
-
DEBUG.setup("eleventy-plugin-vento initialized");
|
|
241
|
-
}
|
|
242
|
-
export {
|
|
243
|
-
VentoPlugin
|
|
244
|
-
};
|