-
-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Pug templates need better filter support #1
Comments
Why shouldn't filters be added as functions visible to pug, with For example, we can have |
// taking https://www.npmjs.com/package/eleventy-plugin-toc as an example
const pluginTOC = require('eleventy-plugin-toc');
const markdownIt = require('markdown-it')
const markdownItAnchor = require('markdown-it-anchor');
module.exports = function(eleventyConfig) {
eleventyConfig.setLibrary('md', markdownIt().use(markdownItAnchor));
eleventyConfig.addPlugin(pluginTOC);
global.filters = eleventyConfig.javascriptFunctions; // magic happens here
eleventyConfig.setPugOptions({ // and here
globals: ['filters']
});
};
aside.aPageNavigation!=filters.toc(content) or aside.aPageNavigation !{filters.toc(content)} And it works! dab noises Another example: {% set previousPost = collections.posts | getPreviousCollectionItem(page) %}
{% set nextPost = collections.posts | getNextCollectionItem(page) %}
{% if previousPost %}Previous Blog Post: <a href="{{ previousPost.url }}">{{ previousPost.data.title }}</a>{% endif %}
{% if nextPost %}Next Blog Post: <a href="{{ nextPost.url }}">{{ nextPost.data.title }}</a>{% endif %} becomes - var prev = filters.getPreviousCollectionItem(collections.posts, page)
- var next = filters.getNextCollectionItem(collections.posts, page)
if prev
a(href=prev.url)=prev.data.title
if next
a(href=next.url)=next.data.title |
I think it's worth mentioning that the above solution solves the problem just fine. Additionally, the built in eleventy filters that you see in so many of the docs' examples like: a(href=filters.url('/my-unsafe-url')) My Link That Will Be Correct |
@wolfejw86 @CosmoMyzrailGorynych Amazing!! The above should be in docs!! |
Has anyone taken a stab at this yet? 🤔 Adding a similar Adding an diff --git a/src/Engines/Pug.js b/src/Engines/Pug.js
index 100b0c6..6788254 100644
--- a/src/Engines/Pug.js
+++ b/src/Engines/Pug.js
@@ -13,6 +13,8 @@ class Pug extends TemplateEngine {
setLibrary(override) {
this.pugLib = override || PugLib;
this.setEngineLib(this.pugLib);
+
+ this.addFilters(this.config.pugFilters);
}
getPugOptions() {
@@ -27,6 +29,16 @@ class Pug extends TemplateEngine {
);
}
+ addFilters(filters) {
+ for (let name in filters) {
+ this.addFilter(name, filters[name]);
+ }
+ }
+
+ addFilter(name, filter) {
+ this.pugOptions.filters[name] = filter;
+ }
+
async compile(str, inputPath) {
let options = this.getPugOptions();
if (!inputPath || inputPath === "pug" || inputPath === "md") {
diff --git a/src/UserConfig.js b/src/UserConfig.js
index e639b0f..2755ad0 100644
--- a/src/UserConfig.js
+++ b/src/UserConfig.js
@@ -49,6 +49,7 @@ class UserConfig {
this.handlebarsPairedShortcodes = {};
this.javascriptFunctions = {};
this.pugOptions = {};
+ this.pugFilters = {};
this.ejsOptions = {};
this.markdownHighlighter = null;
this.libraryOverrides = {};
@@ -222,6 +223,24 @@ class UserConfig {
);
}
+ addPugFilter(name, callback) {
+ name = this.getNamespacedName(name);
+
+ if (this.pugFilters[name]) {
+ debug(
+ chalk.yellow(
+ "Warning, overwriting a Pug filter with `addPugFilter(%o)`."
+ ),
+ name
+ );
+ }
+
+ this.pugFilters[name] = this.benchmarks.config.add(
+ `"${name}" Pug filter`,
+ callback
+ );
+ }
+
addFilter(name, callback) {
debug("Adding universal filter %o", this.getNamespacedName(name));
@@ -232,6 +251,8 @@ class UserConfig {
// TODO remove Handlebars helpers in Universal Filters. Use shortcodes instead (the Handlebars template syntax is the same).
this.addHandlebarsHelper(name, callback);
+
+ this.addPugFilter(name, callback);
}
getFilter(name) {
@@ -239,7 +260,8 @@ class UserConfig {
this.javascriptFunctions[name] ||
this.nunjucksFilters[name] ||
this.liquidFilters[name] ||
- this.handlebarsHelpers[name]
+ this.handlebarsHelpers[name] ||
+ this.pugFilters[name]
);
}
@@ -768,6 +790,7 @@ class UserConfig {
handlebarsPairedShortcodes: this.handlebarsPairedShortcodes,
javascriptFunctions: this.javascriptFunctions,
pugOptions: this.pugOptions,
+ pugFilters: this.pugFilters,
ejsOptions: this.ejsOptions,
markdownHighlighter: this.markdownHighlighter,
libraryOverrides: this.libraryOverrides,
|
Because shakeelmohamed mentioned precedence for 11ty providing the global, it would be nice if pug users didn't require a userland solution. I think this would be a breaking change, but a very appreciated one as a pug user. |
I totally agree, @bever1337. |
I just tried to incorporate this solution but got the error "Cannot set property 'slug' of undefined (via TypeError)"
|
Hi @HerzogVonWiesel, the key word in my previous comment was |
Hey @shakeelmohamed, for sure! Wasn't expecting for it to work, just pointing out an issue I found so we know what to fix when working further on this :) |
(Psst! This Issue should be tagged with |
What changed in 11ty 2.0 to break this established solution? Is there something pug users should tweak? Edit: This could sound vague to non-pug users. I'll try and come up with a reproduction. I've got a lot of incentive to upgrade |
Currently I am getting around the problems in Pug filters by using them only in the frontmatter of a pug layout, as documented. E.g.
But this method fail when objects (not strings) need to be computed, such as the previous/next page links in a blog post:
For me this is the biggest weakness in the Pug + filter problem, a change in the template language from njk to pug requires major architectural redesign in the variables and expressions logic. Ideally the frontmatter "eleventyComputed" should allow one fixed liquid-based filter expressions which should work for both strings and objects, and this must be independent of the rest of the template language. |
Is your feature request related to a problem? Please describe.
One of the best feature of Eleventy is the ability to mix and match different template languages to produce a static site. This advantage falls short when some template languages are more empowered than others.
Currently Pug does not support Eleventy universal filters. This makes it difficult for Pug users to adapt to the Eleventy environment, or for a template in one language to be modified into a different language.
Describe the solution you'd like
In njk/liquid/md a data is evaluated like this: {{ myData | myFilter }}
In Pug a data is used like this: #{ myData }. It does not understand this expression #{ myData | myFilter } as only one variable name should be inside the parenthesis.
My solution is for Eleventy to run one pre-processing step in front of the Pug processing.
During this pre-processing step, Eleventy searches for these expressions #{ *** } and check if they need evaluation (whether there is a | inside the string):
if there is no filter, just skip this variable. It will be Pug's responsibility to perform substitution during run.
if there is a filter expression, Eleventy evaluates the filter and generate a temporary unique variable, and place the variable/value into the data stack, and replace the Pug template variable name.
As Eleventy is a compiler, data values can be determined without side effects during template evaluation. So the invention of temporary variables to store the evaluated eexpressions is safe.
Describe alternatives you've considered
Similar requests but that suggests a solution that requires extending Pug with user-customisation. In my opinion, that is a strategy that will lead to incompatibility between Pug and other template languages.
Additional context
I come into Eleventy because it is described as a "Jekyll in Nodejs". I tried to convert a complete site from Jekyll into Eleventy. Filters are the most problematic issues, as not all Jekyll filters have equivalent (eg. absolute_url, relative_url etc). But this is solveable by plugins.
Pug as my preferred template language further complicate the development, as it has only some of the expressive power of the other languages. Although I can rewrite the logic, I want to keep the Eleventy idioms as much as possible, and that means filters should be retained inside Pug.
The text was updated successfully, but these errors were encountered: