If you’ve tried to use code samples in WordPress, you might have noticed unexpected behavior from the WYSIWYG editor. It will edit the whitespace inside of
<pre> tags, leaving you with some poorly formatted, hard-to-read code. Today, I set out to stop that.
What causes this?
Whenever the WYSIWYG editor opens, it sends the content of the post through a few filters. You can find most of these in
wp-includes/formatting.php. The culprit here is the function
wpautop. This function runs a long list of regular expressions to make your content a little prettier and better formatted. But we don’t want that to happen to our
<pre> tags; they’re pre-formatted. We want those left alone. To do that, I had to find a way to keep the content of the
<pre> element from going through that filter.
WordPress’s plugin system allows you to change its behavior without altering the core code, so you don’t have to re-alter it every time you upgrade. As easy as it would have been, in the short-term, to just edit
wpautop to make it behave properly, I wanted a longer-term solution that would be easier to share with other WordPress users. Therefore, a plugin.
Since a plugin can’t just intercept an arbitrary function call, you have to find a filter hook that can call your function at the appropriate time.
wpautop is called by
wp_richedit_pre, in turn, is hooked into the filter system through the hook
Finally, step one, cut
wp_richedit_pre from the
Step two, redirect
Replace that with a similar function that will call something other than
Here I create a new class to hold my plugin’s functions, aptly named
the_editor_content filter will call this class’s
preformat_intercept method, which will do the same thing as
wp_richedit_pre, but replace the call to
wpautop with a call to
Step three, recurse
safe_autop performs a pretty simple function.
- If there are no
<pre>tags in the text, it just sends everything on to
wpautopand returns the result.
- If the text starts with a
safe_autopsplits it into two parts, the
<pre>element and everything after the
<pre>element. The latter part is sent back through
safe_autopto let recursion run its course. The two parts are then stuck back together and returned.
- If there is a
<pre>tag anywhere else,
safe_autopsplits the text into two parts: everything before the
<pre>and everything else. Each half is sent back to
safe_autop, with the results stuck back together and returned. That means the part before the
<pre>will match the first case and be sent to
wpautop, the rest will match the second case and continue with the recursion.
So after all that, anything not in a
<pre> element goes through
wpautop; anything that is in a
<pre> element is left alone.
So now we’re in good shape, right? When WordPress opens the WYSIWYG editor,
<pre> elements are left alone, their whitespace untouched. But wait, there’s more!
Step four, gnashing of teeth
The WYSIWYG editor has both a “Visual” tab and “Code” tab. If you visit the “Code” tab, you can see all of the HTML for the post. When you go back to the “Visual” tab, the editor sends your content through
wpautop again (you might have changed something you shouldn’t have, after all). But this isn’t the same
Step five, intercept
old_wpautop, and redefine
wpautop to point to the
wp_print_scripts action hook to tell WordPress to run your script, and you’re all set.
If you’ve made it this far, here’s your reward: the Save My
<pre> WordPress plugin.
wpautop before mucking about with it. This didn’t cause any problems, other than throwing an exception. Version 1.1 is now available from the same place.
UPDATE (2008-03-12): Now also available from http://wordpress.org/extend/plugins/save-my-pre/.
UPDATE (2008-09-27): Recent versions of WordPress don’t eat whitespace like they used to. The WYSIWYG still eliminates any leading or trailing whitespace inside of a
<pre>, but everything else remains intact. That seems acceptible to me, so I see no reason to further maintain this plugin. Thanks to all who used it and commented.