mmikkel / Retcon-Craft

A collection of powerful Twig filters for modifying HTML
MIT License
79 stars 9 forks source link

How to grab top level elements? #68

Closed brianrivet-tilt closed 5 months ago

brianrivet-tilt commented 5 months ago

Hi,

I'm having an issue where I am trying to grab top level p, ol, and ul tags in some content using Retcon and add a class to only the top level items. I am tryin to use the :not pseudoclass to make the correct selections, but I keep getting a twig error when I do so. Here's my code:

{{entry.elementContent|raw|retconAttr(['p:not(* > p)', 'ol:not(* > ol)', 'ul:not(* > ul)'], { 'class' : animClass }, false)}}

and the error I get says:

Expected ")", but <whitespace " " at 7> found.

I'm not sure what I'm doing that is causing the error, or if there is a different way to write the selector to get the selection I'm looking for. Can you help me with this?

This is stemming from using nested entries in a ckeditor field and the class being applied to p, ol, and ul tags in the nested entry content that I don't want it applied to. If I can't do this with just a selector, is there a way to have retcon only apply a filter to the output of the field itself and not to any nested elements in the field?

mmikkel commented 5 months ago

I just added something to Retcon that should make this a lot easier – support for the 'body' element selector.

In the context of Retcon operations; you can think of 'body' as the root node or wrapper for the HTML being operated on. This means that in combination with the child combinator (i.e. '>'), it's now possible to easily select top-level nodes only, i.e. by doing stuff like 'body > p' or similar.

If I'm understanding the intention of your code right, this means that to add the class animClass to all top-level <p>, <ul> and <ol> nodes only, you could refactor it to something like this:

{{ entry.elementContent|retconAttr(['body > p', 'body > ol', 'body > ul'], { 'class' : animClass }, false)}}
brianrivet-tilt commented 5 months ago

Works great! Thanks so much for addressing this so quickly!

mmikkel commented 5 months ago

Should I not have the raw filter there first?

No, the |raw filter is never necessary in front of Retcon filters. But, it also shouldn't hurt any.

Now, instead of it applying the class to all of the p, ul, and ol tags regardless of how deeply they are nested, it isn't applying it to any of them at all.

I just tested retconAttr() with an equivalent selector to yours, on the output from a CKEditor field with nested entries, and it works as expected on my end.

Could you add a {% dd entry.elementContent %} to your template and share the output (a screenshot is fine)?

brianrivet-tilt commented 5 months ago

sorry, you can disregard that previous comment. I got ahead of myself and made the code revision without updating the plugin. It works exactly as expected. Thanks!

mmikkel commented 5 months ago

Great, thanks for the follow-up!

christopherhealey commented 5 months ago

Works a charm @mmikkel thanks for adding this, really improves the editing experience.