TinyMCE: wptextpattern: headings on enter
Fixes #31441. git-svn-id: https://develop.svn.wordpress.org/trunk@33452 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
parent
b5f505d3dd
commit
34354fc3c0
|
@ -14,39 +14,19 @@
|
||||||
tinymce.PluginManager.add( 'wptextpattern', function( editor ) {
|
tinymce.PluginManager.add( 'wptextpattern', function( editor ) {
|
||||||
var $$ = editor.$,
|
var $$ = editor.$,
|
||||||
VK = tinymce.util.VK,
|
VK = tinymce.util.VK,
|
||||||
patterns = [],
|
canUndo = false,
|
||||||
canUndo = false;
|
spacePatterns = [
|
||||||
|
{ regExp: /^[*-]\s/, cmd: 'InsertUnorderedList' },
|
||||||
/**
|
{ regExp: /^1[.)]\s/, cmd: 'InsertOrderedList' }
|
||||||
* Add a pattern to format with a callback.
|
],
|
||||||
*
|
enterPatterns = [
|
||||||
* @since 4.3.0
|
{ start: '##', format: 'h2' },
|
||||||
*
|
{ start: '###', format: 'h3' },
|
||||||
* @param {RegExp} regExp RegEx pattern.
|
{ start: '####', format: 'h4' },
|
||||||
* @param {Function} callback Callback.
|
{ start: '#####', format: 'h5' },
|
||||||
*/
|
{ start: '######', format: 'h6' },
|
||||||
function add( regExp, callback ) {
|
{ start: '>', format: 'blockquote' }
|
||||||
patterns.push( {
|
];
|
||||||
regExp: regExp,
|
|
||||||
callback: callback
|
|
||||||
} );
|
|
||||||
}
|
|
||||||
|
|
||||||
add( /^[*-]\s/, function() {
|
|
||||||
this.execCommand( 'InsertUnorderedList' );
|
|
||||||
} );
|
|
||||||
|
|
||||||
add( /^1[.)]\s/, function() {
|
|
||||||
this.execCommand( 'InsertOrderedList' );
|
|
||||||
} );
|
|
||||||
|
|
||||||
add( /^>\s/, function() {
|
|
||||||
this.formatter.toggle( 'blockquote' );
|
|
||||||
} );
|
|
||||||
|
|
||||||
add( /^(#{2,6})\s/, function() {
|
|
||||||
this.formatter.toggle( 'h' + arguments[1].length );
|
|
||||||
} );
|
|
||||||
|
|
||||||
editor.on( 'selectionchange', function() {
|
editor.on( 'selectionchange', function() {
|
||||||
canUndo = false;
|
canUndo = false;
|
||||||
|
@ -57,24 +37,21 @@
|
||||||
editor.undoManager.undo();
|
editor.undoManager.undo();
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
}
|
}
|
||||||
} );
|
|
||||||
|
if ( event.keyCode === VK.ENTER && ! VK.modifierPressed( event ) ) {
|
||||||
|
enter();
|
||||||
|
}
|
||||||
|
}, true );
|
||||||
|
|
||||||
editor.on( 'keyup', function( event ) {
|
editor.on( 'keyup', function( event ) {
|
||||||
var rng, node, text, parent, child;
|
if ( event.keyCode === VK.SPACEBAR || ! VK.modifierPressed( event ) ) {
|
||||||
|
space();
|
||||||
if ( event.keyCode !== VK.SPACEBAR ) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
} );
|
||||||
|
|
||||||
rng = editor.selection.getRng();
|
function firstNode( node ) {
|
||||||
node = rng.startContainer;
|
var parent = editor.dom.getParent( node, 'p' ),
|
||||||
|
child;
|
||||||
if ( ! node || node.nodeType !== 3 ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
text = node.nodeValue;
|
|
||||||
parent = editor.dom.getParent( node, 'p' );
|
|
||||||
|
|
||||||
if ( ! parent ) {
|
if ( ! parent ) {
|
||||||
return;
|
return;
|
||||||
|
@ -92,20 +69,26 @@
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ! child.nodeValue ) {
|
if ( ! child.data ) {
|
||||||
child = child.nextSibling;
|
child = child.nextSibling;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( child !== node ) {
|
return child;
|
||||||
|
}
|
||||||
|
|
||||||
|
function space() {
|
||||||
|
var rng = editor.selection.getRng(),
|
||||||
|
node = rng.startContainer,
|
||||||
|
text;
|
||||||
|
|
||||||
|
if ( firstNode( node ) !== node ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
tinymce.each( patterns, function( pattern ) {
|
text = node.data;
|
||||||
var args,
|
|
||||||
replace = text.replace( pattern.regExp, function() {
|
tinymce.each( spacePatterns, function( pattern ) {
|
||||||
args = arguments;
|
var replace = text.replace( pattern.regExp, '' );
|
||||||
return '';
|
|
||||||
} );
|
|
||||||
|
|
||||||
if ( text === replace ) {
|
if ( text === replace ) {
|
||||||
return;
|
return;
|
||||||
|
@ -118,12 +101,13 @@
|
||||||
editor.undoManager.add();
|
editor.undoManager.add();
|
||||||
|
|
||||||
editor.undoManager.transact( function() {
|
editor.undoManager.transact( function() {
|
||||||
var $$parent;
|
var parent = node.parentNode,
|
||||||
|
$$parent;
|
||||||
|
|
||||||
if ( replace ) {
|
if ( replace ) {
|
||||||
$$( node ).replaceWith( document.createTextNode( replace ) );
|
$$( node ).replaceWith( document.createTextNode( replace ) );
|
||||||
} else {
|
} else {
|
||||||
$$parent = $$( node.parentNode );
|
$$parent = $$( parent );
|
||||||
|
|
||||||
$$( node ).remove();
|
$$( node ).remove();
|
||||||
|
|
||||||
|
@ -133,8 +117,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
editor.selection.setCursorLocation( parent );
|
editor.selection.setCursorLocation( parent );
|
||||||
|
editor.execCommand( pattern.cmd );
|
||||||
pattern.callback.apply( editor, args );
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
// We need to wait for native events to be triggered.
|
// We need to wait for native events to be triggered.
|
||||||
|
@ -144,6 +127,53 @@
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
} );
|
} );
|
||||||
} );
|
}
|
||||||
|
|
||||||
|
function enter() {
|
||||||
|
var selection = editor.selection,
|
||||||
|
rng = selection.getRng(),
|
||||||
|
offset = rng.startOffset,
|
||||||
|
start = rng.startContainer,
|
||||||
|
node = firstNode( start ),
|
||||||
|
i = enterPatterns.length,
|
||||||
|
text, pattern;
|
||||||
|
|
||||||
|
if ( ! node ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
text = node.data;
|
||||||
|
|
||||||
|
while ( i-- ) {
|
||||||
|
if ( text.indexOf( enterPatterns[ i ].start ) === 0 ) {
|
||||||
|
pattern = enterPatterns[ i ];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! pattern ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( node === start ) {
|
||||||
|
if ( tinymce.trim( text ) === pattern.start ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
offset = Math.max( 0, offset - pattern.start.length );
|
||||||
|
}
|
||||||
|
|
||||||
|
editor.undoManager.add();
|
||||||
|
|
||||||
|
editor.undoManager.transact( function() {
|
||||||
|
node.deleteData( 0, pattern.start.length );
|
||||||
|
|
||||||
|
editor.formatter.apply( pattern.format, {}, start );
|
||||||
|
|
||||||
|
rng.setStart( start, offset );
|
||||||
|
rng.collapse( true );
|
||||||
|
selection.setRng( rng );
|
||||||
|
} );
|
||||||
|
}
|
||||||
} );
|
} );
|
||||||
} )( window.tinymce, window.setTimeout );
|
} )( window.tinymce, window.setTimeout );
|
||||||
|
|
|
@ -144,4 +144,31 @@
|
||||||
assert.equal( editor.getContent(), '<ul>\n<li>tes</li>\n</ul>' );
|
assert.equal( editor.getContent(), '<ul>\n<li>tes</li>\n</ul>' );
|
||||||
}, assert.async() );
|
}, assert.async() );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
QUnit.test( 'Heading 3', function( assert ) {
|
||||||
|
editor.setContent( '<p>### test</p>' );
|
||||||
|
editor.selection.setCursorLocation( editor.$( 'p' )[0].firstChild, 8 );
|
||||||
|
|
||||||
|
type( '\n', function() {
|
||||||
|
assert.equal( editor.getContent(), '<h3>test</h3>\n<p> </p>' );
|
||||||
|
}, assert.async() );
|
||||||
|
} );
|
||||||
|
|
||||||
|
QUnit.test( 'Heading 3 with elements.', function( assert ) {
|
||||||
|
editor.setContent( '<p>###<del>test</del></p>' );
|
||||||
|
editor.selection.setCursorLocation( editor.$( 'del' )[0].firstChild, 4 );
|
||||||
|
|
||||||
|
type( '\n', function() {
|
||||||
|
assert.equal( editor.getContent(), '<h3><del>test</del></h3>\n<p> </p>' );
|
||||||
|
}, assert.async() );
|
||||||
|
} );
|
||||||
|
|
||||||
|
QUnit.test( 'Don\'t convert without content', function( assert ) {
|
||||||
|
editor.setContent( '<p>### </p>' );
|
||||||
|
editor.selection.setCursorLocation( editor.$( 'p' )[0].firstChild, 4 );
|
||||||
|
|
||||||
|
type( '\n', function() {
|
||||||
|
assert.equal( editor.getContent(), '<p>### </p>\n<p> </p>' );
|
||||||
|
}, assert.async() );
|
||||||
|
} );
|
||||||
} )( window.jQuery, window.QUnit, window.tinymce, window.Utils.type, window.setTimeout );
|
} )( window.jQuery, window.QUnit, window.tinymce, window.Utils.type, window.setTimeout );
|
||||||
|
|
Loading…
Reference in New Issue