WordPress: Disable Auto Paragraphing, wpautop() and clean_pre() Functions
When it comes to paragraphs, we can all say that WordPress is in love with them. After publishing a post every text block turns into a <p> code, every double <br /> disappears. Your so much worked post design gets ruined. Or does it?
With AutoP WordPress tries to correct errors, and makes the posts much more readable. Even though I had my share of problems, I don’t hate the wpautop. But when it comes to my <pre> tags, I had to do something.
While designing my new theme, I looked and tested lots of code highlighters, php, jquery, mootools, pear, etc etc… The one I choose was, Geshi. Not because others were bad in coding, but I already had too many CSS and JS links, I did not want to add a lot more just for the code highlighting. So, in short, I accepted the server side coding path.
My problems started here. Even though Geshi was working great with HTML characters, WordPress’s wpautop() and clean_pre() were changing my php code which included some html. Both these functions are located in wp-includes/formatting.php. But don’t temper the core file, there is a better way.
First there is no way of disabling the clean_pre function single-handedly, as it is called inside wpautop. But wpautop is called in a few WordPress filters, and not as a direct function. So, disabling these actions will remove two functions together. You’ll need to put these lines in your theme’s functions.php file:
// Remove WordPress Auto P remove_filter( 'the_content', 'wpautop' ); // Auto P is also called in these filters, I'm just adding these lines for your information. // If you want to disable them, uncomment // remove_filter( 'the_content', 'wpautop' ); // remove_filter( 'the_excerpt', 'wpautop' ); // remove_filter( 'comment_text', 'wpautop' ); // <-- Be careful with this one
Great, no more auto p… but wait my blog is messed up!
Now, all your double newlines, are double newlines, but not pharagraphs with breaks. If this is what you wanted, then great, mission accomplished. However, you might not be happy with what you are seeing. You can edit and enclose every pharagraph in every post you’ve published, or simply re-initialize a new wpautop function.
I’ll be using the slightly altered wpautop and clean_pre in here, so don’t get frightened by the length of the code.
// Remove WordPress Auto P remove_filter( 'the_content', 'wpautop' ); // And insert our new Auto P add_filter( 'the_content', 'eg_wpautop' ); function eg_wpautop($pee, $br = 1) { if ( trim($pee) === '' ) return ''; $pee = $pee . "\n"; // just to make things a little easier, pad the end $pee = preg_replace('|<br />\s*<br />|', "\n\n", $pee); // Space things out a little $allblocks = '(?:table|thead|tfoot|caption|col|colgroup|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li|select|option|form|map|area|blockquote|address|math|style|input|p|h[1-6]|hr|fieldset|legend|section|article|aside|hgroup|header|footer|nav|figure|figcaption|details|menu|summary)'; $pee = preg_replace('!(<' . $allblocks . '[^>]*>)!', "\n$1", $pee); $pee = preg_replace('!(</' . $allblocks . '>)!', "$1\n\n", $pee); $pee = str_replace(array("\r\n", "\r"), "\n", $pee); // cross-platform newlines if ( strpos($pee, '<object') !== false ) { $pee = preg_replace('|\s*<param([^>]*)>\s*|', "<param$1>", $pee); // no pee inside object/embed $pee = preg_replace('|\s*</embed>\s*|', '</embed>', $pee); } $pee = preg_replace("/\n\n+/", "\n\n", $pee); // take care of duplicates // make paragraphs, including one at the end $pees = preg_split('/\n\s*\n/', $pee, -1, PREG_SPLIT_NO_EMPTY); $pee = ''; foreach ( $pees as $tinkle ) $pee .= '<p>' . trim($tinkle, "\n") . "</p>\n"; $pee = preg_replace('|<p>\s*</p>|', '', $pee); // under certain strange conditions it could create a P of entirely whitespace $pee = preg_replace('!<p>([^<]+)</(div|address|form)>!', "<p>$1</p></$2>", $pee); $pee = preg_replace('!<p>\s*(</?' . $allblocks . '[^>]*>)\s*</p>!', "$1", $pee); // don't pee all over a tag $pee = preg_replace("|<p>(<li.+?)</p>|", "$1", $pee); // problem with nested lists $pee = preg_replace('|<p><blockquote([^>]*)>|i', "<blockquote$1><p>", $pee); $pee = str_replace('</blockquote></p>', '</p></blockquote>', $pee); $pee = preg_replace('!<p>\s*(</?' . $allblocks . '[^>]*>)!', "$1", $pee); $pee = preg_replace('!(</?' . $allblocks . '[^>]*>)\s*</p>!', "$1", $pee); if ($br) { $pee = preg_replace_callback('/<(script|style).*?<\/\\1>/s', '_autop_newline_preservation_helper', $pee); $pee = preg_replace('|(?<!<br />)\s*\n|', "<br />\n", $pee); // optionally make line breaks $pee = str_replace('<WPPreserveNewline />', "\n", $pee); } $pee = preg_replace('!(</?' . $allblocks . '[^>]*>)\s*<br />!', "$1", $pee); $pee = preg_replace('!<br />(\s*</?(?:p|li|div|dl|dd|dt|th|pre|td|ul|ol)[^>]*>)!', '$1', $pee); if (strpos($pee, '<pre') !== false) $pee = preg_replace_callback('!(<pre[^>]*>)(.*?)</pre>!is', 'eg_clean_pre', $pee ); $pee = preg_replace( "|\n</p>$|", '</p>', $pee ); return $pee; } function eg_clean_pre($matches) { if ( is_array($matches) ) $text = $matches[1] . $matches[2] . "</pre>"; else $text = $matches; $text = str_replace('<br />', '', $text); // I love this line, Geshi adds too many <br /> tags // I don't like this one -> $text = str_replace('<p>', "\n", $text); // I'm not fond of this one either -> $text = str_replace('</p>', '', $text); return $text; }
Now, I’ve removed the WordPress autop, and defined my own eg_wpautop(). I can change, remove or add new lines to the function.
You can see the clean_pre in work near the end:
if (strpos($pee, '<pre') !== false) $pee = preg_replace_callback('!(<pre[^>]*>)(.*?)</pre>!is', 'eg_clean_pre', $pee ); $pee = preg_replace( "|\n</p>$|", '</p>', $pee );
If you don’t want your pre tags get messed up, or your inline p and br tags -which even though are part of your code gets truncated- just remove these lines I commented out. You can also remove the pre tag from any preg_replace and $allblocks variable. For clean_pre, another solution is writing your very own function and assigning it to the preg_replace_callback. This was how I solved my code highlighting/Geshi problem.
Remove and change any line(s) you like from now on, experiment and see what difference it makes on your posts. I’m sure that 99% of the code, you’ll be keeping. It is a hell of a well written function















