在可视化和超文本标记语言标签之间自由切换

时间:2013-09-24 作者:Thought Space Designs

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?

3 个回复
SO网友:Thought Space Designs

好吧,我已经对这个问题进行了大量的更新,它开始变得过载,所以我想我应该把它作为一个答案来写,即使它不是一个完整的答案。

根据@bueltge的回答推断,我实际上回去了,发现他之前的帖子有问题。在那篇文章中,列出了一个我以前从未见过的插件:“保留HTML编辑器标记”。这个插件已经有一段时间没有更新了,但我刚刚用WP 3.6.1测试了它,它功能齐全。该插件自动处理wpautop,为在可视化编辑器中插入br和p标记提供统一格式,并在选项卡之间切换时保留标记。

出于我自己的目的,我用自己的功能扩展了这个插件:自动转换“<;code>;”中的任何html标记保存时标记到各自的实体。这意味着您可以在文本选项卡中的代码标记中编写标准HTML代码,然后将其保存,pre标记中的所有内容将转换为实体,以便在网站前端和可视化编辑器中正确显示。这并不是我找到的最优雅的解决方案,但似乎有效。将此行添加到函数中。激活插件后的php:

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);
现在,只需在代码标记之间键入任何有效的HTML,保存时,当编辑器弹出时,它们都将转换为实体。这允许您更快地编写代码。现在,唯一仍然存在的问题是,如果您有一个“pre”字段,其中包含嵌套的代码标记和HTML,并且您转到visual选项卡并尝试在代码中插入新行,则br标记会被注入HTML中的代码标记中。在TinyMCE中必须有一个选项来禁用此功能。不管怎样,只要您从文本选项卡编辑预处理字段,就可以在选项卡之间自由切换,在任何选项卡下添加任何内容,从任何选项卡保存,并且不必担心格式混乱!

这实际上解决了我最初问题的所有5点。第二点仍然有点离谱,但我相信对于大多数人来说,这解决了这个问题。我确实计划在某个时候筛选这个插件并提取必要的部分,将其与我的发现相结合,然后重新打包以供公众下载。我的目标是创建一个简单的一键式安装插件,并按预期工作。

希望这对大家都有帮助!

SO网友:bueltge

首先,我认为这个问题在WP版本3.5之后就解决了;看见ticket 19666 in trac. 但是tinyMCE有一个钩子,它让我们有机会在编辑器中更改内容,并且您不能在前端解析输出。

一个小的源脚本。我没有用当前的WP版本进行测试,这是针对客户的旧解决方案。

通过插件添加此源代码并增强标记。html标记的函数检查<pre 如果存在,则将替换为标记。

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;
}

SO网友:Marecky

我有一个类似于OP的问题,但对我来说,保持<h1> 在里面<div>.这就是我在文本和视觉选项卡之间切换时想要保留的内容:h1 in div and with div inside

每次我切换标签<h1> 消失了。我做了很多搜索,对于Wordpress 4.7.3,我发现有很多过时的补丁。TinyMCE从版本3升级到了版本4。v.3的解决方案对v.4不起作用。在更多地搜索和阅读TinyMCE第4版原始文档后,我想出了解决方案,尤其是针对我的情况:

安装高级TinyMCE配置插件valid_children 设置为+div[h1],h1[div]indent=true, forced_root_block=falseschema=html5 (当我阅读时forced_root_block 描述我理解为wpautop 替换)因此我得到了这个(并且它可以抵抗标签切换)enter image description here

结束

相关推荐

如何防止tinyMCE编辑器在文本编辑器中完全加载?

我正在研究一个主题。其中部分有编辑模式:使用CodeMirror的语法新模式两种本机模式(视觉和文本编辑器)我有一个奇怪的场景,tinyMCE加载到文本编辑器上,这意味着按钮等类似于视觉编辑器。是否有一个WP挂钩,我可以使用它来防止它完全加载到文本编辑器中我只需要使用本机文本区域,而不需要这些tinyMCE功能。