posthtml-expressions icon indicating copy to clipboard operation
posthtml-expressions copied to clipboard

[Feature Request] : Filters

Open cossssmin opened this issue 4 years ago • 16 comments

Would be awesome if posthtml-expressions offered support for filters, like Nunjucks does.

So you could do stuff like:

locals: { greeting: 'hello there' }
<p>
  {{ greeting | capitalize }}
</p>
<p>
  Hello there
</p>

...or:

<div>{{ [1,2,3] | first }}</div>
<div>1</div>

cossssmin avatar Mar 12 '20 18:03 cossssmin

I am +1 for this. Just a question, does any other template lang provides similar features ?

anikethsaha avatar Mar 12 '20 18:03 anikethsaha

It would be even better if you could register your own filters.

So the plugin would come with built-in fitlters, but you could pass in a filters option:

require('posthtml-expressions')({
  filters: {
    upper: (str) => str.toUpperCase(),
    trim:  (str) => str.trim(),
    join: (array, separator) => array.join(separator)
  }
})

cossssmin avatar Mar 12 '20 18:03 cossssmin

I am +1 for this. Just a question, does any other template lang provides similar features ?

Besides Nunjucks and Jinja (which the former is inspired from), Liquid also has this. There might be others that I don't know of...

cossssmin avatar Mar 12 '20 18:03 cossssmin

Seems like a good feature to add !

anikethsaha avatar Mar 12 '20 18:03 anikethsaha

@cossssmin I like this idea and approach, there is a true feeling that we are creating our own Jinja or Django template

Scrum avatar Mar 23 '20 14:03 Scrum

Glad to hear it! 😊

Now, regarding development, I haven't looked into it, and I have a feeling it'll be pretty complicated (for me, at least) to get it working with that {{ variable | filterName }} syntax. Can you help with that?

For starters maybe we could do a <filter name="filterName"> tag, which you could use like so:

<filter name="uppercase">lorem ipsum</filter>

Result:

LOREM IPSUM

I can totally help with writing the built-in filters that it would include, I guess we could decide on what to port over from Liquid and Nunjucks?

Speaking about built-in filters, these will definitely not cover all needs, so I think the filters option mentioned above would be really, really useful.

cossssmin avatar Mar 23 '20 14:03 cossssmin

<filter name="filterName"> it seems very cumbersome considering that there may be several filters - it will clog HTML

{{ variable | filterName }} - I will make sketches in this direction, but most likely tomorrow))

Scrum avatar Mar 23 '20 14:03 Scrum

Forgot about multiple filters, so this needs to be taken into account.

For example:

{{ "foo\nbar" | striptags(true) | escape | nl2br }}

I think the <filter name=""> tag might still be useful:

  • allow using just one filter name and execute only that
  • instead of applying on a string, user could use this tag and apply a filter on an entire block of HTML

Thoughts?

cossssmin avatar Mar 23 '20 14:03 cossssmin

Thoughts?

So far vague

simple

<filter name="">string</filter>

nested 1

<filter name=""><filter name="">string</filter></filter>

nested 2

<filter name="">string<filter name="">string</filter></filter>

I think the filter to the line will be better

@anikethsaha @voischev What do you think ?

Scrum avatar Mar 23 '20 14:03 Scrum

Yep, I get someone could do that, but you wouldn't have to if we have both {{ var | filterName }} and the <filter> tag. You use the inline one on objects/strings, but for something like this you'd still need a tag, I think:

<filter name="capitalize">
  <section>
    <article>
      <h1>article title</h1>
      <p>lorem ipsum dolor sit amet</p>
    </article>
  </section>
</filter>

Result:

<section>
  <article>
    <h1>Article title</h1>
    <p>Lorem ipsum dolor sit amet</p>
  </article>
</section>

I think this is also why Jinja (docs) Nunjucks (docs) have a filter block. This way, you can apply a filter not just to your own markup, but to stuff that you include with posthtml-include or with posthtml-modules :)

cossssmin avatar Mar 23 '20 15:03 cossssmin

i think , <filter> can have more control over the HTML I guess. (not sure though)

I think we can have PoC for either or both so that we can discuss it with the implementation with just the built-in ones!

anikethsaha avatar Mar 23 '20 15:03 anikethsaha

i think , <filter> can have more control over the HTML I guess. (not sure though)

I think both are useful, as there are situations where you can't use the tag, and vice-versa - remember the @{{ }} + <raw> discussion we had? 🙂

cossssmin avatar Mar 23 '20 15:03 cossssmin

yes, seems like we need both ! 👍

anikethsaha avatar Mar 23 '20 15:03 anikethsaha

let's start with the tag just for the sake of simplicity ? or with the other one !

anikethsaha avatar Mar 23 '20 15:03 anikethsaha

Ok, let's try with tags,

  1. what will the filter chain look like?
  2. In what order to apply?
  3. Ignoring applied filters?
<filter name="capitalize | striptags(true) | escape | nl2br">
  <h1></h1>
  <filter name="!escape"><p></p></filter> // ignore filter escape ?
</filter>

left to right or right to left?

or

<filter name="capitalize">
  <filter name="striptags(true)">
    <filter name="escape">
      <h1></h1>
    </filter>
    <filter name="!capitalize"> // ignore filter capitalize
      <p></p>
    </filter>
  </filter>
</filter>

top to bottom or bottom to top?

Scrum avatar Mar 24 '20 06:03 Scrum

My feedback:

  1. If we go for the first one (multiple filters split by |), the second one would also be possible. I think it would be awesome to be able to call multiple filters on a block with a single filter tag, so I'm all for the first approach 👍

  2. I would say in order of appearance. So, apply the first filter in the attribute, then the next, and so on. I'm not saying LTR or RTL, as that might depend on the user's language and some editors support RTL. In order of appearance would also make it top to bottom or outside to inside, when nesting filters - I suppose this would be easier, instead of going up the tree?

  3. Really cool idea, didn't think of that! Would be very useful for opting out of applying some filter. I can imagine a loop block where you have several filters that format content, and you need to do it in an alternating fashion - so instead of doing double the work (applying another filter to undo the ~previous~ parent one; might not even be possible), it actually does less work. +1 for this!

cossssmin avatar Mar 24 '20 09:03 cossssmin