Eleventy plugin which provides common filters, shortcodes and transforms for Fluid Project websites.
- Node >= 20
- Eleventy >= 3.0.0
- Infusion >= 4.7.1
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.eleventyConfig.js
), load the plugin as follows:
import fluidPlugin from "eleventy-plugin-fluid";
export default function (eleventyConfig) {
eleventyConfig.addPlugin(fluidPlugin);
};
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:
import fluidPlugin from "eleventy-plugin-fluid";
export default function (eleventyConfig) {
- eleventyConfig.addPlugin(fluidPlugin);
+ eleventyConfig.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.
eleventy-plugin-fluid
includes configuration for processing and bundling CSS files using LightningCSS,
and JavaScript files using esbuild.
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:
import fluidPlugin from "eleventy-plugin-fluid";
export default function (eleventyConfig) {
- eleventyConfig.addPlugin(fluidPlugin);
+ eleventyConfig.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.
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:
import fluidPlugin from "eleventy-plugin-fluid";
export default function (eleventyConfig) {
- eleventyConfig.addPlugin(fluidPlugin);
+ eleventyConfig.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
.
eleventy-plugin-fluid
adds support for localization using Eleventy's i18n plugin
and i18n-js
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:
import fluidPlugin from "eleventy-plugin-fluid";
export default function (eleventyConfig) {
- eleventyConfig.addPlugin(fluidPlugin);
+ eleventyConfig.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
.
The localization shortcodes included in eleventy-plugin-fluid
require a global data object
called translations
with the following shape:
{
"en": {
"hello": "Hello {{name}}!"
},
"fr": {
"hello": "Bonjour {{name}} !"
}
}
All content—collections or individual pages—must have a lang
data value corresponding to a configured language. This will
be automatically populated by the Eleventy internationalization plugin
based on the page's inputPath
or configured permalink,
falling back the configured defaultLanguage
.
eleventy-plugin-fluid
also provides four localization-related helpers:
__
is used to translate a string, substituting values for placeholders where
required. For example:
import { __ } from "eleventy-plugin-fluid";
console.log(__(
"hello",
{
"name": "world"
},
{
"lang": "fr",
"translations": {
"en": {
"hello": "Hello {{name}}!"
},
"fr": {
"hello": "Bonjour {{name}} !"
}
}
}
));
Result: Bonjour world !
The first parameter is the key for the translation string in the translations
object, the second parameter is an
object of values to substitute for placeholders in the translation string, and the third parameter is the data object
containing the lang
and translations
values. If the third parameter is not provided, the function will try to
retrieve these values from this.ctx
which provides access to Eleventy's global data.
eleventy-plugin-fluid
also provides a shortcode based on this function:
Nunjucks
{% __ 'hello', {name: 'world'} %}
11ty.js
module.exports = function ({ key, values }) {
return this.__(key, values);
};
Note: Using this function with Liquid requires extra work as Liquid shortcodes cannot accept a JSON object directly.
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:
import { EleventyI18nPlugin } from "@11ty/eleventy";
import { generatePermalink, __ } from "eleventy-plugin-fluid";
export default {
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 => {
// Only localize the permalink if the locale or translations global data are present.
if (data.hasOwnProperty("lang") || data.hasOwnProperty("translations")) {
return generatePermalink(data, "pages", __("pages", {}, data), __("pages", {}, data));
}
return generatePermalink(data, "pages", "pages", "pages");
}
}
};
In this example, the __
function is used
to localize the URL path for the collection.
The languageDirection
filter can be used to determin the language direction (ltr
or rtl
) for an input language:
Nunjucks
<html lang="{{ lang }}" dir="{{ lang | languageDirection }}">
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:
import fluidPlugin from "eleventy-plugin-fluid";
export default function (eleventyConfig) {
- eleventyConfig.addPlugin(fluidPlugin);
+ eleventyConfig.addPlugin(fluidPlugin, {
+ i18n: false
+ });
};
Note: if you do this, you will need to remove any uses of the __
helper in your project.
For additional information on setting up localization/internationalization, see:
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:
import fluidPlugin from "eleventy-plugin-fluid";
export default function (eleventyConfig) {
- eleventyConfig.addPlugin(fluidPlugin);
+ eleventyConfig.addPlugin(fluidPlugin, {
+ markdown: {
+ options: {
+ breaks: "true"
+ }
+ }
+ });
};
You can also enable markdown-it
plugins when
registering eleventy-plugin-fluid
as follows:
import fluidPlugin from "eleventy-plugin-fluid";
+ import markdownItDefList from "markdown-it-deflist";
+ import markdownItEmoji from "markdown-it-emoji";
export default function (eleventyConfig) {
- eleventyConfig.addPlugin(fluidPlugin);
+ eleventyConfig.addPlugin(fluidPlugin, {
+ markdown: {
+ plugins: [
+ // The imported plugin.
+ markdownItDefList,
+ // The imported plugin and an options object for the plugin.
+ [markdownItEmoji, {}]
+ ]
+ }
+ });
};
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.
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
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
Trims an array to the specified length.
{{ ["a", "b", "c"] | limit(2) | dump }}
Output: ["a", "b"]
Processes an input string using Markdown.
{{ "A paragraph with some _emphasis_." | markdown | safe }}
Output: <p>A paragraph with some <em>emphasis</em>.</p>\n
Processes an input string by lowercasing it, replacing whitespace with hyphens, and stripping special characters to create a URL-safe version.
NOTE: This filter has been completely removed as of eleventy-plugin-fluid 3.0.
Instead, use Eleventy's slugify
filter.
Splits an input string into an array based on a provided delimiter.
{{ "a,b,c" | split(",") | dump }}
Output: ["a", "b", "c"]
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.
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>
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">
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">
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>
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"></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.
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.
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
:
import fluidPlugin from "eleventy-plugin-fluid";
export default function (eleventyConfig) {
- eleventyConfig.addPlugin(fluidPlugin);
+ eleventyConfig.addPlugin(fluidPlugin, {
+ webc: {
+ components: "./src/_includes/**/*.webc"
+ }
+ });
};
eleventy-plugin-fluid
adds an HTML minify transform to output files with a .html
extension which minifies them
using html-minifier
.
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.
-
BREAKING:
eleventy-plugin-fluid
v3.x requires Eleventy v3.x and is written in ESM. See this post for upgrade information and guidance. -
BREAKING: The
markdown
filter has been removed. Please use the Eleventy Render plugin'srenderContent
filter instead.{% set string = "**Hi!** %} - {{ string | markdown | safe }} + {{ string | renderContent('md') | safe }}
-
BREAKING: The
renderString
shortcode has been removed. Please use the Eleventy Render plugin'srenderContent
filter instead:{% set string = "**Hi!** %} - {% renderString string, 'md' %} + {{ string | renderContent('md') | safe }}
-
BREAKING: The Eleventy WebC plugin is no longer included. If your project uses WebC, please follow the installation instructions to add the plugin.
-
BREAKING: Sass support is no longer included. If your project uses Sass, please install
eleventy-plugin-fluid-sass
.
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.
eleventy-plugin-fluid
is based on other publicly available software, categorized by license: