eleventy-plugin-vento 2.6.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.
Files changed (88) hide show
  1. package/CHANGELOG.md +223 -0
  2. package/LICENSE +1 -1
  3. package/package.json +61 -56
  4. package/readme.md +98 -76
  5. package/src/engine.js +85 -0
  6. package/src/index.js +130 -0
  7. package/src/modules/create-vento-tag.js +56 -0
  8. package/src/modules/ignore-tag.js +15 -0
  9. package/src/modules/utils.js +22 -0
  10. package/.editorconfig +0 -16
  11. package/.github/actions/setup/action.yml +0 -25
  12. package/.github/renovate.json +0 -13
  13. package/.github/workflows/ci.yml +0 -15
  14. package/.github/workflows/release.yml +0 -33
  15. package/.node-version +0 -1
  16. package/.vscode/settings.json +0 -4
  17. package/.vscode/tests.code-snippets +0 -16
  18. package/VentoPlugin.js +0 -140
  19. package/eslint.config.js +0 -67
  20. package/jsconfig.json +0 -11
  21. package/lib/ssr.js +0 -23
  22. package/release.config.js +0 -31
  23. package/tests/autotrim/__snapshots__/autotrim-all.html +0 -53
  24. package/tests/autotrim/__snapshots__/autotrim-single.html +0 -75
  25. package/tests/autotrim/autotrim.test.js +0 -17
  26. package/tests/autotrim/build/autotrim-all.html +0 -53
  27. package/tests/autotrim/build/autotrim-single.html +0 -75
  28. package/tests/autotrim/index.vto +0 -23
  29. package/tests/basic/__snapshots__/template-basic.html +0 -4
  30. package/tests/basic/basic.test.js +0 -9
  31. package/tests/basic/index.vto +0 -7
  32. package/tests/computed-data/__snapshots__/from-local-key.html +0 -4
  33. package/tests/computed-data/computed-data.test.js +0 -9
  34. package/tests/computed-data/from-local-key.vto +0 -9
  35. package/tests/engine-overrides/__snapshots__/as-html-engine.html +0 -4
  36. package/tests/engine-overrides/__snapshots__/as-md-engine.html +0 -2
  37. package/tests/engine-overrides/as-html-engine.html +0 -7
  38. package/tests/engine-overrides/as-md-engine.md +0 -7
  39. package/tests/engine-overrides/eleventy.config.js +0 -4
  40. package/tests/engine-overrides/engine-overrides.test.js +0 -14
  41. package/tests/filters/__snapshots__/filters-arguments.html +0 -1
  42. package/tests/filters/__snapshots__/filters-basic.html +0 -2
  43. package/tests/filters/basic.vto +0 -5
  44. package/tests/filters/eleventy.config.js +0 -13
  45. package/tests/filters/filters.test.js +0 -19
  46. package/tests/filters/with-arguments.vto +0 -1
  47. package/tests/filters/with-this.vto +0 -1
  48. package/tests/get-instance.js +0 -38
  49. package/tests/includes/__snapshots__/includes-basic.html +0 -8
  50. package/tests/includes/__snapshots__/includes-data.html +0 -8
  51. package/tests/includes/_includes/partial.vto +0 -4
  52. package/tests/includes/basic.vto +0 -7
  53. package/tests/includes/includes.test.js +0 -14
  54. package/tests/includes/with-data.vto +0 -7
  55. package/tests/layouts/__snapshots__/example-layout-1.html +0 -27
  56. package/tests/layouts/__snapshots__/example-layout-2.html +0 -24
  57. package/tests/layouts/_includes/layout1.vto +0 -20
  58. package/tests/layouts/_includes/layout2.vto +0 -17
  59. package/tests/layouts/layouts.test.js +0 -14
  60. package/tests/layouts/page1.vto +0 -11
  61. package/tests/layouts/page2.vto +0 -11
  62. package/tests/permalinks/__snapshots__/permalink-nested.html +0 -15
  63. package/tests/permalinks/__snapshots__/permalink-root.html +0 -15
  64. package/tests/permalinks/_includes/layout.vto +0 -13
  65. package/tests/permalinks/at-nested.vto +0 -7
  66. package/tests/permalinks/at-root.vto +0 -7
  67. package/tests/permalinks/dynamic/dynamic-permalink.vto +0 -6
  68. package/tests/permalinks/dynamic/dynamic.11tydata.json +0 -3
  69. package/tests/permalinks/dynamic-js/dynamic-js.11tydata.js +0 -5
  70. package/tests/permalinks/dynamic-js/dynamic-permalink-js.vto +0 -6
  71. package/tests/permalinks/permalinks.test.js +0 -25
  72. package/tests/permalinks/skip.vto +0 -7
  73. package/tests/shortcodes/__snapshots__/shortcode-with-arguments.html +0 -2
  74. package/tests/shortcodes/basic.vto +0 -1
  75. package/tests/shortcodes/eleventy.config.js +0 -4
  76. package/tests/shortcodes/shortcodes.test.js +0 -14
  77. package/tests/shortcodes/with-arguments.vto +0 -2
  78. package/tests/ssr/__snapshots__/ssr-data.html +0 -1
  79. package/tests/ssr/__snapshots__/ssr-echo.html +0 -7
  80. package/tests/ssr/__snapshots__/ssr-exec.html +0 -1
  81. package/tests/ssr/__snapshots__/ssr-for.html +0 -3
  82. package/tests/ssr/__snapshots__/ssr-if.html +0 -5
  83. package/tests/ssr/data.vto +0 -1
  84. package/tests/ssr/echo.vto +0 -7
  85. package/tests/ssr/exec.vto +0 -1
  86. package/tests/ssr/for.vto +0 -3
  87. package/tests/ssr/if.vto +0 -5
  88. 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
@@ -1,13 +0,0 @@
1
- {
2
- "extends": ["github>noelforte/renovate-config"],
3
- "packageRules": [
4
- {
5
- "matchDepTypes": ["dependencies"],
6
- "semanticCommitType": "upstream",
7
- "semanticCommitScope": null
8
- },
9
- {
10
- "matchDepTypes": ["devDependencies"]
11
- }
12
- ]
13
- }
@@ -1,15 +0,0 @@
1
- name: CI
2
-
3
- on: push
4
-
5
- jobs:
6
- default:
7
- runs-on: ubuntu-latest
8
- steps:
9
- - uses: actions/checkout@v4
10
-
11
- - name: Setup
12
- uses: ./.github/actions/setup
13
-
14
- - name: Test
15
- run: pnpm test
@@ -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
@@ -1,4 +0,0 @@
1
- {
2
- "cSpell.words": ["Vento"],
3
- "deno.enable": false
4
- }
@@ -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,140 +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
- // Set output extension
86
- outputFileExtension: 'html',
87
-
88
- // Read vto files into eleventy
89
- read: true,
90
-
91
- // Main compile function
92
- async compile(inputContent, inputPath) {
93
- return async (data) => {
94
- if (options.addHelpers) {
95
- // Extract a possible namespace from the addHelpers option
96
- const namespace = options.addHelpers;
97
-
98
- // Extract page and eleventy values from data
99
- const { page, eleventy } = data;
100
-
101
- // Rebind functions to page data so this.page, this.eleventy, etc works as intended
102
- for (const helper in helperFunctions) {
103
- helperFunctions[helper] = helperFunctions[helper].bind({
104
- page,
105
- eleventy,
106
- });
107
- }
108
-
109
- // Rebind filters the same way
110
- for (const filter in filters) {
111
- env.filters[filter] = filters[filter].bind({ page, eleventy });
112
- }
113
-
114
- // Merge helpers into page data
115
- if (typeof namespace === 'string') data = { ...data, [namespace]: helperFunctions };
116
- else data = { ...data, ...helperFunctions };
117
- }
118
-
119
- const result = await env.runString(inputContent, data, inputPath);
120
-
121
- if (data.page?.rawInput !== inputContent) {
122
- env.cache.delete(inputPath);
123
- }
124
-
125
- return result.content;
126
- };
127
- },
128
-
129
- compileOptions: {
130
- // Custom permalink compilation
131
- permalink(linkContents) {
132
- if (typeof linkContents !== 'string') return linkContents;
133
- return async (data) => {
134
- const result = await env.runString(linkContents, data);
135
- return result.content;
136
- };
137
- },
138
- },
139
- });
140
- }
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
@@ -1,11 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "module": "NodeNext",
4
- "moduleResolution": "NodeNext",
5
- "baseUrl": ".",
6
- "paths": {
7
- "#lib/*": ["./lib/*"],
8
- "#test-instance": ["./tests/get-instance.js"]
9
- }
10
- }
11
- }
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
- }