eleventy-plugin-vento 2.0.0 → 2.2.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 (57) hide show
  1. package/.github/workflows/ci.yml +2 -2
  2. package/.github/workflows/release.yml +9 -13
  3. package/.vscode/settings.json +2 -1
  4. package/VentoPlugin.js +19 -13
  5. package/eslint.config.js +1 -1
  6. package/package.json +8 -7
  7. package/release.config.js +1 -1
  8. package/tests/autotrim/__snapshots__/autotrim-all.html +53 -0
  9. package/tests/autotrim/__snapshots__/autotrim-single.html +75 -0
  10. package/tests/autotrim/autotrim.test.js +19 -0
  11. package/tests/autotrim/build/autotrim-all.html +53 -0
  12. package/tests/autotrim/build/autotrim-single.html +75 -0
  13. package/{test/input/trimming.vto → tests/autotrim/index.vto} +6 -2
  14. package/tests/basic/__snapshots__/template-basic.html +4 -0
  15. package/tests/basic/basic.test.js +11 -0
  16. package/{test/input/simple.vto → tests/basic/index.vto} +1 -1
  17. package/tests/filters/__snapshots__/filters-arguments.html +1 -0
  18. package/tests/filters/__snapshots__/filters-basic.html +2 -0
  19. package/tests/filters/basic.vto +5 -0
  20. package/tests/filters/filters.test.js +40 -0
  21. package/tests/filters/with-arguments.vto +1 -0
  22. package/tests/filters/with-this.vto +1 -0
  23. package/tests/get-instance.js +35 -0
  24. package/tests/includes/__snapshots__/includes-basic.html +8 -0
  25. package/tests/includes/__snapshots__/includes-data.html +8 -0
  26. package/{test/input → tests/includes}/_includes/partial.vto +1 -0
  27. package/tests/includes/includes.test.js +20 -0
  28. package/tests/includes/with-data.vto +7 -0
  29. package/tests/layouts/__snapshots__/example-layout-1.html +27 -0
  30. package/tests/layouts/__snapshots__/example-layout-2.html +24 -0
  31. package/tests/layouts/layouts.test.js +18 -0
  32. package/{test/input/with-layout.vto → tests/layouts/page1.vto} +2 -2
  33. package/tests/layouts/page2.vto +11 -0
  34. package/tests/permalinks/__snapshots__/permalink-nested.html +15 -0
  35. package/tests/permalinks/__snapshots__/permalink-root.html +15 -0
  36. package/tests/permalinks/_includes/layout.vto +13 -0
  37. package/tests/permalinks/at-nested.vto +7 -0
  38. package/{test/input/root.vto → tests/permalinks/at-root.vto} +2 -1
  39. package/{test/input/directory-data/dir-data.vto → tests/permalinks/dynamic/dynamic-permalink.vto} +1 -1
  40. package/tests/permalinks/dynamic-js/dynamic-js.11tydata.js +5 -0
  41. package/tests/permalinks/dynamic-js/dynamic-permalink-js.vto +6 -0
  42. package/tests/permalinks/permalinks.test.js +25 -0
  43. package/{test/input → tests/permalinks}/skip.vto +1 -1
  44. package/tests/shortcodes/__snapshots__/shortcode-with-arguments.html +2 -0
  45. package/tests/shortcodes/basic.vto +1 -0
  46. package/tests/shortcodes/shortcodes.test.js +24 -0
  47. package/tests/shortcodes/with-arguments.vto +2 -0
  48. package/test/input/eleventy.config.js +0 -23
  49. package/test/input/filters-additional.vto +0 -9
  50. package/test/input/filters.vto +0 -9
  51. package/test/input/permalinks.vto +0 -7
  52. package/test/input/whitespace-control.vto +0 -5
  53. package/test/input/with-shortcodes.vto +0 -6
  54. /package/{test/input/with-includes.vto → tests/includes/basic.vto} +0 -0
  55. /package/{test/input/_includes/page-layout-alt.vto → tests/layouts/_includes/layout1.vto} +0 -0
  56. /package/{test/input/_includes/page-layout.vto → tests/layouts/_includes/layout2.vto} +0 -0
  57. /package/{test/input/directory-data/directory-data.11tydata.json → tests/permalinks/dynamic/dynamic.11tydata.json} +0 -0
@@ -2,12 +2,12 @@ name: CI
2
2
 
3
3
  on:
4
4
  push:
5
- branches: [renovate/**]
5
+ branches: [main, dev, alpha, beta, next, renovate/**]
6
6
  workflow_dispatch:
7
7
  workflow_call:
8
8
 
9
9
  jobs:
10
- ci:
10
+ test:
11
11
  runs-on: ubuntu-latest
12
12
  steps:
13
13
  - uses: actions/checkout@v4
@@ -1,20 +1,14 @@
1
+ # Run releases every monday and wednesday
2
+ # at 12:33 UTC (or manually)
3
+
1
4
  name: Release
2
5
 
3
6
  on:
4
- push:
5
- branches:
6
- - main
7
- - alpha
8
- - beta
9
- - next
10
- - next-major
11
- - v[0-9]+.[0-9]+.[0-9]+
12
- - v[0-9]+.[0-9]+.[0-9]+-[a-z]+.[0-9]+
7
+ schedule:
8
+ - cron: '33 12 * * 1,3'
9
+ workflow_dispatch:
13
10
 
14
11
  jobs:
15
- test:
16
- uses: ./.github/workflows/ci.yml
17
-
18
12
  release:
19
13
  runs-on: ubuntu-latest
20
14
  permissions:
@@ -22,7 +16,6 @@ jobs:
22
16
  id-token: write # to enable use of OIDC for npm provenance
23
17
  issues: write # to be able to comment on released issues
24
18
  pull-requests: write # to be able to comment on released pull requests
25
- needs: test
26
19
  steps:
27
20
  - uses: actions/checkout@v4
28
21
  with:
@@ -31,6 +24,9 @@ jobs:
31
24
  - name: Setup
32
25
  uses: ./.github/actions/setup
33
26
 
27
+ - name: Check project for errors
28
+ run: pnpm test
29
+
34
30
  - name: Verify provenance attestations and registry signatures
35
31
  run: npm audit signatures
36
32
 
@@ -1,3 +1,4 @@
1
1
  {
2
- "cSpell.words": ["Vento"]
2
+ "cSpell.words": ["Vento"],
3
+ "deno.enable": false
3
4
  }
package/VentoPlugin.js CHANGED
@@ -13,7 +13,6 @@
13
13
  * that will be merged with default options.
14
14
  */
15
15
 
16
- import path from 'node:path';
17
16
  import VentoJs from 'ventojs';
18
17
 
19
18
  // Expose autotrim plugin defaults
@@ -35,14 +34,15 @@ export function VentoPlugin(eleventyConfig, options = {}) {
35
34
  }
36
35
 
37
36
  // Pull some bits from eleventyConfig and merge user-options with defaults
38
- const { dir, javascriptFunctions, liquidFilters, nunjucksFilters, nunjucksAsyncFilters } =
37
+ const { directories, javascriptFunctions, liquidFilters, nunjucksFilters, nunjucksAsyncFilters } =
39
38
  eleventyConfig;
39
+
40
40
  options = {
41
41
  addHelpers: true,
42
42
  trimTags: false,
43
43
  plugins: [],
44
44
  ventoOptions: {
45
- includes: path.join(dir.input, dir.includes),
45
+ includes: directories.includes,
46
46
  autoescape: false,
47
47
  },
48
48
  ...options,
@@ -64,15 +64,16 @@ export function VentoPlugin(eleventyConfig, options = {}) {
64
64
  }
65
65
 
66
66
  // Load filters into vento
67
- for (const filter in filters) {
68
- env.filters[filter] = filters[filter];
69
- }
67
+ for (const filter in filters) env.filters[filter] = filters[filter];
70
68
 
71
69
  // Load user-defined plugins into vento
72
70
  for (const plugin of options.plugins) env.use(plugin);
73
71
 
74
72
  // Add autotrim plugin if enabled
75
- if (options.trimTags) env.use(autoTrim({ tags: options.trimTags || ventoDefaultTrimTags }));
73
+ if (options.trimTags === true) env.use(autoTrim());
74
+ else if (options.trimTags) env.use(autoTrim({ tags: options.trimTags }));
75
+
76
+ eleventyConfig.on('eleventy.before', () => env.cache.clear());
76
77
 
77
78
  // Add vto as a template format and create a custom template for it
78
79
  eleventyConfig.addTemplateFormats('vto');
@@ -80,20 +81,25 @@ export function VentoPlugin(eleventyConfig, options = {}) {
80
81
  outputFileExtension: 'html',
81
82
 
82
83
  async compile(inputContent, inputPath) {
83
- env.cache.clear();
84
84
  return async (data) => {
85
85
  if (options.addHelpers) {
86
86
  // Extract a possible namespace from the addHelpers option
87
87
  const namespace = options.addHelpers;
88
88
 
89
+ // Extract page and eleventy values from data
90
+ const { page, eleventy } = data;
91
+
89
92
  // Rebind functions to page data so this.page, this.eleventy, etc works as intended
90
93
  for (const helper in helperFunctions) {
91
- helperFunctions[helper] = helperFunctions[helper].bind(data);
94
+ helperFunctions[helper] = helperFunctions[helper].bind({
95
+ page,
96
+ eleventy,
97
+ });
92
98
  }
93
99
 
94
100
  // Rebind filters the same way
95
- for (const filter in env.filters) {
96
- env.filters[filter] = env.filters[filter].bind(data);
101
+ for (const filter in filters) {
102
+ env.filters[filter] = filters[filter].bind({ page, eleventy });
97
103
  }
98
104
 
99
105
  // Merge helpers into page data
@@ -108,10 +114,10 @@ export function VentoPlugin(eleventyConfig, options = {}) {
108
114
  },
109
115
 
110
116
  compileOptions: {
111
- permalink(linkContents, inputPath) {
117
+ permalink(linkContents) {
112
118
  if (typeof linkContents !== 'string') return linkContents;
113
119
  return async (data) => {
114
- const result = await env.runString(linkContents, data, inputPath);
120
+ const result = await env.runString(linkContents, data);
115
121
  return result.content;
116
122
  };
117
123
  },
package/eslint.config.js CHANGED
@@ -17,7 +17,7 @@ export default [
17
17
 
18
18
  // Configure ignores
19
19
  {
20
- ignores: ['**/.cache', '**/_site', '**/node_modules', '**/functions'],
20
+ ignores: ['**/node_modules'],
21
21
  },
22
22
 
23
23
  // Configure defaults
package/package.json CHANGED
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "name": "eleventy-plugin-vento",
3
- "version": "2.0.0",
3
+ "version": "2.2.0",
4
4
  "description": "Adds support for the Vento templating language to Eleventy.",
5
5
  "type": "module",
6
- "packageManager": "pnpm@9.1.4",
6
+ "packageManager": "pnpm@9.3.0",
7
7
  "engines": {
8
8
  "node": ">=16"
9
9
  },
10
10
  "scripts": {
11
- "test": "rm -rf test/output; cd test/input; eleventy",
12
- "test-serve": "rm -rf test/output; cd test/input; eleventy --serve"
11
+ "test": "vitest",
12
+ "lint": "eslint **/*.js --config ./eslint.config.js"
13
13
  },
14
14
  "main": "./VentoPlugin.js",
15
15
  "exports": {
@@ -32,7 +32,7 @@
32
32
  },
33
33
  "license": "MIT",
34
34
  "dependencies": {
35
- "ventojs": "0.12.6"
35
+ "ventojs": "0.12.7"
36
36
  },
37
37
  "devDependencies": {
38
38
  "@11ty/eleventy": "3.0.0-alpha.10",
@@ -40,8 +40,9 @@
40
40
  "eslint": "9.4.0",
41
41
  "eslint-config-flat-gitignore": "0.1.5",
42
42
  "eslint-config-prettier": "9.1.0",
43
- "globals": "15.3.0",
44
- "semantic-release": "24.0.0"
43
+ "globals": "15.4.0",
44
+ "semantic-release": "24.0.0",
45
+ "vitest": "1.6.0"
45
46
  },
46
47
  "prettier": {
47
48
  "bracketSameLine": true,
package/release.config.js CHANGED
@@ -3,7 +3,7 @@ const presetConfig = {
3
3
  { type: 'feat', section: 'New Features' },
4
4
  { type: 'fix', section: 'Bug Fixes' },
5
5
  { type: 'refactor', section: 'Refactorings' },
6
- { type: 'docs', hidden: 'Documentation' },
6
+ { type: 'docs', section: 'Documentation' },
7
7
  { type: 'chore', hidden: true },
8
8
  { type: 'perf', hidden: true },
9
9
  { type: 'style', hidden: true },
@@ -0,0 +1,53 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Document</title>
7
+ </head>
8
+ <body>
9
+ <main>
10
+ <section>
11
+ <h1>1</h1>
12
+ <p>This is section 1</p>
13
+ </section>
14
+ <section>
15
+ <h1>2</h1>
16
+ <p>This is section 2</p>
17
+ </section>
18
+ <section>
19
+ <h1>3</h1>
20
+ <p>This is section 3</p>
21
+ </section>
22
+ <section>
23
+ <h1>4</h1>
24
+ <p>This is section 4</p>
25
+ </section>
26
+ Section 5 is next!!
27
+ <section>
28
+ <h1>5</h1>
29
+ <p>This is section 5</p>
30
+ </section>
31
+ <section>
32
+ <h1>6</h1>
33
+ <p>This is section 6</p>
34
+ </section>
35
+ <section>
36
+ <h1>7</h1>
37
+ <p>This is section 7</p>
38
+ </section>
39
+ <section>
40
+ <h1>8</h1>
41
+ <p>This is section 8</p>
42
+ </section>
43
+ <section>
44
+ <h1>9</h1>
45
+ <p>This is section 9</p>
46
+ </section>
47
+ <section>
48
+ <h1>10</h1>
49
+ <p>This is section 10</p>
50
+ </section>
51
+ </main>
52
+ </body>
53
+ </html>
@@ -0,0 +1,75 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Document</title>
7
+ </head>
8
+ <body>
9
+ <main>
10
+
11
+
12
+ <section>
13
+ <h1>1</h1>
14
+ <p>This is section 1</p>
15
+ </section>
16
+
17
+
18
+ <section>
19
+ <h1>2</h1>
20
+ <p>This is section 2</p>
21
+ </section>
22
+
23
+
24
+ <section>
25
+ <h1>3</h1>
26
+ <p>This is section 3</p>
27
+ </section>
28
+
29
+
30
+ <section>
31
+ <h1>4</h1>
32
+ <p>This is section 4</p>
33
+ </section>
34
+
35
+
36
+ Section 5 is next!!
37
+
38
+ <section>
39
+ <h1>5</h1>
40
+ <p>This is section 5</p>
41
+ </section>
42
+
43
+
44
+ <section>
45
+ <h1>6</h1>
46
+ <p>This is section 6</p>
47
+ </section>
48
+
49
+
50
+ <section>
51
+ <h1>7</h1>
52
+ <p>This is section 7</p>
53
+ </section>
54
+
55
+
56
+ <section>
57
+ <h1>8</h1>
58
+ <p>This is section 8</p>
59
+ </section>
60
+
61
+
62
+ <section>
63
+ <h1>9</h1>
64
+ <p>This is section 9</p>
65
+ </section>
66
+
67
+
68
+ <section>
69
+ <h1>10</h1>
70
+ <p>This is section 10</p>
71
+ </section>
72
+
73
+ </main>
74
+ </body>
75
+ </html>
@@ -0,0 +1,19 @@
1
+ import { expect, test } from 'vitest';
2
+ import { runBuild } from '../get-instance.js';
3
+
4
+ const [trimSingle, trimAll] = await Promise.all([
5
+ runBuild(import.meta.dirname, { vento: { trimTags: ['set'] } }),
6
+ runBuild(import.meta.dirname, { vento: { trimTags: true } }),
7
+ ]);
8
+
9
+ test('should trim a single tag', async () => {
10
+ const page = trimSingle[0];
11
+ await expect(page.content).toMatchFileSnapshot(
12
+ './build/autotrim-single.html'
13
+ );
14
+ });
15
+
16
+ test('should trim all tags', async () => {
17
+ const page = trimAll[0];
18
+ await expect(page.content).toMatchFileSnapshot('./build/autotrim-all.html');
19
+ });
@@ -0,0 +1,53 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Document</title>
7
+ </head>
8
+ <body>
9
+ <main>
10
+ <section>
11
+ <h1>1</h1>
12
+ <p>This is section 1</p>
13
+ </section>
14
+ <section>
15
+ <h1>2</h1>
16
+ <p>This is section 2</p>
17
+ </section>
18
+ <section>
19
+ <h1>3</h1>
20
+ <p>This is section 3</p>
21
+ </section>
22
+ <section>
23
+ <h1>4</h1>
24
+ <p>This is section 4</p>
25
+ </section>
26
+ Section 5 is next!!
27
+ <section>
28
+ <h1>5</h1>
29
+ <p>This is section 5</p>
30
+ </section>
31
+ <section>
32
+ <h1>6</h1>
33
+ <p>This is section 6</p>
34
+ </section>
35
+ <section>
36
+ <h1>7</h1>
37
+ <p>This is section 7</p>
38
+ </section>
39
+ <section>
40
+ <h1>8</h1>
41
+ <p>This is section 8</p>
42
+ </section>
43
+ <section>
44
+ <h1>9</h1>
45
+ <p>This is section 9</p>
46
+ </section>
47
+ <section>
48
+ <h1>10</h1>
49
+ <p>This is section 10</p>
50
+ </section>
51
+ </main>
52
+ </body>
53
+ </html>
@@ -0,0 +1,75 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Document</title>
7
+ </head>
8
+ <body>
9
+ <main>
10
+
11
+
12
+ <section>
13
+ <h1>1</h1>
14
+ <p>This is section 1</p>
15
+ </section>
16
+
17
+
18
+ <section>
19
+ <h1>2</h1>
20
+ <p>This is section 2</p>
21
+ </section>
22
+
23
+
24
+ <section>
25
+ <h1>3</h1>
26
+ <p>This is section 3</p>
27
+ </section>
28
+
29
+
30
+ <section>
31
+ <h1>4</h1>
32
+ <p>This is section 4</p>
33
+ </section>
34
+
35
+
36
+ Section 5 is next!!
37
+
38
+ <section>
39
+ <h1>5</h1>
40
+ <p>This is section 5</p>
41
+ </section>
42
+
43
+
44
+ <section>
45
+ <h1>6</h1>
46
+ <p>This is section 6</p>
47
+ </section>
48
+
49
+
50
+ <section>
51
+ <h1>7</h1>
52
+ <p>This is section 7</p>
53
+ </section>
54
+
55
+
56
+ <section>
57
+ <h1>8</h1>
58
+ <p>This is section 8</p>
59
+ </section>
60
+
61
+
62
+ <section>
63
+ <h1>9</h1>
64
+ <p>This is section 9</p>
65
+ </section>
66
+
67
+
68
+ <section>
69
+ <h1>10</h1>
70
+ <p>This is section 10</p>
71
+ </section>
72
+
73
+ </main>
74
+ </body>
75
+ </html>
@@ -6,12 +6,16 @@
6
6
  <title>Document</title>
7
7
  </head>
8
8
  <body>
9
- {{ set numbers = [1,2,3,4,5,6,7,8,9,10] }}
9
+ {{ set numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] }}
10
10
  <main>
11
11
  {{ for num of numbers }}
12
+ {{ set current = `section ${num}` }}
13
+ {{ if num === 5 }}
14
+ Section 5 is next!!
15
+ {{ /if }}
12
16
  <section>
13
17
  <h1>{{ num }}</h1>
14
- <p>This is section {{ num }}</p>
18
+ <p>This is {{ current }}</p>
15
19
  </section>
16
20
  {{ /for }}
17
21
  </main>
@@ -0,0 +1,4 @@
1
+
2
+ <h1>Basic Page</h1>
3
+
4
+ This is a standalone page.
@@ -0,0 +1,11 @@
1
+ import { expect, test } from 'vitest';
2
+ import { runBuild } from '../get-instance.js';
3
+
4
+ const results = await runBuild(import.meta.dirname);
5
+
6
+ test('renders a basic template', async () => {
7
+ const page = results[0];
8
+ await expect(page.content).toMatchFileSnapshot(
9
+ './__snapshots__/template-basic.html'
10
+ );
11
+ });
@@ -1,5 +1,5 @@
1
1
  ---
2
- title: Simple Page
2
+ title: Basic Page
3
3
  ---
4
4
 
5
5
  <h1>{{ title }}</h1>
@@ -0,0 +1 @@
1
+ This is a <strong>really cool</strong> filter.
@@ -0,0 +1,2 @@
1
+
2
+ Page title is 'A BASIC PAGE'
@@ -0,0 +1,5 @@
1
+ ---
2
+ title: A basic page
3
+ ---
4
+
5
+ Page title is '{{ title |> uppercase }}'
@@ -0,0 +1,40 @@
1
+ import { expect, test } from 'vitest';
2
+ import { runBuild } from '../get-instance.js';
3
+
4
+ const results = await runBuild(import.meta.dirname, {
5
+ eleventy(configApi) {
6
+ configApi.addFilter(
7
+ 'uppercase',
8
+ /** @param {string} content */
9
+ (content) => content.toUpperCase()
10
+ );
11
+
12
+ configApi.addFilter(
13
+ 'wrapWith',
14
+ (content, tag) => `<${tag}>${content}</${tag}>`
15
+ );
16
+
17
+ configApi.addFilter('pageUrlCompare', function (url) {
18
+ return url === this.page.url;
19
+ });
20
+ },
21
+ });
22
+
23
+ test('transforms string with built-in method', async () => {
24
+ const page = results.find(({ url }) => url === '/basic/');
25
+ await expect(page.content).toMatchFileSnapshot(
26
+ './__snapshots__/filters-basic.html'
27
+ );
28
+ });
29
+
30
+ test('transforms string with passed arguments', async () => {
31
+ const page = results.find(({ url }) => url === '/with-arguments/');
32
+ await expect(page.content).toMatchFileSnapshot(
33
+ './__snapshots__/filters-arguments.html'
34
+ );
35
+ });
36
+
37
+ test('verify page context in scoped data', async () => {
38
+ const page = results.find(({ url }) => url === '/with-this/');
39
+ expect(page.content).toBe('true\n');
40
+ });
@@ -0,0 +1 @@
1
+ This is a {{ 'really cool' |> wrapWith('strong') }} filter.
@@ -0,0 +1 @@
1
+ {{ page.url |> pageUrlCompare }}
@@ -0,0 +1,35 @@
1
+ import { VentoPlugin } from 'eleventy-plugin-vento';
2
+ import Eleventy from '@11ty/eleventy';
3
+
4
+ /**
5
+ * @typedef {object} ExtensionsOptions
6
+ * @property {import('eleventy-plugin-vento').VentoPluginOptions} vento
7
+ * @property {import('@11ty/eleventy/src/UserConfig.js')} eleventy
8
+ *
9
+ * @typedef {{ url: string, inputPath: string, outputPath: string, rawInput: string, content: string }} PageObject
10
+ * @typedef {PageObject[]} EleventyOutput
11
+ */
12
+
13
+ /**
14
+ * @param {string} fromInput
15
+ * @param {ExtensionsOptions} [extensions={}]
16
+ */
17
+ export async function runBuild(fromInput, extensions = {}) {
18
+ const instance = new Eleventy(fromInput, '_site', {
19
+ quiet: true,
20
+
21
+ /** @param {import('@11ty/eleventy/src/UserConfig.js').default} eleventyConfig */
22
+ config(eleventyConfig) {
23
+ eleventyConfig.addPlugin(VentoPlugin, extensions.vento || {});
24
+
25
+ eleventyConfig.ignores.add('**/__snapshots__/**');
26
+
27
+ if (extensions.eleventy) extensions.eleventy.call(this, eleventyConfig);
28
+ },
29
+ });
30
+
31
+ /** @type {Promise<EleventyOutput>} */
32
+ const results = await instance.toJSON();
33
+
34
+ return results;
35
+ }
@@ -0,0 +1,8 @@
1
+
2
+ <h1>Page with includes</h1>
3
+
4
+ <section class="include">
5
+ <p>This content is included.</p>
6
+ <p>Passed data for `extra` key: ''</p>
7
+ </section>
8
+
@@ -0,0 +1,8 @@
1
+
2
+ <h1>Page with includes (data passing)</h1>
3
+
4
+ <section class="include">
5
+ <p>This content is included.</p>
6
+ <p>Passed data for `extra` key: 'super fancy data'</p>
7
+ </section>
8
+
@@ -1,3 +1,4 @@
1
1
  <section class="include">
2
2
  <p>This content is included.</p>
3
+ <p>Passed data for `extra` key: '{{ extra }}'</p>
3
4
  </section>
@@ -0,0 +1,20 @@
1
+ import { expect, test } from 'vitest';
2
+ import { runBuild } from '../get-instance.js';
3
+
4
+ console.log(import.meta.dirname);
5
+
6
+ const results = await runBuild(import.meta.dirname);
7
+
8
+ test('include a page', async () => {
9
+ const page = results.find(({ url }) => url === '/basic/');
10
+ await expect(page.content).toMatchFileSnapshot(
11
+ './__snapshots__/includes-basic.html'
12
+ );
13
+ });
14
+
15
+ test('include a page with data passing', async () => {
16
+ const page = results.find(({ url }) => url === '/with-data/');
17
+ await expect(page.content).toMatchFileSnapshot(
18
+ './__snapshots__/includes-data.html'
19
+ );
20
+ });
@@ -0,0 +1,7 @@
1
+ ---
2
+ title: Page with includes (data passing)
3
+ ---
4
+
5
+ <h1>{{ title }}</h1>
6
+
7
+ {{ include 'partial.vto' { extra: 'super fancy data' } }}
@@ -0,0 +1,27 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Page with layout</title>
7
+ </head>
8
+ <body>
9
+ <header>
10
+ <h1>Page title: Page with layout</h1>
11
+ </header>
12
+ <main>
13
+ <section>This is an alternative layout.</section>
14
+ <section>
15
+ <p>This is a page that uses the first layout.</p>
16
+
17
+ <p>This is another paragraph.</p>
18
+ <p>This is another paragraph.</p>
19
+ <p>This is another paragraph.</p>
20
+
21
+ </section>
22
+ </main>
23
+ <footer>
24
+ <p>I am a footer, outside the layout</p>
25
+ </footer>
26
+ </body>
27
+ </html>
@@ -0,0 +1,24 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Page with layout</title>
7
+ </head>
8
+ <body>
9
+ <header>
10
+ <h1>Page title: Page with layout</h1>
11
+ </header>
12
+ <main>
13
+ <p>This is a page that uses the second layout.</p>
14
+
15
+ <p>This is another paragraph.</p>
16
+ <p>This is another paragraph.</p>
17
+ <p>This is another paragraph.</p>
18
+
19
+ </main>
20
+ <footer>
21
+ <p>I am a footer, outside the layout</p>
22
+ </footer>
23
+ </body>
24
+ </html>
@@ -0,0 +1,18 @@
1
+ import { expect, test } from 'vitest';
2
+ import { runBuild } from '../get-instance.js';
3
+
4
+ const results = await runBuild(import.meta.dirname);
5
+
6
+ test('render page with example layout 1', async () => {
7
+ const page = results.find(({ url }) => url === '/page1/');
8
+ await expect(page.content).toMatchFileSnapshot(
9
+ './__snapshots__/example-layout-1.html'
10
+ );
11
+ });
12
+
13
+ test('render page with example layout 2', async () => {
14
+ const page = results.find(({ url }) => url === '/page2/');
15
+ await expect(page.content).toMatchFileSnapshot(
16
+ './__snapshots__/example-layout-2.html'
17
+ );
18
+ });
@@ -1,9 +1,9 @@
1
1
  ---
2
2
  title: Page with layout
3
- layout: page-layout.vto
3
+ layout: layout1.vto
4
4
  ---
5
5
 
6
- <p>This is a page that uses a layout.</p>
6
+ <p>This is a page that uses the first layout.</p>
7
7
 
8
8
  <p>This is another paragraph.</p>
9
9
  <p>This is another paragraph.</p>
@@ -0,0 +1,11 @@
1
+ ---
2
+ title: Page with layout
3
+ layout: layout2.vto
4
+ ---
5
+
6
+ <p>This is a page that uses the second layout.</p>
7
+
8
+ <p>This is another paragraph.</p>
9
+ <p>This is another paragraph.</p>
10
+ <p>This is another paragraph.</p>
11
+
@@ -0,0 +1,15 @@
1
+ <!doctype html>
2
+ <html>
3
+ <head><title>Nested Page</title></head>
4
+ <body>
5
+ <header>
6
+ <h1>Page title: Nested Page</h1>
7
+ </header>
8
+ <main>
9
+ This content lives at `/page/at/nested/permalink/`
10
+ </main>
11
+ <footer>
12
+ <p>Page footer</p>
13
+ </footer>
14
+ </body>
15
+ </html>
@@ -0,0 +1,15 @@
1
+ <!doctype html>
2
+ <html>
3
+ <head><title>Root page</title></head>
4
+ <body>
5
+ <header>
6
+ <h1>Page title: Root page</h1>
7
+ </header>
8
+ <main>
9
+ This should render on the homepage.
10
+ </main>
11
+ <footer>
12
+ <p>Page footer</p>
13
+ </footer>
14
+ </body>
15
+ </html>
@@ -0,0 +1,13 @@
1
+ <!doctype html>
2
+ <html>
3
+ <head><title>{{ title }}</title></head>
4
+ <body>
5
+ <header>
6
+ <h1>Page title: {{ title }}</h1>
7
+ </header>
8
+ <main>{{ content }}</main>
9
+ <footer>
10
+ <p>Page footer</p>
11
+ </footer>
12
+ </body>
13
+ </html>
@@ -0,0 +1,7 @@
1
+ ---
2
+ permalink: /page/at/nested/permalink/
3
+ title: Nested Page
4
+ layout: layout.vto
5
+ ---
6
+
7
+ This content lives at `/page/at/nested/permalink/`
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  permalink: /
3
- layout: page-layout.vto
3
+ title: Root page
4
+ layout: layout.vto
4
5
  ---
5
6
 
6
7
  This should render on the homepage.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: Directory data test page
3
- layout: page-layout.vto
3
+ layout: layout.vto
4
4
  ---
5
5
 
6
6
  This page has directory data set with dynamic permalinks
@@ -0,0 +1,5 @@
1
+ export default {
2
+ permalink({ title }) {
3
+ return `${this.slugify(title)}.html`;
4
+ },
5
+ };
@@ -0,0 +1,6 @@
1
+ ---
2
+ title: Directory data test page (js)
3
+ layout: layout.vto
4
+ ---
5
+
6
+ This page has directory data set with dynamic permalinks
@@ -0,0 +1,25 @@
1
+ import { expect, test } from 'vitest';
2
+ import { runBuild } from '../get-instance.js';
3
+
4
+ const results = await runBuild(import.meta.dirname);
5
+
6
+ test('render a page at a nested permalink', async () => {
7
+ const page = results.find(({ url }) => url === '/page/at/nested/permalink/');
8
+ await expect(page.content).toMatchFileSnapshot('./__snapshots__/permalink-nested.html');
9
+ });
10
+
11
+ test('render a page at root url', async () => {
12
+ const page = results.find(({ url }) => url === '/');
13
+ expect(page.content).toMatchFileSnapshot('./__snapshots__/permalink-root.html');
14
+ });
15
+
16
+ test('render a page at a dynamic permalink', async () => {
17
+ const page = results.find(({ url }) => url === '/directory-data-test-page.html');
18
+
19
+ expect(page).toBeDefined();
20
+ });
21
+
22
+ test('skips rendering a file', () => {
23
+ const writtenTemplates = results.filter(({ url }) => Boolean(url));
24
+ expect(writtenTemplates.length).toBe(4);
25
+ });
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: Skipped
3
- layout: page-layout.vto
3
+ layout: layout.vto
4
4
  permalink: false
5
5
  ---
6
6
 
@@ -0,0 +1,2 @@
1
+ Release the possums!!!
2
+ Release 5 MILLION possums!!!
@@ -0,0 +1 @@
1
+ {{ helloWorld() }}
@@ -0,0 +1,24 @@
1
+ import { test } from 'vitest';
2
+ import { runBuild } from '../get-instance.js';
3
+
4
+ const results = await runBuild(import.meta.dirname, {
5
+ eleventy(configApi) {
6
+ configApi.addShortcode('helloWorld', () => 'Hello world!');
7
+ configApi.addShortcode(
8
+ 'possumPosse',
9
+ (number = 'the') => `Release ${number} possums!!!`
10
+ );
11
+ },
12
+ });
13
+
14
+ test.concurrent('shortcode without argument', ({ expect }) => {
15
+ const page = results.find(({ url }) => url === '/basic/');
16
+ expect(page.content).toBe('Hello world!\n');
17
+ });
18
+
19
+ test.concurrent('shortcode with arguments', async ({ expect }) => {
20
+ const page = results.find(({ url }) => url === '/with-arguments/');
21
+ await expect(page.content).toMatchFileSnapshot(
22
+ './__snapshots__/shortcode-with-arguments.html'
23
+ );
24
+ });
@@ -0,0 +1,2 @@
1
+ {{ possumPosse() }}
2
+ {{ possumPosse('5 MILLION') }}
@@ -1,23 +0,0 @@
1
- import { VentoPlugin, ventoDefaultTrimTags } from 'eleventy-plugin-vento';
2
-
3
- export const config = {
4
- dir: {
5
- input: '.',
6
- output: '../output',
7
- },
8
- };
9
-
10
- /** @param {import('@11ty/eleventy/src/UserConfig.js').default} eleventyConfig */
11
- export default async function (eleventyConfig) {
12
- eleventyConfig.addFilter('italicize', (content) => `<em>${content}</em>`);
13
-
14
- eleventyConfig.addFilter('appendURL', function (content) {
15
- return `${content} ${this.page.url}`;
16
- });
17
-
18
- eleventyConfig.addPlugin(VentoPlugin, {
19
- trimTags: [...ventoDefaultTrimTags, 'for'],
20
- });
21
-
22
- eleventyConfig.addShortcode('possumPosse', (number = 'the') => `Release ${number} possums!!!`);
23
- }
@@ -1,9 +0,0 @@
1
- ---
2
- title: Page with filters
3
- ---
4
-
5
- <h1>{{ title }}</h1>
6
-
7
- This is a page with a filter. {{ 'Page URL:' |> appendURL }}
8
-
9
- Built with {{ eleventy.generator |> italicize }}
@@ -1,9 +0,0 @@
1
- ---
2
- title: Page with filters
3
- ---
4
-
5
- <h1>{{ title }}</h1>
6
-
7
- This is a page with a filter.
8
-
9
- Built with {{ eleventy.generator |> italicize }}
@@ -1,7 +0,0 @@
1
- ---
2
- permalink: /test/page/permalink/
3
- title: Test page
4
- layout: page-layout.vto
5
- ---
6
-
7
- This content lives at `/test/page/permalink/`
@@ -1,5 +0,0 @@
1
- {{ set name = "Bob" }}
2
- {{ if true }}
3
- Hello, {{ name }}!
4
- {{ set variable = 10 }}
5
- {{ /if }}
@@ -1,6 +0,0 @@
1
- ---
2
- title: Page with shortcodes
3
- layout: page-layout.vto
4
- ---
5
-
6
- {{ possumPosse(32) }}