Make WordPress Core

Ticket #31441: 31441.3.patch

File 31441.3.patch, 9.0 KB (added by iseulde, 10 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, 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
     43                        if ( node.nodeType !== 3 ) {
     44                                return;
     45                        }
     46
     47                        parent = editor.dom.getParent( node, 'p' );
     48
     49                        if ( ! parent ) {
     50                                return;
     51                        }
     52
     53                        while ( child = parent.firstChild ) {
     54                                if ( child.nodeType !== 3 ) {
     55                                        parent = child;
     56                                } else {
     57                                        break;
     58                                }
     59                        }
     60
     61                        if ( child !== node ) {
     62                                return;
     63                        }
     64
     65                        tinymce.each( patterns, function( pattern ) {
     66                                var text = node.nodeValue,
     67                                        replace = node.nodeValue.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                                }, 0 );
     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);
    204227                        }
    205228                }
    206229
  • 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( $, module, test, _type, setTimeout ) {
     2
     3        var editor;
     4
     5        function type( chr ) {
     6                typeof chr === 'string' ? tinymce.each( chr.split( '' ), _type ) : _type( chr );
     7        }
     8
     9        module( 'tinymce.plugins.wptextpattern', {
     10                beforeEach: function() {
     11                        stop();
     12
     13                        $( '#qunit-fixture' ).append( '<textarea id="editor">' );
     14
     15                        tinymce.init( {
     16                                selector: '#editor',
     17                                plugins: 'wptextpattern',
     18                                init_instance_callback: function() {
     19                                        editor = arguments[0];
     20                                        editor.focus();
     21                                        start();
     22                                }
     23                        } );
     24                },
     25                afterEach: function( assert ) {
     26                        editor.remove();
     27                }
     28        } );
     29
     30        test( 'Unordered list.', function( assert ) {
     31                type( '* test' );
     32                assert.equal( editor.getContent(), '<ul>\n<li>test</li>\n</ul>' );
     33        } );
     34
     35        test( 'Ordered list.', function( assert ) {
     36                type( '1. test' );
     37                assert.equal( editor.getContent(), '<ol>\n<li>test</li>\n</ol>' );
     38        } );
     39
     40        test( 'Ordered list with content.', function( assert ) {
     41                editor.setContent( '<p><strong>test</strong></p>' );
     42                editor.selection.setCursorLocation();
     43                type( '* ' );
     44                assert.equal( editor.getContent(), '<ul>\n<li><strong>test</strong></li>\n</ul>' );
     45        } );
     46
     47        test( 'Only transform inside a P tag.', function( assert ) {
     48                editor.setContent( '<h1>test</h1>' );
     49                editor.selection.setCursorLocation();
     50                type( '* ' );
     51                assert.equal( editor.getContent(), '<h1>* test</h1>' );
     52        } );
     53
     54        test( 'Only transform at the start of a P tag.', function( assert ) {
     55                editor.setContent( '<p>test <strong>test</strong></p>' );
     56                editor.selection.setCursorLocation( editor.$( 'strong' )[0].firstChild, 0 );
     57                type( '* ' );
     58                assert.equal( editor.getContent(), '<p>test <strong>* test</strong></p>' );
     59        } );
     60
     61        test( 'Only transform when at the cursor is at the start.', function( assert ) {
     62                editor.setContent( '<p>* test</p>' );
     63                editor.selection.setCursorLocation( editor.$( 'p' )[0].firstChild, 6 );
     64                type( ' test' );
     65                assert.equal( editor.getContent(), '<p>* test test</p>' );
     66        } );
     67
     68        test( 'Backspace should undo the transformation.', function( assert ) {
     69                var done = assert.async();
     70
     71                editor.setContent( '<p>test</p>' );
     72                editor.selection.setCursorLocation();
     73                type( '* ' );
     74
     75                setTimeout( function() {
     76                        type( '\b' );
     77                        assert.equal( editor.getContent(), '<p>* test</p>' );
     78                        assert.equal( editor.selection.getRng().startOffset, 2 );
     79                        done();
     80                }, 0 );
     81        } );
     82
     83        test( 'Backspace should undo the transformation only right after it happened.', function( assert ) {
     84                var done = assert.async();
     85
     86                editor.setContent( '<p>test</p>' );
     87                editor.selection.setCursorLocation();
     88                type( '* ' );
     89
     90                // Wait until we can undo.
     91                setTimeout( function() {
     92                        editor.selection.setCursorLocation( editor.$( 'li' )[0].firstChild, 4 );
     93
     94                        // Wait for the `selectionchange` event.
     95                        setTimeout( function() {
     96                                type( '\b' );
     97                                assert.equal( editor.getContent(), '<ul>\n<li>tes</li>\n</ul>' );
     98                                done();
     99                        }, 0 );
     100                }, 0 );
     101        } );
     102
     103} )( window.jQuery, window.QUnit.module, window.QUnit.test, window.Utils.type, window.setTimeout );