TinyMCE: wptextpattern: Handle unconverted inline patterns

Make sure the right text is matched when it already contains characters of the pattern.
Adds two more unit tests.

Fixes #37693.



git-svn-id: https://develop.svn.wordpress.org/trunk@39075 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
Ella van Dorpe 2016-11-01 20:05:48 +00:00
parent 9cac5048b4
commit 0f00396bb6
3 changed files with 58 additions and 24 deletions

View File

@ -15,15 +15,27 @@
return;
}
/**
* Escapes characters for use in a Regular Expression.
*
* @param {String} string Characters to escape
*
* @return {String} Escaped characters
*/
function escapeRegExp( string ) {
return string.replace( /[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&' );
}
tinymce.PluginManager.add( 'wptextpattern', function( editor ) {
var VK = tinymce.util.VK;
var settings = editor.settings.wptextpattern || {};
var spacePatterns = [
var spacePatterns = settings.space || [
{ regExp: /^[*-]\s/, cmd: 'InsertUnorderedList' },
{ regExp: /^1[.)]\s/, cmd: 'InsertOrderedList' }
];
var enterPatterns = [
var enterPatterns = settings.enter || [
{ start: '##', format: 'h2' },
{ start: '###', format: 'h3' },
{ start: '####', format: 'h4' },
@ -33,7 +45,7 @@
{ regExp: /^(-){3,}$/, element: 'hr' }
];
var inlinePatterns = [
var inlinePatterns = settings.inline || [
{ start: '`', end: '`', format: 'code' }
];
@ -81,40 +93,39 @@
var format;
var zero;
// We need a non empty text node with an offset greater than zero.
if ( ! node || node.nodeType !== 3 || ! node.data.length || ! offset ) {
return;
}
// The ending character should exist in the patterns registered.
if ( tinymce.inArray( chars, node.data.charAt( offset - 1 ) ) === -1 ) {
return;
}
function findStart( node ) {
var i = inlinePatterns.length;
var offset;
var string = node.data.slice( 0, offset );
while ( i-- ) {
pattern = inlinePatterns[ i ];
offset = node.data.indexOf( pattern.end );
tinymce.each( inlinePatterns, function( p ) {
var regExp = new RegExp( escapeRegExp( p.start ) + '\\S+' + escapeRegExp( p.end ) + '$' );
var match = string.match( regExp );
if ( offset !== -1 ) {
return offset;
}
if ( ! match ) {
return;
}
}
startOffset = findStart( node );
endOffset = node.data.lastIndexOf( pattern.end );
// Don't allow pattern characters in the text.
if ( node.data.slice( match.index + p.start.length, offset - p.end.length ).indexOf( p.start.slice( 0, 1 ) ) !== -1 ) {
return;
}
if ( startOffset === endOffset || endOffset === -1 ) {
return;
}
startOffset = match.index;
endOffset = offset - p.end.length;
pattern = p;
if ( endOffset - startOffset <= pattern.start.length ) {
return;
}
return false;
} );
if ( node.data.slice( startOffset + pattern.start.length, endOffset ).indexOf( pattern.start.slice( 0, 1 ) ) !== -1 ) {
if ( ! pattern ) {
return;
}

View File

@ -491,6 +491,7 @@
</div><!-- #widgets-left -->
</div><!-- end widget templates -->
<script src="../../src/wp-includes/js/tinymce/tinymce.js"></script>
<script src="../../src/wp-includes/js/tinymce/plugins/wptextpattern/plugin.js"></script>
<script src="editor/js/utils.js"></script>
<script src="wp-includes/js/tinymce/plugins/wptextpattern/plugin.js"></script>

View File

@ -155,6 +155,12 @@
selector: '#editor',
skin: false,
plugins: 'wptextpattern',
wptextpattern: {
inline: [
{ start: '`', end: '`', format: 'code' },
{ start: '``', end: '``', format: 'bold' }
]
},
init_instance_callback: function() {
editor = arguments[0];
editor.focus();
@ -299,19 +305,26 @@
}, assert.async() );
} );
QUnit.test( 'Inline: single.', function( assert ) {
QUnit.test( 'Inline: single character.', function( assert ) {
type( '`test`', function() {
assert.equal( editor.getContent(), '<p><code>test</code></p>' );
assert.equal( editor.selection.getRng().startOffset, 1 );
}, assert.async() );
} );
QUnit.test( 'Inline: two characters.', function( assert ) {
type( '``test``', function() {
assert.equal( editor.getContent(), '<p><strong>test</strong></p>' );
assert.equal( editor.selection.getRng().startOffset, 1 );
}, assert.async() );
} );
QUnit.test( 'Inline: after typing.', function( assert ) {
editor.setContent( '<p>test test test</p>' );
editor.selection.setCursorLocation( editor.$( 'p' )[0].firstChild, 5 );
type( '`', function() {
editor.selection.setCursorLocation( editor.$( 'p' )[0].firstChild, 11 );
editor.selection.setCursorLocation( editor.$( 'p' )[0].firstChild, 10 );
}, '`', function() {
assert.equal( editor.getContent(), '<p>test <code>test</code> test</p>' );
assert.equal( editor.selection.getRng().startOffset, 1 );
@ -323,4 +336,13 @@
assert.equal( editor.getContent(), '<p>test `````</p>' );
}, assert.async() );
} );
QUnit.test( 'Convert with previously unconverted pattern', function( assert ) {
editor.setContent( '<p>`test` test&nbsp;</p>' );
editor.selection.setCursorLocation( editor.$( 'p' )[0].firstChild, 12 );
type( '`test`', function() {
assert.equal( editor.getContent(), '<p>`test` test&nbsp;<code>test</code></p>' );
}, assert.async() );
} );
} )( window.jQuery, window.QUnit, window.tinymce, window.setTimeout );