This is an advanced tutorial so only try this if you are comfortable with Javascript and PHP. In addition, if you want to try it out, only do this on a test or staging site and NOT a production site.
One of the biggest problems with Gutenberg autop for me is that it messes up my code, WordPress shortcodes, and scripts. Most of my articles were written before Gutenberg, and if I edit any of them using Gutenberg, my code blocks get all their formatting totally messed up. This article describes a way to remove code, WordPress shortcodes, and scripts from being operated on by Gutenberg autop.
NOTE that it requires editing then replacing the default Gutenberg autop.js file with my own copy. I DO NOT overwrite the original file, but simply re-register my own edited autop.js file.
1. Create a Copy of the autop.js Gutenberg File
The Gutenberg autop.js file resides in wp-includes/js/dist. The first thing that I do is create a copy of that file in my own plugin or theme space. Then, I replace the default autop.js with my own copy by doing the following:
function admin_init() { global $current_screen; // If this is not the edit post page, then return. if (! isset( $current_screen ) || $current_screen->id !== 'post') return; // Entire page does not load when you try to dequeue wp-autop add_action( 'admin_enqueue_scripts', 'gutenberg_replace_scripts', 0 ); }
Line 4 – Only load in our edited autop.js file when in the edit post screen.
Line 7 – Add a function to do the file replacement. In this way, if we want to quickly go back to the WordPress default, we can easily do so by simply commenting out this one line of code.
function gutenberg_replace_scripts() { global $wp_scripts; $wp_scripts->registered['wp-autop']->src = MY_PLUGIN_URL. 'js/autop.js'; }
In the gutenberg_replace_scripts function I directly replace the source of the script. This is because some of the scripts have dependencies that may be lost if we try to deregister and then reregister the functions. In Line 3, use the url of your duplicate autop.js file. This is the one that we will edit, NOT the original or core file.
2. Protect Code, Shortcodes, and Scripts from autop
Within the core autop.js file, there is already a very elegant piece of code for doing this. Truly, my hats off to the person who produced this concise, readable, yet effective method for removing particular blocks of markup from autop and removep. I modified the existing code slightly to get it to remove shortcodes.
// Shiba - remove certain shortcodes const preserve = []; text = text.replace(/\[(php|html|css|js)\][\s\S]*?\[\/\1\]/g, match => { preserve.push(match); return '<wp-preserve>'; });
I use the Syntax Highlighter Evolved plugin to style my code blocks, so they are encapsulated within php, html, css, and js shortcodes. The code above extracts all such blocks, stores them in the preserve array, and then returns a wp-preserve marker to indicate the position of the removed block of shortcode. We will need this later when we restore our removed blocks. I put this code block at the top of the autop function BEFORE it really starts to process text.
I can also remove html code markups and scripts by using exactly the same method. I just slightly modify the regular expression to suit. This site has a lot of great information on regular expressions.
text = text.replace(/<(pre|code|script)[^>]*>[\s\S]*?<\/\1>/g, match => { preserve.push(match); return '<wp-preserve2>'; });
The code above removes pre, code, and script html blocks from being operated on by autop. I place this below my shortcode removal code.
Finally, at the end of autop, I need to restore all the blocks that I removed. To restore the shortcodes, code, and scripts, I do the following:
// Restore Shiba shortcodes and other pre/code elements if (preserve.length) { text = text.replace(/<wp-preserve>/g, () => { return ( preserve.shift() ); }); text = text.replace(/<wp-preserve2>/g, () => { return ( preserve.shift() ); }); }
I place the above code towards the end of the autop function AFTER it has finished its text replacements.
Line 2 – Check if we have any stored text in our preserve array.
Line 3 – If there is stored text, we find the first wp-preserve tag.
Line 5 – We replace that tag with the first block of stored text and so on until we have restored all the preserved blocks.
3. Repeat for Removep Function
I repeat the same process for the removep function in the same file. And that is it! This will remove the specified shortcodes and HTML blocks from being processed by Gutenberg autop and removep functions.
As a test, I wrote this entire article using the code view of the Gutenberg editor, with just free form text and shortcodes. Below is a screen shot of my Gutenberg code view. Note that the code blocks are untouched by autop and removep.
I had to do some additional tweaks to unescape the text, which I describe in this article on how the power of Gutenberg blocks can be combined with free form text. Rather than losing legacy content, this will enable us to enhance what we had before with the new power of blocks.
I have also translated the javascript replacement method above into PHP. Below is how I use it in PHP to apply autop on server side.
function the_content($content) { $content = preg_replace_callback('/\[(php|html|css|js|caption)[^\]]*\][\s\S]*?\[\/\1\]/', function($matches) { $this->preserve[] = $matches[0]; return '<wp-preserve>'; }, $content); $content = wpautop($content); if (count($this->preserve)) { $content = preg_replace_callback('/<wp-preserve>/', function($matches) { return array_shift($this->preserve); }, $content); } return $content; }
NOTE: The preserve functions above will only work with simple structures like shortcodes as well as HTML code and scripts. It WILL NOT work with nested structures such as nested Gutenberg blocks.
Happy Coding!