Expose Universal Filters and Shortcodes in configuration API (to load into custom engines that support them)
Is your feature request related to a problem? Please describe.
It would be nice to have access to a list of Universal Filters and Shortcodes in the configuration API. I just released eleventy-plugin-vento
v1 to add support for the Vento templating language by @oscarotero. Vento has the ability to use custom filters and tags, but retrieving these things from Eleventy via a plugin feels a bit brittle.
Currently my implementation is approximately as follows (shortened for brevity):
// Create empty sets to hold user defined functions
const filters = {};
const helperFunctions = {};
for (const fn in eleventyConfig.javascriptFunctions) {
if (
eleventyConfig.liquidFilters[fn] &&
(eleventyConfig.nunjucksFilters[fn] || eleventyConfig.nunjucksAsyncFilters[fn])
) {
filters[fn] = javascriptFunctions[fn];
} else {
helperFunctions[fn] = javascriptFunctions[fn];
}
}
and then farther down...
eleventyConfig.addExtension('vto', {
async compile(inputContent, inputPath) {
return async (data) => {
// Rebind functions to page data so this.page,
// this.eleventy, etc works as intended
for (const helper in helperFunctions) {
helperFunctions[helper] = helperFunctions[helper].bind(data);
}
// Rebind filters the same way
for (const filter in filters) {
VentoLib.filters[filter] = filters[filter].bind(data);
}
// Merge helpers into page data
data = { ...data, ...helperFunctions };
};
},
});
Note that this does not include shortcodes, as the helperFunctions
object seems to do the trick to handle single shortcodes.
Describe the solution you'd like
It would be great to be able to retrieve all filters at once via an eleventyConfig.universalFilters
call to make loading in easily.
As for single and paired shortcodes, it would be great to have similiar properties (eleventyConfig.universalShortcodes
/eleventyConfig.universalPairedShortcodes
) to achieve a similar result.
It would also be nice to have some sort of mechanism for adding page context data to filters/shortcodes in custom templating languages, although I'm not quite sure what that would look like beyond the .bind(data)
technique I used above since the bundled engines Eleventy ships with seem to rely on some internal methods to manage adding context to filters and shortcodes. I'm also curious if Eleventy does any sort of caching work when exposing this.page
and this.eleventy
contexts when running shortcodes and filters for bundled engines and if plugins could take advantage of that pipeline in some way.
Describe alternatives you've considered
As far as I know, there aren't any documented mechanisms to retrieve Universal Shortcodes/Filters. While there's plenty of ways to get data into the data cascade for custom templating languages (getData()
, getInstanceFromPath()
), retrieving data from the data cascade for custom templating languages outside of Eleventy's internal methods looks to be a bit harder to do.
My current approach gets close enough; merging javascriptFunctions()
into the data cascade and binding page data to this
since Vento can run JS directly. However, this doesn't handle paired shortcodes/custom tags, which is a feature I'd like to eventually have in Vento templates within Eleventy. This would require more filtering of eleventyConfig.javascriptFunctions
in order to extract the shortcodes and manually set up the integrations with Eleventy and Vento, which might be out-of-scope for what a plugin can do.
Additional context
With the deprecation of HAML, Handlebars, EJS, and Pug in core for v3 and some of them moving to plugin-land, I realize that I might be ahead of the curve here.
I'd be curious to know if there's a preferred way to integrate a filter-and-custom-tag-capable language with Eleventy's core functionality inside of a plugin. If not, will there be plans to do so to accommodate some of the templating languages being moved into plugins for v3?