Skip to content

Eleventy plugin which provides common filters, shortcodes and transforms for Fluid Project websites.

License

Notifications You must be signed in to change notification settings

greatislander/eleventy-plugin-fluid

 
 

Repository files navigation

eleventy-plugin-fluid

License: BSD 3-Clause Latest Release NPM Package codecov

Eleventy plugin which provides common filters, shortcodes and transforms for Fluid Project websites.

Requirements

  • Node >= 18
  • Eleventy >= 2.0.1
  • Infusion >= 4.6.0

Installation

Add eleventy-plugin-fluid to your Eleventy-based static site by running:

npx install-peerdeps eleventy-plugin-fluid

(You can also run npm install --save eleventy-plugin-fluid, but you'll then need to install the specified infusion peer dependency in your project as well; the install-peerdeps command handles both at the same time.)

Then, in your Eleventy configuration file (usually eleventy.config.js), load the plugin as follows:

const fluidPlugin = require("eleventy-plugin-fluid");

module.exports = function (config) {
    config.addPlugin(fluidPlugin);
};

Usage

For any options passed to eleventy-plugin-fluid in the configurations described below, you can override the default rather than merging with it by passing the option with override: as a prefix to the key. For example, to override the default options for the css configuration block, you could do the following:

const fluidPlugin = require("eleventy-plugin-fluid");

module.exports = function (config) {
-    config.addPlugin(fluidPlugin);
+    config.addPlugin(fluidPlugin, {
+        "override:css": {
+              // Your options here.
+        }
+    });
};

Note that if you don't override required defaults when using this method, your configuration will not be valid, so proceed with caution if you are using this technique.

Asset Handling

eleventy-plugin-fluid includes configuration for processing and bundling Sass and CSS files using Sass and LightningCSS, and JavaScript files using esbuild.

CSS

By default, any CSS files found in the ./src/assets/styles/ directory or its children will be processed unless the filename begins with an underscore (_). For this reason, if you are using CSS partials via the @import rule, you should name them according to the pattern _partial.css to prevent them from being transformed as standalone files (this convention will be familiar to those who have worked with Sass and Sass partials).

Options for LightningCSS may be modified by passing values to the css option when registering eleventy-plugin-fluid in your config:

const fluidPlugin = require("eleventy-plugin-fluid");

module.exports = function (config) {
-    config.addPlugin(fluidPlugin);
+    config.addPlugin(fluidPlugin, {
+        css: {
+              cssModules: true,
+        }
+    });
};

Default values are as follows:

let options = {
    /* Where should Eleventy look for CSS files to process? */
    basePath: `./${eleventyConfig.dir.input || "src"}/assets/styles`,
    /* Should CSS files be processed? */
    enabled: true,
    /* See: https://lightningcss.dev/minification.html */
    minify: true,
    /* Not yet supported, see https://github.com/fluid-project/eleventy-plugin-fluid/issues/170 */
    sourceMap: false,
    /* See: https://lightningcss.dev/transpilation.html#draft-syntax */
    drafts: {
        nesting: true
    },
    /* A Browserslist configuration string (see: https://browsersl.ist) */
    browserslist: "> 1%"
};

If you wish to disable CSS processing altogether, set the enabled key of the options.css object to false.

If you wish to disable Browserslist altogether, you can pass an empty array ([]) to the browserslist key.

For more options, see the LightningCSS docs.

Sass

Sass processing is disabled by default. When enabled, any Sass files with the .scss extension found in the ./src/assets/styles/ directory or its children will be processed unless the filename begins with an underscore (_). To enable Sass and disable CSS, add the following configuration when registering eleventy-plugin-fluid in your config:

const fluidPlugin = require("eleventy-plugin-fluid");

module.exports = function (config) {
-    config.addPlugin(fluidPlugin);
+    config.addPlugin(fluidPlugin, {
+        css: {
+              enabled: false
+        },
+        sass: {
+              enabled: true
+        }
+    });
};

Options for Sass may be modified by passing values to the sass option when registering eleventy-plugin-fluid in your config:

const fluidPlugin = require("eleventy-plugin-fluid");

module.exports = function (config) {
-    config.addPlugin(fluidPlugin);
+    config.addPlugin(fluidPlugin, {
+        css: {
+              enabled: false
+        },
+        sass: {
+              browserslist: '> 1.5%',
+              enabled: true
+        }
+    });
};

Default values are as follows:

let options = {
    /* Where should Eleventy look for Sass files to process? */
    basePath: `./${eleventyConfig.dir.input || "src"}/assets/styles`,
    /* Should Sass files be processed? */
    enabled: false,
    /* See: https://lightningcss.dev/minification.html */
    minify: true,
    /* Not yet supported, see https://github.com/fluid-project/eleventy-plugin-fluid/issues/170 */
    sourceMap: false,
    /* See: https://lightningcss.dev/transpilation.html#draft-syntax */
    drafts: {
        nesting: true
    },
    /* A Browserslist configuration string (see: https://browsersl.ist) */
    browserslist: "> 1%"
};

Note that all of these will be passed to LightningCSS, not Sass, with the exception of basePath, enabled, and sourceMap.

If you wish to disable Sass processing altogether, set the enabled key of the options.sass object to false.

If you wish to disable Browserslist altogether, you can pass an empty array ([]) to the browserslist key.

For more options, see the Sass and LightningCSS docs.

JavaScript

By default, any JavaScript files with the .js extension found in the ./src/assets/scripts/ directory or its children will be processed with esbuild unless the filename begins with an underscore (_).

Options for esbuild may be modified by passing values to the js option when registering eleventy-plugin-fluid in your config:

const fluidPlugin = require("eleventy-plugin-fluid");

module.exports = function (config) {
-    config.addPlugin(fluidPlugin);
+    config.addPlugin(fluidPlugin, {
+        js: {
+            target: "esnext"
+        }
+    });
};

Default values are as follows:

let options = {
    /* Where should Eleventy look for JavaScript files to process? */
    basePath: `./${eleventyConfig.dir.input || "src"}/assets/scripts`,
    /* Should JavaScript files be processed? */
    enabled: true,
    /* See: https://esbuild.github.io/api/#minify */
    minify: true,
    /* See: https://esbuild.github.io/content-types/#javascript */
    target: "es2020",
    basePath: `./${eleventyConfig.dir.output || "_site"}/assets/styles`
};

If you wish to disable JavaScript processing altogether, set the enabled key of the options.js object to false.

Localization

eleventy-plugin-fluid adds support for localization using Eleventy's i18n plugin and eleventy-plugin-i18n-gettext for string translation.

By default, the following languages are configured:

  • en
  • en-CA
  • en-US
  • es
  • fa
  • fr
  • pt-br

You can add support for additional languages by passing values to the supportedLanguages option when registering eleventy-plugin-fluid in your config:

const fluidPlugin = require("eleventy-plugin-fluid");

module.exports = function (config) {
-    config.addPlugin(fluidPlugin);
+    config.addPlugin(fluidPlugin, {
+        supportedLanguages: {
+            de: {
+                // The slug which will be used in URLs to content in this language.
+                slug: "de",
+                // The slug which will be used to localize UIO (see: https://docs.fluidproject.org/infusion/development/localizationinthepreferencesframework#specifying-a-localization)
+                uioSlug: "de",
+                // The direction of the language.
+                dir: "ltr",
+                // The endonym of the language.
+                name: "Deutsch"
+            }
+        }
+    });
};

eleventy-plugin-fluid provides the following global data:

{
  "defaultLanguage": "en",
  "defaultLanguageDir": "ltr",
  "supportedLanguages": {
      "en": {
          "slug": "en",
          "uioSlug": "en",
          "dir": "ltr",
          "name": "English"
      },
      "en-CA": {
          "slug": "en-ca",
          "uioSlug": "en_CA",
          "dir": "ltr",
          "name": "English (Canada)"
      },
      "en-US": {
          "slug": "en-us",
          "uioSlug": "en_US",
          "dir": "ltr",
          "name": "English (United States)"
      },
      "es": {
          "slug": "es",
          "uioSlug": "es",
          "dir": "ltr",
          "name": "Español"
      },
      "fa": {
          "slug": "fa",
          "uioSlug": "fa",
          "dir": "rtl",
          "name": "فارسی"
      },
      "fr": {
          "slug": "fr",
          "uioSlug": "fr",
          "dir": "ltr",
          "name": "Français"
      },
      "pt-BR": {
          "slug": "pt-br",
          "uioSlug": "pt_BR",
          "dir": "ltr",
          "name": "Português (Brasil)"
      }
  }
}

The defaultLanguage can be overridden by passing a new value to the defaultLanguage options key when registering eleventy-plugin-fluid.

By default, eleventy-plugin-fluid also configures a localesDirectory for eleventy-plugin-i18n-getttext as ./src/_locales. This can be overridden by passing a new value to the localesDirectory options key when registering eleventy-plugin-fluid.

eleventy-plugin-fluid also provides two localization-related helpers:

generatePermalink

generatePermalink is used to generate localized permalinks for a collection type, with full support for pagination. Here's an example, as used in an 11tydata.js file:

const { EleventyI18nPlugin } = require("@11ty/eleventy");
const { generatePermalink } = require("eleventy-plugin-fluid");
const { _ } = require("eleventy-plugin-i18n-gettext");

module.exports = {
    layout: "layouts/base.njk",
    eleventyComputed: {
        lang: data => EleventyI18nPlugin.LangUtils.getLanguageCodeFromInputPath(data.page.inputPath),
        langDir: data => data.supportedLanguages[data.lang].dir,
        locale: data => data.lang,
        permalink: data => {
            const locale = data.locale;
            return generatePermalink(data, "pages", _(locale, "pages"), _(locale, "page"));
        }
    }
};

In this example, eleventy-plugin-i18n-gettext is used to localize the URL path for the collection. The _() method provided by eleventy-plugin-i18n-gettext requires a variable called locale as its first parameter (see this issue).

localizeData

localizeData is used to localize directory data for a directory of content in a specific language (where the directory name is the language code). Here's an example, as used in an 11tydata.js file:

const { localizeData } = require("eleventy-plugin-fluid");

module.exports = () => {
    return localizeData({}, __dirname);
};

This helper is a wrapper for i18n.enhance11tydata.

Disabling String Translation

If you don't need string translation features in your project, you can disable string translation by setting the i18n option to false when registering eleventy-plugin-fluid in your config:

const fluidPlugin = require("eleventy-plugin-fluid");

module.exports = function (config) {
-    config.addPlugin(fluidPlugin);
+    config.addPlugin(fluidPlugin, {
+        i18n: false
+    });
};

Note that if you do this, you will need to remove any uses of the localizeData helper or eleventy-plugin-i18n-gettext functions in your project.

Additional Reference

For additional information on setting up localization/internationalization, see:

Markdown Configuration

eleventy-plugin-fluid amends Eleventy's default Markdown configuration as follows (for more information see markdown-it):

{
    "html": true,
    "linkify": true,
    "typographer": true
}

Options for Markdown may be modified by passing values to the markdown option when registering eleventy-plugin-fluid in your config:

const fluidPlugin = require("eleventy-plugin-fluid");

module.exports = function (config) {
-    config.addPlugin(fluidPlugin);
+    config.addPlugin(fluidPlugin, {
+        markdown: {
+            options: {
+                breaks: "true"
+            }
+        }
+    });
};

You can also enable markdown-it plugins when registering eleventy-plugin-fluid as follows:

const fluidPlugin = require("eleventy-plugin-fluid");

module.exports = function (config) {
-    config.addPlugin(fluidPlugin);
+    config.addPlugin(fluidPlugin, {
+        markdown: {
+            plugins: [
+                // The npm package name of the plugin, which must be installed in your project.
+                "markdown-it-emoji",
+                // The npm package name of the plugin, which must be installed in your project, and an options object for the plugin.
+                ["markdown-it-anchor", {}]
+            ]
+        }
+    });
};

Filters

All examples use the Nunjucks template language. Eleventy supports a number of other template languages; see Eleventy's documentation on filters for usage with different template languages.

formatDate

Formats a date string.

{{ "Sun Jun 21 2020 18:00:00 GMT-0300 (Atlantic Daylight Time)" | formatDate }}

Output: June 21st, 2020

Optionally, a locale parameter can be supplied to format a date in a locale other than English.

{{ "Sun Jun 21 2020 18:00:00 GMT-0300 (Atlantic Daylight Time)" | formatDate('fr') }}

Output: 21 juin 2020

isoDate

Formats a date string to ISO 8601 format.

{{ "Sun Jun 21 2020 18:00:00 GMT-0300 (Atlantic Daylight Time)") | isoDate }}

Output: 2020-06-21T21:00:00.000Z

limit

Trims an array to the specified length.

{{ ["a", "b", "c"] | limit(2) | dump }}

Output: ["a", "b"]

markdown

Processes an input string using Markdown.

{{ "A paragraph with some _emphasis_." | markdown | safe }}

Output: <p>A paragraph with some <em>emphasis</em>.</p>\n

slug (deprecated)

Processes an input string by lowercasing it, replacing whitespace with hyphens, and stripping special characters to create a URL-safe version.

NOTE: This filter is deprecated and the slug-filter.js file has been removed as of eleventy-plugin-fluid 1.0. Instead, use Eleventy's new slugify filter.

split

Splits an input string into an array based on a provided delimiter.

{{ "a,b,c" | split(",") | dump }}

Output: ["a", "b", "c"]

Shortcodes

All examples use the Nunjucks template language. Eleventy supports a number of other template languages; see Eleventy's documentation on shortcodes for usage with different template languages.

figure

Outputs a <figure> element with a <figcaption>. The first and second parameters in the opening tag of the shortcode are the image URL and alternative text respectively. Caption content, which can use Markdown, goes in between the opening and closing shortcode tags.

{% figure "/assets/image.png", "A description of this image." %}
An illustration of something, found [here](https://example.com).
{% endfigure %}

Output:

<figure>
    <img src="/assets/image.png" alt="A description of this image." />
    <figcaption>
        <p>An illustration of something, found <a href="https://example.com">here</a>.</p>
    </figcaption>
</figure>

renderString

Renders a string with a supported template engine using the Eleventy Render plugin. This can be particularly useful when front matter data from a template needs to be processed using Markdown.

---
title: About
subtitle: Learn about our [mission](/about/mission/), [vision](/about/vision/), and [values](/about/values/).
---
This is what we do.
<h1>{{ title }}</h1>
<div class="subtitle">
  {% renderString subtitle, "md" %}
</div>
{{ content | safe }}

Result:

<h1>About</h1>
<div class="subtitle">
  <p>Learn about our <a href="/about/mission/">mission</a>, <a href="/about/vision/">vision</a>, and <a href="/about/values/">values</a>.</p>
</div>
<p>This is what we do.</p>

By default, the following template formats are supported:

For example, you could enable Vue support when registering eleventy-plugin-fluid as follows:

const fluidPlugin = require("eleventy-plugin-fluid");
+ const eleventyVue = require("@11ty/eleventy-plugin-vue");

module.exports = function (config) {
+    config.addPlugin(eleventyVue);
-    config.addPlugin(fluidPlugin);
+    config.addPlugin(fluidPlugin, {
+        templateFormats: [
+            "vue"
+        ]
+    });
};

uioStyles

Outputs links to the required CSS assets for an instance of Infusion User Interface Options. Use this when you want the out-of-the-box/drop-in experience with UI Options styles overriding the site styles. This is the quickest way to start, but harder to customize and fit with your site's own styling.

{% uioStyles %}

Result:

<link href="/lib/infusion/src/framework/core/css/fluid.css" rel="stylesheet">
<link href="/lib/infusion/src/framework/preferences/css/Enactors.css" rel="stylesheet">
<link href="/lib/infusion/src/framework/preferences/css/PrefsEditor.css" rel="stylesheet">
<link href="/lib/infusion/src/framework/preferences/css/SeparatedPanelPrefsEditor.css" rel="stylesheet">

uioStyleProps

Outputs links to the required CSS assets for an instance of Infusion User Interface Options. This only includes the related CSS Custom Properties. Use this when you want to have control over how the enactor styles are applied.

See: Integrating UI Options Styling Preferences

{% uioStyleProps %}

Result:

<link href="/lib/infusion/src/framework/core/css/fluid.css" rel="stylesheet">
<link href="/lib/infusion/src/framework/preferences/css/Contrast_base.css" rel="stylesheet">
<link href="/lib/infusion/src/framework/preferences/css/EnhanceInputs_base.css" rel="stylesheet">
<link href="/lib/infusion/src/framework/preferences/css/Font_base.css" rel="stylesheet">
<link href="/lib/infusion/src/framework/preferences/css/PrefsEditor.css" rel="stylesheet">
<link href="/lib/infusion/src/framework/preferences/css/SeparatedPanelPrefsEditor.css" rel="stylesheet">

uioScripts

Outputs links to the required JavaScript assets for an instance of Infusion User Interface Options.

{% uioScripts %}

Result:

<link rel="preload" href="/lib/infusion/infusion-uio.js" as="script" />
<script src="/lib/infusion/infusion-uio.js"></script>

uioTemplate

Outputs the required HTML template markup for an instance of Infusion User Interface Options. This should used directly after the opening <body> tag.

{% uioTemplate %}

Result:

<div class="flc-prefsEditor-separatedPanel fl-prefsEditor-separatedPanel">
  <div class="fl-panelBar fl-panelBar-smallScreen" id ="Editorspace">
    <span class="fl-prefsEditor-buttons">
    <button class="flc-slidingPanel-toggleButton fl-prefsEditor-showHide"> Show/Hide</button>
    <button class="flc-prefsEditor-reset fl-prefsEditor-reset"><span class="fl-icon-undo"></span> Reset</button>
    </span>
  </div>
  <div class="flc-slidingPanel-panel flc-prefsEditor-iframe"></div>
  <div class="fl-panelBar fl-panelBar-wideScreen">
  <span class="fl-prefsEditor-buttons">
    <button class="flc-slidingPanel-toggleButton fl-prefsEditor-showHide"> Show/Hide</button>
      <button class="flc-prefsEditor-reset fl-prefsEditor-reset"><span class="fl-icon-undo"></span> Reset</button>
  </span>
  </div>
</div>

If you want to use a custom integration of User Interface Options, you can insert the required markup directly into your base template.

uioInit

Outputs the required JavaScript to initialize an instance of Infusion User Interface Options. This should used directly before the closing </body> tag.

{% uioInit %}

Result:

<script>
  fluid.uiOptions.multilingual(".flc-prefsEditor-separatedPanel", {
    "auxiliarySchema": {
        "terms": {
            "templatePrefix": "/lib/infusion/src/framework/preferences/html",
            "messagePrefix": "/lib/infusion/src/framework/preferences/messages"
        },
        "fluid.prefs.tableOfContents": {
            "enactor": {
                "tocTemplate": "/lib/infusion/src/components/tableOfContents/html/TableOfContents.html",
                "tocMessage": "/lib/infusion/src/framework/preferences/messages/tableOfContents-enactor.json",
                "ignoreForToC": {
                    "ignoreClass": ".flc-toc-ignore"
                }
            }
        }
    },
    "prefsEditorLoader": {
        "lazyLoad": true
    }
  });
</script>

Optionally, to support localization, you can pass in locale and direction arguments.

{% uioInit "fa", "rtl" %}

Result:

<script>
  fluid.uiOptions.multilingual(".flc-prefsEditor-separatedPanel", {
    "auxiliarySchema": {
        "terms": {
            "templatePrefix": "/lib/infusion/src/framework/preferences/html",
            "messagePrefix": "/lib/infusion/src/framework/preferences/messages"
        },
        "fluid.prefs.tableOfContents": {
            "enactor": {
                "tocTemplate": "/lib/infusion/src/components/tableOfContents/html/TableOfContents.html",
                "tocMessage": "/lib/infusion/src/framework/preferences/messages/tableOfContents-enactor.json",
                "ignoreForToC": {
                    "ignoreClass": ".flc-toc-ignore"
                }
            }
        }
    },
    "prefsEditorLoader": {
        "lazyLoad": true
    },
    "locale": "fa",
    "direction": "rtl"
  });
</script>

If you want to use a custom integration of User Interface Options, you can insert the required script tag directly into your base template.

Template Languages

WebC

eleventy-plugin-fluid adds the Eleventy WebC plugin for WebC support. By default, the plugin will look for WebC components in ./src/_components/**/*.webc. This, and other options, can be modified when registering eleventy-plugin-fluid:

const fluidPlugin = require("eleventy-plugin-fluid");

module.exports = function (config) {
-    config.addPlugin(fluidPlugin);
+    config.addPlugin(fluidPlugin, {
+        webc: {
+            components: "./src/_includes/**/*.webc"
+        }
+    });
};

Transforms

HTML Minify

eleventy-plugin-fluid adds an HTML minify transform to output files with a .html extension which minifies them using html-minifier.

Passthrough Copy

By default, eleventy-plugin-fluid copies the required assets for an instance of Infusion User Interface Options into the lib/infusion directory of the build directory.

Development

Releasing

This package uses Conventional Commits, enforced with commitlint. This facilitates releasing new versions of the package via Release Please. To cut a release, merge the current release pull request.

This will tag an appropriate semantic version based on the nature of the recent commits to the project and update the changelog.

You will then need to publish the updated version to the npm registry. This requires an npm account with appropriate maintainer permissions. To publish the package, run:

npm publish

For more information on publishing to npm, see the npm publish documentation.

Third Party Software in eleventy-plugin-fluid

eleventy-plugin-fluid is based on other publicly available software, categorized by license:

ISC License

MIT License

About

Eleventy plugin which provides common filters, shortcodes and transforms for Fluid Project websites.

Resources

License

Code of conduct

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • JavaScript 96.0%
  • Nunjucks 2.9%
  • Other 1.1%