Ticket #31441: 31441.3.patch
File 31441.3.patch, 9.0 KB (added by , 10 years ago) |
---|
-
src/wp-includes/class-wp-editor.php
368 368 'wplink', 369 369 'wpdialogs', 370 370 'wpview', 371 'wptextpattern' 371 372 ); 372 373 373 374 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
131 131 132 132 // TODO: Replace this with the new event logic in 3.5 133 133 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 } 135 146 136 147 function fakeEvent(target, type, evt) { 137 148 editor.dom.fire(target, type, evt); … … 139 150 140 151 // Numeric keyCode 141 152 if (typeof(chr) == "number") { 142 charCode = keyCode = chr; 153 charCode = chr; 154 keyCode = charCodeToKeyCode(charCode); 143 155 } else if (typeof(chr) == "string") { 144 156 // String value 145 157 if (chr == '\b') { … … 150 162 charCode = chr.charCodeAt(0); 151 163 } else { 152 164 charCode = chr.charCodeAt(0); 153 keyCode = charCode ;165 keyCode = charCodeToKeyCode(charCode); 154 166 } 155 167 } else { 156 168 evt = chr; 169 170 if (evt.charCode) { 171 chr = String.fromCharCode(evt.charCode); 172 } 173 174 if (evt.keyCode) { 175 keyCode = evt.keyCode; 176 } 157 177 } 158 178 159 179 evt = evt || {keyCode: keyCode, charCode: charCode}; … … 196 216 if (rng.startContainer.nodeType == 3 && rng.collapsed) { 197 217 rng.startContainer.insertData(rng.startOffset, chr); 198 218 rng.setStart(rng.startContainer, rng.startOffset + 1); 199 rng.collapse(true);200 editor.selection.setRng(rng);201 219 } else { 202 rng.insertNode(editor.getDoc().createTextNode(chr)); 220 textNode = editor.getDoc().createTextNode(chr); 221 rng.insertNode(textNode); 222 rng.setStart(textNode, 1); 203 223 } 224 225 rng.collapse(true); 226 editor.selection.setRng(rng); 204 227 } 205 228 } 206 229 -
tests/qunit/index.html
39 39 <script src="wp-includes/js/shortcode.js"></script> 40 40 <script src="wp-admin/js/customize-controls.js"></script> 41 41 <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 42 51 </body> 43 52 </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 );