eleventy-plugin-vento 2.5.0 → 3.0.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 +223 -0
- package/LICENSE +1 -1
- package/package.json +61 -56
- package/readme.md +98 -76
- package/src/engine.js +85 -0
- package/src/index.js +130 -0
- package/src/modules/create-vento-tag.js +56 -0
- package/src/modules/ignore-tag.js +15 -0
- package/src/modules/utils.js +22 -0
- package/.editorconfig +0 -16
- package/.github/actions/setup/action.yml +0 -25
- package/.github/renovate.json +0 -13
- package/.github/workflows/ci.yml +0 -15
- package/.github/workflows/release.yml +0 -33
- package/.node-version +0 -1
- package/.vscode/settings.json +0 -4
- package/.vscode/tests.code-snippets +0 -16
- package/VentoPlugin.js +0 -130
- package/eslint.config.js +0 -67
- package/jsconfig.json +0 -11
- package/lib/ssr.js +0 -23
- package/release.config.js +0 -31
- package/tests/autotrim/__snapshots__/autotrim-all.html +0 -53
- package/tests/autotrim/__snapshots__/autotrim-single.html +0 -75
- package/tests/autotrim/autotrim.test.js +0 -17
- package/tests/autotrim/build/autotrim-all.html +0 -53
- package/tests/autotrim/build/autotrim-single.html +0 -75
- package/tests/autotrim/index.vto +0 -23
- package/tests/basic/__snapshots__/template-basic.html +0 -4
- package/tests/basic/basic.test.js +0 -9
- package/tests/basic/index.vto +0 -7
- package/tests/filters/__snapshots__/filters-arguments.html +0 -1
- package/tests/filters/__snapshots__/filters-basic.html +0 -2
- package/tests/filters/basic.vto +0 -5
- package/tests/filters/filters.test.js +0 -33
- package/tests/filters/with-arguments.vto +0 -1
- package/tests/filters/with-this.vto +0 -1
- package/tests/get-instance.js +0 -35
- package/tests/includes/__snapshots__/includes-basic.html +0 -8
- package/tests/includes/__snapshots__/includes-data.html +0 -8
- package/tests/includes/_includes/partial.vto +0 -4
- package/tests/includes/basic.vto +0 -7
- package/tests/includes/includes.test.js +0 -14
- package/tests/includes/with-data.vto +0 -7
- package/tests/layouts/__snapshots__/example-layout-1.html +0 -27
- package/tests/layouts/__snapshots__/example-layout-2.html +0 -24
- package/tests/layouts/_includes/layout1.vto +0 -20
- package/tests/layouts/_includes/layout2.vto +0 -17
- package/tests/layouts/layouts.test.js +0 -14
- package/tests/layouts/page1.vto +0 -11
- package/tests/layouts/page2.vto +0 -11
- package/tests/permalinks/__snapshots__/permalink-nested.html +0 -15
- package/tests/permalinks/__snapshots__/permalink-root.html +0 -15
- package/tests/permalinks/_includes/layout.vto +0 -13
- package/tests/permalinks/at-nested.vto +0 -7
- package/tests/permalinks/at-root.vto +0 -7
- package/tests/permalinks/dynamic/dynamic-permalink.vto +0 -6
- package/tests/permalinks/dynamic/dynamic.11tydata.json +0 -3
- package/tests/permalinks/dynamic-js/dynamic-js.11tydata.js +0 -5
- package/tests/permalinks/dynamic-js/dynamic-permalink-js.vto +0 -6
- package/tests/permalinks/permalinks.test.js +0 -25
- package/tests/permalinks/skip.vto +0 -7
- package/tests/shortcodes/__snapshots__/shortcode-with-arguments.html +0 -2
- package/tests/shortcodes/basic.vto +0 -1
- package/tests/shortcodes/shortcodes.test.js +0 -19
- package/tests/shortcodes/with-arguments.vto +0 -2
- package/tests/ssr/__snapshots__/ssr-data.html +0 -1
- package/tests/ssr/__snapshots__/ssr-echo.html +0 -7
- package/tests/ssr/__snapshots__/ssr-exec.html +0 -1
- package/tests/ssr/__snapshots__/ssr-for.html +0 -3
- package/tests/ssr/__snapshots__/ssr-if.html +0 -5
- package/tests/ssr/data.vto +0 -1
- package/tests/ssr/echo.vto +0 -7
- package/tests/ssr/exec.vto +0 -1
- package/tests/ssr/for.vto +0 -3
- package/tests/ssr/if.vto +0 -5
- package/tests/ssr/ssr.test.js +0 -29
package/src/engine.js
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Class to facilitate ventojs processing
|
|
3
|
+
*
|
|
4
|
+
* @typedef {{eleventy?: Record<string, unknown>, page?: Record<string, unknown>}} EleventyContext
|
|
5
|
+
* @typedef {Context & Record<string, unknown>} EleventyData
|
|
6
|
+
* @typedef {(...args: unknown[]) => unknown} EleventyFunction
|
|
7
|
+
* @typedef {import('ventojs/src/environment.js').Environment} VentoEnvironment
|
|
8
|
+
* @typedef {VentoEnvironment & { _11ty: { ctx: Context, tags: Record<string, EleventyFunction> }}} EleventyVentoEnvironment
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
// External library
|
|
12
|
+
import ventojs from 'ventojs';
|
|
13
|
+
|
|
14
|
+
// Internal modules
|
|
15
|
+
import { createVentoTag } from './modules/create-vento-tag.js';
|
|
16
|
+
|
|
17
|
+
// TODO: Update this if it becomes possible to import `augmentKeys` from Eleventy.
|
|
18
|
+
const DATA_KEYS = ['page', 'eleventy'];
|
|
19
|
+
|
|
20
|
+
export class VentoEngine {
|
|
21
|
+
#env;
|
|
22
|
+
|
|
23
|
+
/** @param {import('ventojs/src/environment.js').Options} options */
|
|
24
|
+
constructor(options) {
|
|
25
|
+
/** Initialize vento @type {EleventyVentoEnvironment} */
|
|
26
|
+
this.#env = ventojs(options);
|
|
27
|
+
this.#env._11ty = { ctx: {}, functions: {} };
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** @param {string?} key */
|
|
31
|
+
emptyCache(key) {
|
|
32
|
+
return key ? this.#env.cache.delete(key) : this.#env.cache.clear();
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** @param {import('ventojs/src/environment.js').Plugin[]} plugins */
|
|
36
|
+
loadPlugins(plugins) {
|
|
37
|
+
for (const plugin of plugins) {
|
|
38
|
+
this.#env.use(plugin);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** @param {PageData} newContext */
|
|
43
|
+
loadContext(newContext) {
|
|
44
|
+
// Loop through allowed keys and load those into the context
|
|
45
|
+
for (const key of DATA_KEYS) {
|
|
46
|
+
this.#env._11ty.ctx[key] = newContext[key];
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** @param {Record<string, EleventyFunction>} filters */
|
|
51
|
+
loadFilters(filters) {
|
|
52
|
+
for (const [name, fn] of Object.entries(filters)) {
|
|
53
|
+
this.#env.filters[name] = (...args) => fn.apply(this.#env._11ty.ctx, args);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* @param {Record<string, EleventyFunction>} shortcodes
|
|
59
|
+
* @param {boolean} paired
|
|
60
|
+
*/
|
|
61
|
+
loadShortcodes(shortcodes, paired = false) {
|
|
62
|
+
for (const [name, fn] of Object.entries(shortcodes)) {
|
|
63
|
+
this.#env._11ty.functions[name] = fn;
|
|
64
|
+
this.#env.tags.push(createVentoTag(name, paired));
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* @param {PageData} data
|
|
70
|
+
* @param {string} content
|
|
71
|
+
* @param {string} path
|
|
72
|
+
*/
|
|
73
|
+
async process(data, content, path) {
|
|
74
|
+
// Reload context
|
|
75
|
+
this.loadContext(data);
|
|
76
|
+
|
|
77
|
+
// Process the templates
|
|
78
|
+
const result = await this.#env.runString(content, data, path);
|
|
79
|
+
|
|
80
|
+
// Clear the cache for this path if the input doesn't match
|
|
81
|
+
if (data.page?.rawInput !== content) this.#env.cache.clear(path);
|
|
82
|
+
|
|
83
|
+
return result.content;
|
|
84
|
+
}
|
|
85
|
+
}
|
package/src/index.js
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Main plugin declaration
|
|
3
|
+
*
|
|
4
|
+
* @typedef VentoPluginOptions
|
|
5
|
+
* @prop {import('ventojs/src/environment.js').Plugin[]} plugins
|
|
6
|
+
* Array of vento plugins to use when compiling templates
|
|
7
|
+
* @prop {boolean|string[]} autotrim
|
|
8
|
+
* Enable Vento's [`autoTrim`](https://vento.js.org/plugins/auto-trim/)
|
|
9
|
+
* plugin to remove whitespace from tags in output
|
|
10
|
+
* @prop {boolean} [shortcodes=true]
|
|
11
|
+
* Create vento tags for Eleventy [Shortcodes](https://www.11ty.dev/docs/shortcodes/)
|
|
12
|
+
* @prop {boolean} [pairedShortcodes=true]
|
|
13
|
+
* Create vento tags for Eleventy [Paired Shortcodes](https://www.11ty.dev/docs/shortcodes/#paired-shortcodes)
|
|
14
|
+
* @prop {boolean} [filters=true]
|
|
15
|
+
* Create vento filters for Eleventy [Filters](https://www.11ty.dev/docs/filters/)
|
|
16
|
+
* @prop {boolean} [ignoreTag=false]
|
|
17
|
+
* Enables/disables tag ignore (`{{! ... }}`) syntax in templates
|
|
18
|
+
* @prop {import('ventojs').Options} ventoOptions
|
|
19
|
+
* Options to pass on to the `ventojs` engine.
|
|
20
|
+
* (See [Vento Docs](https://vento.js.org/configuration/#options))
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
// External modules
|
|
24
|
+
import autotrimPlugin, { defaultTags as autotrimDefaultTags } from 'ventojs/plugins/auto_trim.js';
|
|
25
|
+
|
|
26
|
+
// Local modules
|
|
27
|
+
import { VentoEngine } from './engine.js';
|
|
28
|
+
import { ignoreTagPlugin } from './modules/ignore-tag.js';
|
|
29
|
+
import { runCompatibilityCheck } from './modules/utils.js';
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @param {import('@11ty/eleventy').UserConfig} eleventyConfig
|
|
33
|
+
* @param {Partial<VentoPluginOptions>} userOptions
|
|
34
|
+
*/
|
|
35
|
+
export function VentoPlugin(eleventyConfig, userOptions) {
|
|
36
|
+
runCompatibilityCheck(eleventyConfig);
|
|
37
|
+
|
|
38
|
+
/** @type {VentoPluginOptions} */
|
|
39
|
+
const options = {
|
|
40
|
+
// Define defaults
|
|
41
|
+
autotrim: false,
|
|
42
|
+
plugins: [],
|
|
43
|
+
filters: true,
|
|
44
|
+
shortcodes: true,
|
|
45
|
+
pairedShortcodes: true,
|
|
46
|
+
ignoreTag: false,
|
|
47
|
+
ventoOptions: {
|
|
48
|
+
includes: eleventyConfig.directories.includes,
|
|
49
|
+
},
|
|
50
|
+
|
|
51
|
+
// Merge in user-provided options
|
|
52
|
+
...userOptions,
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
// Get list of filters, shortcodes and paired shortcodes
|
|
56
|
+
const filters = eleventyConfig.getFilters();
|
|
57
|
+
const shortcodes = eleventyConfig.getShortcodes();
|
|
58
|
+
const pairedShortcodes = eleventyConfig.getPairedShortcodes();
|
|
59
|
+
|
|
60
|
+
// Add autotrim plugin if enabled
|
|
61
|
+
if (options.autotrim) {
|
|
62
|
+
const defaults = ['@vento', '@11ty'];
|
|
63
|
+
|
|
64
|
+
/** @type {Set<string>} */
|
|
65
|
+
const tagSet = new Set(options.autotrim === true ? defaults : options.autotrim);
|
|
66
|
+
|
|
67
|
+
if (tagSet.has('@vento')) {
|
|
68
|
+
tagSet.delete('@vento');
|
|
69
|
+
for (const name of autotrimDefaultTags) {
|
|
70
|
+
tagSet.add(name);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (tagSet.has('@11ty')) {
|
|
75
|
+
tagSet.delete('@11ty');
|
|
76
|
+
for (const name in pairedShortcodes) {
|
|
77
|
+
tagSet.add(name);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
options.plugins.push(autotrimPlugin({ tags: [...tagSet] }));
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Add ignore tag plugin if enabled
|
|
85
|
+
if (options.ignoreTag) {
|
|
86
|
+
options.plugins.push(ignoreTagPlugin);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Create the vento engine instance
|
|
90
|
+
const vento = new VentoEngine(options.ventoOptions);
|
|
91
|
+
|
|
92
|
+
// Ensure cache is empty
|
|
93
|
+
vento.emptyCache();
|
|
94
|
+
|
|
95
|
+
// Load plugins
|
|
96
|
+
vento.loadPlugins(options.plugins);
|
|
97
|
+
|
|
98
|
+
// Add filters, single and paired shortcodes if enabled
|
|
99
|
+
if (options.filters) {
|
|
100
|
+
vento.loadFilters(filters);
|
|
101
|
+
}
|
|
102
|
+
if (options.shortcodes) {
|
|
103
|
+
vento.loadShortcodes(shortcodes, false);
|
|
104
|
+
}
|
|
105
|
+
if (options.pairedShortcodes) {
|
|
106
|
+
vento.loadShortcodes(pairedShortcodes, true);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Add vto as a template format
|
|
110
|
+
eleventyConfig.addTemplateFormats('vto');
|
|
111
|
+
|
|
112
|
+
// Add extension handling
|
|
113
|
+
eleventyConfig.addExtension('vto', {
|
|
114
|
+
outputFileExtension: 'html',
|
|
115
|
+
read: true,
|
|
116
|
+
|
|
117
|
+
// Main compile function
|
|
118
|
+
async compile(inputContent, inputPath) {
|
|
119
|
+
return async (data) => vento.process(data, inputContent, inputPath);
|
|
120
|
+
},
|
|
121
|
+
|
|
122
|
+
// Custom permalink compilation
|
|
123
|
+
compileOptions: {
|
|
124
|
+
permalink(linkContents) {
|
|
125
|
+
if (typeof linkContents !== 'string') return linkContents;
|
|
126
|
+
return async (data) => vento.process(data, linkContents);
|
|
127
|
+
},
|
|
128
|
+
},
|
|
129
|
+
});
|
|
130
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Helper function that creates vento tags from eleventy functions
|
|
3
|
+
*
|
|
4
|
+
* @param {string} name
|
|
5
|
+
* @param {boolean} paired
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export function createVentoTag(name, paired) {
|
|
9
|
+
/** @type {import("ventojs/src/environment.js").Tag} */
|
|
10
|
+
const tag = (env, code, output, tokens) => {
|
|
11
|
+
if (!code.startsWith(name)) return;
|
|
12
|
+
|
|
13
|
+
// Declare helper object path strings
|
|
14
|
+
const fn = `__env._11ty.functions.${name}`;
|
|
15
|
+
const ctx = '__env._11ty.ctx';
|
|
16
|
+
let args = [code.replace(name, '').trim()];
|
|
17
|
+
|
|
18
|
+
const varname = output.startsWith('__shortcode_content')
|
|
19
|
+
? `${output}_precomp`
|
|
20
|
+
: '__shortcode_content';
|
|
21
|
+
|
|
22
|
+
// Create an array to hold compiled template code
|
|
23
|
+
const compiled = [];
|
|
24
|
+
|
|
25
|
+
if (paired) {
|
|
26
|
+
args.unshift(env.compileFilters(tokens, varname, env.options.autoescape));
|
|
27
|
+
compiled.push(
|
|
28
|
+
'{',
|
|
29
|
+
`let ${varname} = "";`,
|
|
30
|
+
...env.compileTokens(tokens, varname, [`/${name}`])
|
|
31
|
+
);
|
|
32
|
+
if (tokens.length > 0 && (tokens[0][0] !== 'tag' || tokens[0][1] !== `/${name}`)) {
|
|
33
|
+
throw new Error(`Missing closing tag for ${name} tag: ${code}`);
|
|
34
|
+
}
|
|
35
|
+
tokens.shift();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Compile arguments into a string
|
|
39
|
+
args = args.some(Boolean) ? `, ${args.filter(Boolean).join(', ')}` : '';
|
|
40
|
+
|
|
41
|
+
compiled.push(
|
|
42
|
+
'{',
|
|
43
|
+
`const __shortcode_result = await ${fn}.call(${ctx + args});`,
|
|
44
|
+
`${output} += ${env.compileFilters(tokens, '__shortcode_result', env.options.autoescape)}`,
|
|
45
|
+
'}'
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
if (paired) compiled.push('}');
|
|
49
|
+
|
|
50
|
+
// console.log(compiled);
|
|
51
|
+
|
|
52
|
+
return compiled.join('\n');
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
return Object.defineProperty(tag, 'name', { value: paired ? `${name}PairedTag` : `${name}Tag` });
|
|
56
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Definition for tag that preserves vento syntax in output
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/** @type {import('ventojs/src/environment.js').Tag} */
|
|
6
|
+
function ignoreTag(_env, code, output, _tokens) {
|
|
7
|
+
if (!code.startsWith('!')) return;
|
|
8
|
+
const compiled = `{{${code.replace(/!(>?)\s+/, '$1 ')}}}`;
|
|
9
|
+
return `${output} += "${compiled}";`;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/** @type {import('ventojs/src/environment.js').Plugin} */
|
|
13
|
+
export function ignoreTagPlugin(env) {
|
|
14
|
+
env.tags.push(ignoreTag);
|
|
15
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// Declare required APIs
|
|
2
|
+
const REQUIRED_API_METHODS = [
|
|
3
|
+
['getShortcodes', 'v3.0.0-alpha.15'],
|
|
4
|
+
['getPairedShortcodes', 'v3.0.0-alpha.15'],
|
|
5
|
+
['getFilters', 'v3.0.0-alpha.15'],
|
|
6
|
+
['addExtension', 'v1.0.0'],
|
|
7
|
+
];
|
|
8
|
+
|
|
9
|
+
export function logError(message) {
|
|
10
|
+
console.error(`[eleventy-plugin-vento] ${message}`);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/** @param {import("@11ty/eleventy").UserConfig} configApi */
|
|
14
|
+
export function runCompatibilityCheck(configApi) {
|
|
15
|
+
for (const [method, version] of REQUIRED_API_METHODS) {
|
|
16
|
+
if (!configApi?.[method]) {
|
|
17
|
+
logError(
|
|
18
|
+
`Eleventy plugin compatibility error: '${method}' not available. Use Eleventy ${version} or later.`
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
package/.editorconfig
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
# EditorConfig is awesome: https://EditorConfig.org
|
|
2
|
-
|
|
3
|
-
# top-most EditorConfig file
|
|
4
|
-
root = true
|
|
5
|
-
|
|
6
|
-
[*]
|
|
7
|
-
charset = utf-8
|
|
8
|
-
end_of_line = lf
|
|
9
|
-
insert_final_newline = true
|
|
10
|
-
indent_style = tab
|
|
11
|
-
indent_size = 2
|
|
12
|
-
trim_trailing_whitespace = true
|
|
13
|
-
max_line_length = 100
|
|
14
|
-
|
|
15
|
-
[*.{yaml,yml,md}]
|
|
16
|
-
indent_style = space
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
name: Setup
|
|
2
|
-
description: Setup project with pnpm
|
|
3
|
-
|
|
4
|
-
outputs:
|
|
5
|
-
cache-hit:
|
|
6
|
-
description: 'Whether restoring the cache was successful or not'
|
|
7
|
-
value: ${{ steps.setup-node.outputs.cache-hit }}
|
|
8
|
-
|
|
9
|
-
runs:
|
|
10
|
-
using: composite
|
|
11
|
-
steps:
|
|
12
|
-
- name: Setup pnpm
|
|
13
|
-
uses: pnpm/action-setup@v4
|
|
14
|
-
|
|
15
|
-
- name: Setup node
|
|
16
|
-
id: setup-node
|
|
17
|
-
uses: actions/setup-node@v4
|
|
18
|
-
with:
|
|
19
|
-
node-version-file: .node-version
|
|
20
|
-
cache: pnpm
|
|
21
|
-
cache-dependency-path: pnpm-lock.yaml
|
|
22
|
-
|
|
23
|
-
- name: Install dependencies
|
|
24
|
-
run: pnpm install --frozen-lockfile
|
|
25
|
-
shell: bash
|
package/.github/renovate.json
DELETED
package/.github/workflows/ci.yml
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
name: Release
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
workflow_run:
|
|
5
|
-
types: [completed]
|
|
6
|
-
workflows: [CI]
|
|
7
|
-
branches: [main, alpha, beta, next]
|
|
8
|
-
|
|
9
|
-
jobs:
|
|
10
|
-
release:
|
|
11
|
-
if: github.event.workflow_run.conclusion == 'success'
|
|
12
|
-
runs-on: ubuntu-latest
|
|
13
|
-
permissions:
|
|
14
|
-
contents: write # to be able to publish a GitHub release
|
|
15
|
-
id-token: write # to enable use of OIDC for npm provenance
|
|
16
|
-
issues: write # to be able to comment on released issues
|
|
17
|
-
pull-requests: write # to be able to comment on released pull requests
|
|
18
|
-
steps:
|
|
19
|
-
- uses: actions/checkout@v4
|
|
20
|
-
with:
|
|
21
|
-
fetch-depth: 0
|
|
22
|
-
|
|
23
|
-
- name: Setup
|
|
24
|
-
uses: ./.github/actions/setup
|
|
25
|
-
|
|
26
|
-
- name: Verify provenance attestations and registry signatures
|
|
27
|
-
run: npm audit signatures
|
|
28
|
-
|
|
29
|
-
- name: Release
|
|
30
|
-
env:
|
|
31
|
-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
32
|
-
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
33
|
-
run: pnpm exec semantic-release
|
package/.node-version
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
20.15.1
|
package/.vscode/settings.json
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"New test suite": {
|
|
3
|
-
"scope": "javascript",
|
|
4
|
-
"prefix": "VentoPluginTest",
|
|
5
|
-
"body": [
|
|
6
|
-
"import { expect, test } from 'vitest';",
|
|
7
|
-
"import { runBuild } from '#test-instance';\n",
|
|
8
|
-
"const results = await runBuild(import.meta.dirname, {",
|
|
9
|
-
"\t${1:eleventy(configApi) {\\}},",
|
|
10
|
-
"\t${2:vento: {\\}},",
|
|
11
|
-
"});"
|
|
12
|
-
],
|
|
13
|
-
"description": "Create a new test suite for eleventy-plugin-vento",
|
|
14
|
-
"isFileTemplate": true
|
|
15
|
-
}
|
|
16
|
-
}
|
package/VentoPlugin.js
DELETED
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file Adds support for the Vento templating language to Eleventy.
|
|
3
|
-
*
|
|
4
|
-
* @typedef VentoPluginOptions
|
|
5
|
-
* @prop {Function[]} [plugins=[]] An array of plugins to load into vento.
|
|
6
|
-
* @prop {string|boolean} [addHelpers=true]
|
|
7
|
-
* Whether [Javascript Functions](https://www.11ty.dev/docs/languages/javascript/#javascript-template-functions)
|
|
8
|
-
* should be merged into data provided to templates. If a string, functions will be namespaced under
|
|
9
|
-
* a property with this name.
|
|
10
|
-
* @prop {boolean|string[]} [trimTags=false] Whether to automatically trim tags from output. Uses Vento's
|
|
11
|
-
* [autoTrim](https://vento.js.org/plugins/auto-trim/) plugin under the hood.
|
|
12
|
-
* @prop {import('ventojs').Options} [ventoOptions] Vento engine configuration object
|
|
13
|
-
* that will be merged with default options.
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
import VentoJs from 'ventojs';
|
|
17
|
-
import { ssr } from '#lib/ssr.js';
|
|
18
|
-
|
|
19
|
-
// Expose autotrim plugin defaults
|
|
20
|
-
import {
|
|
21
|
-
default as autoTrim,
|
|
22
|
-
defaultTags as ventoDefaultTrimTags,
|
|
23
|
-
} from 'ventojs/plugins/auto_trim.js';
|
|
24
|
-
export { ventoDefaultTrimTags };
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* @param {import('@11ty/eleventy/src/UserConfig.js').default} eleventyConfig
|
|
28
|
-
* @param {VentoPluginOptions} options
|
|
29
|
-
*/
|
|
30
|
-
export function VentoPlugin(eleventyConfig, options = {}) {
|
|
31
|
-
if (!('addExtension' in eleventyConfig)) {
|
|
32
|
-
console.log(
|
|
33
|
-
`[eleventy-plugin-vento] WARN Eleventy plugin compatibility: Custom templates are required for this plugin, please use Eleventy v1.0 or newer.`
|
|
34
|
-
);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// Pull some bits from eleventyConfig and merge user-options with defaults
|
|
38
|
-
const { directories, javascriptFunctions, liquidFilters, nunjucksFilters, nunjucksAsyncFilters } =
|
|
39
|
-
eleventyConfig;
|
|
40
|
-
|
|
41
|
-
options = {
|
|
42
|
-
addHelpers: true,
|
|
43
|
-
trimTags: false,
|
|
44
|
-
plugins: [],
|
|
45
|
-
ventoOptions: {
|
|
46
|
-
includes: directories.includes,
|
|
47
|
-
autoescape: false,
|
|
48
|
-
},
|
|
49
|
-
...options,
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
// Init vento
|
|
53
|
-
const env = VentoJs(options.ventoOptions);
|
|
54
|
-
|
|
55
|
-
// Create empty sets to hold user defined functions
|
|
56
|
-
const filters = {};
|
|
57
|
-
const helperFunctions = {};
|
|
58
|
-
|
|
59
|
-
for (const fn in javascriptFunctions) {
|
|
60
|
-
if (liquidFilters[fn] && (nunjucksFilters[fn] || nunjucksAsyncFilters[fn])) {
|
|
61
|
-
filters[fn] = javascriptFunctions[fn];
|
|
62
|
-
} else {
|
|
63
|
-
helperFunctions[fn] = javascriptFunctions[fn];
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// Load filters into vento
|
|
68
|
-
for (const filter in filters) env.filters[filter] = filters[filter];
|
|
69
|
-
|
|
70
|
-
// Load user-defined plugins into vento
|
|
71
|
-
for (const plugin of options.plugins) env.use(plugin);
|
|
72
|
-
|
|
73
|
-
// Load ssr plugin
|
|
74
|
-
env.use(ssr);
|
|
75
|
-
|
|
76
|
-
// Add autotrim plugin if enabled
|
|
77
|
-
if (options.trimTags === true) env.use(autoTrim());
|
|
78
|
-
else if (options.trimTags) env.use(autoTrim({ tags: options.trimTags }));
|
|
79
|
-
|
|
80
|
-
eleventyConfig.on('eleventy.before', () => env.cache.clear());
|
|
81
|
-
|
|
82
|
-
// Add vto as a template format and create a custom template for it
|
|
83
|
-
eleventyConfig.addTemplateFormats('vto');
|
|
84
|
-
eleventyConfig.addExtension('vto', {
|
|
85
|
-
outputFileExtension: 'html',
|
|
86
|
-
|
|
87
|
-
async compile(inputContent, inputPath) {
|
|
88
|
-
return async (data) => {
|
|
89
|
-
if (options.addHelpers) {
|
|
90
|
-
// Extract a possible namespace from the addHelpers option
|
|
91
|
-
const namespace = options.addHelpers;
|
|
92
|
-
|
|
93
|
-
// Extract page and eleventy values from data
|
|
94
|
-
const { page, eleventy } = data;
|
|
95
|
-
|
|
96
|
-
// Rebind functions to page data so this.page, this.eleventy, etc works as intended
|
|
97
|
-
for (const helper in helperFunctions) {
|
|
98
|
-
helperFunctions[helper] = helperFunctions[helper].bind({
|
|
99
|
-
page,
|
|
100
|
-
eleventy,
|
|
101
|
-
});
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// Rebind filters the same way
|
|
105
|
-
for (const filter in filters) {
|
|
106
|
-
env.filters[filter] = filters[filter].bind({ page, eleventy });
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// Merge helpers into page data
|
|
110
|
-
if (typeof namespace === 'string') data = { ...data, [namespace]: helperFunctions };
|
|
111
|
-
else data = { ...data, ...helperFunctions };
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
const result = await env.runString(inputContent, data, inputPath);
|
|
115
|
-
|
|
116
|
-
return result.content;
|
|
117
|
-
};
|
|
118
|
-
},
|
|
119
|
-
|
|
120
|
-
compileOptions: {
|
|
121
|
-
permalink(linkContents) {
|
|
122
|
-
if (typeof linkContents !== 'string') return linkContents;
|
|
123
|
-
return async (data) => {
|
|
124
|
-
const result = await env.runString(linkContents, data);
|
|
125
|
-
return result.content;
|
|
126
|
-
};
|
|
127
|
-
},
|
|
128
|
-
},
|
|
129
|
-
});
|
|
130
|
-
}
|
package/eslint.config.js
DELETED
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import js from '@eslint/js';
|
|
2
|
-
|
|
3
|
-
// Configs
|
|
4
|
-
import gitignore from 'eslint-config-flat-gitignore';
|
|
5
|
-
import eslintConfigPrettier from 'eslint-config-prettier';
|
|
6
|
-
|
|
7
|
-
// Plugins
|
|
8
|
-
import globals from 'globals';
|
|
9
|
-
|
|
10
|
-
export default [
|
|
11
|
-
// Set ignores from gitignore
|
|
12
|
-
gitignore(),
|
|
13
|
-
|
|
14
|
-
// Import configuration presets
|
|
15
|
-
js.configs.recommended,
|
|
16
|
-
eslintConfigPrettier,
|
|
17
|
-
|
|
18
|
-
// Configure ignores
|
|
19
|
-
{
|
|
20
|
-
ignores: ['**/node_modules'],
|
|
21
|
-
},
|
|
22
|
-
|
|
23
|
-
// Configure defaults
|
|
24
|
-
{
|
|
25
|
-
languageOptions: {
|
|
26
|
-
ecmaVersion: 'latest',
|
|
27
|
-
},
|
|
28
|
-
rules: {
|
|
29
|
-
'no-unused-vars': [
|
|
30
|
-
'error',
|
|
31
|
-
{
|
|
32
|
-
argsIgnorePattern: '^_',
|
|
33
|
-
},
|
|
34
|
-
],
|
|
35
|
-
'no-else-return': [
|
|
36
|
-
'error',
|
|
37
|
-
{
|
|
38
|
-
allowElseIf: false,
|
|
39
|
-
},
|
|
40
|
-
],
|
|
41
|
-
'prefer-regex-literals': ['error', { disallowRedundantWrapping: true }],
|
|
42
|
-
'prefer-object-spread': 'error',
|
|
43
|
-
'prefer-const': ['error', { destructuring: 'all' }],
|
|
44
|
-
'prefer-arrow-callback': ['error', { allowNamedFunctions: true }],
|
|
45
|
-
'prefer-destructuring': [
|
|
46
|
-
'error',
|
|
47
|
-
{
|
|
48
|
-
VariableDeclarator: { array: false, object: true },
|
|
49
|
-
AssignmentExpression: { array: false, object: false },
|
|
50
|
-
},
|
|
51
|
-
],
|
|
52
|
-
'object-shorthand': ['error', 'always'],
|
|
53
|
-
'arrow-body-style': ['error', 'as-needed'],
|
|
54
|
-
eqeqeq: ['error', 'smart'],
|
|
55
|
-
},
|
|
56
|
-
},
|
|
57
|
-
|
|
58
|
-
// Match all node-files
|
|
59
|
-
{
|
|
60
|
-
files: ['**/*.js'],
|
|
61
|
-
languageOptions: {
|
|
62
|
-
globals: {
|
|
63
|
-
...globals.node,
|
|
64
|
-
},
|
|
65
|
-
},
|
|
66
|
-
},
|
|
67
|
-
];
|
package/jsconfig.json
DELETED
package/lib/ssr.js
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @typedef {import('ventojs/src/tokenizer.js').Token} Token
|
|
3
|
-
* @typedef {import('ventojs/src/environment.js').Environment} Environment
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
/** @param {Environment} env */
|
|
7
|
-
export function ssr(env) {
|
|
8
|
-
env.tags.push(ssrTag);
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* @param {string} code
|
|
13
|
-
* @param {Environment} env
|
|
14
|
-
* @param {string} output
|
|
15
|
-
* @param {Token[]} tokens
|
|
16
|
-
*/
|
|
17
|
-
function ssrTag(env, code, output, _tokens) {
|
|
18
|
-
if (!code.startsWith('!')) return;
|
|
19
|
-
|
|
20
|
-
const compiled = `{{${code.replace(/!(>?)\s+/, '$1 ')} }}`;
|
|
21
|
-
|
|
22
|
-
return `${output} += "${compiled}";`;
|
|
23
|
-
}
|