verbb / shortcodes

Craft CMS 3 shortcode plugin

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Shortcodes in Redactor fields wrapped with <p>

joeydi opened this issue · comments

I've created a shortcode that includes a Twig template, which is working fine. My only issue is that the entire template contents are wrapped in a paragraph tag. Is there any way to avoid this?

I assume the shortcodes filter would need to be applied before any default filters for the Redactor field are applied, but I have no idea if that's possible. Any ideas?

@joeydi That's interesting. Will you post some example input and the twig template that handles the shortcode?

Visual editor:
Screen Shot 2019-07-09 at 3 14 04 PM

HTML editor:
Screen Shot 2019-07-09 at 3 14 17 PM

Template:

<div class="shortcode">
    <h1>Testing</h1>
</div>

Output:

<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim.</p>
<p>Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim.</p>
<p>
    <div class="shortcode">
        <h1>Testing</h1>
    </div>
    <br />
</p>

I'm guessing the issue is that Redactor automatically adds the paragraph tag for new lines. Even if I go into the HTML editor and remove the tags, when I save the post they are added back in.

Screen Shot 2019-07-09 at 3 24 13 PM

If I switch to the HTML editor and wrap the shortcode in a <div> the paragraph tag is not added, but that's not going to work for the content editors who are not expected to know HTML.

Ah right! I understand now. Unfortunately the parser doesn't pick up on surrounding text or tags but an extra replace filter before the shortcodes filter should work. Something like this:

{{ content | replace('/<p>[\\s\\r\\n]+?(\\[.+\\])[\\s\\r\\n]+?<\\/p>/', '$1') }}

That regular expression should handle situations where there might be extra spaces and line breaks (just in case) like:

<p>[careers]</p>
<p>  [careers]  </p>
<p>
    [careers]</p>

Let me know if that works and I'll update the documentation!

A quick fix. I see that there's <br /> tag inside the <p> tag pair. This updated replace will hopefully do the trick:

{{ content | replace('/<p>[\\s\\r\\n(?:<br ?\\/?>)]+?(\\[.+\\])[\\s\\r\\n(?:<br ?\\/?>)]+?<\\/p>/', '$1') }}
commented

Just stumbled across this issue and wanted to chip in

Scenario
I imported my Wordpress content (using Feedme) and my content was being imported into Craft into this mess:

Problem/Error

<p>[gallery type="columns" link="file" ids="</p>
<figure><img class="redactor-autoparser-object" src="blabla.jpg" data-image="uc3lak3dazik"></figure>
 <p>|"]</p>

Instead of being imported as :

[gallery type="columns" link="file" ids="blabla.jpg|(..possibly more image urls)"]

Solution
After some digging in, I figured that this kind of formatting had nothing to do with either of Feedme or Shortcodes but with Redactor. autoparse

I created a new config file inside config\redactor (named it Import.json) and turned off autoparse:

{
    "autoparse": false
}

Note This configuration needs to be selected into the Redactor field which you want this to take effect. By default, any new redactor field defined will take the settings named Default.

{{ content | replace('/<p>[\\s\\r\\n]+?(\\[.+\\])[\\s\\r\\n]+?<\\/p>/', '$1') }}

That regular expression should handle situations where there might be extra spaces and line breaks (just in case) like:

<p>[careers]</p>
<p>  [careers]  </p>
<p>
    [careers]</p>

A great suggestion Sam, thank you.

Would be great to have it supported as part of the | shortcodes filter to avoid manually doing this each time though.

We have created a secondary TWIG filter to handle it for the moment.

Also the following regex worked where the other didn't for us.

'/<p>[\s\R]*(\\[.+\\])[\s\R]*<\\/p>/'

@walshmichael I agree. I thought about adding it by default, but my gut tells me it would break people's existing stuff and wouldn't work in every situation.

I'm trying to think of the best approach. Perhaps a Twig filter included with the plugin that defaults to a regex like you posted, with the ability to override the regex? Open to any idea!

@samhernandez I do agree. I wouldn't suggest it be integrated into the existing | shortscodes filter for that reason also.

An additional core plugin Twig filter would just be a convenience so one can opt in or out of this behaviour without compiling their own extension per project.

This approach would fit most scenarios nicely, with the optional custom regex making it possible to filter block level elements for only certain shortcodes for more advanced requirements down to the end user.

Just need to come up with a new filter naming convention 🤔

Thanks for taking a look!

{{ content | replace('/<p>[\\s\\r\\n]+?(\\[.+\\])[\\s\\r\\n]+?<\\/p>/', '$1') }}

That regular expression should handle situations where there might be extra spaces and line breaks (just in case) like:

Would be great to have it supported as part of the | shortcodes filter to avoid manually doing this each time though.

I don't think this should be part of how shortcodes behaves. Simply because there are plenty of times where the wrapping element is required. For example within lists. There's nothing to suggest that having it within a paragraph would be unthinkable either. I've had this same issue but I solved it with a (albeit clunky) |replace filter.

That said, a |shortcodes-clean (or whatever) secondary filter would be an option. Like @walshmichael said.

Yep, certainly leaning towards a shortcodes-clean seperate filter to manage this.

Just so I'm following along, if you have a solo <p>[shortcode]</p> it should replace that with content-of-shortcode, stripping out the paragraph tags?

Yep, certainly leaning towards a shortcodes-clean seperate filter to manage this.

Just so I'm following along, if you have a solo <p>[shortcode]</p> it should replace that with content-of-shortcode, stripping out the paragraph tags?

Yes that makes the most sense imho. The question becomes how to handle things like <p dir="ltr">[shortcode]</p> for example. Imo, it should strip away all surrounding tags. There's a reason one would use a filter like that, after all.

Yup, I would assume any attributes would be ignored, and so long as the shortcode "code" is surrounded immediately by HTML tags, it strips them out.