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:
parent
9cac5048b4
commit
0f00396bb6
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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 </p>' );
|
||||
editor.selection.setCursorLocation( editor.$( 'p' )[0].firstChild, 12 );
|
||||
|
||||
type( '`test`', function() {
|
||||
assert.equal( editor.getContent(), '<p>`test` test <code>test</code></p>' );
|
||||
}, assert.async() );
|
||||
} );
|
||||
} )( window.jQuery, window.QUnit, window.tinymce, window.setTimeout );
|
||||
|
Loading…
Reference in New Issue
Block a user