Closed pixelastic closed 6 years ago
Correct: Universal filters do not yet support pug.
https://pugjs.org/language/filters.html#custom-filters
I think this would be a small task to add.
Any way I could help with that? Happy to submit a PR if you could point me toward examples for other templating languages.
Here are the exact steps that you’d need to do 😅
One concern that I do have before we move forward there is that the filters documentation actually kinda looks like tags, not filters. This is something that you might have more insight on than me, since you likely have more Pug experience?
Typically tags in other template langs look like {% myTag myArg %}
or a paired version {% myTag myArg %}myContent{% endmyTag %}
. You’re calling a function and passing in args and content. Whereas filters operate on and augment existing content {% myArg | myFilter %}
.
The weird part about reading these docs is that Pug filters seem more like Tags? Or maybe they just kind of operate like both?
Either way, I think that discussion will probably culminate in whether or not we would add Pug filters to the 11ty/eleventy#13 universal shortcode implementation too and probably won’t affect this immediate filter work.
Add method to add a single Pug filter to the config (this example goes through how it’s done for Liquid):
Add to the actual template engine in Pug.js (this is pointing to Liquid.js):
Looks like the filters
object will be added to getPugOptions
here:
Add a test to TemplateRenderPugTest.js
, here’s the Liquid example: https://github.com/11ty/eleventy/blob/master/test/TemplateRenderLiquidTest.js#L58
You have a fair point with the filter/tag difference. I don't have that much experience with pug (I actually never used filters, always used mixins in the past).
After reading the code you pointed my understanding is that eleventy already allows user to pass their own custom pug config to the pug engine. And that pug filters are defined through the options.filters
key, that will be read by eleventy.
My conclusion is that if I want to implement my own url
filter for pug files, I can just do it with the existing code, by using the pug engine options. It won't have the cleaner eleventyConfig.addFilter
or eleventyConfig.addPugFilter
API, but will still work. Is that correct?
What I'm still a bit unsure about is if I can read the eleventy config (to get access to the prefixPath) from my own custom pug filter, or would I need to have it wrapped as a real eleventy filter to have it?
Great observations!!
After reading the code you pointed my understanding is that eleventy already allows user to pass their own custom pug config to the pug engine. And that pug filters are defined through the options.filters key, that will be read by eleventy. My conclusion is that if I want to implement my own url filter for pug files, I can just do it with the existing code, by using the pug engine options. It won't have the cleaner eleventyConfig.addFilter or eleventyConfig.addPugFilter API, but will still work. Is that correct?
Yes, I believe that to be true too!
The main benefit to supplementing the eleventyConfig.addFilter
method with pug support is that all of the built-in universal filters would automatically be available in pug, automatically. So, you wouldn’t need to write your own url
filter?
If you’re stuck on writing your own url
filter for other reasons, there’s not much reason to use pathPrefix
at all is there? This is an eleventy config for the built-in url filter. If you’re not using the built-in url filter, then pathPrefix doesn’t buy you much ¯_(ツ)_/¯
I suppose if you’re mixing template engines in a project—but if you’re using the built-in url
filter in some places and not others—the universal filter support would be greatly preferred.
Lemme know if you want to PR Pug filter support—if not, I can do it—NBD!
So... I spent some more time on this and I'm hitting a wall here.
As you pointed, what Pug calls filters are not filters in the sense of pipeable operations on variables like Liquid has for example. Filters in pug are used to compile/transpile languages. Like converting CoffeeScript to JavaScript, syntax highlighting a piece of code or minifying CSS. One can use them for more trivial conversions (like adding a pathPrefix if needed), but in the end they are used to output markup and not variables. It means, that it is not possible to use them in HTML attribute, they have to be used at the HTML tag level...
Another similar mechanism offered by pug are mixins. The syntax is slightly different but they also are required to be used to output HTML markup and can't be used in attributes either.
The last mechanism provided by Pug is simply to declare a JavaScript function inside a pug template and use it immediatly
- function url(input) { return `/${input}.html` }
a(href=url('foo')) Content
<a href="/foo.html">Content</a>
I tried to hack into the Pug.js
engine file to inline the url
and slug
method before each pug content but as I'm inlining them as strings, I can't pass the methods easily (and it would have been a dirty hack anyway).
Pug being fully in JS, I wouldn't be surprised if there is a way to directly pass methods to be available in the global scope, but I could not find any mention of that in the doc. I found that it was possible to pass custom data (as json) using the CLI, so maybe it's possible to pass more but I haven't found how yet.
This proved more complex than I expected this to be, so I'm going to leave it there for now, until I find a way to pass custom methods to pug.
Our messages crossed :)
For the record, I managed to have the universal url
filter working as a pug filter. But this is no use as this cannot be used inside of an HTML attribute. In other words:
// This does not work, filters cannot be used in attributes
link(type="text/css", rel="stylesheet", href={url() /style.css})
// This works (<div>/{pathPrefix}/style.css</div>) but is not very useful :)
div
:url() /style.css
I don't even really need the url filter TBH, I thought I would when I submitted the issue initially, then found another way around. I still wanted to see if I could contribute, but I now think this might not be the easiest issue to start grasping the internals of eleventy :)
@pixelastic oh goodness, wow. That no-attributes limitation is a hefty one. Hmm, let’s sit on this for a bit. I really appreciate you looking at it!
This does kind of highlight the need to maybe expose these built-in universal filters as plugins that Eleventy consumes. That would make them at least require
-able if projects needed an escape hatch.
This repository is now using lodash style issue management for enhancements. This means enhancement issues will now be closed instead of leaving them open.
The enhancement backlog can be found here: https://github.com/11ty/eleventy/issues?utf8=%E2%9C%93&q=label%3Aneeds-votes+sort%3Areactions-%2B1-desc+
Anyone landing here, there is an easy tolution to this working right here - https://github.com/11ty/eleventy-plugin-template-languages/issues/1
Thanks for the solution, which in summary adds the eleventyConfig's magical "javascriptFunctions" object to globals,
globals.filters = eleventyConfig.javascriptFunctions
and then making pug treat that as a global object
eleventyConfig.setPugOptions( { globals: ['filters'] } ),
hence making pug recognise these expressions filters.myFunction()
The solution works for the list of "universal filters", like url, log, slug, and user filters added with addFilter(), but not for filters added for specific template languages.
For instance the eleventy-navigation 0.1.6 and older, filters were written with addNunjucksFilter, so they are excluded from the javascriptFunctions object. That plugin has already been updated to universal filters in its repo but not yet released. I guess it is best to recommend all plugin writers to only use universal filters from now on.
Anyone know how this translate to eleventy v3?
Hello,
I've started using 11ty recently and so far I'm impressed by how everything "just works".
Still, my first road block is adding CSS files to the website, and putting their inclusion path right in the layout. If I read the doc correctly, I need to use the
url
filter, but I don't think this is available for.pug
files.Can you confirm that's the case, and maybe provide another solution? Maybe just manually adding
pathPrefix
in my layout?Thanks a lot