22

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>
&lt;script type=&quot;text/javascript&quot; src=&quot;/path/to/jquery.easycolumns.js&quot;&gt;&lt;/script&gt;
</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:

  1. A post can be edited from the Visual or HTML editor.
  2. A post's content is not modified in any way when switching between the two tabs.
  3. When saving a post from the HTML editor, no extra content is added.
  4. When saving a post from the HTML editor, no entities are converted.
  5. 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?

4
  • 2
    Nice post. That TinyMCE has caused me nothing but headaches. I've recently switched it out for CKEditor, though it's too soon to say how it's holding up. One problem you didn't mention in your post is the extra cr** when pasting from Word.
    – Twifty
    Commented Sep 24, 2013 at 18:08
  • I used CKeditor on our own site for a while thinking this was the solution I required, but unfortunately the issue at hand here lies with Wordpress' handling and formatting of the data it receives from TinyMCE, and not TinyMCE itself. There's gotta be a way to hook into Wordpress at the right time to create the desired effect. But regardless CKeditor is definitely a good plugin, just not what I'm looking for. Commented Sep 24, 2013 at 18:35
  • 1
    Also, you are aware of the "paste from word" feature in the "kitchen sink" of TinyMCE correct? That should take care of your issue with "extra crap" when pasting from Word. Commented Sep 24, 2013 at 19:42
  • 7
    Excellent question. To spice it up: I will reward the solution with a bounty of 200. I will wait until there is actually an answer, so the bounty doesn’t expire too early.
    – fuxia
    Commented Sep 24, 2013 at 23:46

3 Answers 3

5

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:

function code_content_conversion_filter( $content ) {
        return preg_replace_callback( '|<code.*>(.*)</code|isU' , 'convert_entities', $content );
}

function convert_entities( $matches ) {
        return str_replace( $matches[1], htmlspecialchars($matches[1], ENT_QUOTES | ENT_HTML5, 'UTF-8', FALSE ), $matches[0] );
}

add_filter( 'content_save_pre', 'code_content_conversion_filter', 0);

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!

3

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.

add_filter( 'tiny_mce_before_init', 'fb_correction_content_tiny_mce' );

function fb_correction_content_tiny_mce( $init ) {

    $init['setup'] = "function(ed) {
        ed.onBeforeSetContent.add( function(ed, o) {

            if ( o.content.indexOf('<pre') != -1 ) {
                o.content = o.content.replace(
                    /<pre[^>]*>[\\s\\S]+?<\\/pre>/g,
                    function(a) {
                        return a.replace(/(\\r\\n|\\n)/g, '<br />');
                    }
                );
            }
        } );
    }";

    return $init;
}
5
  • The issue that was solved in 3.5 isn't quite the same issue. The issue I have isn't that line breaks are stripped when switching from Visual to HTML, it's that all of my tags, even those in pre tags, seem to be interpreted as source HTML and not display as they aren't encoded as entities in the HTML panel. Will this function modify the behavior of TinyMCE so that the HTML in pre's will be displayed instead of processed? Commented Sep 25, 2013 at 15:36
  • In a small test works this, the entities will leave on switch from html to visual, also back and with save content.
    – bueltge
    Commented Sep 26, 2013 at 12:32
  • I'll test this later on today to make sure it accomplishes what I'm looking for. Commented Sep 26, 2013 at 13:06
  • OK, wait for your reply and maybe it helps. I have tested this with the source from your example on the question. If I understand it not right, please enhance this here.
    – bueltge
    Commented Sep 26, 2013 at 17:09
  • See my answer... Commented Sep 27, 2013 at 0:30
0

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: h1 in div and with div inside

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:

  1. Install Advanced TinyMCE Configuration plugin
  2. set TinyMCE valid_children setting to +div[h1],h1[div]
  3. I additonnaly configured indent=true, forced_root_block=false and schema=html5 (when I read forced_root_block description I understood it as a wpautop substitute)

As a result I get this (and it is resistant to tabs switching) enter image description here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.