WordPress.org

Make WordPress Core

Changeset 32899


Ignore:
Timestamp:
06/21/2015 10:00:42 PM (6 years ago)
Author:
azaozz
Message:

Update the TinyMCE initialization:

  • Replace wp_htmledit_pre() and wp_richedit_pre() with format_for_editor().
  • Replace the 'htmledit_pre' and 'richedit_pre' filters with 'format_for_editor'.
  • Do not run the post content through wpautop() in PHP when the visual editor is default. Run the textarea content through the JS wpautop on initializing TinyMCE.
  • Simplify both editors initialization.
  • Improve setting of wpActiveEditor in Quicktags.
  • Improve editor.js, use tinymce.$ when possible.

See #32425.

Location:
trunk/src
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-admin/css/edit.css

    r32841 r32899  
    424424.mce-fullscreen #wp-content-wrap .mce-statusbar {
    425425    visibility: visible !important;
     426}
     427
     428.mce-fullscreen #wp-content-wrap .mce-tinymce .mce-wp-dfw {
     429    display: none;
    426430}
    427431
  • trunk/src/wp-admin/js/editor.js

    r31186 r32899  
    1 /* global tinymce, tinyMCEPreInit, QTags, setUserSetting */
    2 
    3 window.switchEditors = {
    4 
    5     switchto: function( el ) {
    6         var aid = el.id,
    7             l = aid.length,
    8             id = aid.substr( 0, l - 5 ),
    9             mode = aid.substr( l - 4 );
    10 
    11         this.go( id, mode );
    12     },
    13 
    14     // mode can be 'html', 'tmce', or 'toggle'; 'html' is used for the 'Text' editor tab.
    15     go: function( id, mode ) {
    16         var t = this, ed, wrap_id, txtarea_el, iframe, editorHeight, toolbarHeight,
    17             DOM = tinymce.DOM; //DOMUtils outside the editor iframe
    18 
    19         id = id || 'content';
    20         mode = mode || 'toggle';
    21 
    22         ed = tinymce.get( id );
    23         wrap_id = 'wp-' + id + '-wrap';
    24         txtarea_el = DOM.get( id );
    25 
    26         if ( 'toggle' === mode ) {
    27             if ( ed && ! ed.isHidden() ) {
    28                 mode = 'html';
    29             } else {
    30                 mode = 'tmce';
    31             }
    32         }
    33 
    34         function getToolbarHeight() {
    35             var node = DOM.select( '.mce-toolbar-grp', ed.getContainer() )[0],
     1
     2( function( $ ) {
     3    function SwitchEditors() {
     4        var tinymce, $$,
     5            exports = {};
     6
     7        function init() {
     8            if ( ! tinymce && window.tinymce ) {
     9                tinymce = window.tinymce;
     10                $$ = tinymce.$;
     11
     12                $$( document ).on( 'click', function( event ) {
     13                    var id, mode,
     14                        target = $$( event.target );
     15
     16                    if ( target.hasClass( 'wp-switch-editor' ) ) {
     17                        id = target.attr( 'data-wp-editor-id' );
     18                        mode = target.hasClass( 'switch-tmce' ) ? 'tmce' : 'html';
     19                        switchEditor( id, mode );
     20                    }
     21                });
     22            }
     23        }
     24
     25        function getToolbarHeight( editor ) {
     26            var node = $$( '.mce-toolbar-grp', editor.getContainer() )[0],
    3627                height = node && node.clientHeight;
    3728
     
    4334        }
    4435
    45         if ( 'tmce' === mode || 'tinymce' === mode ) {
    46             if ( ed && ! ed.isHidden() ) {
    47                 return false;
    48             }
    49 
    50             if ( typeof( QTags ) !== 'undefined' ) {
    51                 QTags.closeAllTags( id );
    52             }
    53 
    54             editorHeight = txtarea_el ? parseInt( txtarea_el.style.height, 10 ) : 0;
    55 
    56             if ( tinyMCEPreInit.mceInit[ id ] && tinyMCEPreInit.mceInit[ id ].wpautop ) {
    57                 txtarea_el.value = t.wpautop( txtarea_el.value );
    58             }
    59 
    60             if ( ed ) {
    61                 ed.show();
    62 
    63                 // No point resizing the iframe in iOS
    64                 if ( ! tinymce.Env.iOS && editorHeight ) {
    65                     toolbarHeight = getToolbarHeight();
    66                     editorHeight = editorHeight - toolbarHeight + 14;
    67 
    68                     // height cannot be under 50 or over 5000
    69                     if ( editorHeight > 50 && editorHeight < 5000 ) {
    70                         ed.theme.resizeTo( null, editorHeight );
    71                     }
    72                 }
    73             } else {
    74                 tinymce.init( tinyMCEPreInit.mceInit[id] );
    75             }
    76 
    77             DOM.removeClass( wrap_id, 'html-active' );
    78             DOM.addClass( wrap_id, 'tmce-active' );
    79             DOM.setAttrib( txtarea_el, 'aria-hidden', true );
    80             setUserSetting( 'editor', 'tinymce' );
    81 
    82         } else if ( 'html' === mode ) {
    83 
    84             if ( ed && ed.isHidden() ) {
    85                 return false;
    86             }
    87 
    88             if ( ed ) {
    89                 if ( ! tinymce.Env.iOS ) {
    90                     iframe = DOM.get( id + '_ifr' );
    91                     editorHeight = iframe ? parseInt( iframe.style.height, 10 ) : 0;
    92 
    93                     if ( editorHeight ) {
    94                         toolbarHeight = getToolbarHeight();
    95                         editorHeight = editorHeight + toolbarHeight - 14;
     36        function switchEditor( id, mode ) {
     37            id = id || 'content';
     38            mode = mode || 'toggle';
     39
     40            var editorHeight, toolbarHeight, iframe,
     41                editor = tinymce.get( id ),
     42                wrap = $$( '#wp-' + id + '-wrap' ),
     43                $textarea = $$( '#' + id ),
     44                textarea = $textarea[0];
     45
     46            if ( 'toggle' === mode ) {
     47                if ( editor && ! editor.isHidden() ) {
     48                    mode = 'html';
     49                } else {
     50                    mode = 'tmce';
     51                }
     52            }
     53
     54            if ( 'tmce' === mode || 'tinymce' === mode ) {
     55                if ( editor && ! editor.isHidden() ) {
     56                    return false;
     57                }
     58
     59                if ( typeof( window.QTags ) !== 'undefined' ) {
     60                    window.QTags.closeAllTags( id );
     61                }
     62
     63                editorHeight = parseInt( textarea.style.height, 10 ) || 0;
     64
     65                if ( editor ) {
     66                    editor.show();
     67
     68                    // No point resizing the iframe in iOS
     69                    if ( ! tinymce.Env.iOS && editorHeight ) {
     70                        toolbarHeight = getToolbarHeight( editor );
     71                        editorHeight = editorHeight - toolbarHeight + 14;
    9672
    9773                        // height cannot be under 50 or over 5000
    9874                        if ( editorHeight > 50 && editorHeight < 5000 ) {
    99                             txtarea_el.style.height = editorHeight + 'px';
     75                            editor.theme.resizeTo( null, editorHeight );
    10076                        }
    10177                    }
    102                 }
    103 
    104                 ed.hide();
    105             } else {
    106                 // The TinyMCE instance doesn't exist, run the content through 'pre_wpautop()' and show the textarea
    107                 if ( tinyMCEPreInit.mceInit[ id ] && tinyMCEPreInit.mceInit[ id ].wpautop ) {
    108                     txtarea_el.value = t.pre_wpautop( txtarea_el.value );
    109                 }
    110 
    111                 DOM.setStyles( txtarea_el, {'display': '', 'visibility': ''} );
    112             }
    113 
    114             DOM.removeClass( wrap_id, 'tmce-active' );
    115             DOM.addClass( wrap_id, 'html-active' );
    116             DOM.setAttrib( txtarea_el, 'aria-hidden', false );
    117             setUserSetting( 'editor', 'html' );
    118         }
    119         return false;
    120     },
    121 
    122     _wp_Nop: function( content ) {
    123         var blocklist1, blocklist2,
    124             preserve_linebreaks = false,
    125             preserve_br = false;
    126 
    127         // Protect pre|script tags
    128         if ( content.indexOf( '<pre' ) !== -1 || content.indexOf( '<script' ) !== -1 ) {
    129             preserve_linebreaks = true;
    130             content = content.replace( /<(pre|script)[^>]*>[\s\S]+?<\/\1>/g, function( a ) {
    131                 a = a.replace( /<br ?\/?>(\r\n|\n)?/g, '<wp-line-break>' );
    132                 a = a.replace( /<\/?p( [^>]*)?>(\r\n|\n)?/g, '<wp-line-break>' );
    133                 return a.replace( /\r?\n/g, '<wp-line-break>' );
     78                } else {
     79                    tinymce.init( window.tinyMCEPreInit.mceInit[id] );
     80                }
     81
     82                wrap.removeClass( 'html-active' ).addClass( 'tmce-active' );
     83                $textarea.attr( 'aria-hidden', true );
     84                window.setUserSetting( 'editor', 'tinymce' );
     85
     86            } else if ( 'html' === mode ) {
     87                if ( editor && editor.isHidden() ) {
     88                    return false;
     89                }
     90
     91                if ( editor ) {
     92                    if ( ! tinymce.Env.iOS ) {
     93                        iframe = editor.iframeElement;
     94                        editorHeight = iframe ? parseInt( iframe.style.height, 10 ) : 0;
     95
     96                        if ( editorHeight ) {
     97                            toolbarHeight = getToolbarHeight( editor );
     98                            editorHeight = editorHeight + toolbarHeight - 14;
     99
     100                            // height cannot be under 50 or over 5000
     101                            if ( editorHeight > 50 && editorHeight < 5000 ) {
     102                                textarea.style.height = editorHeight + 'px';
     103                            }
     104                        }
     105                    }
     106
     107                    editor.hide();
     108                } else {
     109                    // The TinyMCE instance doesn't exist, show the textarea
     110                    $textarea.css({ 'display': '', 'visibility': '' });
     111                }
     112
     113                wrap.removeClass( 'tmce-active' ).addClass( 'html-active' );
     114                $textarea.attr( 'aria-hidden', false );
     115                window.setUserSetting( 'editor', 'html' );
     116            }
     117        }
     118
     119        // Replace paragraphs with double line breaks
     120        function removep( html ) {
     121            var blocklist = 'blockquote|ul|ol|li|table|thead|tbody|tfoot|tr|th|td|h[1-6]|fieldset',
     122                blocklist1 = blocklist + '|div|p',
     123                blocklist2 = blocklist + '|pre',
     124                preserve_linebreaks = false,
     125                preserve_br = false;
     126
     127            if ( ! html ) {
     128                return '';
     129            }
     130
     131            // Protect pre|script tags
     132            if ( html.indexOf( '<pre' ) !== -1 || html.indexOf( '<script' ) !== -1 ) {
     133                preserve_linebreaks = true;
     134                html = html.replace( /<(pre|script)[^>]*>[\s\S]+?<\/\1>/g, function( a ) {
     135                    a = a.replace( /<br ?\/?>(\r\n|\n)?/g, '<wp-line-break>' );
     136                    a = a.replace( /<\/?p( [^>]*)?>(\r\n|\n)?/g, '<wp-line-break>' );
     137                    return a.replace( /\r?\n/g, '<wp-line-break>' );
     138                });
     139            }
     140
     141            // keep <br> tags inside captions and remove line breaks
     142            if ( html.indexOf( '[caption' ) !== -1 ) {
     143                preserve_br = true;
     144                html = html.replace( /\[caption[\s\S]+?\[\/caption\]/g, function( a ) {
     145                    return a.replace( /<br([^>]*)>/g, '<wp-temp-br$1>' ).replace( /[\r\n\t]+/, '' );
     146                });
     147            }
     148
     149            // Pretty it up for the source editor
     150            html = html.replace( new RegExp( '\\s*</(' + blocklist1 + ')>\\s*', 'g' ), '</$1>\n' );
     151            html = html.replace( new RegExp( '\\s*<((?:' + blocklist1 + ')(?: [^>]*)?)>', 'g' ), '\n<$1>' );
     152
     153            // Mark </p> if it has any attributes.
     154            html = html.replace( /(<p [^>]+>.*?)<\/p>/g, '$1</p#>' );
     155
     156            // Separate <div> containing <p>
     157            html = html.replace( /<div( [^>]*)?>\s*<p>/gi, '<div$1>\n\n' );
     158
     159            // Remove <p> and <br />
     160            html = html.replace( /\s*<p>/gi, '' );
     161            html = html.replace( /\s*<\/p>\s*/gi, '\n\n' );
     162            html = html.replace( /\n[\s\u00a0]+\n/g, '\n\n' );
     163            html = html.replace( /\s*<br ?\/?>\s*/gi, '\n' );
     164
     165            // Fix some block element newline issues
     166            html = html.replace( /\s*<div/g, '\n<div' );
     167            html = html.replace( /<\/div>\s*/g, '</div>\n' );
     168            html = html.replace( /\s*\[caption([^\[]+)\[\/caption\]\s*/gi, '\n\n[caption$1[/caption]\n\n' );
     169            html = html.replace( /caption\]\n\n+\[caption/g, 'caption]\n\n[caption' );
     170
     171            html = html.replace( new RegExp('\\s*<((?:' + blocklist2 + ')(?: [^>]*)?)\\s*>', 'g' ), '\n<$1>' );
     172            html = html.replace( new RegExp('\\s*</(' + blocklist2 + ')>\\s*', 'g' ), '</$1>\n' );
     173            html = html.replace( /<li([^>]*)>/g, '\t<li$1>' );
     174
     175            if ( html.indexOf( '<option' ) !== -1 ) {
     176                html = html.replace( /\s*<option/g, '\n<option' );
     177                html = html.replace( /\s*<\/select>/g, '\n</select>' );
     178            }
     179
     180            if ( html.indexOf( '<hr' ) !== -1 ) {
     181                html = html.replace( /\s*<hr( [^>]*)?>\s*/g, '\n\n<hr$1>\n\n' );
     182            }
     183
     184            if ( html.indexOf( '<object' ) !== -1 ) {
     185                html = html.replace( /<object[\s\S]+?<\/object>/g, function( a ) {
     186                    return a.replace( /[\r\n]+/g, '' );
     187                });
     188            }
     189
     190            // Unmark special paragraph closing tags
     191            html = html.replace( /<\/p#>/g, '</p>\n' );
     192            html = html.replace( /\s*(<p [^>]+>[\s\S]*?<\/p>)/g, '\n$1' );
     193
     194            // Trim whitespace
     195            html = html.replace( /^\s+/, '' );
     196            html = html.replace( /[\s\u00a0]+$/, '' );
     197
     198            // put back the line breaks in pre|script
     199            if ( preserve_linebreaks ) {
     200                html = html.replace( /<wp-line-break>/g, '\n' );
     201            }
     202
     203            // and the <br> tags in captions
     204            if ( preserve_br ) {
     205                html = html.replace( /<wp-temp-br([^>]*)>/g, '<br$1>' );
     206            }
     207
     208            return html;
     209        }
     210
     211        // Similar to `wpautop()` in formatting.php
     212        function autop( text ) {
     213            var preserve_linebreaks = false,
     214                preserve_br = false,
     215                blocklist = 'table|thead|tfoot|caption|col|colgroup|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li|pre' +
     216                    '|form|map|area|blockquote|address|math|style|p|h[1-6]|hr|fieldset|legend|section' +
     217                    '|article|aside|hgroup|header|footer|nav|figure|figcaption|details|menu|summary';
     218
     219            // Normalize line breaks
     220            text = text.replace( /\r\n|\r/g, '\n' );
     221
     222            if ( text.indexOf( '\n' ) === -1 ) {
     223                return text;
     224            }
     225
     226            if ( text.indexOf( '<object' ) !== -1 ) {
     227                text = text.replace( /<object[\s\S]+?<\/object>/g, function( a ) {
     228                    return a.replace( /\n+/g, '' );
     229                });
     230            }
     231
     232            text = text.replace( /<[^<>]+>/g, function( a ) {
     233                return a.replace( /[\n\t ]+/g, ' ' );
    134234            });
    135         }
    136 
    137         // keep <br> tags inside captions and remove line breaks
    138         if ( content.indexOf( '[caption' ) !== -1 ) {
    139             preserve_br = true;
    140             content = content.replace( /\[caption[\s\S]+?\[\/caption\]/g, function( a ) {
    141                 return a.replace( /<br([^>]*)>/g, '<wp-temp-br$1>' ).replace( /[\r\n\t]+/, '' );
     235
     236            // Protect pre|script tags
     237            if ( text.indexOf( '<pre' ) !== -1 || text.indexOf( '<script' ) !== -1 ) {
     238                preserve_linebreaks = true;
     239                text = text.replace( /<(pre|script)[^>]*>[\s\S]+?<\/\1>/g, function( a ) {
     240                    return a.replace( /\n/g, '<wp-line-break>' );
     241                });
     242            }
     243
     244            // keep <br> tags inside captions and convert line breaks
     245            if ( text.indexOf( '[caption' ) !== -1 ) {
     246                preserve_br = true;
     247                text = text.replace( /\[caption[\s\S]+?\[\/caption\]/g, function( a ) {
     248                    // keep existing <br>
     249                    a = a.replace( /<br([^>]*)>/g, '<wp-temp-br$1>' );
     250                    // no line breaks inside HTML tags
     251                    a = a.replace( /<[^<>]+>/g, function( b ) {
     252                        return b.replace( /[\n\t ]+/, ' ' );
     253                    });
     254                    // convert remaining line breaks to <br>
     255                    return a.replace( /\s*\n\s*/g, '<wp-temp-br />' );
     256                });
     257            }
     258
     259            text = text + '\n\n';
     260            text = text.replace( /<br \/>\s*<br \/>/gi, '\n\n' );
     261            text = text.replace( new RegExp( '(<(?:' + blocklist + ')(?: [^>]*)?>)', 'gi' ), '\n$1' );
     262            text = text.replace( new RegExp( '(</(?:' + blocklist + ')>)', 'gi' ), '$1\n\n' );
     263            text = text.replace( /<hr( [^>]*)?>/gi, '<hr$1>\n\n' ); // hr is self closing block element
     264            text = text.replace( /\s*<option/gi, '<option' ); // No <p> or <br> around <option>
     265            text = text.replace( /<\/option>\s*/gi, '</option>' );
     266            text = text.replace( /\n\s*\n+/g, '\n\n' );
     267            text = text.replace( /([\s\S]+?)\n\n/g, '<p>$1</p>\n' );
     268            text = text.replace( /<p>\s*?<\/p>/gi, '');
     269            text = text.replace( new RegExp( '<p>\\s*(</?(?:' + blocklist + ')(?: [^>]*)?>)\\s*</p>', 'gi' ), '$1' );
     270            text = text.replace( /<p>(<li.+?)<\/p>/gi, '$1');
     271            text = text.replace( /<p>\s*<blockquote([^>]*)>/gi, '<blockquote$1><p>');
     272            text = text.replace( /<\/blockquote>\s*<\/p>/gi, '</p></blockquote>');
     273            text = text.replace( new RegExp( '<p>\\s*(</?(?:' + blocklist + ')(?: [^>]*)?>)', 'gi' ), '$1' );
     274            text = text.replace( new RegExp( '(</?(?:' + blocklist + ')(?: [^>]*)?>)\\s*</p>', 'gi' ), '$1' );
     275            text = text.replace( /\s*\n/gi, '<br />\n');
     276            text = text.replace( new RegExp( '(</?(?:' + blocklist + ')[^>]*>)\\s*<br />', 'gi' ), '$1' );
     277            text = text.replace( /<br \/>(\s*<\/?(?:p|li|div|dl|dd|dt|th|pre|td|ul|ol)>)/gi, '$1' );
     278            text = text.replace( /(?:<p>|<br ?\/?>)*\s*\[caption([^\[]+)\[\/caption\]\s*(?:<\/p>|<br ?\/?>)*/gi, '[caption$1[/caption]' );
     279
     280            text = text.replace( /(<(?:div|th|td|form|fieldset|dd)[^>]*>)(.*?)<\/p>/g, function( a, b, c ) {
     281                if ( c.match( /<p( [^>]*)?>/ ) ) {
     282                    return a;
     283                }
     284
     285                return b + '<p>' + c + '</p>';
    142286            });
    143         }
    144 
    145         // Pretty it up for the source editor
    146         blocklist1 = 'blockquote|ul|ol|li|table|thead|tbody|tfoot|tr|th|td|div|h[1-6]|p|fieldset';
    147         content = content.replace( new RegExp( '\\s*</(' + blocklist1 + ')>\\s*', 'g' ), '</$1>\n' );
    148         content = content.replace( new RegExp( '\\s*<((?:' + blocklist1 + ')(?: [^>]*)?)>', 'g' ), '\n<$1>' );
    149 
    150         // Mark </p> if it has any attributes.
    151         content = content.replace( /(<p [^>]+>.*?)<\/p>/g, '$1</p#>' );
    152 
    153         // Separate <div> containing <p>
    154         content = content.replace( /<div( [^>]*)?>\s*<p>/gi, '<div$1>\n\n' );
    155 
    156         // Remove <p> and <br />
    157         content = content.replace( /\s*<p>/gi, '' );
    158         content = content.replace( /\s*<\/p>\s*/gi, '\n\n' );
    159         content = content.replace( /\n[\s\u00a0]+\n/g, '\n\n' );
    160         content = content.replace( /\s*<br ?\/?>\s*/gi, '\n' );
    161 
    162         // Fix some block element newline issues
    163         content = content.replace( /\s*<div/g, '\n<div' );
    164         content = content.replace( /<\/div>\s*/g, '</div>\n' );
    165         content = content.replace( /\s*\[caption([^\[]+)\[\/caption\]\s*/gi, '\n\n[caption$1[/caption]\n\n' );
    166         content = content.replace( /caption\]\n\n+\[caption/g, 'caption]\n\n[caption' );
    167 
    168         blocklist2 = 'blockquote|ul|ol|li|table|thead|tbody|tfoot|tr|th|td|h[1-6]|pre|fieldset';
    169         content = content.replace( new RegExp('\\s*<((?:' + blocklist2 + ')(?: [^>]*)?)\\s*>', 'g' ), '\n<$1>' );
    170         content = content.replace( new RegExp('\\s*</(' + blocklist2 + ')>\\s*', 'g' ), '</$1>\n' );
    171         content = content.replace( /<li([^>]*)>/g, '\t<li$1>' );
    172 
    173         if ( content.indexOf( '<option' ) !== -1 ) {
    174             content = content.replace( /\s*<option/g, '\n<option' );
    175             content = content.replace( /\s*<\/select>/g, '\n</select>' );
    176         }
    177 
    178         if ( content.indexOf( '<hr' ) !== -1 ) {
    179             content = content.replace( /\s*<hr( [^>]*)?>\s*/g, '\n\n<hr$1>\n\n' );
    180         }
    181 
    182         if ( content.indexOf( '<object' ) !== -1 ) {
    183             content = content.replace( /<object[\s\S]+?<\/object>/g, function( a ) {
    184                 return a.replace( /[\r\n]+/g, '' );
    185             });
    186         }
    187 
    188         // Unmark special paragraph closing tags
    189         content = content.replace( /<\/p#>/g, '</p>\n' );
    190         content = content.replace( /\s*(<p [^>]+>[\s\S]*?<\/p>)/g, '\n$1' );
    191 
    192         // Trim whitespace
    193         content = content.replace( /^\s+/, '' );
    194         content = content.replace( /[\s\u00a0]+$/, '' );
    195 
    196         // put back the line breaks in pre|script
    197         if ( preserve_linebreaks ) {
    198             content = content.replace( /<wp-line-break>/g, '\n' );
    199         }
    200 
    201         // and the <br> tags in captions
    202         if ( preserve_br ) {
    203             content = content.replace( /<wp-temp-br([^>]*)>/g, '<br$1>' );
    204         }
    205 
    206         return content;
    207     },
    208 
    209     _wp_Autop: function(pee) {
    210         var preserve_linebreaks = false,
    211             preserve_br = false,
    212             blocklist = 'table|thead|tfoot|caption|col|colgroup|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li|pre' +
    213                 '|form|map|area|blockquote|address|math|style|p|h[1-6]|hr|fieldset|legend|section' +
    214                 '|article|aside|hgroup|header|footer|nav|figure|figcaption|details|menu|summary';
    215 
    216         if ( pee.indexOf( '<object' ) !== -1 ) {
    217             pee = pee.replace( /<object[\s\S]+?<\/object>/g, function( a ) {
    218                 return a.replace( /[\r\n]+/g, '' );
    219             });
    220         }
    221 
    222         pee = pee.replace( /<[^<>]+>/g, function( a ){
    223             return a.replace( /[\r\n]+/g, ' ' );
    224         });
    225 
    226         // Protect pre|script tags
    227         if ( pee.indexOf( '<pre' ) !== -1 || pee.indexOf( '<script' ) !== -1 ) {
    228             preserve_linebreaks = true;
    229             pee = pee.replace( /<(pre|script)[^>]*>[\s\S]+?<\/\1>/g, function( a ) {
    230                 return a.replace( /(\r\n|\n)/g, '<wp-line-break>' );
    231             });
    232         }
    233 
    234         // keep <br> tags inside captions and convert line breaks
    235         if ( pee.indexOf( '[caption' ) !== -1 ) {
    236             preserve_br = true;
    237             pee = pee.replace( /\[caption[\s\S]+?\[\/caption\]/g, function( a ) {
    238                 // keep existing <br>
    239                 a = a.replace( /<br([^>]*)>/g, '<wp-temp-br$1>' );
    240                 // no line breaks inside HTML tags
    241                 a = a.replace( /<[a-zA-Z0-9]+( [^<>]+)?>/g, function( b ) {
    242                     return b.replace( /[\r\n\t]+/, ' ' );
    243                 });
    244                 // convert remaining line breaks to <br>
    245                 return a.replace( /\s*\n\s*/g, '<wp-temp-br />' );
    246             });
    247         }
    248 
    249         pee = pee + '\n\n';
    250         pee = pee.replace( /<br \/>\s*<br \/>/gi, '\n\n' );
    251         pee = pee.replace( new RegExp( '(<(?:' + blocklist + ')(?: [^>]*)?>)', 'gi' ), '\n$1' );
    252         pee = pee.replace( new RegExp( '(</(?:' + blocklist + ')>)', 'gi' ), '$1\n\n' );
    253         pee = pee.replace( /<hr( [^>]*)?>/gi, '<hr$1>\n\n' ); // hr is self closing block element
    254         pee = pee.replace( /\s*<option/gi, '<option' ); // No <p> or <br> around <option>
    255         pee = pee.replace( /<\/option>\s*/gi, '</option>' );
    256         pee = pee.replace( /\r\n|\r/g, '\n' );
    257         pee = pee.replace( /\n\s*\n+/g, '\n\n' );
    258         pee = pee.replace( /([\s\S]+?)\n\n/g, '<p>$1</p>\n' );
    259         pee = pee.replace( /<p>\s*?<\/p>/gi, '');
    260         pee = pee.replace( new RegExp( '<p>\\s*(</?(?:' + blocklist + ')(?: [^>]*)?>)\\s*</p>', 'gi' ), '$1' );
    261         pee = pee.replace( /<p>(<li.+?)<\/p>/gi, '$1');
    262         pee = pee.replace( /<p>\s*<blockquote([^>]*)>/gi, '<blockquote$1><p>');
    263         pee = pee.replace( /<\/blockquote>\s*<\/p>/gi, '</p></blockquote>');
    264         pee = pee.replace( new RegExp( '<p>\\s*(</?(?:' + blocklist + ')(?: [^>]*)?>)', 'gi' ), '$1' );
    265         pee = pee.replace( new RegExp( '(</?(?:' + blocklist + ')(?: [^>]*)?>)\\s*</p>', 'gi' ), '$1' );
    266         pee = pee.replace( /\s*\n/gi, '<br />\n');
    267         pee = pee.replace( new RegExp( '(</?(?:' + blocklist + ')[^>]*>)\\s*<br />', 'gi' ), '$1' );
    268         pee = pee.replace( /<br \/>(\s*<\/?(?:p|li|div|dl|dd|dt|th|pre|td|ul|ol)>)/gi, '$1' );
    269         pee = pee.replace( /(?:<p>|<br ?\/?>)*\s*\[caption([^\[]+)\[\/caption\]\s*(?:<\/p>|<br ?\/?>)*/gi, '[caption$1[/caption]' );
    270 
    271         pee = pee.replace( /(<(?:div|th|td|form|fieldset|dd)[^>]*>)(.*?)<\/p>/g, function( a, b, c ) {
    272             if ( c.match( /<p( [^>]*)?>/ ) ) {
    273                 return a;
    274             }
    275 
    276             return b + '<p>' + c + '</p>';
    277         });
    278 
    279         // put back the line breaks in pre|script
    280         if ( preserve_linebreaks ) {
    281             pee = pee.replace( /<wp-line-break>/g, '\n' );
    282         }
    283 
    284         if ( preserve_br ) {
    285             pee = pee.replace( /<wp-temp-br([^>]*)>/g, '<br$1>' );
    286         }
    287 
    288         return pee;
    289     },
    290 
    291     pre_wpautop: function( content ) {
    292         var t = this, o = { o: t, data: content, unfiltered: content },
    293             q = typeof( jQuery ) !== 'undefined';
    294 
    295         if ( q ) {
    296             jQuery( 'body' ).trigger( 'beforePreWpautop', [ o ] );
    297         }
    298 
    299         o.data = t._wp_Nop( o.data );
    300 
    301         if ( q ) {
    302             jQuery('body').trigger('afterPreWpautop', [ o ] );
    303         }
    304 
    305         return o.data;
    306     },
    307 
    308     wpautop: function( pee ) {
    309         var t = this, o = { o: t, data: pee, unfiltered: pee },
    310             q = typeof( jQuery ) !== 'undefined';
    311 
    312         if ( q ) {
    313             jQuery( 'body' ).trigger('beforeWpautop', [ o ] );
    314         }
    315 
    316         o.data = t._wp_Autop( o.data );
    317 
    318         if ( q ) {
    319             jQuery( 'body' ).trigger('afterWpautop', [ o ] );
    320         }
    321 
    322         return o.data;
     287
     288            // put back the line breaks in pre|script
     289            if ( preserve_linebreaks ) {
     290                text = text.replace( /<wp-line-break>/g, '\n' );
     291            }
     292
     293            if ( preserve_br ) {
     294                text = text.replace( /<wp-temp-br([^>]*)>/g, '<br$1>' );
     295            }
     296
     297            return text;
     298        }
     299
     300        // Add old events
     301        function pre_wpautop( html ) {
     302            var obj = { o: exports, data: html, unfiltered: html };
     303
     304            if ( $ ) {
     305                $( 'body' ).trigger( 'beforePreWpautop', [ obj ] );
     306            }
     307
     308            obj.data = removep( obj.data );
     309
     310            if ( $ ) {
     311                $( 'body' ).trigger( 'afterPreWpautop', [ obj ] );
     312            }
     313
     314            return obj.data;
     315        }
     316
     317        function wpautop( text ) {
     318            var obj = { o: exports, data: text, unfiltered: text };
     319
     320            if ( $ ) {
     321                $( 'body' ).trigger( 'beforeWpautop', [ obj ] );
     322            }
     323
     324            obj.data = autop( obj.data );
     325
     326            if ( $ ) {
     327                $( 'body' ).trigger( 'afterWpautop', [ obj ] );
     328            }
     329
     330            return obj.data;
     331        }
     332
     333        if ( $ ) {
     334            $( document ).ready( init );
     335        } else if ( document.addEventListener ) {
     336            document.addEventListener( 'DOMContentLoaded', init, false );
     337            window.addEventListener( 'load', init, false );
     338        } else if ( window.attachEvent ) {
     339            window.attachEvent( 'onload', init );
     340            document.attachEvent( 'onreadystatechange', function() {
     341                if ( 'complete' === document.readyState ) {
     342                    init();
     343                }
     344            } );
     345        }
     346
     347        window.wp = window.wp || {};
     348        window.wp.editor = window.wp.editor || {};
     349        window.wp.editor.autop = wpautop;
     350        window.wp.editor.removep = pre_wpautop;
     351
     352        exports = {
     353            go: switchEditor,
     354            wpautop: wpautop,
     355            pre_wpautop: pre_wpautop,
     356            _wp_Autop: autop,
     357            _wp_Nop: removep
     358        };
     359
     360        return exports;
    323361    }
    324 };
     362
     363    window.switchEditors = new SwitchEditors();
     364}( window.jQuery ));
  • trunk/src/wp-includes/class-wp-editor.php

    r32699 r32899  
    144144     */
    145145    public static function editor( $content, $editor_id, $settings = array() ) {
    146 
    147146        $set = self::parse_settings( $editor_id, $settings );
    148         $editor_class = ' class="' . trim( $set['editor_class'] . ' wp-editor-area' ) . '"';
     147        $editor_class = ' class="' . trim( esc_attr( $set['editor_class'] ) . ' wp-editor-area' ) . '"';
    149148        $tabindex = $set['tabindex'] ? ' tabindex="' . (int) $set['tabindex'] . '"' : '';
    150         $switch_class = 'html-active';
     149        $default_editor = 'html';
    151150        $toolbar = $buttons = $autocomplete = '';
     151        $editor_id_attr = esc_attr( $editor_id );
    152152
    153153        if ( $set['drag_drop_upload'] ) {
     
    155155        }
    156156
    157         if ( ! empty( $set['editor_height'] ) )
    158             $height = ' style="height: ' . $set['editor_height'] . 'px"';
    159         else
    160             $height = ' rows="' . $set['textarea_rows'] . '"';
    161 
    162         if ( !current_user_can( 'upload_files' ) )
     157        if ( ! empty( $set['editor_height'] ) ) {
     158            $height = ' style="height: ' . (int) $set['editor_height'] . 'px"';
     159        } else {
     160            $height = ' rows="' . (int) $set['textarea_rows'] . '"';
     161        }
     162
     163        if ( ! current_user_can( 'upload_files' ) ) {
    163164            $set['media_buttons'] = false;
    164 
    165         if ( ! self::$this_quicktags && self::$this_tinymce ) {
    166             $switch_class = 'tmce-active';
     165        }
     166
     167        if ( self::$this_tinymce ) {
    167168            $autocomplete = ' autocomplete="off"';
    168         } elseif ( self::$this_quicktags && self::$this_tinymce ) {
    169             $default_editor = $set['default_editor'] ? $set['default_editor'] : wp_default_editor();
    170             $autocomplete = ' autocomplete="off"';
    171 
    172             // 'html' is used for the "Text" editor tab.
    173             if ( 'html' === $default_editor ) {
    174                 add_filter('the_editor_content', 'wp_htmledit_pre');
    175                 $switch_class = 'html-active';
     169
     170            if ( self::$this_quicktags ) {
     171                $default_editor = $set['default_editor'] ? $set['default_editor'] : wp_default_editor();
     172                // 'html' is used for the "Text" editor tab.
     173                if ( 'html' !== $default_editor ) {
     174                    $default_editor = 'tinymce';
     175                }
     176
     177                $buttons .= '<button type="button" id="' . $editor_id_attr . '-tmce" class="wp-switch-editor switch-tmce"' .
     178                    ' data-wp-editor-id="' . $editor_id_attr . '">' . __('Visual') . "</button>\n";
     179                $buttons .= '<button type="button" id="' . $editor_id_attr . '-html" class="wp-switch-editor switch-html"' .
     180                    ' data-wp-editor-id="' . $editor_id_attr . '">' . _x( 'Text', 'Name for the Text editor tab (formerly HTML)' ) . "</button>\n";
    176181            } else {
    177                 add_filter('the_editor_content', 'wp_richedit_pre');
    178                 $switch_class = 'tmce-active';
    179             }
    180 
    181             $buttons .= '<button type="button" id="' . $editor_id . '-tmce" class="wp-switch-editor switch-tmce" onclick="switchEditors.switchto(this);">' . __('Visual') . "</button>\n";
    182             $buttons .= '<button type="button" id="' . $editor_id . '-html" class="wp-switch-editor switch-html" onclick="switchEditors.switchto(this);">' . _x( 'Text', 'Name for the Text editor tab (formerly HTML)' ) . "</button>\n";
    183         }
    184 
     182                $default_editor = 'tinymce';
     183            }
     184        }
     185
     186        $switch_class = 'html' === $default_editor ? 'html-active' : 'tmce-active';
    185187        $wrap_class = 'wp-core-ui wp-editor-wrap ' . $switch_class;
    186188
     
    189191        }
    190192
    191         echo '<div id="wp-' . $editor_id . '-wrap" class="' . $wrap_class . '">';
     193        echo '<div id="wp-' . $editor_id_attr . '-wrap" class="' . $wrap_class . '">';
    192194
    193195        if ( self::$editor_buttons_css ) {
    194             wp_print_styles('editor-buttons');
     196            wp_print_styles( 'editor-buttons' );
    195197            self::$editor_buttons_css = false;
    196198        }
    197199
    198         if ( !empty($set['editor_css']) )
     200        if ( ! empty( $set['editor_css'] ) ) {
    199201            echo $set['editor_css'] . "\n";
    200 
    201         if ( !empty($buttons) || $set['media_buttons'] ) {
    202             echo '<div id="wp-' . $editor_id . '-editor-tools" class="wp-editor-tools hide-if-no-js">';
     202        }
     203
     204        if ( ! empty( $buttons ) || $set['media_buttons'] ) {
     205            echo '<div id="wp-' . $editor_id_attr . '-editor-tools" class="wp-editor-tools hide-if-no-js">';
    203206
    204207            if ( $set['media_buttons'] ) {
    205208                self::$has_medialib = true;
    206209
    207                 if ( !function_exists('media_buttons') )
    208                     include(ABSPATH . 'wp-admin/includes/media.php');
    209 
    210                 echo '<div id="wp-' . $editor_id . '-media-buttons" class="wp-media-buttons">';
     210                if ( ! function_exists( 'media_buttons' ) )
     211                    include( ABSPATH . 'wp-admin/includes/media.php' );
     212
     213                echo '<div id="wp-' . $editor_id_attr . '-media-buttons" class="wp-media-buttons">';
    211214
    212215                /**
     
    225228        }
    226229
     230        $quicktags_toolbar = '';
     231
     232        if ( self::$this_quicktags ) {
     233            if ( 'content' === $editor_id && ! empty( $GLOBALS['current_screen'] ) && $GLOBALS['current_screen']->base === 'post' ) {
     234                $toolbar_id = 'ed_toolbar';
     235            } else {
     236                $toolbar_id = 'qt_' . $editor_id_attr . '_toolbar';
     237            }
     238
     239            $quicktags_toolbar = '<div id="' . $toolbar_id . '" class="quicktags-toolbar"></div>';
     240        }
     241
    227242        /**
    228243         * Filter the HTML markup output that displays the editor.
     
    232247         * @param string $output Editor's HTML markup.
    233248         */
    234         $the_editor = apply_filters( 'the_editor', '<div id="wp-' . $editor_id . '-editor-container" class="wp-editor-container">' .
    235             '<textarea' . $editor_class . $height . $tabindex . $autocomplete . ' cols="40" name="' . $set['textarea_name'] . '" ' .
    236             'id="' . $editor_id . '">%s</textarea></div>' );
     249        $the_editor = apply_filters( 'the_editor', '<div id="wp-' . $editor_id_attr . '-editor-container" class="wp-editor-container">' .
     250            $quicktags_toolbar .
     251            '<textarea' . $editor_class . $height . $tabindex . $autocomplete . ' cols="40" name="' . esc_attr( $set['textarea_name'] ) . '" ' .
     252            'id="' . $editor_id_attr . '">%s</textarea></div>' );
    237253
    238254        /**
     
    243259         * @param string $content Default editor content.
    244260         */
    245         $content = apply_filters( 'the_editor_content', $content );
     261        $content = apply_filters( 'the_editor_content', $content, $default_editor );
     262
     263        // Back-compat for the `htmledit_pre` and `richedit_pre` filters
     264        if ( 'html' === $default_editor && has_filter( 'htmledit_pre' ) ) {
     265            // TODO: needs _deprecated_filter(), use _deprecated_function() as substitute for now
     266            _deprecated_function( 'add_filter( htmledit_pre )', '4.3.0', 'add_filter( format_for_editor )' );
     267            $content = apply_filters( 'htmledit_pre', $content );
     268        } elseif ( 'tinymce' === $default_editor && has_filter( 'richedit_pre' ) ) {
     269            _deprecated_function( 'add_filter( richedit_pre )', '4.3.0', 'add_filter( format_for_editor )' );
     270            $content = apply_filters( 'richedit_pre', $content );
     271        }
    246272
    247273        printf( $the_editor, $content );
    248274        echo "\n</div>\n\n";
    249275
    250         self::editor_settings($editor_id, $set);
     276        self::editor_settings( $editor_id, $set );
    251277    }
    252278
     
    479505                    'skin' => 'lightgray',
    480506                    'language' => self::$mce_locale,
    481                     'formats' => "{
    482                         alignleft: [
    483                             {selector: 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li', styles: {textAlign:'left'}},
    484                             {selector: 'img,table,dl.wp-caption', classes: 'alignleft'}
    485                         ],
    486                         aligncenter: [
    487                             {selector: 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li', styles: {textAlign:'center'}},
    488                             {selector: 'img,table,dl.wp-caption', classes: 'aligncenter'}
    489                         ],
    490                         alignright: [
    491                             {selector: 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li', styles: {textAlign:'right'}},
    492                             {selector: 'img,table,dl.wp-caption', classes: 'alignright'}
    493                         ],
    494                         strikethrough: {inline: 'del'}
    495                     }",
     507                    'formats' => '{' .
     508                        'alignleft: [' .
     509                            '{selector: "p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li", styles: {textAlign:"left"}},' .
     510                            '{selector: "img,table,dl.wp-caption", classes: "alignleft"}' .
     511                        '],' .
     512                        'aligncenter: [' .
     513                            '{selector: "p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li", styles: {textAlign:"center"}},' .
     514                            '{selector: "img,table,dl.wp-caption", classes: "aligncenter"}' .
     515                        '],' .
     516                        'alignright: [' .
     517                            '{selector: "p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li", styles: {textAlign:"right"}},' .
     518                            '{selector: "img,table,dl.wp-caption", classes: "alignright"}' .
     519                        '],' .
     520                        'strikethrough: {inline: "del"}' .
     521                    '}',
    496522                    'relative_urls' => false,
    497523                    'remove_script_host' => false,
     
    651677            );
    652678
    653             if ( $first_run )
    654                 $mceInit = array_merge( self::$first_init, $mceInit );
     679            // Merge with the first part of the init array
     680            $mceInit = array_merge( self::$first_init, $mceInit );
    655681
    656682            if ( is_array( $set['tinymce'] ) )
     
    663689             * and "extended_valid_elements" can be done through this filter. Best
    664690             * is to use the default cleanup by not specifying valid_elements,
    665              * as TinyMCE contains full set of XHTML 1.0.
     691             * as TinyMCE checks against the full set of HTML 5.0 elements and attributes.
    666692             */
    667693            if ( $set['teeny'] ) {
     
    11831209
    11841210        ( function() {
    1185             var init, edId, qtId, firstInit, wrapper;
     1211            var init, id, $wrap;
    11861212
    11871213            if ( typeof tinymce !== 'undefined' ) {
    1188                 for ( edId in tinyMCEPreInit.mceInit ) {
    1189                     if ( firstInit ) {
    1190                         init = tinyMCEPreInit.mceInit[edId] = tinymce.extend( {}, firstInit, tinyMCEPreInit.mceInit[edId] );
    1191                     } else {
    1192                         init = firstInit = tinyMCEPreInit.mceInit[edId];
    1193                     }
    1194 
    1195                     wrapper = tinymce.DOM.select( '#wp-' + edId + '-wrap' )[0];
    1196 
    1197                     if ( ( tinymce.DOM.hasClass( wrapper, 'tmce-active' ) || ! tinyMCEPreInit.qtInit.hasOwnProperty( edId ) ) &&
    1198                         ! init.wp_skip_init ) {
    1199 
    1200                         try {
    1201                             tinymce.init( init );
    1202 
    1203                             if ( ! window.wpActiveEditor ) {
    1204                                 window.wpActiveEditor = edId;
    1205                             }
    1206                         } catch(e){}
     1214                for ( id in tinyMCEPreInit.mceInit ) {
     1215                    init = tinyMCEPreInit.mceInit[id];
     1216                    $wrap = tinymce.$( '#wp-' + id + '-wrap' );
     1217
     1218                    if ( ( $wrap.hasClass( 'tmce-active' ) || ! tinyMCEPreInit.qtInit.hasOwnProperty( id ) ) && ! init.wp_skip_init ) {
     1219                        tinymce.init( init );
     1220
     1221                        if ( ! window.wpActiveEditor ) {
     1222                            window.wpActiveEditor = id;
     1223                        }
    12071224                    }
    12081225                }
     
    12101227
    12111228            if ( typeof quicktags !== 'undefined' ) {
    1212                 for ( qtId in tinyMCEPreInit.qtInit ) {
    1213                     try {
    1214                         quicktags( tinyMCEPreInit.qtInit[qtId] );
    1215 
    1216                         if ( ! window.wpActiveEditor ) {
    1217                             window.wpActiveEditor = qtId;
    1218                         }
    1219                     } catch(e){};
    1220                 }
    1221             }
    1222 
    1223             if ( typeof jQuery !== 'undefined' ) {
    1224                 jQuery('.wp-editor-wrap').on( 'click.wp-editor', function() {
    1225                     if ( this.id ) {
    1226                         window.wpActiveEditor = this.id.slice( 3, -5 );
    1227                     }
    1228                 });
    1229             } else {
    1230                 for ( qtId in tinyMCEPreInit.qtInit ) {
    1231                     document.getElementById( 'wp-' + qtId + '-wrap' ).onclick = function() {
    1232                         window.wpActiveEditor = this.id.slice( 3, -5 );
     1229                for ( id in tinyMCEPreInit.qtInit ) {
     1230                    quicktags( tinyMCEPreInit.qtInit[id] );
     1231
     1232                    if ( ! window.wpActiveEditor ) {
     1233                        window.wpActiveEditor = id;
    12331234                    }
    12341235                }
  • trunk/src/wp-includes/css/editor.css

    r32677 r32899  
    287287.mce-path .mce-divider {
    288288    font-size: 12px;
    289     line-height: 18px;
    290289}
    291290
     
    10601059    border-bottom: 1px solid #dedede;
    10611060    background: #f5f5f5;
     1061    min-height: 30px;
    10621062}
    10631063
  • trunk/src/wp-includes/default-filters.php

    r32896 r32899  
    203203
    204204add_filter( 'http_request_host_is_external', 'allowed_http_request_hosts', 10, 2 );
     205
     206// Prepare the content for the Visual or Text editor
     207add_filter( 'the_editor_content', 'format_for_editor', 10, 2 );
    205208
    206209// Actions
  • trunk/src/wp-includes/deprecated.php

    r32116 r32899  
    34923492    return false;
    34933493}
     3494
     3495/**
     3496 * Formats text for the rich text editor.
     3497 *
     3498 * The filter 'richedit_pre' is applied here. If $text is empty the filter will
     3499 * be applied to an empty string.
     3500 *
     3501 * @since 2.0.0
     3502 * @deprecated 4.3.0
     3503 *
     3504 * @param string $text The text to be formatted.
     3505 * @return string The formatted text after filter is applied.
     3506 */
     3507function wp_richedit_pre($text) {
     3508    _deprecated_function( __FUNCTION__, '4.3', 'format_for_editor()' );
     3509
     3510    if ( empty( $text ) ) {
     3511        /**
     3512         * Filter text returned for the rich text editor.
     3513         *
     3514         * This filter is first evaluated, and the value returned, if an empty string
     3515         * is passed to wp_richedit_pre(). If an empty string is passed, it results
     3516         * in a break tag and line feed.
     3517         *
     3518         * If a non-empty string is passed, the filter is evaluated on the wp_richedit_pre()
     3519         * return after being formatted.
     3520         *
     3521         * @since 2.0.0
     3522         * @deprecated 4.3.0
     3523         *
     3524         * @param string $output Text for the rich text editor.
     3525         */
     3526        return apply_filters( 'richedit_pre', '' );
     3527    }
     3528
     3529    $output = convert_chars($text);
     3530    $output = wpautop($output);
     3531    $output = htmlspecialchars($output, ENT_NOQUOTES, get_option( 'blog_charset' ) );
     3532
     3533    /** This filter is documented in wp-includes/deprecated.php */
     3534    return apply_filters( 'richedit_pre', $output );
     3535}
     3536
     3537/**
     3538 * Formats text for the HTML editor.
     3539 *
     3540 * Unless $output is empty it will pass through htmlspecialchars before the
     3541 * 'htmledit_pre' filter is applied.
     3542 *
     3543 * @since 2.5.0
     3544 * @deprecated 4.3.0
     3545 *
     3546 * @param string $output The text to be formatted.
     3547 * @return string Formatted text after filter applied.
     3548 */
     3549function wp_htmledit_pre($output) {
     3550    _deprecated_function( __FUNCTION__, '4.3', 'format_for_editor()' );
     3551
     3552    if ( !empty($output) )
     3553        $output = htmlspecialchars($output, ENT_NOQUOTES, get_option( 'blog_charset' ) ); // convert only < > &
     3554
     3555    /**
     3556     * Filter the text before it is formatted for the HTML editor.
     3557     *
     3558     * @since 2.5.0
     3559     * @deprecated 4.3.0
     3560     *
     3561     * @param string $output The HTML-formatted text.
     3562     */
     3563    return apply_filters( 'htmledit_pre', $output );
     3564}
     3565
  • trunk/src/wp-includes/formatting.php

    r32897 r32899  
    30633063
    30643064/**
    3065  * Formats text for the rich text editor.
    3066  *
    3067  * The filter 'richedit_pre' is applied here. If $text is empty the filter will
    3068  * be applied to an empty string.
    3069  *
    3070  * @since 2.0.0
     3065 * Formats text for the editor.
     3066 *
     3067 * Generally the browsers treat everything inside a textarea as text, but
     3068 * it is still a good idea to HTML entity encode `<`, `>` and `&` in the content.
     3069 *
     3070 * The filter 'format_for_editor' is applied here. If $text is empty the filter will
     3071 * be applied to an empty string.
     3072 *
     3073 * @since 4.3.0
    30713074 *
    30723075 * @param string $text The text to be formatted.
    3073  * @return string The formatted text after filter is applied.
    3074  */
    3075 function wp_richedit_pre( $text ) {
    3076     if ( empty( $text ) ) {
    3077         /**
    3078          * Filter text returned for the rich text editor.
    3079          *
    3080          * This filter is first evaluated, and the value returned, if an empty string
    3081          * is passed to wp_richedit_pre(). If an empty string is passed, it results
    3082          * in a break tag and line feed.
    3083          *
    3084          * If a non-empty string is passed, the filter is evaluated on the wp_richedit_pre()
    3085          * return after being formatted.
    3086          *
    3087          * @since 2.0.0
    3088          *
    3089          * @param string $output Text for the rich text editor.
    3090          */
    3091         return apply_filters( 'richedit_pre', '' );
    3092     }
    3093 
    3094     $output = convert_chars($text);
    3095     $output = wpautop($output);
    3096     $output = htmlspecialchars($output, ENT_NOQUOTES, get_option( 'blog_charset' ) );
    3097 
    3098     /** This filter is documented in wp-includes/formatting.php */
    3099     return apply_filters( 'richedit_pre', $output );
    3100 }
    3101 
    3102 /**
    3103  * Formats text for the HTML editor.
    3104  *
    3105  * Unless $output is empty it will pass through htmlspecialchars before the
    3106  * 'htmledit_pre' filter is applied.
    3107  *
    3108  * @since 2.5.0
    3109  *
    3110  * @param string $output The text to be formatted.
    3111  * @return string Formatted text after filter applied.
    3112  */
    3113 function wp_htmledit_pre( $output ) {
    3114     if ( !empty($output) )
    3115         $output = htmlspecialchars($output, ENT_NOQUOTES, get_option( 'blog_charset' ) ); // convert only < > &
     3076 * @return string The formatted text after filter is applied. <?
     3077 */
     3078function format_for_editor( $text, $default_editor = null ) {
     3079    // Back-compat: check if any characters need encoding.
     3080    if ( ! empty( $text ) && ( false !== strpos( $text, '<' ) || false !== strpos( $text, '>' ) ||
     3081        preg_match( '/&(?!#(?:\d+|x[a-f0-9]+);|[a-z1-4]{1,8};)/i', $text ) ) ) {
     3082
     3083        $text = htmlspecialchars( $text, ENT_NOQUOTES, get_option( 'blog_charset' ) );
     3084    }
    31163085
    31173086    /**
    3118      * Filter the text before it is formatted for the HTML editor.
    3119      *
    3120      * @since 2.5.0
    3121      *
    3122      * @param string $output The HTML-formatted text.
     3087     * Filter the text after it is formatted for the editor.
     3088     *
     3089     * @since 4.3.0
     3090     *
     3091     * @param string $text The formatted text.
    31233092     */
    3124     return apply_filters( 'htmledit_pre', $output );
     3093    return apply_filters( 'format_for_editor', $text, $default_editor );
    31253094}
    31263095
  • trunk/src/wp-includes/js/quicktags.js

    r32883 r32899  
    164164            canvas = document.getElementById(id),
    165165            name = 'qt_' + id,
    166             tb, onclick, toolbar_id;
     166            tb, onclick, toolbar_id, wrap, setActiveEditor;
    167167
    168168        if ( !id || !canvas ) {
     
    183183        }
    184184
    185         tb = document.createElement('div');
    186         tb.id = toolbar_id;
    187         tb.className = 'quicktags-toolbar';
    188         tb.onclick = function() {
    189             window.wpActiveEditor = id;
    190         };
     185        tb = document.getElementById( toolbar_id );
     186
     187        if ( ! tb ) {
     188            tb = document.createElement('div');
     189            tb.id = toolbar_id;
     190            tb.className = 'quicktags-toolbar';
     191        }
    191192
    192193        canvas.parentNode.insertBefore(tb, canvas);
     
    215216        };
    216217
     218        setActiveEditor = function() {
     219            window.wpActiveEditor = id;
     220        };
     221
     222        wrap = document.getElementById( 'wp-' + id + '-wrap' );
     223
    217224        if ( tb.addEventListener ) {
    218             tb.addEventListener('click', onclick, false);
     225            tb.addEventListener( 'click', onclick, false );
     226           
     227            if ( wrap ) {
     228                wrap.addEventListener( 'click', setActiveEditor, false );
     229            }
    219230        } else if ( tb.attachEvent ) {
    220             tb.attachEvent('onclick', onclick);
     231            tb.attachEvent( 'onclick', onclick );
     232
     233            if ( wrap ) {
     234                wrap.attachEvent( 'onclick', setActiveEditor );
     235            }
    221236        }
    222237
  • trunk/src/wp-includes/js/tinymce/plugins/wordpress/plugin.js

    r32856 r32899  
    1 /* global tinymce, getUserSetting, setUserSetting */
    2 
     1/* global getUserSetting, setUserSetting */
     2( function( tinymce ) {
    33// Set the minimum value for the modals z-index higher than #wpadminbar (100000)
    44tinymce.ui.FloatPanel.zIndex = 100100;
    55
    66tinymce.PluginManager.add( 'wordpress', function( editor ) {
    7     var DOM = tinymce.DOM,
     7    var wpAdvButton, style,
     8        DOM = tinymce.DOM,
    89        each = tinymce.each,
    910        __ = editor.editorManager.i18n.translate,
    10         wpAdvButton, style;
    11 
    12     if ( typeof window.jQuery !== 'undefined' ) {
    13         window.jQuery( document ).triggerHandler( 'tinymce-editor-setup', [ editor ] );
     11        $ = window.jQuery,
     12        wp = window.wp,
     13        hasWpautop = ( wp && wp.editor && wp.editor.autop && editor.getParam( 'wpautop', true ) );
     14
     15    if ( $ ) {
     16        $( document ).triggerHandler( 'tinymce-editor-setup', [ editor ] );
    1417    }
    1518
     
    8992
    9093    // Replace Read More/Next Page tags with images
    91     editor.on( 'BeforeSetContent', function( e ) {
    92         var title;
    93 
    94         if ( e.content ) {
    95             if ( e.content.indexOf( '<!--more' ) !== -1 ) {
     94    editor.on( 'BeforeSetContent', function( event ) {
     95        var title,
     96            paragraph = tinymce.Env.webkit ? '<p><br /></p>' : '<p></p>';
     97
     98        if ( event.content ) {
     99            if ( event.content.indexOf( '<!--more' ) !== -1 ) {
    96100                title = __( 'Read more...' );
    97101
    98                 e.content = e.content.replace( /<!--more(.*?)-->/g, function( match, moretext ) {
     102                event.content = event.content.replace( /<!--more(.*?)-->/g, function( match, moretext ) {
    99103                    return '<img src="' + tinymce.Env.transparentSrc + '" data-wp-more="more" data-wp-more-text="' + moretext + '" ' +
    100104                        'class="wp-more-tag mce-wp-more" title="' + title + '" data-mce-resize="false" data-mce-placeholder="1" />';
     
    102106            }
    103107
    104             if ( e.content.indexOf( '<!--nextpage-->' ) !== -1 ) {
     108            if ( event.content.indexOf( '<!--nextpage-->' ) !== -1 ) {
    105109                title = __( 'Page break' );
    106110
    107                 e.content = e.content.replace( /<!--nextpage-->/g,
     111                event.content = event.content.replace( /<!--nextpage-->/g,
    108112                    '<img src="' + tinymce.Env.transparentSrc + '" data-wp-more="nextpage" class="wp-more-tag mce-wp-nextpage" ' +
    109113                        'title="' + title + '" data-mce-resize="false" data-mce-placeholder="1" />' );
     114            }
     115
     116            // Remove spaces from empty paragraphs.
     117            event.content = event.content.replace( /<p>(?:&nbsp;|\u00a0|\uFEFF|\s)+<\/p>/gi, paragraph );
     118
     119            if ( event.load && event.format !== 'raw' && hasWpautop ) {
     120                event.content = wp.editor.autop( event.content );
    110121            }
    111122        }
     
    202213
    203214    editor.addCommand( 'WP_Medialib', function() {
    204         if ( typeof wp !== 'undefined' && wp.media && wp.media.editor ) {
     215        if ( wp && wp.media && wp.media.editor ) {
    205216            wp.media.editor.open( editor.id );
    206217        }
     
    235246    // Menubar
    236247    // Insert->Add Media
    237     if ( typeof wp !== 'undefined' && wp.media && wp.media.editor ) {
     248    if ( wp && wp.media && wp.media.editor ) {
    238249        editor.addMenuItem( 'add_media', {
    239250            text: 'Add Media',
     
    289300            dom = editor.dom;
    290301
    291         if ( tinymce.Env.iOS ) {
     302        if ( env.iOS ) {
    292303            dom.addClass( doc.documentElement, 'ios' );
    293304        }
     
    319330
    320331        // Remove invalid parent paragraphs when inserting HTML
    321         // TODO: still needed?
    322         editor.on( 'BeforeSetContent', function( e ) {
    323             if ( e.content ) {
    324                 e.content = e.content.replace(/<p>\s*<(p|div|ul|ol|dl|table|blockquote|h[1-6]|fieldset|pre|address)( [^>]*)?>/gi, '<$1$2>');
    325                 e.content = e.content.replace(/<\/(p|div|ul|ol|dl|table|blockquote|h[1-6]|fieldset|pre|address)>\s*<\/p>/gi, '</$1>');
     332        editor.on( 'BeforeSetContent', function( event ) {
     333            if ( event.content ) {
     334                event.content = event.content.replace( /<p>\s*<(p|div|ul|ol|dl|table|blockquote|h[1-6]|fieldset|pre)( [^>]*)?>/gi, '<$1$2>' )
     335                    .replace( /<\/(p|div|ul|ol|dl|table|blockquote|h[1-6]|fieldset|pre)>\s*<\/p>/gi, '</$1>' );
    326336            }
    327337        });
    328338
    329         if ( typeof window.jQuery !== 'undefined' ) {
    330             window.jQuery( document ).triggerHandler( 'tinymce-editor-init', [editor] );
     339        if ( $ ) {
     340            $( document ).triggerHandler( 'tinymce-editor-init', [editor] );
    331341        }
    332342
    333343        if ( window.tinyMCEPreInit && window.tinyMCEPreInit.dragDropUpload ) {
    334344            dom.bind( doc, 'dragstart dragend dragover drop', function( event ) {
    335                 if ( typeof window.jQuery !== 'undefined' ) {
     345                if ( $ ) {
    336346                    // Trigger the jQuery handlers.
    337                     window.jQuery( document ).trigger( new window.jQuery.Event( event ) );
     347                    $( document ).trigger( new $.Event( event ) );
    338348                }
    339349            });
     
    363373    });
    364374
    365     editor.on( 'SaveContent', function( e ) {
     375    editor.on( 'SaveContent', function( event ) {
    366376        // If editor is hidden, we just want the textarea's value to be saved
    367377        if ( ! editor.inline && editor.isHidden() ) {
    368             e.content = e.element.value;
     378            event.content = event.element.value;
    369379            return;
    370380        }
    371381
    372382        // Keep empty paragraphs :(
    373         e.content = e.content.replace( /<p>(?:<br ?\/?>|\u00a0|\uFEFF| )*<\/p>/g, '<p>&nbsp;</p>' );
    374 
    375         if ( editor.getParam( 'wpautop', true ) && typeof window.switchEditors !== 'undefined' ) {
    376             e.content = window.switchEditors.pre_wpautop( e.content );
    377         }
    378     });
    379 
    380     // Remove spaces from empty paragraphs.
    381     editor.on( 'BeforeSetContent', function( event ) {
    382         var paragraph = tinymce.Env.webkit ? '<p><br /></p>' : '<p></p>';
    383 
    384         if ( event.content ) {
    385             event.content = event.content.replace( /<p>(?:&nbsp;|\u00a0|\uFEFF|\s)+<\/p>/gi, paragraph );
     383        event.content = event.content.replace( /<p>(?:<br ?\/?>|\u00a0|\uFEFF| )*<\/p>/g, '<p>&nbsp;</p>' );
     384
     385        if ( hasWpautop ) {
     386            event.content = wp.editor.removep( event.content );
    386387        }
    387388    });
     
    393394        if ( tinymce.Env.iOS ) {
    394395            editor.settings.height = 300;
     396        }
     397
     398        // Start hidden when the Text editor is set to load first.
     399        if ( tinymce.$( '#wp-' + editor.id + '-wrap' ).hasClass( 'html-active' ) ) {
     400            editor.hide();
    395401        }
    396402
     
    416422
    417423        editor.addShortcut( 'meta+s', '', function() {
    418             if ( typeof wp !== 'undefined' && wp.autosave ) {
     424            if ( wp && wp.autosave ) {
    419425                wp.autosave.server.triggerSave();
    420426            }
     
    738744    };
    739745});
     746
     747}( window.tinymce ));
Note: See TracChangeset for help on using the changeset viewer.