Make WordPress Core

Changeset 39911


Ignore:
Timestamp:
01/16/2017 12:48:49 AM (8 years ago)
Author:
azaozz
Message:

Docs: some improvements/fixes for editor.js.

See #38933.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-admin/js/editor.js

    r39738 r39911  
    22( function( $ ) {
    33    /**
    4      * @summary Creates the tinyMCE editors.
     4     * @summary Utility functions for the editor.
    55     *
    6      * Creates the tinyMCE editor and binds all events used for switching
    7      * from visual to text mode.
    8      *
    9      * @since 4.3.0
    10      *
    11      * @class
     6     * @since 2.5.0
    127     */
    138    function SwitchEditors() {
     
    1510            exports = {};
    1611
    17         /**
    18          * @summary Initializes the event binding for switching editors.
    19          *
    20          * @since 4.3.0
    21          *
    22          * @returns {void}
    23          */
    2412        function init() {
    2513            if ( ! tinymce && window.tinymce ) {
     
    2816
    2917                /**
    30                  * @summary Handles onclick events for the editor buttons.
     18                 * @summary Handles onclick events for the Visual/Text tabs.
    3119                 *
    3220                 * @since 4.3.0
    33                  *
    34                  * Handles an onclick event on the document.
    35                  * Switches the editor between visual and text,
    36                  * if the clicked element has the 'wp-switch-editor' class.
    37                  * If the class name is switch-html switches to the HTML editor,
    38                  * if the class name is switch-tmce
    39                  * switches to the TMCE editor.
    4021                 *
    4122                 * @returns {void}
     
    5536
    5637        /**
    57          * @summary Retrieves the height of the toolbar based on the container the
    58          * editor is placed in.
     38         * @summary Returns the height of the editor toolbar(s) in px.
    5939         *
    6040         * @since 3.9.0
    6141         *
    62          * @param {Object} editor The tinyMCE editor.
     42         * @param {Object} editor The TinyMCE editor.
    6343         * @returns {number} If the height is between 10 and 200 return the height,
    6444         * else return 30.
     
    7656
    7757        /**
    78          * @summary Switches the editor between visual and text.
    79          *
    80          * @since 4.3.0
     58         * @summary Switches the editor between Visual and Text mode.
     59         *
     60         * @since 2.5.0
    8161         *
    8262         * @memberof switchEditors
    8363         *
    84          * @param {string} id The id of the editor you want to change the editor mode for.
    85          * If no id is given, it defaults to content.
    86          * @param {string} mode The mode you want to switch to.
    87          * If an undefined mode is given, it defaults to toggle.
    88          *
     64         * @param {string} id The id of the editor you want to change the editor mode for. Default: `content`.
     65         * @param {string} mode The mode you want to switch to. Default: `toggle`.
    8966         * @returns {void}
    9067         */
     
    9976                textarea = $textarea[0];
    10077
    101             // Toggle the mode between visual and textual representation.
    10278            if ( 'toggle' === mode ) {
    10379                if ( editor && ! editor.isHidden() ) {
     
    10884            }
    10985
    110 
    111             // If the mode is tmce or tinymce, show the editor.
    11286            if ( 'tmce' === mode || 'tinymce' === mode ) {
    113 
    114                 /*
    115                  * If the editor isn't hidden we are already in tmce mode
    116                  * and we don't need to switch.
    117                  * Return false to stop event bubbling.
    118                  */
     87                // If the editor is visible we are already in `tinymce` mode.
    11988                if ( editor && ! editor.isHidden() ) {
    12089                    return false;
    12190                }
    12291
    123                 // Close the QuickTags toolbars if they are visible.
     92                // Insert closing tags for any open tags in QuickTags.
    12493                if ( typeof( window.QTags ) !== 'undefined' ) {
    12594                    window.QTags.closeAllTags( id );
     
    131100                    editor.show();
    132101
    133                     // Don't resize the iframe in iOS.
     102                    // No point to resize the iframe in iOS.
    134103                    if ( ! tinymce.Env.iOS && editorHeight ) {
    135104                        toolbarHeight = getToolbarHeight( editor );
    136105                        editorHeight = editorHeight - toolbarHeight + 14;
    137106
    138                         // Height must be between 50 and 5000.
     107                        // Sane limit for the editor height.
    139108                        if ( editorHeight > 50 && editorHeight < 5000 ) {
    140109                            editor.theme.resizeTo( null, editorHeight );
     
    149118                window.setUserSetting( 'editor', 'tinymce' );
    150119
    151             // Hide the editor if mode is html.
    152120            } else if ( 'html' === mode ) {
    153 
    154                 /*
    155                  * If the editor is hidden we are already in html mode and
    156                  * we don't need to switch.
    157                  * Return false to stop event bubbling.
    158                  */
     121                // If the editor is hidden (Quicktags is shown) we don't need to switch.
    159122                if ( editor && editor.isHidden() ) {
    160123                    return false;
     
    162125
    163126                if ( editor ) {
    164 
    165                     // Don't resize the iframe in iOS.
     127                    // Don't resize the textarea in iOS. The iframe is forced to 100% height there, we shouldn't match it.
    166128                    if ( ! tinymce.Env.iOS ) {
    167129                        iframe = editor.iframeElement;
     
    172134                            editorHeight = editorHeight + toolbarHeight - 14;
    173135
    174                             // Height must be between 50 and 5000.
     136                            // Sane limit for the textarea height.
    175137                            if ( editorHeight > 50 && editorHeight < 5000 ) {
    176138                                textarea.style.height = editorHeight + 'px';
     
    181143                    editor.hide();
    182144                } else {
    183                     // The TinyMCE instance doesn't exist, show the textarea.
     145                    // There is probably a JS error on the page. The TinyMCE editor instance doesn't exist. Show the textarea.
    184146                    $textarea.css({ 'display': '', 'visibility': '' });
    185147                }
     
    192154
    193155        /**
    194          * @summary Replaces all paragraphs with double line breaks.
    195          *
    196          * Replaces all paragraphs with double line breaks. Taking into account
    197          * the elements where the <p> should be preserved.
    198          * Unifies all whitespaces.
    199          * Adds indenting with tabs to li, dt and dd elements.
    200          * Trims whitespaces from beginning and end of the html input.
    201          *
    202          * @since 4.3.0
     156         * @summary Replaces <p> tags with two line breaks. "Opposite" of wpautop().
     157         *
     158         * Replaces <p> tags with two line breaks except where the <p> has attributes.
     159         * Unifies whitespace.
     160         * Indents <li>, <dt> and <dd> for better readability.
     161         *
     162         * @since 2.5.0
    203163         *
    204164         * @memberof switchEditors
    205165         *
    206166         * @param {string} html The content from the editor.
    207          * @return {string} The formatted html string.
     167         * @return {string} The content with stripped paragraph tags.
    208168         */
    209169        function removep( html ) {
     
    219179            }
    220180
    221             /*
    222              * Protect script and style tags by replacing them with <wp-preserve>.
    223              * Push matches into the preserve array.
    224              */
     181            // Protect script and style tags.
    225182            if ( html.indexOf( '<script' ) !== -1 || html.indexOf( '<style' ) !== -1 ) {
    226183                html = html.replace( /<(script|style)[^>]*>[\s\S]*?<\/\1>/g, function( match ) {
     
    230187            }
    231188
    232             /*
    233              * Protect pre tags by replacing all newlines and
    234              * <br> tags with <wp-line-break>.
    235              */
     189            // Protect pre tags.
    236190            if ( html.indexOf( '<pre' ) !== -1 ) {
    237191                preserve_linebreaks = true;
     
    243197            }
    244198
    245             /*
    246              * Keep <br> tags inside captions and remove line breaks by replacing
    247              * them with <wp-temp-br>.
    248              */
     199            // Remove line breaks but keep <br> tags inside image captions.
    249200            if ( html.indexOf( '[caption' ) !== -1 ) {
    250201                preserve_br = true;
     
    254205            }
    255206
    256             // Format the text to be readable in the source editor.
     207            // Normalize white space characters before and after block tags.
    257208            html = html.replace( new RegExp( '\\s*</(' + blocklist1 + ')>\\s*', 'g' ), '</$1>\n' );
    258209            html = html.replace( new RegExp( '\\s*<((?:' + blocklist1 + ')(?: [^>]*)?)>', 'g' ), '\n<$1>' );
     
    261212            html = html.replace( /(<p [^>]+>.*?)<\/p>/g, '$1</p#>' );
    262213
    263             // If the content of a container starts with a paragraph, replace the <p> tag with 2 newlines.
     214            // Preserve the first <p> inside a <div>.
    264215            html = html.replace( /<div( [^>]*)?>\s*<p>/gi, '<div$1>\n\n' );
    265216
    266             // Remove <p> and </p> tags.
     217            // Remove paragraph tags.
    267218            html = html.replace( /\s*<p>/gi, '' );
    268219            html = html.replace( /\s*<\/p>\s*/gi, '\n\n' );
    269220
    270             // Remove white spaces between newlines. u00a0 is a no breaking space.
     221            // Normalize white space chars and remove multiple line breaks.
    271222            html = html.replace( /\n[\s\u00a0]+\n/g, '\n\n' );
    272223
    273             // Remove <br> tags.
     224            // Rrplace <br> tags with a line break.
    274225            html = html.replace( /\s*<br ?\/?>\s*/gi, '\n' );
    275226
    276             /*
    277              * Fix some block element newline issues.
    278              * Replace white spaces with newlines in combination with <div> tags.
    279              */
     227            // Fix line breaks around <div>.
    280228            html = html.replace( /\s*<div/g, '\n<div' );
    281229            html = html.replace( /<\/div>\s*/g, '</div>\n' );
    282230
    283             // Replace white spaces with newlines in combination with [caption] shortcodes.
     231            // Fix line breaks around caption shortcodes.
    284232            html = html.replace( /\s*\[caption([^\[]+)\[\/caption\]\s*/gi, '\n\n[caption$1[/caption]\n\n' );
    285 
    286             /*
    287              * Limit the newlines in combination with [caption]'s to a maximum of
    288              * two consecutive occurrences.
    289              * .
    290              */
    291233            html = html.replace( /caption\]\n\n+\[caption/g, 'caption]\n\n[caption' );
    292234
    293             /*
    294              * Replace white spaces with newlines in combination with
    295              * all elements listed in blocklist2.
    296              */
     235            // Pad block elements tags with a line break.
    297236            html = html.replace( new RegExp('\\s*<((?:' + blocklist2 + ')(?: [^>]*)?)\\s*>', 'g' ), '\n<$1>' );
    298237            html = html.replace( new RegExp('\\s*</(' + blocklist2 + ')>\\s*', 'g' ), '</$1>\n' );
    299238
    300             // Add indentation by adding a tab in front of <li>, <dt> and <dd> tags.
     239            // Indent <li>, <dt> and <dd> tags.
    301240            html = html.replace( /<((li|dt|dd)[^>]*)>/g, ' \t<$1>' );
    302241
    303             // Replace white spaces with newlines in combination with <select> and <option> tags.
     242            // Fix line breaks around <select> and <option>.
    304243            if ( html.indexOf( '<option' ) !== -1 ) {
    305244                html = html.replace( /\s*<option/g, '\n<option' );
     
    307246            }
    308247
    309             // Replace white spaces with 2 newlines in combination with <hr> tags.
     248            // Pad <hr> with two line breaks.
    310249            if ( html.indexOf( '<hr' ) !== -1 ) {
    311250                html = html.replace( /\s*<hr( [^>]*)?>\s*/g, '\n\n<hr$1>\n\n' );
    312251            }
    313252
    314             // Remove newlines in <object> tags.
     253            // Remove line breaks in <object> tags.
    315254            if ( html.indexOf( '<object' ) !== -1 ) {
    316255                html = html.replace( /<object[\s\S]+?<\/object>/g, function( a ) {
     
    322261            html = html.replace( /<\/p#>/g, '</p>\n' );
    323262
    324 
    325             // Add a new line before <p> tags when there is content inside the paragraph
     263            // Pad remaining <p> tags whit a line break.
    326264            html = html.replace( /\s*(<p [^>]+>[\s\S]*?<\/p>)/g, '\n$1' );
    327265
    328             /*
    329              * Remove whitespaces at the start and end of a string.
    330              * u00a0 is a no breaking space.
    331              */
     266            // Trim.
    332267            html = html.replace( /^\s+/, '' );
    333268            html = html.replace( /[\s\u00a0]+$/, '' );
    334269
    335             // Replace <wp-line-break> tags with a newline.
    336270            if ( preserve_linebreaks ) {
    337271                html = html.replace( /<wp-line-break>/g, '\n' );
    338272            }
    339273
    340             // Restore the <wp-temp-br> with <br> tags.
    341274            if ( preserve_br ) {
    342275                html = html.replace( /<wp-temp-br([^>]*)>/g, '<br$1>' );
     
    354287
    355288        /**
    356          * @summary Adds paragraph tags to the text.
    357          *
    358          * Adds paragraph tags to the text taking into account block level elements.
    359          * Normalizes the whitespaces and newlines.
     289         * @summary Replaces two line breaks with a paragraph tag and one line break with a <br>.
    360290         *
    361291         * Similar to `wpautop()` in formatting.php.
    362292         *
    363          * @since 4.3.0
     293         * @since 2.5.0
    364294         *
    365295         * @memberof switchEditors
     
    371301            var preserve_linebreaks = false,
    372302                preserve_br = false,
    373 
    374                 // A list containing all block level elements.
    375303                blocklist = 'table|thead|tfoot|caption|col|colgroup|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li|pre' +
    376304                    '|form|map|area|blockquote|address|math|style|p|h[1-6]|hr|fieldset|legend|section' +
     
    380308            text = text.replace( /\r\n|\r/g, '\n' );
    381309
    382             // If there are no newlines, return the text.
    383310            if ( text.indexOf( '\n' ) === -1 ) {
    384311                return text;
    385312            }
    386313
     314            // Remove line breaks from <object>.
    387315            if ( text.indexOf( '<object' ) !== -1 ) {
    388 
    389                 // If there are multiple newlines in an <object>, remove them.
    390316                text = text.replace( /<object[\s\S]+?<\/object>/g, function( a ) {
    391317                    return a.replace( /\n+/g, '' );
     
    393319            }
    394320
    395             // Replace all new lines and tabs with spaces inside tags.
     321            // Remove line breaks from tags.
    396322            text = text.replace( /<[^<>]+>/g, function( a ) {
    397323                return a.replace( /[\n\t ]+/g, ' ' );
    398324            });
    399325
    400             // Protect <pre> and <script> tags by replacing them with <wp-line-break>.
     326            // Preserve line breaks in <pre> and <script> tags.
    401327            if ( text.indexOf( '<pre' ) !== -1 || text.indexOf( '<script' ) !== -1 ) {
    402328                preserve_linebreaks = true;
     
    410336                preserve_br = true;
    411337
    412                 // Replace all white spaces and <br> tags with <wp-temp-br>.
    413338                text = text.replace( /\[caption[\s\S]+?\[\/caption\]/g, function( a ) {
    414 
    415                     // Protect <br> tags by converting them to <wp-temp-br> tags.
    416339                    a = a.replace( /<br([^>]*)>/g, '<wp-temp-br$1>' );
    417340
    418                     // Replace all new lines and tabs with spaces inside HTML tags.
    419341                    a = a.replace( /<[^<>]+>/g, function( b ) {
    420 
    421                         // Replace newlines and tabs with a space.
    422342                        return b.replace( /[\n\t ]+/, ' ' );
    423343                    });
    424344
    425                     // Convert remaining line breaks to <wp-temp-br />.
    426345                    return a.replace( /\s*\n\s*/g, '<wp-temp-br />' );
    427346                });
    428347            }
    429348
    430             // Append 2 newlines at the end of the text.
    431349            text = text + '\n\n';
    432 
    433             /*
    434              * Replace a <br> tag followed by 1 or more spaces
    435              * and another <br> tag with 2 newlines.
    436              */
    437350            text = text.replace( /<br \/>\s*<br \/>/gi, '\n\n' );
    438351
    439             /*
    440              * Replace a block level element open tag with 2 newlines
    441              * followed by the captured block level element.
    442              */
     352            // Pad block tags with two line breaks.
    443353            text = text.replace( new RegExp( '(<(?:' + blocklist + ')(?: [^>]*)?>)', 'gi' ), '\n\n$1' );
    444 
    445             /*
    446              * Replace a block level element closing tag with the captured
    447              * block level element followed by 2 newlines.
    448              */
    449354            text = text.replace( new RegExp( '(</(?:' + blocklist + ')>)', 'gi' ), '$1\n\n' );
    450 
    451             // Add 2 newlines to a <hr> tag. <hr> is a self closing block element.
    452355            text = text.replace( /<hr( [^>]*)?>/gi, '<hr$1>\n\n' );
    453356
    454             // Remove the spaces before an <option> tag.
     357            // Remove white space chars around <option>.
    455358            text = text.replace( /\s*<option/gi, '<option' );
    456 
    457             // Remove the spaces after an <option> closing tag.
    458359            text = text.replace( /<\/option>\s*/gi, '</option>' );
    459360
    460             // Remove the spaces between two newlines.
     361            // Normalize multiple line breaks and white space chars.
    461362            text = text.replace( /\n\s*\n+/g, '\n\n' );
    462363
    463             // Convert 2 newlines to a paragraph and a single newline.
     364            // Convert two line breaks to a paragraph.
    464365            text = text.replace( /([\s\S]+?)\n\n/g, '<p>$1</p>\n' );
    465366
     
    467368            text = text.replace( /<p>\s*?<\/p>/gi, '');
    468369
    469             // Remove spaces and <p> tags around block level elements.
     370            // Remove <p> tags that are around block tags.
    470371            text = text.replace( new RegExp( '<p>\\s*(</?(?:' + blocklist + ')(?: [^>]*)?>)\\s*</p>', 'gi' ), '$1' );
    471 
    472             // Remove <p> tags around li elements.
    473372            text = text.replace( /<p>(<li.+?)<\/p>/gi, '$1');
    474373
    475             // Remove spaces and <p> tags from blockquotes.
     374            // Fix <p> in blockquotes.
    476375            text = text.replace( /<p>\s*<blockquote([^>]*)>/gi, '<blockquote$1><p>');
    477 
    478             // Place the <blockquote> outside of the paragraph.
    479376            text = text.replace( /<\/blockquote>\s*<\/p>/gi, '</p></blockquote>');
    480377
    481             // Remove spaces at the start and <p> tags from block level elements.
     378            // Remove <p> tags that are wrapped around block tags.
    482379            text = text.replace( new RegExp( '<p>\\s*(</?(?:' + blocklist + ')(?: [^>]*)?>)', 'gi' ), '$1' );
    483 
    484             // Remove spaces at the end and <p> tags from block level elements.
    485380            text = text.replace( new RegExp( '(</?(?:' + blocklist + ')(?: [^>]*)?>)\\s*</p>', 'gi' ), '$1' );
    486381
    487             // Remove spaces and newlines after a <br> tag.
    488382            text = text.replace( /(<br[^>]*>)\s*\n/gi, '$1' );
    489383
    490             // Replace spaces followed by a newline with a <br> tag followed by a new line.
     384            // Add <br> tags.
    491385            text = text.replace( /\s*\n/g, '<br />\n');
    492386
    493             // Remove <br> tag that follows a block element directly, ignoring spaces.
     387            // Remove <br> tags that are around block tags.
    494388            text = text.replace( new RegExp( '(</?(?:' + blocklist + ')[^>]*>)\\s*<br />', 'gi' ), '$1' );
    495 
    496             /*
    497              * Remove a br tag preceding white spaces followed by a
    498              * <p>, <li>, <div>, <dl>, <dd>, <dt>, <th>, <pre>, <td>, <ul>, or <ol> tag.
    499              */
    500389            text = text.replace( /<br \/>(\s*<\/?(?:p|li|div|dl|dd|dt|th|pre|td|ul|ol)>)/gi, '$1' );
    501390
    502             // Remove white spaces, <p> and <br> tags in captions.
     391            // Remove <p> and <br> around captions.
    503392            text = text.replace( /(?:<p>|<br ?\/?>)*\s*\[caption([^\[]+)\[\/caption\]\s*(?:<\/p>|<br ?\/?>)*/gi, '[caption$1[/caption]' );
    504393
    505             /**
    506              * @summary Makes sure there is a paragraph open tag for a close tag.
    507              *
    508              * @since 2.9.0
    509              *
    510              * Makes sure there is a paragraph open tag when there is a paragraph close tag
    511              * in a div, th, td, form, fieldset or dd element.
    512              * @param {string} a The complete match.
    513              * @param {string} b The first capture group.
    514              * @param {string} c The second capture group.
    515              * @returns {string} The string in paragraph tags.
    516              */
     394            // Make sure there is <p> when there is </p> inside block tags that can contain other blocks.
    517395            text = text.replace( /(<(?:div|th|td|form|fieldset|dd)[^>]*>)(.*?)<\/p>/g, function( a, b, c ) {
    518 
    519                 /*
    520                  * Check if the matched group has a p open tag in it. If so, we don't need to
    521                  * enclose it with a paragraph.
    522                  */
    523396                if ( c.match( /<p( [^>]*)?>/ ) ) {
    524397                    return a;
    525398                }
    526399
    527                 /*
    528                  * If there is no p open tag in the matched string,
    529                  * add it and return the string including p tags.
    530                  */
    531400                return b + '<p>' + c + '</p>';
    532401            });
     
    546415
    547416        /**
    548          * @summary Modifies the data when a switch is made from HTML to text.
    549          *
    550          * Modifies the data when a switch is made.
    551          * Remove the <p> tags from text.
    552          * Returns the modified text.
    553          * Adds a trigger on beforePreWpautop and afterPreWpautop.
    554          *
    555          * @since 2.5.0
     417         * @summary Fires custom jQuery events `beforePreWpautop` and `afterPreWpautop` when jQuery is available.
     418         *
     419         * @since 2.9.0
    556420         *
    557421         * @memberof switchEditors
    558422         *
    559423         * @param {String} html The content from the visual editor.
    560          * @returns {String} the modified text.
     424         * @returns {String} the filtered content.
    561425         */
    562426        function pre_wpautop( html ) {
     
    577441
    578442        /**
    579          * @summary Modifies the data when a switch is made from text to HTML.
    580          *
    581          * Modifies the data when a switch is made. Runs autop to add p tags from text.
    582          * Returns the modified text. Adds a trigger on beforeWpautop and afterWpautop.
    583          *
    584          * @since 2.5.0
     443         * @summary Fires custom jQuery events `beforeWpautop` and `afterWpautop` when jQuery is available.
     444         *
     445         * @since 2.9.0
    585446         *
    586447         * @memberof switchEditors
    587448         *
    588449         * @param {String} text The content from the text editor.
    589          * @returns {String} the modified text.
     450         * @returns {String} filtered content.
    590451         */
    591452        function wpautop( text ) {
     
    605466        }
    606467
    607         // Bind the init function to be run when the document is loaded.
    608468        if ( $ ) {
    609469            $( document ).ready( init );
    610470        } else if ( document.addEventListener ) {
    611 
    612             // Use the addEventListener to bind the init event on document load.
    613471            document.addEventListener( 'DOMContentLoaded', init, false );
    614472            window.addEventListener( 'load', init, false );
    615 
    616473        } else if ( window.attachEvent ) {
    617 
    618             // Use the addEvent to bind the init event on document load.
    619474            window.attachEvent( 'onload', init );
    620475            document.attachEvent( 'onreadystatechange', function() {
     
    625480        }
    626481
    627         /*
    628          * Make sure the window.wp object exists so autop and removep
    629          * can be bound to it.
    630          */
    631482        window.wp = window.wp || {};
    632483        window.wp.editor = window.wp.editor || {};
Note: See TracChangeset for help on using the changeset viewer.