eleventy-plugin-vento 2.0.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/.github/workflows/ci.yml +2 -2
  2. package/.github/workflows/release.yml +7 -11
  3. package/.vscode/settings.json +2 -1
  4. package/VentoPlugin.js +15 -10
  5. package/package.json +6 -5
  6. package/test/autotrim/__snapshots__/autotrim-all.html +53 -0
  7. package/test/autotrim/__snapshots__/autotrim-single.html +75 -0
  8. package/test/autotrim/autotrim.test.js +19 -0
  9. package/test/autotrim/build/autotrim-all.html +53 -0
  10. package/test/autotrim/build/autotrim-single.html +75 -0
  11. package/test/{input/trimming.vto → autotrim/index.vto} +6 -2
  12. package/test/basic/__snapshots__/template-basic.html +4 -0
  13. package/test/basic/basic.test.js +11 -0
  14. package/test/{input/simple.vto → basic/index.vto} +1 -1
  15. package/test/filters/__snapshots__/filters-arguments.html +1 -0
  16. package/test/filters/__snapshots__/filters-basic.html +2 -0
  17. package/test/filters/basic.vto +5 -0
  18. package/test/filters/filters.test.js +40 -0
  19. package/test/filters/with-arguments.vto +1 -0
  20. package/test/filters/with-this.vto +1 -0
  21. package/test/get-instance.js +35 -0
  22. package/test/includes/__snapshots__/includes-basic.html +8 -0
  23. package/test/includes/__snapshots__/includes-data.html +8 -0
  24. package/test/{input → includes}/_includes/partial.vto +1 -0
  25. package/test/includes/includes.test.js +20 -0
  26. package/test/includes/with-data.vto +7 -0
  27. package/test/layouts/__snapshots__/example-layout-1.html +27 -0
  28. package/test/layouts/__snapshots__/example-layout-2.html +24 -0
  29. package/test/layouts/layouts.test.js +18 -0
  30. package/test/{input/with-layout.vto → layouts/page1.vto} +2 -2
  31. package/test/layouts/page2.vto +11 -0
  32. package/test/permalinks/__snapshots__/permalink-nested.html +15 -0
  33. package/test/permalinks/__snapshots__/permalink-root.html +15 -0
  34. package/test/permalinks/_includes/layout.vto +13 -0
  35. package/test/permalinks/at-nested.vto +7 -0
  36. package/test/{input/root.vto → permalinks/at-root.vto} +2 -1
  37. package/test/{input/directory-data/dir-data.vto → permalinks/dynamic/dynamic-permalink.vto} +1 -1
  38. package/test/permalinks/permalinks.test.js +31 -0
  39. package/test/{input → permalinks}/skip.vto +1 -1
  40. package/test/shortcodes/__snapshots__/shortcode-with-arguments.html +2 -0
  41. package/test/shortcodes/basic.vto +1 -0
  42. package/test/shortcodes/shortcodes.test.js +24 -0
  43. package/test/shortcodes/with-arguments.vto +2 -0
  44. package/test/input/eleventy.config.js +0 -23
  45. package/test/input/filters-additional.vto +0 -9
  46. package/test/input/filters.vto +0 -9
  47. package/test/input/permalinks.vto +0 -7
  48. package/test/input/whitespace-control.vto +0 -5
  49. package/test/input/with-shortcodes.vto +0 -6
  50. /package/test/{input/with-includes.vto → includes/basic.vto} +0 -0
  51. /package/test/{input/_includes/page-layout-alt.vto → layouts/_includes/layout1.vto} +0 -0
  52. /package/test/{input/_includes/page-layout.vto → layouts/_includes/layout2.vto} +0 -0
  53. /package/test/{input/directory-data/directory-data.11tydata.json → 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,28 +1,24 @@
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
12
  test:
16
13
  uses: ./.github/workflows/ci.yml
17
-
18
14
  release:
19
15
  runs-on: ubuntu-latest
16
+ needs: test
20
17
  permissions:
21
18
  contents: write # to be able to publish a GitHub release
22
19
  id-token: write # to enable use of OIDC for npm provenance
23
20
  issues: write # to be able to comment on released issues
24
21
  pull-requests: write # to be able to comment on released pull requests
25
- needs: test
26
22
  steps:
27
23
  - uses: actions/checkout@v4
28
24
  with:
@@ -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,14 @@ 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 }));
76
75
 
77
76
  // Add vto as a template format and create a custom template for it
78
77
  eleventyConfig.addTemplateFormats('vto');
@@ -86,14 +85,20 @@ export function VentoPlugin(eleventyConfig, options = {}) {
86
85
  // Extract a possible namespace from the addHelpers option
87
86
  const namespace = options.addHelpers;
88
87
 
88
+ // Extract page and eleventy values from data
89
+ const { page, eleventy } = data;
90
+
89
91
  // Rebind functions to page data so this.page, this.eleventy, etc works as intended
90
92
  for (const helper in helperFunctions) {
91
- helperFunctions[helper] = helperFunctions[helper].bind(data);
93
+ helperFunctions[helper] = helperFunctions[helper].bind({
94
+ page,
95
+ eleventy,
96
+ });
92
97
  }
93
98
 
94
99
  // Rebind filters the same way
95
- for (const filter in env.filters) {
96
- env.filters[filter] = env.filters[filter].bind(data);
100
+ for (const filter in filters) {
101
+ env.filters[filter] = filters[filter].bind({ page, eleventy });
97
102
  }
98
103
 
99
104
  // Merge helpers into page data
package/package.json CHANGED
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "name": "eleventy-plugin-vento",
3
- "version": "2.0.0",
3
+ "version": "2.1.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.2.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": {
@@ -41,7 +41,8 @@
41
41
  "eslint-config-flat-gitignore": "0.1.5",
42
42
  "eslint-config-prettier": "9.1.0",
43
43
  "globals": "15.3.0",
44
- "semantic-release": "24.0.0"
44
+ "semantic-release": "24.0.0",
45
+ "vitest": "1.6.0"
45
46
  },
46
47
  "prettier": {
47
48
  "bracketSameLine": 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,31 @@
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(
9
+ './__snapshots__/permalink-nested.html'
10
+ );
11
+ });
12
+
13
+ test('render a page at root url', async () => {
14
+ const page = results.find(({ url }) => url === '/');
15
+ expect(page.content).toMatchFileSnapshot(
16
+ './__snapshots__/permalink-root.html'
17
+ );
18
+ });
19
+
20
+ test('render a page at a dynamic permalink', async () => {
21
+ const page = results.find(
22
+ ({ url }) => url === '/directory-data-test-page.html'
23
+ );
24
+
25
+ expect(page).toBeDefined();
26
+ });
27
+
28
+ test('skips rendering a file', () => {
29
+ const writtenTemplates = results.filter(({ url }) => Boolean(url));
30
+ expect(writtenTemplates.length).toBe(3);
31
+ });
@@ -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) }}