WordPress.org

Make WordPress Core

Ticket #31441: 31441.5.patch

File 31441.5.patch, 9.7 KB (added by iseulde, 5 years ago)
  • src/wp-includes/class-wp-editor.php

     
    368368                                                'wplink',
    369369                                                'wpdialogs',
    370370                                                'wpview',
     371                                                'wptextpattern'
    371372                                        );
    372373
    373374                                        if ( ! self::$has_medialib ) {
  • src/wp-includes/js/tinymce/plugins/wptextpattern/plugin.js

     
     1( function( tinymce, setTimeout ) {
     2        tinymce.PluginManager.add( 'wptextpattern', function( editor ) {
     3                var $$ = editor.$,
     4                        patterns = [],
     5                        canUndo = false;
     6
     7                function add( regExp, callback ) {
     8                        patterns.push( {
     9                                regExp: regExp,
     10                                callback: callback
     11                        } );
     12                }
     13
     14                add( /^[*-]\s/, function() {
     15                        this.execCommand( 'InsertUnorderedList' );
     16                } );
     17
     18                add( /^1[.)]\s/, function() {
     19                        this.execCommand( 'InsertOrderedList' );
     20                } );
     21
     22                editor.on( 'selectionchange', function() {
     23                        canUndo = false;
     24                } );
     25
     26                editor.on( 'keydown', function( event ) {
     27                        if ( canUndo && event.keyCode === tinymce.util.VK.BACKSPACE ) {
     28                                editor.undoManager.undo();
     29                                event.preventDefault();
     30                        }
     31                } );
     32
     33                editor.on( 'keyup', function( event ) {
     34                        var rng, node, text, parent, child;
     35
     36                        if ( event.keyCode !== tinymce.util.VK.SPACEBAR ) {
     37                                return;
     38                        }
     39
     40                        rng = editor.selection.getRng();
     41                        node = rng.startContainer;
     42                        text = node.nodeValue;
     43
     44                        if ( node.nodeType !== 3 ) {
     45                                return;
     46                        }
     47
     48                        parent = editor.dom.getParent( node, 'p' );
     49
     50                        if ( ! parent ) {
     51                                return;
     52                        }
     53
     54                        while ( child = parent.firstChild ) {
     55                                if ( child.nodeType !== 3 ) {
     56                                        parent = child;
     57                                } else {
     58                                        break;
     59                                }
     60                        }
     61
     62                        if ( child !== node ) {
     63                                return;
     64                        }
     65
     66                        tinymce.each( patterns, function( pattern ) {
     67                                var replace = text.replace( pattern.regExp, '' );
     68
     69                                if ( text === replace ) {
     70                                        return;
     71                                }
     72
     73                                if ( rng.startOffset !== text.length - replace.length ) {
     74                                        return;
     75                                }
     76
     77                                editor.undoManager.add();
     78
     79                                editor.undoManager.transact( function() {
     80                                        editor.selection.setCursorLocation( node, 0 );
     81
     82                                        if ( replace ) {
     83                                                $$( node ).replaceWith( document.createTextNode( replace ) );
     84                                        } else  {
     85                                                $$( node.parentNode ).empty().append( '<br>' );
     86                                        }
     87
     88                                        pattern.callback.apply( editor );
     89                                } );
     90
     91                                // We need to wait for native events to be triggered.
     92                                setTimeout( function() {
     93                                        canUndo = true;
     94                                } );
     95
     96                                return false;
     97                        } );
     98                } );
     99        } );
     100} )( window.tinymce, window.setTimeout );
  • tests/qunit/editor/js/utils.js

     
    131131
    132132        // TODO: Replace this with the new event logic in 3.5
    133133        function type(chr) {
    134                 var editor = tinymce.activeEditor, keyCode, charCode, evt, startElm, rng;
     134                var editor = tinymce.activeEditor, keyCode, charCode, evt, startElm, rng, textNode;
     135
     136                function charCodeToKeyCode(charCode) {
     137                        var lookup = {
     138                                '0': 48, '1': 49, '2': 50, '3': 51, '4': 52, '5': 53, '6': 54, '7': 55, '8': 56, '9': 57,'a': 65, 'b': 66, 'c': 67,
     139                                'd': 68, 'e': 69, 'f': 70, 'g': 71, 'h': 72, 'i': 73, 'j': 74, 'k': 75, 'l': 76, 'm': 77, 'n': 78, 'o': 79, 'p': 80, 'q': 81,
     140                                'r': 82, 's': 83, 't': 84, 'u': 85,     'v': 86, 'w': 87, 'x': 88, 'y': 89, ' ': 32, ',': 188, '-': 189, '.': 190, '/': 191, '\\': 220,
     141                                '[': 219, ']': 221, '\'': 222, ';': 186, '=': 187, ')': 41
     142                        };
     143
     144                        return lookup[String.fromCharCode(charCode)];
     145                }
    135146
    136147                function fakeEvent(target, type, evt) {
    137148                        editor.dom.fire(target, type, evt);
     
    139150
    140151                // Numeric keyCode
    141152                if (typeof(chr) == "number") {
    142                         charCode = keyCode = chr;
     153                        charCode = chr;
     154                        keyCode = charCodeToKeyCode(charCode);
    143155                } else if (typeof(chr) == "string") {
    144156                        // String value
    145157                        if (chr == '\b') {
     
    150162                                charCode = chr.charCodeAt(0);
    151163                        } else {
    152164                                charCode = chr.charCodeAt(0);
    153                                 keyCode = charCode;
     165                                keyCode = charCodeToKeyCode(charCode);
    154166                        }
    155167                } else {
    156168                        evt = chr;
     169
     170                        if (evt.charCode) {
     171                                chr = String.fromCharCode(evt.charCode);
     172                        }
     173
     174                        if (evt.keyCode) {
     175                                keyCode = evt.keyCode;
     176                        }
    157177                }
    158178
    159179                evt = evt || {keyCode: keyCode, charCode: charCode};
     
    196216                                if (rng.startContainer.nodeType == 3 && rng.collapsed) {
    197217                                        rng.startContainer.insertData(rng.startOffset, chr);
    198218                                        rng.setStart(rng.startContainer, rng.startOffset + 1);
    199                                         rng.collapse(true);
    200                                         editor.selection.setRng(rng);
    201219                                } else {
    202                                         rng.insertNode(editor.getDoc().createTextNode(chr));
     220                                        textNode = editor.getDoc().createTextNode(chr);
     221                                        rng.insertNode(textNode);
     222                                        rng.setStart(textNode, 1);
    203223                                }
     224
     225                                rng.collapse(true);
     226                                editor.selection.setRng(rng);
     227
     228                                console.log(editor.getContent())
    204229                        }
    205230                }
    206231
  • tests/qunit/index.html

     
    3939                <script src="wp-includes/js/shortcode.js"></script>
    4040                <script src="wp-admin/js/customize-controls.js"></script>
    4141                <script src="wp-admin/js/customize-controls-utils.js"></script>
     42
     43                <!-- TinyMCE -->
     44
     45                <script src="../../src/wp-includes/js/tinymce/tinymce.js"></script>
     46
     47                <script src="editor/js/utils.js"></script>
     48
     49                <script src="wp-includes/js/tinymce/plugins/wptextpattern/plugin.js"></script>
     50
    4251        </body>
    4352</html>
  • tests/qunit/wp-includes/js/tinymce/plugins/wptextpattern/plugin.js

     
     1( function( $, QUnit, tinymce, _type, setTimeout ) {
     2        var editor;
     3
     4        function type() {
     5                var args = arguments;
     6
     7                setTimeout( function() {
     8                        if ( typeof args[0] === 'string' ) {
     9                                args[0] = args[0].split( '' );
     10                        }
     11
     12                        if ( typeof args[0] === 'function' ) {
     13                                args[0]();
     14                        } else {
     15                                _type( args[0].shift() );
     16                        }
     17
     18                        if ( ! args[0].length ) {
     19                                [].shift.call( args );
     20                        }
     21
     22                        if ( args.length ) {
     23                                type.apply( null, args );
     24                        }
     25                } );
     26        }
     27
     28        QUnit.module( 'tinymce.plugins.wptextpattern', {
     29                beforeEach: function( assert ) {
     30                        var done = assert.async();
     31
     32                        $( '#qunit-fixture' ).append( '<textarea id="editor">' );
     33
     34                        tinymce.init( {
     35                                selector: '#editor',
     36                                plugins: 'wptextpattern',
     37                                init_instance_callback: function() {
     38                                        editor = arguments[0];
     39                                        editor.focus();
     40                                        editor.selection.setCursorLocation();
     41                                        setTimeout( done );
     42                                }
     43                        } );
     44                },
     45                afterEach: function() {
     46                        editor.remove();
     47                }
     48        } );
     49
     50        QUnit.test( 'Unordered list.', function( assert ) {
     51                var done = assert.async();
     52
     53                type( '* test', function() {
     54                        assert.equal( editor.getContent(), '<ul>\n<li>test</li>\n</ul>' );
     55                        done();
     56                } );
     57        } );
     58
     59        QUnit.test( 'Ordered list.', function( assert ) {
     60                var done = assert.async();
     61
     62                type( '1. test', function() {
     63                        assert.equal( editor.getContent(), '<ol>\n<li>test</li>\n</ol>' );
     64                        done();
     65                } );
     66        } );
     67
     68        QUnit.test( 'Ordered list with content.', function( assert ) {
     69                var done = assert.async();
     70
     71                editor.setContent( '<p><strong>test</strong></p>' );
     72                editor.selection.setCursorLocation();
     73
     74                type( '* ', function() {
     75                        assert.equal( editor.getContent(), '<ul>\n<li><strong>test</strong></li>\n</ul>' );
     76                        done();
     77                } );
     78        } );
     79
     80        QUnit.test( 'Only transform inside a P tag.', function( assert ) {
     81                var done = assert.async();
     82
     83                editor.setContent( '<h1>test</h1>' );
     84                editor.selection.setCursorLocation();
     85
     86                type( '* ', function() {
     87                        assert.equal( editor.getContent(), '<h1>* test</h1>' );
     88                        done();
     89                } );
     90        } );
     91
     92        QUnit.test( 'Only transform at the start of a P tag.', function( assert ) {
     93                var done = assert.async();
     94
     95                editor.setContent( '<p>test <strong>test</strong></p>' );
     96                editor.selection.setCursorLocation( editor.$( 'strong' )[0].firstChild, 0 );
     97
     98                type( '* ', function() {
     99                        assert.equal( editor.getContent(), '<p>test <strong>* test</strong></p>' );
     100                        done();
     101                } );
     102        } );
     103
     104        QUnit.test( 'Only transform when at the cursor is at the start.', function( assert ) {
     105                var done = assert.async();
     106
     107                editor.setContent( '<p>* test</p>' );
     108                editor.selection.setCursorLocation( editor.$( 'p' )[0].firstChild, 6 );
     109
     110                type( ' test', function() {
     111                        assert.equal( editor.getContent(), '<p>* test test</p>' );
     112                        done();
     113                } );
     114        } );
     115
     116        QUnit.test( 'Backspace should undo the transformation.', function( assert ) {
     117                var done = assert.async();
     118
     119                editor.setContent( '<p>test</p>' );
     120                editor.selection.setCursorLocation();
     121
     122                type( '* \b', function() {
     123                        assert.equal( editor.getContent(), '<p>* test</p>' );
     124                        assert.equal( editor.selection.getRng().startOffset, 2 );
     125                        done();
     126                } );
     127        } );
     128
     129        QUnit.test( 'Backspace should undo the transformation only right after it happened.', function( assert ) {
     130                var done = assert.async();
     131
     132                editor.setContent( '<p>test</p>' );
     133                editor.selection.setCursorLocation();
     134
     135                type( '* ', function() {
     136                        editor.selection.setCursorLocation( editor.$( 'li' )[0].firstChild, 4 );
     137                        // Gecko.
     138                        editor.fire( 'click' );
     139                }, '\b', function() {
     140                        assert.equal( editor.getContent(), '<ul>\n<li>tes</li>\n</ul>' );
     141                        done();
     142                } );
     143        } );
     144} )( window.jQuery, window.QUnit, window.tinymce, window.Utils.type, window.setTimeout );