Stray closing paragraph tag when using shortcodes

I’m using a basic shortcode to wrap some text in an expandable div. What appears to be happening is that the wpautop is inserting a stray closing paragraph tag at the beginning and a stray opening paragraph tag at the end of the content being wrapped.

Here’s how it looks in the editor:

Read More

[expandable text=”Show Content”]

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras
fermentum facilisis malesuada. Suspendisse potenti. Aenean dui turpis,
ornare in ipsum eget, vestibulum egestas nulla.

[/expandable]

And the rendered HTML:

<div class="expandable"><a href="#" class="expand-link">Show Content</a></p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras fermentum facilisis malesuada. Suspendisse potenti. Aenean dui turpis, ornare in ipsum eget, vestibulum egestas nulla.</p>
<p></div>

This is the shortcode function:

function expandable_content_shortcode( $atts, $content = null ) {
    $args = shortcode_atts( array(
        'text' => __( 'View More', $this->plugin_slug ),
        'linklocation' => 'top'
    ), $atts, 'expandable' );

    if ( $args['linklocation'] === 'top' ) {
        $output = '<div class="expandable-content"><a href="#" class="expand-link">' . $args['text'] . '</a>' . $content . '</div>';
    } else {
        $output = '<div class="expandable-content">' . $content . '<a href="#" class="expand-link">' . $args['text'] . '</a></div>';
    }

    return $output;
}

Related posts

2 comments

  1. This is frustrating issue as I can’t depend on the content editors to be savvy enough with WordPress / HTML to understand how the text they input will be parsed…

    –EDIT–

    Having thought of this a bit more I have reconsidered my earlier answer. HTML5+ comes with the Tidy extension, if you are able to use this on your server then the following will work:

    function cleanUpAutoP($content)
        {
            $tidy = new Tidy();
            // Switch out the encoding an doctype in $tidyArgs to suit your use case
            // 'show-body-only' HTML to be parsed as a fragment
            // rather than a whole document
            $tidyArgs = array(  'doctype' => 'html',
                                'input-encoding' => 'utf8',
                                'output-encoding' => 'utf8',
                                'show-body-only' => true
                        );
            // Return the repaired string
            return $tidy->repairString($content, $tidyArgs);
        }
    

    This way you can enjoy all the benefits of sweet, sweet P tags without the fear that wpautop will have messed something up. Further options for $tidyArgs can be seen in the documentation.

    If Tidy is not available for whatever reason this should still work:

    function cleanUpAutoP($content) {
    
        // Replace all OPENING paragraph tags with <br /><br />
        $content = preg_replace('/<p[^>]*>/', '<br /><br />', $content);
    
        // Remove all CLOSING p tags
        $content = str_replace('</p>', '', $content);
    
    
        return $content;
    }
    

    The obvious drawback of the latter method that I cannot apply styles to p tags in shortcodes, but until a better solution comes along, or the issue is fixed in WordPress, it will do!

  2. Install the WP RAW HTML plugin.

    This inserts extra check boxes to the the right of each post in the admin – check the box that says ‘Disable automatic paragraph creation’, this will solve your problem.

    But make sure you have surrounded content on that post with the correct

    tags.

    You can do this by removing a filter, but this solution allows you to only disable it when required and is much easier.

Comments are closed.