WordPress.org

Make WordPress Core

Ticket #32425: 32425.patch

File 32425.patch, 45.6 KB (added by azaozz, 6 years ago)
  • src/wp-admin/js/editor.js

     
    1 /* global tinymce, tinyMCEPreInit, QTags, setUserSetting */
    21
    3 window.switchEditors = {
     2( function( $ ) {
     3        function switchEditors() {
     4                var tinymce, mce$, exports;
    45
    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 );
     6                function init() {
     7                        if ( ! tinymce && window.tinymce ) {
     8                                tinymce = window.tinymce;
     9                                mce$ = tinymce.$;
    1010
    11                 this.go( id, mode );
    12         },
     11                                mce$( document ).on( 'click', function( event ) {
     12                                        var id, mode, target = mce$( event.target );
    1313
    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';
     14                                        if ( target.hasClass( 'wp-switch-editor' ) ) {
     15                                                id = target.attr( 'data-wp-editor-id' );
     16                                                mode = target.hasClass( 'switch-tmce' ) ? 'tmce' : 'html';
     17                                                switchEditor( id, mode );
     18                                        }
     19                                });
    3120                        }
    3221                }
    3322
    34                 function getToolbarHeight() {
    35                         var node = DOM.select( '.mce-toolbar-grp', ed.getContainer() )[0],
     23                function getToolbarHeight( editor ) {
     24                        var node = mce$( '.mce-toolbar-grp', editor.getContainer() )[0],
    3625                                height = node && node.clientHeight;
    3726
    3827                        if ( height && height > 10 && height < 200 ) {
     
    4231                        return 30;
    4332                }
    4433
    45                 if ( 'tmce' === mode || 'tinymce' === mode ) {
    46                         if ( ed && ! ed.isHidden() ) {
    47                                 return false;
    48                         }
     34                function switchEditor( id, mode ) {
     35                        id = id || 'content';
     36                        mode = mode || 'toggle';
    4937
    50                         if ( typeof( QTags ) !== 'undefined' ) {
    51                                 QTags.closeAllTags( id );
     38                        var editorHeight, toolbarHeight, iframe,
     39                                editor = tinymce.get( id ),
     40                                wrap = mce$( '#wp-' + id + '-wrap' ),
     41                                $textarea = mce$( '#' + id ),
     42                                textarea = $textarea[0];
     43
     44                        if ( 'toggle' === mode ) {
     45                                if ( editor && ! editor.isHidden() ) {
     46                                        mode = 'html';
     47                                } else {
     48                                        mode = 'tmce';
     49                                }
    5250                        }
    5351
    54                         editorHeight = txtarea_el ? parseInt( txtarea_el.style.height, 10 ) : 0;
     52                        if ( 'tmce' === mode || 'tinymce' === mode ) {
     53                                if ( editor && ! editor.isHidden() ) {
     54                                        return false;
     55                                }
    5556
    56                         if ( tinyMCEPreInit.mceInit[ id ] && tinyMCEPreInit.mceInit[ id ].wpautop ) {
    57                                 txtarea_el.value = t.wpautop( txtarea_el.value );
    58                         }
     57                                if ( typeof( window.QTags ) !== 'undefined' ) {
     58                                        window.QTags.closeAllTags( id );
     59                                }
    5960
    60                         if ( ed ) {
    61                                 ed.show();
     61                                editorHeight = parseInt( textarea.style.height, 10 ) || 0;
    6262
    63                                 // No point resizing the iframe in iOS
    64                                 if ( ! tinymce.Env.iOS && editorHeight ) {
    65                                         toolbarHeight = getToolbarHeight();
    66                                         editorHeight = editorHeight - toolbarHeight + 14;
     63                                if ( editor ) {
     64                                        editor.show();
    6765
    68                                         // height cannot be under 50 or over 5000
    69                                         if ( editorHeight > 50 && editorHeight < 5000 ) {
    70                                                 ed.theme.resizeTo( null, editorHeight );
     66                                        // No point resizing the iframe in iOS
     67                                        if ( ! tinymce.Env.iOS && editorHeight ) {
     68                                                toolbarHeight = getToolbarHeight( editor );
     69                                                editorHeight = editorHeight - toolbarHeight + 14;
     70
     71                                                // height cannot be under 50 or over 5000
     72                                                if ( editorHeight > 50 && editorHeight < 5000 ) {
     73                                                        editor.theme.resizeTo( null, editorHeight );
     74                                                }
    7175                                        }
     76                                } else {
     77                                        tinymce.init( window.tinyMCEPreInit.mceInit[id] );
    7278                                }
    73                         } else {
    74                                 tinymce.init( tinyMCEPreInit.mceInit[id] );
    75                         }
    7679
    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' );
     80                                wrap.removeClass( 'html-active' ).addClass( 'tmce-active' );
     81                                $textarea.attr( 'aria-hidden', true );
     82                                window.setUserSetting( 'editor', 'tinymce' );
    8183
    82                 } else if ( 'html' === mode ) {
     84                        } else if ( 'html' === mode ) {
     85                                if ( editor && editor.isHidden() ) {
     86                                        return false;
     87                                }
    8388
    84                         if ( ed && ed.isHidden() ) {
    85                                 return false;
    86                         }
     89                                if ( editor ) {
     90                                        if ( ! tinymce.Env.iOS ) {
     91                                                iframe = editor.iframeElement;
     92                                                editorHeight = iframe ? parseInt( iframe.style.height, 10 ) : 0;
    8793
    88                         if ( ed ) {
    89                                 if ( ! tinymce.Env.iOS ) {
    90                                         iframe = DOM.get( id + '_ifr' );
    91                                         editorHeight = iframe ? parseInt( iframe.style.height, 10 ) : 0;
     94                                                if ( editorHeight ) {
     95                                                        toolbarHeight = getToolbarHeight( editor );
     96                                                        editorHeight = editorHeight + toolbarHeight - 14;
    9297
    93                                         if ( editorHeight ) {
    94                                                 toolbarHeight = getToolbarHeight();
    95                                                 editorHeight = editorHeight + toolbarHeight - 14;
    96 
    97                                                 // height cannot be under 50 or over 5000
    98                                                 if ( editorHeight > 50 && editorHeight < 5000 ) {
    99                                                         txtarea_el.style.height = editorHeight + 'px';
     98                                                        // height cannot be under 50 or over 5000
     99                                                        if ( editorHeight > 50 && editorHeight < 5000 ) {
     100                                                                textarea.style.height = editorHeight + 'px';
     101                                                        }
    100102                                                }
    101103                                        }
    102                                 }
    103104
    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 );
     105                                        editor.hide();
     106                                } else {
     107                                        // The TinyMCE instance doesn't exist, show the textarea
     108                                        $textarea.css({ 'display': '', 'visibility': '' });
    109109                                }
    110110
    111                                 DOM.setStyles( txtarea_el, {'display': '', 'visibility': ''} );
     111                                wrap.removeClass( 'tmce-active' ).addClass( 'html-active' );
     112                                $textarea.attr( 'aria-hidden', false );
     113                                window.setUserSetting( 'editor', 'html' );
    112114                        }
    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' );
    118115                }
    119                 return false;
    120         },
    121116
    122         _wp_Nop: function( content ) {
    123                 var blocklist1, blocklist2,
    124                         preserve_linebreaks = false,
    125                         preserve_br = false;
     117                function _preWpautop( content ) {
     118                        var blocklist1, blocklist2,
     119                                preserve_linebreaks = false,
     120                                preserve_br = false;
    126121
    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>' );
    134                         });
    135                 }
     122                        // Protect pre|script tags
     123                        if ( content.indexOf( '<pre' ) !== -1 || content.indexOf( '<script' ) !== -1 ) {
     124                                preserve_linebreaks = true;
     125                                content = content.replace( /<(pre|script)[^>]*>[\s\S]+?<\/\1>/g, function( a ) {
     126                                        a = a.replace( /<br ?\/?>(\r\n|\n)?/g, '<wp-line-break>' );
     127                                        a = a.replace( /<\/?p( [^>]*)?>(\r\n|\n)?/g, '<wp-line-break>' );
     128                                        return a.replace( /\r?\n/g, '<wp-line-break>' );
     129                                });
     130                        }
    136131
    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]+/, '' );
    142                         });
    143                 }
     132                        // keep <br> tags inside captions and remove line breaks
     133                        if ( content.indexOf( '[caption' ) !== -1 ) {
     134                                preserve_br = true;
     135                                content = content.replace( /\[caption[\s\S]+?\[\/caption\]/g, function( a ) {
     136                                        return a.replace( /<br([^>]*)>/g, '<wp-temp-br$1>' ).replace( /[\r\n\t]+/, '' );
     137                                });
     138                        }
    144139
    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>' );
     140                        // Pretty it up for the source editor
     141                        blocklist1 = 'blockquote|ul|ol|li|table|thead|tbody|tfoot|tr|th|td|div|h[1-6]|p|fieldset';
     142                        content = content.replace( new RegExp( '\\s*</(' + blocklist1 + ')>\\s*', 'g' ), '</$1>\n' );
     143                        content = content.replace( new RegExp( '\\s*<((?:' + blocklist1 + ')(?: [^>]*)?)>', 'g' ), '\n<$1>' );
    149144
    150                 // Mark </p> if it has any attributes.
    151                 content = content.replace( /(<p [^>]+>.*?)<\/p>/g, '$1</p#>' );
     145                        // Mark </p> if it has any attributes.
     146                        content = content.replace( /(<p [^>]+>.*?)<\/p>/g, '$1</p#>' );
    152147
    153                 // Separate <div> containing <p>
    154                 content = content.replace( /<div( [^>]*)?>\s*<p>/gi, '<div$1>\n\n' );
     148                        // Separate <div> containing <p>
     149                        content = content.replace( /<div( [^>]*)?>\s*<p>/gi, '<div$1>\n\n' );
    155150
    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' );
     151                        // Remove <p> and <br />
     152                        content = content.replace( /\s*<p>/gi, '' );
     153                        content = content.replace( /\s*<\/p>\s*/gi, '\n\n' );
     154                        content = content.replace( /\n[\s\u00a0]+\n/g, '\n\n' );
     155                        content = content.replace( /\s*<br ?\/?>\s*/gi, '\n' );
    161156
    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' );
     157                        // Fix some block element newline issues
     158                        content = content.replace( /\s*<div/g, '\n<div' );
     159                        content = content.replace( /<\/div>\s*/g, '</div>\n' );
     160                        content = content.replace( /\s*\[caption([^\[]+)\[\/caption\]\s*/gi, '\n\n[caption$1[/caption]\n\n' );
     161                        content = content.replace( /caption\]\n\n+\[caption/g, 'caption]\n\n[caption' );
    167162
    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>' );
     163                        blocklist2 = 'blockquote|ul|ol|li|table|thead|tbody|tfoot|tr|th|td|h[1-6]|pre|fieldset';
     164                        content = content.replace( new RegExp('\\s*<((?:' + blocklist2 + ')(?: [^>]*)?)\\s*>', 'g' ), '\n<$1>' );
     165                        content = content.replace( new RegExp('\\s*</(' + blocklist2 + ')>\\s*', 'g' ), '</$1>\n' );
     166                        content = content.replace( /<li([^>]*)>/g, '\t<li$1>' );
    172167
    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                 }
     168                        if ( content.indexOf( '<option' ) !== -1 ) {
     169                                content = content.replace( /\s*<option/g, '\n<option' );
     170                                content = content.replace( /\s*<\/select>/g, '\n</select>' );
     171                        }
    177172
    178                 if ( content.indexOf( '<hr' ) !== -1 ) {
    179                         content = content.replace( /\s*<hr( [^>]*)?>\s*/g, '\n\n<hr$1>\n\n' );
    180                 }
     173                        if ( content.indexOf( '<hr' ) !== -1 ) {
     174                                content = content.replace( /\s*<hr( [^>]*)?>\s*/g, '\n\n<hr$1>\n\n' );
     175                        }
    181176
    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                 }
     177                        if ( content.indexOf( '<object' ) !== -1 ) {
     178                                content = content.replace( /<object[\s\S]+?<\/object>/g, function( a ) {
     179                                        return a.replace( /[\r\n]+/g, '' );
     180                                });
     181                        }
    187182
    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' );
     183                        // Unmark special paragraph closing tags
     184                        content = content.replace( /<\/p#>/g, '</p>\n' );
     185                        content = content.replace( /\s*(<p [^>]+>[\s\S]*?<\/p>)/g, '\n$1' );
    191186
    192                 // Trim whitespace
    193                 content = content.replace( /^\s+/, '' );
    194                 content = content.replace( /[\s\u00a0]+$/, '' );
     187                        // Trim whitespace
     188                        content = content.replace( /^\s+/, '' );
     189                        content = content.replace( /[\s\u00a0]+$/, '' );
    195190
    196                 // put back the line breaks in pre|script
    197                 if ( preserve_linebreaks ) {
    198                         content = content.replace( /<wp-line-break>/g, '\n' );
    199                 }
     191                        // put back the line breaks in pre|script
     192                        if ( preserve_linebreaks ) {
     193                                content = content.replace( /<wp-line-break>/g, '\n' );
     194                        }
    200195
    201                 // and the <br> tags in captions
    202                 if ( preserve_br ) {
    203                         content = content.replace( /<wp-temp-br([^>]*)>/g, '<br$1>' );
     196                        // and the <br> tags in captions
     197                        if ( preserve_br ) {
     198                                content = content.replace( /<wp-temp-br([^>]*)>/g, '<br$1>' );
     199                        }
     200
     201                        return content;
    204202                }
    205203
    206                 return content;
    207         },
     204                function _wpautop( pee ) {
     205                        var preserve_linebreaks = false,
     206                                preserve_br = false,
     207                                blocklist = 'table|thead|tfoot|caption|col|colgroup|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li|pre' +
     208                                        '|form|map|area|blockquote|address|math|style|p|h[1-6]|hr|fieldset|legend|section' +
     209                                        '|article|aside|hgroup|header|footer|nav|figure|figcaption|details|menu|summary';
    208210
    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';
     211                        if ( pee.indexOf( '<object' ) !== -1 ) {
     212                                pee = pee.replace( /<object[\s\S]+?<\/object>/g, function( a ) {
     213                                        return a.replace( /[\r\n]+/g, '' );
     214                                });
     215                        }
    215216
    216                 if ( pee.indexOf( '<object' ) !== -1 ) {
    217                         pee = pee.replace( /<object[\s\S]+?<\/object>/g, function( a ) {
    218                                 return a.replace( /[\r\n]+/g, '' );
     217                        pee = pee.replace( /<[^<>]+>/g, function( a ){
     218                                return a.replace( /[\r\n]+/g, ' ' );
    219219                        });
    220                 }
    221220
    222                 pee = pee.replace( /<[^<>]+>/g, function( a ){
    223                         return a.replace( /[\r\n]+/g, ' ' );
    224                 });
     221                        // Protect pre|script tags
     222                        if ( pee.indexOf( '<pre' ) !== -1 || pee.indexOf( '<script' ) !== -1 ) {
     223                                preserve_linebreaks = true;
     224                                pee = pee.replace( /<(pre|script)[^>]*>[\s\S]+?<\/\1>/g, function( a ) {
     225                                        return a.replace( /(\r\n|\n)/g, '<wp-line-break>' );
     226                                });
     227                        }
    225228
    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                 }
     229                        // keep <br> tags inside captions and convert line breaks
     230                        if ( pee.indexOf( '[caption' ) !== -1 ) {
     231                                preserve_br = true;
     232                                pee = pee.replace( /\[caption[\s\S]+?\[\/caption\]/g, function( a ) {
     233                                        // keep existing <br>
     234                                        a = a.replace( /<br([^>]*)>/g, '<wp-temp-br$1>' );
     235                                        // no line breaks inside HTML tags
     236                                        a = a.replace( /<[a-zA-Z0-9]+( [^<>]+)?>/g, function( b ) {
     237                                                return b.replace( /[\r\n\t]+/, ' ' );
     238                                        });
     239                                        // convert remaining line breaks to <br>
     240                                        return a.replace( /\s*\n\s*/g, '<wp-temp-br />' );
     241                                });
     242                        }
    233243
    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 />' );
     244                        pee = pee + '\n\n';
     245                        pee = pee.replace( /<br \/>\s*<br \/>/gi, '\n\n' );
     246                        pee = pee.replace( new RegExp( '(<(?:' + blocklist + ')(?: [^>]*)?>)', 'gi' ), '\n$1' );
     247                        pee = pee.replace( new RegExp( '(</(?:' + blocklist + ')>)', 'gi' ), '$1\n\n' );
     248                        pee = pee.replace( /<hr( [^>]*)?>/gi, '<hr$1>\n\n' ); // hr is self closing block element
     249                        pee = pee.replace( /\s*<option/gi, '<option' ); // No <p> or <br> around <option>
     250                        pee = pee.replace( /<\/option>\s*/gi, '</option>' );
     251                        pee = pee.replace( /\r\n|\r/g, '\n' );
     252                        pee = pee.replace( /\n\s*\n+/g, '\n\n' );
     253                        pee = pee.replace( /([\s\S]+?)\n\n/g, '<p>$1</p>\n' );
     254                        pee = pee.replace( /<p>\s*?<\/p>/gi, '');
     255                        pee = pee.replace( new RegExp( '<p>\\s*(</?(?:' + blocklist + ')(?: [^>]*)?>)\\s*</p>', 'gi' ), '$1' );
     256                        pee = pee.replace( /<p>(<li.+?)<\/p>/gi, '$1');
     257                        pee = pee.replace( /<p>\s*<blockquote([^>]*)>/gi, '<blockquote$1><p>');
     258                        pee = pee.replace( /<\/blockquote>\s*<\/p>/gi, '</p></blockquote>');
     259                        pee = pee.replace( new RegExp( '<p>\\s*(</?(?:' + blocklist + ')(?: [^>]*)?>)', 'gi' ), '$1' );
     260                        pee = pee.replace( new RegExp( '(</?(?:' + blocklist + ')(?: [^>]*)?>)\\s*</p>', 'gi' ), '$1' );
     261                        pee = pee.replace( /\s*\n/gi, '<br />\n');
     262                        pee = pee.replace( new RegExp( '(</?(?:' + blocklist + ')[^>]*>)\\s*<br />', 'gi' ), '$1' );
     263                        pee = pee.replace( /<br \/>(\s*<\/?(?:p|li|div|dl|dd|dt|th|pre|td|ul|ol)>)/gi, '$1' );
     264                        pee = pee.replace( /(?:<p>|<br ?\/?>)*\s*\[caption([^\[]+)\[\/caption\]\s*(?:<\/p>|<br ?\/?>)*/gi, '[caption$1[/caption]' );
     265
     266                        pee = pee.replace( /(<(?:div|th|td|form|fieldset|dd)[^>]*>)(.*?)<\/p>/g, function( a, b, c ) {
     267                                if ( c.match( /<p( [^>]*)?>/ ) ) {
     268                                        return a;
     269                                }
     270
     271                                return b + '<p>' + c + '</p>';
    246272                        });
    247                 }
    248273
    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]' );
     274                        // put back the line breaks in pre|script
     275                        if ( preserve_linebreaks ) {
     276                                pee = pee.replace( /<wp-line-break>/g, '\n' );
     277                        }
    270278
    271                 pee = pee.replace( /(<(?:div|th|td|form|fieldset|dd)[^>]*>)(.*?)<\/p>/g, function( a, b, c ) {
    272                         if ( c.match( /<p( [^>]*)?>/ ) ) {
    273                                 return a;
     279                        if ( preserve_br ) {
     280                                pee = pee.replace( /<wp-temp-br([^>]*)>/g, '<br$1>' );
    274281                        }
    275282
    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' );
     283                        return pee;
    282284                }
    283285
    284                 if ( preserve_br ) {
    285                         pee = pee.replace( /<wp-temp-br([^>]*)>/g, '<br$1>' );
    286                 }
     286                function preWpautop( content ) {
     287                        var obj = { o: exports, data: content, unfiltered: content };
    287288
    288                 return pee;
    289         },
     289                        if ( $ ) {
     290                                $( 'body' ).trigger( 'beforePreWpautop', [ obj ] );
     291                        }
    290292
    291         pre_wpautop: function( content ) {
    292                 var t = this, o = { o: t, data: content, unfiltered: content },
    293                         q = typeof( jQuery ) !== 'undefined';
     293                        obj.data = _preWpautop( obj.data );
    294294
    295                 if ( q ) {
    296                         jQuery( 'body' ).trigger( 'beforePreWpautop', [ o ] );
     295                        if ( $ ) {
     296                                $( 'body' ).trigger( 'afterPreWpautop', [ obj ] );
     297                        }
     298
     299                        return obj.data;
    297300                }
    298301
    299                 o.data = t._wp_Nop( o.data );
     302                function wpautop( content ) {
     303                        var obj = { o: exports, data: content, unfiltered: content };
    300304
    301                 if ( q ) {
    302                         jQuery('body').trigger('afterPreWpautop', [ o ] );
    303                 }
     305                        if ( $ ) {
     306                                $( 'body' ).trigger( 'beforeWpautop', [ obj ] );
     307                        }
    304308
    305                 return o.data;
    306         },
     309                        obj.data = _wpautop( obj.data );
    307310
    308         wpautop: function( pee ) {
    309                 var t = this, o = { o: t, data: pee, unfiltered: pee },
    310                         q = typeof( jQuery ) !== 'undefined';
     311                        if ( $ ) {
     312                                $( 'body' ).trigger( 'afterWpautop', [ obj ] );
     313                        }
    311314
    312                 if ( q ) {
    313                         jQuery( 'body' ).trigger('beforeWpautop', [ o ] );
     315                        return obj.data;
    314316                }
    315317
    316                 o.data = t._wp_Autop( o.data );
    317 
    318                 if ( q ) {
    319                         jQuery( 'body' ).trigger('afterWpautop', [ o ] );
     318                if ( $ ) {
     319                        $( document ).ready( init );
     320                } else if ( document.addEventListener ) {
     321                        document.addEventListener( 'DOMContentLoaded', init, false );
     322                        window.addEventListener( 'load', init, false );
     323                } else if ( window.attachEvent ) {
     324                        window.attachEvent( 'onload', init );
     325                        document.attachEvent( 'onreadystatechange', function() {
     326                                if ( 'complete' === document.readyState ) {
     327                                        init();
     328                                }
     329                        } );
    320330                }
    321331
    322                 return o.data;
     332                exports = {
     333                        wpautop: wpautop,
     334                        preWpautop: preWpautop,
     335
     336                        // Back-compat
     337                        go: switchEditor,
     338                        pre_wpautop: preWpautop,
     339                        _wp_Autop: _wpautop,
     340                        _wp_Nop: _preWpautop
     341                };
     342
     343                return exports;
    323344        }
    324 };
     345
     346        window.switchEditors = new switchEditors();
     347}( window.jQuery ));
  • src/wp-includes/class-wp-editor.php

     
    137137         * @param array $settings See the _parse_settings() method for description.
    138138         */
    139139        public static function editor( $content, $editor_id, $settings = array() ) {
    140 
    141140                $set = self::parse_settings( $editor_id, $settings );
    142                 $editor_class = ' class="' . trim( $set['editor_class'] . ' wp-editor-area' ) . '"';
     141                $editor_class = ' class="' . esc_attr( trim( $set['editor_class'] ) ) . ' wp-editor-area"';
    143142                $tabindex = $set['tabindex'] ? ' tabindex="' . (int) $set['tabindex'] . '"' : '';
    144143                $switch_class = 'html-active';
    145144                $toolbar = $buttons = $autocomplete = '';
     145                $default_editor = null;
     146                $editor_id_attr = esc_attr( $editor_id );
    146147
    147148                if ( $set['drag_drop_upload'] ) {
    148149                        self::$drag_drop_upload = true;
    149150                }
    150151
    151                 if ( ! empty( $set['editor_height'] ) )
    152                         $height = ' style="height: ' . $set['editor_height'] . 'px"';
    153                 else
    154                         $height = ' rows="' . $set['textarea_rows'] . '"';
     152                if ( ! empty( $set['editor_height'] ) ) {
     153                        $height = ' style="height: ' . (int) $set['editor_height'] . 'px"';
     154                } else {
     155                        $height = ' rows="' . (int) $set['textarea_rows'] . '"';
     156                }
    155157
    156                 if ( !current_user_can( 'upload_files' ) )
     158                if ( ! current_user_can( 'upload_files' ) ) {
    157159                        $set['media_buttons'] = false;
     160                }
    158161
    159                 if ( ! self::$this_quicktags && self::$this_tinymce ) {
    160                         $switch_class = 'tmce-active';
     162                if ( self::$this_tinymce ) {
    161163                        $autocomplete = ' autocomplete="off"';
    162                 } elseif ( self::$this_quicktags && self::$this_tinymce ) {
    163164                        $default_editor = $set['default_editor'] ? $set['default_editor'] : wp_default_editor();
    164                         $autocomplete = ' autocomplete="off"';
    165165
    166                         // 'html' is used for the "Text" editor tab.
    167                         if ( 'html' === $default_editor ) {
    168                                 add_filter('the_editor_content', 'wp_htmledit_pre');
    169                                 $switch_class = 'html-active';
     166                        if ( self::$this_quicktags ) {
     167                                // 'html' is used for the "Text" editor tab.
     168                                if ( 'html' !== $default_editor ) {
     169                                        $switch_class = 'tmce-active';
     170                                }
     171
     172                                $buttons .= '<button type="button" id="' . $editor_id_attr . '-tmce" class="wp-switch-editor switch-tmce"' .
     173                                        ' data-wp-editor-id="' . $editor_id_attr . '">' . __('Visual') . "</button>\n";
     174                                $buttons .= '<button type="button" id="' . $editor_id_attr . '-html" class="wp-switch-editor switch-html"' .
     175                                        ' data-wp-editor-id="' . $editor_id_attr . '">' . _x( 'Text', 'Name for the Text editor tab (formerly HTML)' ) . "</button>\n";
    170176                        } else {
    171                                 add_filter('the_editor_content', 'wp_richedit_pre');
    172177                                $switch_class = 'tmce-active';
    173178                        }
    174 
    175                         $buttons .= '<button type="button" id="' . $editor_id . '-tmce" class="wp-switch-editor switch-tmce" onclick="switchEditors.switchto(this);">' . __('Visual') . "</button>\n";
    176                         $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";
    177179                }
    178180
    179181                $wrap_class = 'wp-core-ui wp-editor-wrap ' . $switch_class;
     
    182184                        $wrap_class .= ' has-dfw';
    183185                }
    184186
    185                 echo '<div id="wp-' . $editor_id . '-wrap" class="' . $wrap_class . '">';
     187                echo '<div id="wp-' . $editor_id_attr . '-wrap" class="' . $wrap_class . '">';
    186188
    187189                if ( self::$editor_buttons_css ) {
    188                         wp_print_styles('editor-buttons');
     190                        wp_print_styles( 'editor-buttons' );
    189191                        self::$editor_buttons_css = false;
    190192                }
    191193
    192                 if ( !empty($set['editor_css']) )
     194                if ( ! empty( $set['editor_css'] ) ) {
    193195                        echo $set['editor_css'] . "\n";
     196                }
    194197
    195                 if ( !empty($buttons) || $set['media_buttons'] ) {
    196                         echo '<div id="wp-' . $editor_id . '-editor-tools" class="wp-editor-tools hide-if-no-js">';
     198                if ( ! empty( $buttons ) || $set['media_buttons'] ) {
     199                        echo '<div id="wp-' . $editor_id_attr . '-editor-tools" class="wp-editor-tools hide-if-no-js">';
    197200
    198201                        if ( $set['media_buttons'] ) {
    199202                                self::$has_medialib = true;
    200203
    201                                 if ( !function_exists('media_buttons') )
    202                                         include(ABSPATH . 'wp-admin/includes/media.php');
     204                                if ( ! function_exists( 'media_buttons' ) )
     205                                        include( ABSPATH . 'wp-admin/includes/media.php' );
    203206
    204                                 echo '<div id="wp-' . $editor_id . '-media-buttons" class="wp-media-buttons">';
     207                                echo '<div id="wp-' . $editor_id_attr . '-media-buttons" class="wp-media-buttons">';
    205208
    206209                                /**
    207210                                 * Fires after the default media button(s) are displayed.
     
    218221                        echo "</div>\n";
    219222                }
    220223
     224                $quicktags_toolbar = '';
     225
     226                if ( self::$this_quicktags ) {
     227                        if ( 'content' === $editor_id && ! empty( $GLOBALS['current_screen'] ) && $GLOBALS['current_screen']->base === 'post' ) {
     228                                $toolbar_id = 'ed_toolbar';
     229                        } else {
     230                                $toolbar_id = 'qt_' . $editor_id_attr . '_toolbar';
     231                        }
     232
     233                        $quicktags_toolbar = '<div id="' . $toolbar_id . '" class="quicktags-toolbar"></div>';
     234                }
     235
    221236                /**
    222237                 * Filter the HTML markup output that displays the editor.
    223238                 *
     
    225240                 *
    226241                 * @param string $output Editor's HTML markup.
    227242                 */
    228                 $the_editor = apply_filters( 'the_editor', '<div id="wp-' . $editor_id . '-editor-container" class="wp-editor-container">' .
    229                         '<textarea' . $editor_class . $height . $tabindex . $autocomplete . ' cols="40" name="' . $set['textarea_name'] . '" ' .
    230                         'id="' . $editor_id . '">%s</textarea></div>' );
     243                $the_editor = apply_filters( 'the_editor', '<div id="wp-' . $editor_id_attr . '-editor-container" class="wp-editor-container">' .
     244                        $quicktags_toolbar .
     245                        '<textarea' . $editor_class . $height . $tabindex . $autocomplete . ' cols="40" name="' . esc_attr( $set['textarea_name'] ) . '" ' .
     246                        'id="' . $editor_id_attr . '">%s</textarea></div>' );
    231247
    232248                /**
    233249                 * Filter the default editor content.
     
    238254                 */
    239255                $content = apply_filters( 'the_editor_content', $content );
    240256
     257                // Back-compat for the `htmledit_pre` and `richedit_pre` filters
     258                if ( 'html' === $default_editor && has_filter( 'htmledit_pre' ) ) {
     259                        // TODO: needs _deprecated_filter(), use _deprecated_function() as substitute for now
     260                        _deprecated_function( 'add_filter( htmledit_pre )', '4.3.0', 'add_filter( format_for_editor )' );
     261                        $content = apply_filters( 'htmledit_pre', $content );
     262                } elseif ( null !== $default_editor && has_filter( 'richedit_pre' ) ) {
     263                        _deprecated_function( 'add_filter( richedit_pre )', '4.3.0', 'add_filter( format_for_editor )' );
     264                        $content = apply_filters( 'richedit_pre', $content );
     265                }
     266
    241267                printf( $the_editor, $content );
    242268                echo "\n</div>\n\n";
    243269
     
    470496                                        'theme' => 'modern',
    471497                                        'skin' => 'lightgray',
    472498                                        'language' => self::$mce_locale,
    473                                         'formats' => "{
    474                                                 alignleft: [
    475                                                         {selector: 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li', styles: {textAlign:'left'}},
    476                                                         {selector: 'img,table,dl.wp-caption', classes: 'alignleft'}
    477                                                 ],
    478                                                 aligncenter: [
    479                                                         {selector: 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li', styles: {textAlign:'center'}},
    480                                                         {selector: 'img,table,dl.wp-caption', classes: 'aligncenter'}
    481                                                 ],
    482                                                 alignright: [
    483                                                         {selector: 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li', styles: {textAlign:'right'}},
    484                                                         {selector: 'img,table,dl.wp-caption', classes: 'alignright'}
    485                                                 ],
    486                                                 strikethrough: {inline: 'del'}
    487                                         }",
     499                                        'formats' => '{' .
     500                                                'alignleft: [' .
     501                                                        '{selector: "p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li", styles: {textAlign:"left"}},' .
     502                                                        '{selector: "img,table,dl.wp-caption", classes: "alignleft"}' .
     503                                                '],' .
     504                                                'aligncenter: [' .
     505                                                        '{selector: "p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li", styles: {textAlign:"center"}},' .
     506                                                        '{selector: "img,table,dl.wp-caption", classes: "aligncenter"}' .
     507                                                '],' .
     508                                                'alignright: [' .
     509                                                        '{selector: "p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li", styles: {textAlign:"right"}},' .
     510                                                        '{selector: "img,table,dl.wp-caption", classes: "alignright"}' .
     511                                                '],' .
     512                                                'strikethrough: {inline: "del"}' .
     513                                        '}',
    488514                                        'relative_urls' => false,
    489515                                        'remove_script_host' => false,
    490516                                        'convert_urls' => false,
     
    654680                                'body_class' => $body_class
    655681                        );
    656682
    657                         if ( $first_run )
    658                                 $mceInit = array_merge( self::$first_init, $mceInit );
     683                        // Merge with the first part of the init array
     684                        $mceInit = array_merge( self::$first_init, $mceInit );
    659685
    660686                        if ( is_array( $set['tinymce'] ) )
    661687                                $mceInit = array_merge( $mceInit, $set['tinymce'] );
     
    666692                         * before tinyMCE.init. Setting "valid_elements", "invalid_elements"
    667693                         * and "extended_valid_elements" can be done through this filter. Best
    668694                         * is to use the default cleanup by not specifying valid_elements,
    669                          * as TinyMCE contains full set of XHTML 1.0.
     695                         * as TinyMCE checks against the full set of HTML 5.0 elements and attributes.
    670696                         */
    671697                        if ( $set['teeny'] ) {
    672698
     
    11661192                ?>
    11671193
    11681194                ( function() {
    1169                         var init, edId, qtId, firstInit, wrapper;
     1195                        var init, id;
    11701196
    11711197                        if ( typeof tinymce !== 'undefined' ) {
    1172                                 for ( edId in tinyMCEPreInit.mceInit ) {
    1173                                         if ( firstInit ) {
    1174                                                 init = tinyMCEPreInit.mceInit[edId] = tinymce.extend( {}, firstInit, tinyMCEPreInit.mceInit[edId] );
    1175                                         } else {
    1176                                                 init = firstInit = tinyMCEPreInit.mceInit[edId];
    1177                                         }
     1198                                for ( id in tinyMCEPreInit.mceInit ) {
     1199                                        init = tinyMCEPreInit.mceInit[id];
    11781200
    1179                                         wrapper = tinymce.DOM.select( '#wp-' + edId + '-wrap' )[0];
     1201                                        if ( ! init.wp_skip_init ) {
     1202                                                tinymce.init( init );
    11801203
    1181                                         if ( ( tinymce.DOM.hasClass( wrapper, 'tmce-active' ) || ! tinyMCEPreInit.qtInit.hasOwnProperty( edId ) ) &&
    1182                                                 ! init.wp_skip_init ) {
    1183 
    1184                                                 try {
    1185                                                         tinymce.init( init );
    1186 
    1187                                                         if ( ! window.wpActiveEditor ) {
    1188                                                                 window.wpActiveEditor = edId;
    1189                                                         }
    1190                                                 } catch(e){}
     1204                                                if ( ! window.wpActiveEditor ) {
     1205                                                        window.wpActiveEditor = id;
     1206                                                }
    11911207                                        }
    11921208                                }
    11931209                        }
    11941210
    11951211                        if ( typeof quicktags !== 'undefined' ) {
    1196                                 for ( qtId in tinyMCEPreInit.qtInit ) {
    1197                                         try {
    1198                                                 quicktags( tinyMCEPreInit.qtInit[qtId] );
     1212                                for ( id in tinyMCEPreInit.qtInit ) {
     1213                                        quicktags( tinyMCEPreInit.qtInit[id] );
    11991214
    1200                                                 if ( ! window.wpActiveEditor ) {
    1201                                                         window.wpActiveEditor = qtId;
    1202                                                 }
    1203                                         } catch(e){};
    1204                                 }
    1205                         }
    1206 
    1207                         if ( typeof jQuery !== 'undefined' ) {
    1208                                 jQuery('.wp-editor-wrap').on( 'click.wp-editor', function() {
    1209                                         if ( this.id ) {
    1210                                                 window.wpActiveEditor = this.id.slice( 3, -5 );
     1215                                        if ( ! window.wpActiveEditor ) {
     1216                                                window.wpActiveEditor = id;
    12111217                                        }
    1212                                 });
    1213                         } else {
    1214                                 for ( qtId in tinyMCEPreInit.qtInit ) {
    1215                                         document.getElementById( 'wp-' + qtId + '-wrap' ).onclick = function() {
    1216                                                 window.wpActiveEditor = this.id.slice( 3, -5 );
    1217                                         }
    12181218                                }
    12191219                        }
    12201220                }());
  • src/wp-includes/css/editor.css

     
    286286.mce-path-item,
    287287.mce-path .mce-divider {
    288288        font-size: 12px;
    289         line-height: 18px;
    290289}
    291290
    292291.mce-toolbar .mce-btn,
     
    10661065        position: relative;
    10671066        border-bottom: 1px solid #dedede;
    10681067        background: #f5f5f5;
     1068        min-height: 30px;
    10691069}
    10701070
    10711071.has-dfw .quicktags-toolbar {
  • src/wp-includes/default-filters.php

     
    346346add_action( 'before_delete_post', '_reset_front_page_settings_for_post' );
    347347add_action( 'wp_trash_post',      '_reset_front_page_settings_for_post' );
    348348
     349// Prepare the content for both Visual and Text editors
     350add_filter( 'the_editor_content', 'format_for_editor' );
     351
    349352// Post Formats
    350353add_filter( 'request', '_post_format_request' );
    351354add_filter( 'term_link', '_post_format_link', 10, 3 );
  • src/wp-includes/deprecated.php

     
    34913491
    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
  • src/wp-includes/formatting.php

     
    29802980}
    29812981
    29822982/**
    2983  * Formats text for the rich text editor.
     2983 * Formats text for the editor.
    29842984 *
    2985  * The filter 'richedit_pre' is applied here. If $text is empty the filter will
     2985 * The filter 'format_for_editor' is applied here. If $text is empty the filter will
    29862986 * be applied to an empty string.
    29872987 *
    2988  * @since 2.0.0
     2988 * @since 4.3.0
    29892989 *
    29902990 * @param string $text The text to be formatted.
    29912991 * @return string The formatted text after filter is applied.
    29922992 */
    2993 function wp_richedit_pre($text) {
    2994         if ( empty( $text ) ) {
    2995                 /**
    2996                  * Filter text returned for the rich text editor.
    2997                  *
    2998                  * This filter is first evaluated, and the value returned, if an empty string
    2999                  * is passed to wp_richedit_pre(). If an empty string is passed, it results
    3000                  * in a break tag and line feed.
    3001                  *
    3002                  * If a non-empty string is passed, the filter is evaluated on the wp_richedit_pre()
    3003                  * return after being formatted.
    3004                  *
    3005                  * @since 2.0.0
    3006                  *
    3007                  * @param string $output Text for the rich text editor.
    3008                  */
    3009                 return apply_filters( 'richedit_pre', '' );
     2993function format_for_editor( $text ) {
     2994        if ( ! empty( $text ) ) {
     2995                $text = htmlspecialchars( $text, ENT_NOQUOTES, get_option( 'blog_charset' ) ); // convert only < > &
    30102996        }
    30112997
    3012         $output = convert_chars($text);
    3013         $output = wpautop($output);
    3014         $output = htmlspecialchars($output, ENT_NOQUOTES, get_option( 'blog_charset' ) );
    3015 
    3016         /** This filter is documented in wp-includes/formatting.php */
    3017         return apply_filters( 'richedit_pre', $output );
    3018 }
    3019 
    3020 /**
    3021  * Formats text for the HTML editor.
    3022  *
    3023  * Unless $output is empty it will pass through htmlspecialchars before the
    3024  * 'htmledit_pre' filter is applied.
    3025  *
    3026  * @since 2.5.0
    3027  *
    3028  * @param string $output The text to be formatted.
    3029  * @return string Formatted text after filter applied.
    3030  */
    3031 function wp_htmledit_pre($output) {
    3032         if ( !empty($output) )
    3033                 $output = htmlspecialchars($output, ENT_NOQUOTES, get_option( 'blog_charset' ) ); // convert only < > &
    3034 
    30352998        /**
    3036          * Filter the text before it is formatted for the HTML editor.
     2999         * Filter the text after it is formatted for the editor.
    30373000         *
    3038          * @since 2.5.0
     3001         * @since 4.3.0
    30393002         *
    3040          * @param string $output The HTML-formatted text.
     3003         * @param string $text The formatted text.
    30413004         */
    3042         return apply_filters( 'htmledit_pre', $output );
     3005        return apply_filters( 'format_for_editor', $text );
    30433006}
    30443007
    30453008/**
  • src/wp-includes/js/quicktags.js

     
    163163                        id = settings.id,
    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 ) {
    169169                        return false;
     
    182182                        toolbar_id = name + '_toolbar';
    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 );
    191186
     187                if ( ! tb ) {
     188                        tb = document.createElement('div');
     189                        tb.id = toolbar_id;
     190                        tb.className = 'quicktags-toolbar';
     191                }
     192
    192193                canvas.parentNode.insertBefore(tb, canvas);
    193194                t.toolbar = tb;
    194195
     
    214215                        }
    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
    223238                t.getButton = function(id) {
  • src/wp-includes/js/tinymce/plugins/wordpress/plugin.js

     
    88                each = tinymce.each,
    99                __ = editor.editorManager.i18n.translate,
    1010                wpAdvButton, style,
     11                hasWpautop = ( editor.getParam( 'wpautop', true ) && typeof window.switchEditors !== 'undefined' ),
     12                jq = window.jQuery,
    1113                last = 0;
    1214
    13         if ( typeof window.jQuery !== 'undefined' ) {
    14                 window.jQuery( document ).triggerHandler( 'tinymce-editor-setup', [ editor ] );
     15        if ( jq ) {
     16                jq( document ).triggerHandler( 'tinymce-editor-setup', [ editor ] );
    1517        }
    1618
    1719        function toggleToolbars( state ) {
     
    8991    });
    9092
    9193        // Replace Read More/Next Page tags with images
    92         editor.on( 'BeforeSetContent', function( e ) {
    93                 var title;
     94        editor.on( 'BeforeSetContent', function( event ) {
     95                var title,
     96                        paragraph = tinymce.Env.webkit ? '<p><br /></p>' : '<p></p>';
    9497
    95                 if ( e.content ) {
    96                         if ( e.content.indexOf( '<!--more' ) !== -1 ) {
     98                if ( event.content ) {
     99                        if ( event.content.indexOf( '<!--more' ) !== -1 ) {
    97100                                title = __( 'Read more...' );
    98101
    99                                 e.content = e.content.replace( /<!--more(.*?)-->/g, function( match, moretext ) {
     102                                event.content = event.content.replace( /<!--more(.*?)-->/g, function( match, moretext ) {
    100103                                        return '<img src="' + tinymce.Env.transparentSrc + '" data-wp-more="more" data-wp-more-text="' + moretext + '" ' +
    101104                                                'class="wp-more-tag mce-wp-more" title="' + title + '" data-mce-resize="false" data-mce-placeholder="1" />';
    102105                                });
    103106                        }
    104107
    105                         if ( e.content.indexOf( '<!--nextpage-->' ) !== -1 ) {
     108                        if ( event.content.indexOf( '<!--nextpage-->' ) !== -1 ) {
    106109                                title = __( 'Page break' );
    107110
    108                                 e.content = e.content.replace( /<!--nextpage-->/g,
     111                                event.content = event.content.replace( /<!--nextpage-->/g,
    109112                                        '<img src="' + tinymce.Env.transparentSrc + '" data-wp-more="nextpage" class="wp-more-tag mce-wp-nextpage" ' +
    110113                                                'title="' + title + '" data-mce-resize="false" data-mce-placeholder="1" />' );
    111114                        }
     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 = window.switchEditors.wpautop( event.content );
     121                        }
    112122                }
    113123        });
    114124
     
    289299                        doc = editor.getDoc(),
    290300                        dom = editor.dom;
    291301
    292                 if ( tinymce.Env.iOS ) {
     302                if ( env.iOS ) {
    293303                        dom.addClass( doc.documentElement, 'ios' );
    294304                }
    295305
     
    318328                        }
    319329                });
    320330
     331                // Start hidden when the Text editor is set to load first.
     332                if ( tinymce.$( '#wp-' + editor.id + '-wrap' ).hasClass( 'html-active' ) ) {
     333                        editor.hide();
     334                }
     335
    321336                // Remove invalid parent paragraphs when inserting HTML
    322                 // TODO: still needed?
    323                 editor.on( 'BeforeSetContent', function( e ) {
    324                         if ( e.content ) {
    325                                 e.content = e.content.replace(/<p>\s*<(p|div|ul|ol|dl|table|blockquote|h[1-6]|fieldset|pre|address)( [^>]*)?>/gi, '<$1$2>');
    326                                 e.content = e.content.replace(/<\/(p|div|ul|ol|dl|table|blockquote|h[1-6]|fieldset|pre|address)>\s*<\/p>/gi, '</$1>');
     337                editor.on( 'BeforeSetContent', function( event ) {
     338                        if ( event.content ) {
     339                                event.content = event.content.replace( /<p>\s*<(p|div|ul|ol|dl|table|blockquote|h[1-6]|fieldset|pre)( [^>]*)?>/gi, '<$1$2>' )
     340                                        .replace( /<\/(p|div|ul|ol|dl|table|blockquote|h[1-6]|fieldset|pre)>\s*<\/p>/gi, '</$1>' );
    327341                        }
    328342                });
    329343
    330                 if ( typeof window.jQuery !== 'undefined' ) {
    331                         window.jQuery( document ).triggerHandler( 'tinymce-editor-init', [editor] );
     344                if ( jq ) {
     345                        jq( document ).triggerHandler( 'tinymce-editor-init', [editor] );
    332346                }
    333347
    334348                if ( window.tinyMCEPreInit && window.tinyMCEPreInit.dragDropUpload ) {
    335349                        dom.bind( doc, 'dragstart dragend dragover drop', function( event ) {
    336                                 if ( typeof window.jQuery !== 'undefined' ) {
     350                                if ( jq ) {
    337351                                        // Trigger the jQuery handlers.
    338                                         window.jQuery( document ).trigger( new window.jQuery.Event( event ) );
     352                                        jq( document ).trigger( new jq.Event( event ) );
    339353                                }
    340354                        });
    341355                }
     
    364378        });
    365379
    366380        // Word count
    367         if ( typeof window.jQuery !== 'undefined' ) {
     381        if ( jq ) {
    368382                editor.on( 'keyup', function( e ) {
    369383                        var key = e.keyCode || e.charCode;
    370384
     
    373387                        }
    374388
    375389                        if ( 13 === key || 8 === last || 46 === last ) {
    376                                 window.jQuery( document ).triggerHandler( 'wpcountwords', [ editor.getContent({ format : 'raw' }) ] );
     390                                jq( document ).triggerHandler( 'wpcountwords', [ editor.getContent({ format : 'raw' }) ] );
    377391                        }
    378392
    379393                        last = key;
     
    390404                // Keep empty paragraphs :(
    391405                e.content = e.content.replace( /<p>(?:<br ?\/?>|\u00a0|\uFEFF| )*<\/p>/g, '<p>&nbsp;</p>' );
    392406
    393                 if ( editor.getParam( 'wpautop', true ) && typeof window.switchEditors !== 'undefined' ) {
     407                if ( hasWpautop ) {
    394408                        e.content = window.switchEditors.pre_wpautop( e.content );
    395409                }
    396410        });
    397411
    398         // Remove spaces from empty paragraphs.
    399         editor.on( 'BeforeSetContent', function( event ) {
    400                 var paragraph = tinymce.Env.webkit ? '<p><br /></p>' : '<p></p>';
    401 
    402                 if ( event.content ) {
    403                         event.content = event.content.replace( /<p>(?:&nbsp;|\u00a0|\uFEFF|\s)+<\/p>/gi, paragraph );
    404                 }
    405         });
    406 
    407412        editor.on( 'preInit', function() {
    408413                // Don't replace <i> with <em> and <b> with <strong> and don't remove them when empty
    409414                editor.schema.addValidElements( '@[id|accesskey|class|dir|lang|style|tabindex|title|contenteditable|draggable|dropzone|hidden|spellcheck|translate],i,b' );