Make WordPress Core

Changeset 32899


Ignore:
Timestamp:
06/21/2015 10:00:42 PM (11 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.