# Taking control of the wpautop filter

WordPress does automatic paragraph formatting using the wpautop filter, some PHP code originally developed by Matt Mullenweg. For most of the time that this blog has existed, I’ve disabled the wpautop filter using the following two lines in my theme’s functions.php file:

remove_filter('the_content', 'wpautop');
remove_filter('the_excerpt', 'wpautop');

I’m not the only one to do this. But, I’m tired of having to manually type <p>s for every paragraph in every post that I write.

I’d like to be able have it back on, but preferably a bit smarter so that you don’t get all that crap (also common on bulletin boards with empty paragraphs around undetected block-level elements, especially if these are non-standard, related to plugins.

At the very least I want to be able to turn it off for when it does annoy me, on these moments that I don’t want auto-anything. Also, I need this if I don’t want to break the nearly 300 posts that I formatted manually. So, I want to use a custom field to turn the filter on or off.

I found an unpublished plugin (unpublished in the sense that the source isn’t hosted somewhere proper such as wordpress.org/extend/plugins/) which does some of what I want in a somewhat messy unmaintained manner. After years of just entering those damn <p>s (and over a year since this draft was in the making), I decided to do my own plugin for post-by-post (and global) control of the wpautop filter. It’s called wpautop-control:

<?php
/*
Plugin Name: wpautop-control
Plugin URI: http://blog.bigsmoke.us/tag/wpautop-control/
Description: This plugin allows you fine control of when and when not to enable the wpautop filter on posts.
Author: Rowan Rodrik van der Molen
Author URI: http://blog.bigsmoke.us/
Version: 1.0
*/

}

function wpautop_control_options() {
if (!current_user_can('manage_options'))  {
wp_die( __('You do not have sufficient permissions to access this page.') );
}

?>
<div class="wrap">
<h2>wpautop control options</h2>

<form method="post" action="options.php">
<?php settings_fields('wpautop-control') ?>
<table class="form-table">
<tr valign="top">
<th scope="row">wpautop filter on by default?</th>
<td>
<label><input type="radio" name="wpautop_on_by_default" value="1" <?php if ( get_option('wpautop_on_by_default') == '1' ) echo 'checked="1"' ?>> yes</label>
<label><input type="radio" name="wpautop_on_by_default" value="0" <?php if ( get_option('wpautop_on_by_default') == '0' ) echo 'checked="1"' ?>> no</label>
</td>
</table>

<p class="submit">
<input type="submit" class="button-primary" value="Save Changes" />
</p>
</form>
</div>
<?php
}

function wpautop_control_settings() {
register_setting('wpautop-control', 'wpautop_on_by_default', 'intval');
}
}

function wpautop_control_filter($content) { global$post;

// Get the keys and values of the custom fields:
$post_wpautop_value = get_post_meta($post->ID, 'wpautop', true);

$default_wpautop_value = get_option('wpautop_on_by_default');$remove_filter = false;
if ( empty($post_wpautop_value) )$remove_filter = ! $default_wpautop_value; elseif ($post_wpautop_value == 'true')
$remove_filter = false; elseif ($post_wpautop_value == 'false')
$remove_filter = true; if ($remove_filter ) {
remove_filter('the_content', 'wpautop');
remove_filter('the_excerpt', 'wpautop');
}

return \$content;
}
}

?>

(I’ve requested the plugin to be added to the WordPress plugin repository, so that it won’t have to be reinvented another 20 times in the next year or so.) 😉

After installing the plugin, you can choose whether to enable or disable wpautop by default. Then, for every post where you want to deviate from the default, you can set the wpautop custom field to ‘true’ or ‘false’.

I want the new default to be to enable the filter, but since all my old posts have been manually formatted, I want all these to have the wpautop field added and set to ‘false’.

Adding the appropriate custom field values to all existing posts is easy thanks to MySQL’s INSERT … SELECT syntax:

INSERT INTO wp_postmeta (post_id, meta_key, meta_value)
SELECT wp_posts.ID, 'wpautop', 'false'
FROM wp_posts
WHERE post_type = 'post';

1. On Oct 22, 2012 at 12:15

[…] the filter again, but I didn’t want this to affect all my old posts. Hence this plugin. See this blog post for more […]

2. Comment by David
On October 23, 2012 at 02:56

You are a great person.

3. Comment by John
On December 6, 2012 at 11:01

does this work for pages too, or only posts?

4. Comment by Rowan Rodrik
On December 6, 2012 at 18:45

Hi John, It should work on pages too. If it doesn’t, just let me know, and I’ll fix it.

On March 12, 2013 at 20:20

I have a rougue tag on our home page that i have no idea where or how to get rid of it?
Since pages are not html editable how do i track down and remove this nasty little tag that is keeping my slides from aligning top / sitting flush up to the header border?

6. Comment by rodrigo
On November 27, 2014 at 13:42

Hello everyone!
Could one of you guys explain to me how can I turn the wpautop off on one page?
How do I insert the tag in the page? I’m trying to draw a SVG image… and the s are just making my life soooo dificult.
Thanks!

7. Comment by rodrigo
On November 27, 2014 at 13:43

Hello everyone.
Could someone just write the tag here? To turn wpautop off?
Thanks!!
{"extraction_info": {"found_math": true, "script_math_tex": 0, "script_math_asciimath": 0, "math_annotations": 0, "math_alttext": 0, "mathml": 0, "mathjax_tag": 0, "mathjax_inline_tex": 1, "mathjax_display_tex": 0, "mathjax_asciimath": 1, "img_math": 0, "codecogs_latex": 0, "wp_latex": 0, "mimetex.cgi": 0, "/images/math/codecogs": 0, "mathtex.cgi": 0, "katex": 0, "math-container": 0, "wp-katex-eq": 0, "align": 0, "equation": 0, "x-ck12": 0, "texerror": 0, "math_score": 0.3011408746242523, "perplexity": 5652.373729397938}, "config": {"markdown_headings": true, "markdown_code": true, "boilerplate_config": {"ratio_threshold": 0.18, "absolute_threshold": 10, "end_threshold": 15, "enable": true}, "remove_buttons": true, "remove_image_figures": true, "remove_link_clusters": true, "table_config": {"min_rows": 2, "min_cols": 3, "format": "plain"}, "remove_chinese": true, "remove_edit_buttons": true, "extract_latex": true}, "warc_path": "s3://commoncrawl/crawl-data/CC-MAIN-2019-30/segments/1563195526714.15/warc/CC-MAIN-20190720214645-20190721000645-00380.warc.gz"}