So this question has been raised many times under different flags, however I’d like to present a unified thread for an ultimate solution to this issue.
In WordPress, by default, when switching back and forth between the HTML and Visual editors in TinyMCE, certain tags are stripped out of content, and other weird functionality occurs. Two known workarounds for writing more efficient HTML code are using removing the wp_auto_p function using filters, and installing TinyMCE Advanced & enabling the “stop removing p & br tags” option.
This only works so well, unfortunately.
Take, for instance, the following example:
<h2>How does it work?</h2>
<p>In order to use jQuery Easy Columns, you must install it as you would any other jQuery plugin. First, download the zip file using the button above. After downloading the file, extract it to a location of your choice, and move the extracted folder to your server using your favorite FTP client. After moving the plugin to your server (and of course calling the jQuery source into your document), call it in on your site using the following snippet of code:</p>
<pre>
<script type="text/javascript" src="/path/to/jquery.easycolumns.js"></script>
</pre>
If I type this code into the HTML editor, with both options listed above already enabled, then when I switch between the two different editors, nothing happens, which is expected. Unfortunately, when saving, the code automatically converts to this:
<h2>How does it work?</h2>
<p>In order to use jQuery Easy Columns, you must install it as you would any other jQuery plugin. First, download the zip file using the button above. After downloading the file, extract it to a location of your choice, and move the extracted folder to your server using your favorite FTP client. After moving the plugin to your server (and of course calling the jQuery source into your document), call it in on your site using the following snippet of code:</p>
<pre>
<script type="text/javascript" src="/path/to/jquery.easycolumns.js"></script>
</pre>
As you can see, all entities inside the pre tag are converted back into actual HTML characters. Then, if I save this same post again, I get something like the following:
<h2>How does it work?</h2>
<p>In order to use jQuery Easy Columns, you must install it as you would any other jQuery plugin. First, download the zip file using the button above. After downloading the file, extract it to a location of your choice, and move the extracted folder to your server using your favorite FTP client. After moving the plugin to your server (and of course calling the jQuery source into your document), call it in on your site using the following snippet of code:</p>
<pre><br />
<script type="text/javascript" src="/path/to/jquery.easycolumns.js"></script><br />
</pre>
Note that WordPress will actually inject br tags into the post. Needless to say, when this post has been updated a few times, when viewing it on the frontend, the display is nowhere near the intended display.
The only way I’ve seemed to get rid of all of the added “formatting functionality” has been to disable the Visual editor through my profile.
This is a fine solution for me, considering I’m a professional web developer. For my clients, this solution is far from elegant. My clients will, for the most part, be using the visual editor. A lot of my clients aren’t very tech savvy, and sometimes need me to fix their posts when the layout breaks. This limits me to using the visual editor, as I can’t change to the HTML editor without fear of breaking the layout.
Mainly, (and I think there’s a large community that could benefit from this answer), what explicit steps can I follow to ensure the following:
- A post can be edited from the Visual or HTML editor.
- A post’s content is not modified in any way when switching between the two tabs.
- When saving a post from the HTML editor, no extra content is added.
- When saving a post from the HTML editor, no entities are converted.
- BONUS: When saving a post from the HTML editor, any code (HTML for example) that’s wrapped inside a pre tag and not already converted to entities will be automatically converted to entities.
Essentially, if we can create the aforementioned behavior in TinyMCE through the use of a third party plugin, we can quell all other questions regarding false formatting through the use of TinyMCE. I feel that many people could benefit from this.
It just seems logical that there is a certain functionality one would expect from a WYSIWIG editor, and this goes against it. According to all logic and reason, WordPress’ built in formatting functions are pretty useless with their current setup. It seems to me that if they want to use these formatting options, their best bet would be to enable one editor or the other, not both.
AND PLEASE: Don’t answer this thread with workarounds and downloads for other WYSIWIG editors that ‘fix’ the problem. This is an underlying problem (although not truly a bug) with the WordPress core that needs to be corrected.
EDIT: Alright, I’ve been working on this and I’m thinking reverse engineering will be the best way to solve this issue. So for right now, I’ve disabled wpautop (which just for clarity is a function that hooks into “the_content” filter to add p and br tags before the text is displayed, not when the text is saved. I think there exists some confusion as to how this function operates. wpautop isn’t responsible for the changes you see happening when you switch between editor tabs. That’s something entirely different.
Anyway, I’ve disabled wpautop, as is good practice when you use the HTML editor. From that point, I disabled the visual editor to start first with the html entity errors that are present when saving a post. Thanks to the help of one C. Bavota, I found a snippet to convert any tags in the HTML editor to their equivalent entities before displaying them on the front end of the site (credit: http://bavotasan.com/2012/convert-pre-tag-contents-to-html-entities-in-wordpress/).
#add_filter( 'the_content', 'pre_content_filter', 0 );
/**
* Converts pre tag contents to HTML entities
*
* This function is attached to the 'the_content' filter hook.
*
* @author c.bavota
*/
function pre_content_filter( $content ) {
return preg_replace_callback( '|<pre.*>(.*)</pre|isU' , 'convert_pre_entities', $content );
}
function convert_pre_entities( $matches ) {
return str_replace( $matches[1], htmlentities($matches[1] ), $matches[0] );
}
add_filter( 'the_content', 'pre_content_filter', 10, 2 );
This effectively eliminates issues with WordPress converting all entities into tags upon save by circumventing it. Now, you can use the HTML editor, and write standard code in between “pre” tags without doing the entity conversion yourself. This takes care of all of the issues with entity conversion in WordPress, and makes sure everything displays correctly on the front end. Now, we need to figure out what to hook into to modify the behavior experienced when clicking back and forth between tabs. Right now, it would appear that when moving from the HTML to the visual tab, the contents of the HTML tab are interpreted by javascript or something to try to provide a live update of what the content should look like. This causes the tags (which are displayed in non entity form in the HTML tab) to be processed instead of displayed. Then, when switching back to the HTML tab, it would appear that TinyMCE passes the current data along. This means when you switch back, you lose your HTML structure. We need to figure out a way to tell TinyMCE to convert everything in pre tags to it’s equivalent entities before loading it into the window (essentially the backend version of what we did on the frontend but with tinymce and javascript instead of php and hooks), so that it’s displayed instead of processed. Suggestions?
EDIT 2:
After some more research, converting the entities in the pre tag when they are displayed works fine for content within the pre tag, but say I have a blog post with a line like this:
“Next, we need to add this line to our HTML file: <p>Hello, World!</p>”
Looking at this line, you can tell that the code is supposed to be displayed on the site, and not parsed, however when the post is saved, these entities get decoded on the next post edit load, and on every subsequent save they are saved as raw html tags, which causes them to be parsed on the front end. The only solution I can think of so far would be to write in similar code for the “code” tag as I’m using for the pre, and then just wrap small one liners in the “code” tag, and large chunks in the “pre” tag. Anybody have any other ideas?
Alright so I’ve already updated this question a ton and it’s starting to get overloaded, so I figured I’d write this as an answer even though it isn’t a full one.
Extrapolating from @bueltge’s answer, I actually went back and found his previous post in question. In that post, there was a plugin listed that I’ve never seen before: “Preserved HTML Editor Markup”. This plugin hasn’t been updated in a while, but I just tested it with WP 3.6.1 and it’s fully functional. This plugin automatically takes care of wpautop, provides a unified format for inserting br and p tags within the visual editor, and preserves your markup when switching between tabs.
For my own purposes, I expanded upon this plugin with my own functionality: automatic conversion of any html tags within “<code>” tags to their respective entities on save. This means you can write standard HTML code in code tags within the text tab, and then save it, and all the stuff in the pre tags will convert to entities for proper display on the front end of the site and the visual editor. It’s not the most elegant solution I’ve found yet, but it seems to work. Add this line to your functions.php after activating the plugin:
Now, just type any valid HTML in between code tags, and when you save, when the editor pops back up, they’ll all be converted to entities. This allows you to write code quicker. Now, the only thing that’s still an issue is that if you have a “pre” field with a nested code tag and HTML in it, and you go to the visual tab and try to insert a new line into the code, a br tag gets injected into your code tag in the HTML. There has to be an option to disable this in TinyMCE. Regardless, as long as you edit your pre fields from the text tab, you can feel free to switch freely between the tabs, add any content under any tab, save from either tab, and not have to worry about messed up formatting!
This actually solves all 5 points of my initial question. Point 2 is still a little bit flaky, but I believe for most peoples purposes, this takes care of the issue. I do plan on sifting through this plugin at some point and extracting the necessary parts, combining it with my finds, and repackaging it for public download. My goal here is to create a simple one click install plugin that wrks as expected.
Hope this helps everybody!
At first, I think this problem was solved since WP version 3.5; see ticket 19666 in trac. But the tinyMCE have a hook there give us the chance to change the content inside the editor and you must not parse on output on frontend.
A small source script. I have no test this with a current WP version, was a older solution for a customer.
Add this source via plugin and enhance the markup. The function check for the html-tag
<pre
and if exists, then will be replace with markup.I had a problem similar to OP, but for me there was an issue with keeping
<h1>
in<div>
.This is what I wanted to keep while switching between Text and Visual tabs:
Every time I switched tab
<h1>
disappeared. I did a lot of searching, and for WordPress 4.7.3 I found out there there is plenty of outdated fixes. There was a mayor upgrade of TinyMCE from version 3 to 4. Solutions for v.3 didn’t work out for v.4.After more googling and reading TinyMCE version 4 original documentation I came up with the solution for especially my case:
valid_children
setting to+div[h1],h1[div]
indent=true
,forced_root_block=false
andschema=html5
(when I readforced_root_block
description I understood it as awpautop
substitute)As a result I get this (and it is resistant to tabs switching)