Skip to content

noelforte/eleventy-plugin-vento

Repository files navigation

eleventy-plugin-vento 🌬️🎈🐀

Eleventy v3 and later

Github Actions Status eleventy-plugin-vento on npm changesets on GitHub

An Eleventy plugin that adds support for Vento templates.

Contents

Installing
Usage
Plugin Options
Filters
Shortcodes (Single & Paired)
Vento Plugins
Auto-Trimming Tags
Debugging

Installing

npm install eleventy-plugin-vento

Usage

This plugin is ESM only and cannot be required from CommonJS.

If you're using CommonJS and loading it asynchronously (ie await import), you will need at minimum Eleventy v3.0.0-alpha.15 which provides internal methods this plugin uses to retrieve Eleventy features from the config API.

In your Eleventy config:

import { VentoPlugin } from 'eleventy-plugin-vento';

export default function (eleventyConfig) {
  eleventyConfig.addPlugin(VentoPlugin);
}

Plugin Options

This plugin ships with default options out of the box, but you can pass an options object to your addPlugin call to configure things further. The below example shows the configurable options as well as their defaults.

import { VentoPlugin } from 'eleventy-plugin-vento';

export default function (eleventyConfig) {
  eleventyConfig.addPlugin(VentoPlugin, {
    // An array of Vento plugins to use when compiling
    plugins: [],

    // Enable/disable Eleventy Shortcodes, Paired Shortcodes,
    // and Filters in .vto templates
    shortcodes: true,
    pairedShortcodes: true,
    filters: true,

    // Define tags that should be trimmed, or set to true
    // to trim the default tags (see section on Auto-trimming)
    autotrim: false,

    // A Vento configuration object
    ventoOptions: {
      includes: eleventyConfig.directories.includes,
    },
  });
}

View the full list of options to pass as a Vento Configuration object (as ventoOptions).

Filters

Note

Remember, Vento can pipe any JS data type to any built-in global as the first-argument or any .prototype method in addition to declared filters. For instance to print the eleventy variable as JSON you could use the following snippet:

{{ eleventy |> JSON.stringify }}

In these cases, Eleventy filters may not be needed depending on your usage.

Filters that are added via Eleventy's .addFilter() or .addAsyncFilter() methods will be automatically loaded into Vento. Since Vento filters and Eleventy filters follow the same syntax for filters (content as first argument), the implementation is 1:1.

If you'd prefer to set filters yourself (via a plugin or other method) or prevent Eleventy from loading filters into Vento, set filters: false in the plugin options.

Filters and this

Eleventy provides filters with scoped data via the this.page and this.eleventy objects (see Filters#Scoped data in Filters in Eleventy's docs for more details). Likewise, Vento provides filters with this.env and this.data representing the Vento environment and the current template data. This plugin merges both objects together to make this.page (and eleventy/env/data) available on all filters processed by Vento.

This feature enables re-use of the Vento environment this plugin provides, within Eleventy filters. As an example use case, you could create a filter that compiles dynamic data and cache it with Vento's own cache to improve performance:

import 'hash' from 'node:crypto'; // since Node v20.12.0

const sha1Hash(str) => hash('sha1', str, 'hex');

eleventyConfig.addFilter('vento', function (content) {
  const file = `dynamicString:${sha1Hash(content)}`;
  const res = this.env.runString(content, this.data, file);
  return res.content;
});

Relevant documentation

Vento: See Filters and Pipes

Eleventy: See Filters

Shortcodes (Single & Paired)

Note

Remember, Vento can print any return value from a Javascript expression, as well as run arbitrary JavaScript in templates through its {{> ...}} operator. In these cases, shortcodes may not be needed depending on your usage.

Single and Paired Shortcodes added via Eleventy's .addShortcode(), .addAsyncShortcode(), .addPairedShortcode() or .addAsyncPairedShortcode() will be automatically loaded into Vento.

When using shortcodes in your templates, write them like any other Vento tag:

{{ myShortcode }}

To pass arguments, add a space and your arguments, comma-separated. Arguments are interpreted as JavaScript so type-safety should be considered (quote strings, use booleans if your shortcode expects them, etc.)

{{ myShortcode 'arg1', 'arg2' }}
{{ myBooleanShortcode false, false, true }}
{{ myNumberShortcode 10, 20, 0 }}
{{ myObjectShortcode { key1: 'val1', key2: 'val2' } }}

For paired shortcodes, the syntax is the same, just add a closing tag. Paired shortcodes also accept arguments and can re-process nested Vento tags (including other shortcodes).

{{ codeBlock 'css' }} <!-- takes arguments too -->
  a {
    color: red;
  }
{{ /codeBlock }}

{{ blockQuote }}
  To be or not to be, that is the question.
  {{ attribute 'William Shakespeare' }} <!-- you can use vento syntax here too -->
{{ /blockQuote }}

If you'd prefer to set shortcodes yourself (via a plugin or other method) or prevent Eleventy from loading shortcodes into Vento, set shortcodes: false and/or pairedShortcodes: false in the plugin options.

Important

While it's straightforward to load filters via a Vento plugin that appends filters to the filters object as env.filters.[filter_name](), creating custom tags in Vento is more involved. It's highly advised to keep these two options enabled unless you know what you're doing.

Relevant Documentation

Eleventy: See Shortcodes and the sub-section on Paired Shortcodes.

Vento Plugins

Note

The auto_trim plugin that ships with Vento has a specific implementation in the scope of this plugin. See Auto-Trimming Tags for more details._

If you'd like to extend the Vento library with any plugins, include them in an array passed to the plugins option.

import { VentoPlugin } from 'eleventy-plugin-vento';

function myCustomPlugin() {
  // ...plugin code...
}

export default function (eleventyConfig) {
  eleventyConfig.addPlugin(VentoPlugin, {
    plugins: [myCustomPlugin],
  });
}

Auto-Trimming Tags

One exception to Vento plugins is the autoTrim plugin which is bundled with Vento, and by extension, this plugin. This plugin provides a convenient way to control whitespace in the output by collapsing spaces left behind when Vento's tags are removed.

To trim space around the default tags and all Eleventy paired shortcodes, set the autotrim plugin option to true.

eleventyConfig.addPlugin(VentoPlugin, {
  autotrim: true,
});

The default set of tags that are trimmed are defined by Vento itself. To set your own list of tags, set autotrim to an array of tags:

eleventyConfig.addPlugin(VentoPlugin, {
  autotrim: ['set', 'if', 'for'],
});

If instead, you'd like to extend instead of replace the default tag list, add the value @vento and/or @11ty. These placeholders will expand to the Vento default tags and Eleventy paired shortcode tags when the plugin executes.

import { VentoPlugin } from 'eleventy-plugin-vento';

eleventyConfig.addPlugin(VentoPlugin, {
  autotrim: {
    tags: ['@vento', '@11ty', 'tag'],
  },
});

Relevant documentation

Vento: See Auto Trim Plugin.

Debugging

Like Eleventy, this plugin uses the debug package to handle verbose logging. The following DEBUG namespaces are implemented:

  • Eleventy:Vento - Logs initial setup of the plugin, loading features, pre-page compile setup steps (like changing page and eleventy objects)
  • Eleventy:Vento:Cache - Logs updates to Vento's own internal cache, which is used in tandem with Eleventy's cache.
  • Eleventy:Vento:Render - Logs when templates are rendered

Because it is a child of the Eleventy: namespace, the following command will include output from this plugin as well:

$ DEBUG='Eleventy:*' npx @11ty/eleventy

Alternatively, use a finer grained namespace to see only the output generated by eleventy-plugin-vento.

$ DEBUG='Eleventy:Vento*' npx @11ty/eleventy
$ DEBUG='Eleventy:Vento:Template' npx @11ty/eleventy

Relevant Documentation

Eleventy: See Debug Mode.

Debug: See debug on npm.