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;
|
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 ) {
|
tinymce.PluginManager.add( 'wptextpattern', function( editor ) {
|
||||||
var VK = tinymce.util.VK;
|
var VK = tinymce.util.VK;
|
||||||
|
var settings = editor.settings.wptextpattern || {};
|
||||||
|
|
||||||
var spacePatterns = [
|
var spacePatterns = settings.space || [
|
||||||
{ regExp: /^[*-]\s/, cmd: 'InsertUnorderedList' },
|
{ regExp: /^[*-]\s/, cmd: 'InsertUnorderedList' },
|
||||||
{ regExp: /^1[.)]\s/, cmd: 'InsertOrderedList' }
|
{ regExp: /^1[.)]\s/, cmd: 'InsertOrderedList' }
|
||||||
];
|
];
|
||||||
|
|
||||||
var enterPatterns = [
|
var enterPatterns = settings.enter || [
|
||||||
{ start: '##', format: 'h2' },
|
{ start: '##', format: 'h2' },
|
||||||
{ start: '###', format: 'h3' },
|
{ start: '###', format: 'h3' },
|
||||||
{ start: '####', format: 'h4' },
|
{ start: '####', format: 'h4' },
|
||||||
|
@ -33,7 +45,7 @@
|
||||||
{ regExp: /^(-){3,}$/, element: 'hr' }
|
{ regExp: /^(-){3,}$/, element: 'hr' }
|
||||||
];
|
];
|
||||||
|
|
||||||
var inlinePatterns = [
|
var inlinePatterns = settings.inline || [
|
||||||
{ start: '`', end: '`', format: 'code' }
|
{ start: '`', end: '`', format: 'code' }
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -81,40 +93,39 @@
|
||||||
var format;
|
var format;
|
||||||
var zero;
|
var zero;
|
||||||
|
|
||||||
|
// We need a non empty text node with an offset greater than zero.
|
||||||
if ( ! node || node.nodeType !== 3 || ! node.data.length || ! offset ) {
|
if ( ! node || node.nodeType !== 3 || ! node.data.length || ! offset ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The ending character should exist in the patterns registered.
|
||||||
if ( tinymce.inArray( chars, node.data.charAt( offset - 1 ) ) === -1 ) {
|
if ( tinymce.inArray( chars, node.data.charAt( offset - 1 ) ) === -1 ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
function findStart( node ) {
|
var string = node.data.slice( 0, offset );
|
||||||
var i = inlinePatterns.length;
|
|
||||||
var offset;
|
|
||||||
|
|
||||||
while ( i-- ) {
|
tinymce.each( inlinePatterns, function( p ) {
|
||||||
pattern = inlinePatterns[ i ];
|
var regExp = new RegExp( escapeRegExp( p.start ) + '\\S+' + escapeRegExp( p.end ) + '$' );
|
||||||
offset = node.data.indexOf( pattern.end );
|
var match = string.match( regExp );
|
||||||
|
|
||||||
if ( offset !== -1 ) {
|
if ( ! match ) {
|
||||||
return offset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
startOffset = findStart( node );
|
|
||||||
endOffset = node.data.lastIndexOf( pattern.end );
|
|
||||||
|
|
||||||
if ( startOffset === endOffset || endOffset === -1 ) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( endOffset - startOffset <= pattern.start.length ) {
|
// 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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( node.data.slice( startOffset + pattern.start.length, endOffset ).indexOf( pattern.start.slice( 0, 1 ) ) !== -1 ) {
|
startOffset = match.index;
|
||||||
|
endOffset = offset - p.end.length;
|
||||||
|
pattern = p;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
} );
|
||||||
|
|
||||||
|
if ( ! pattern ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -491,6 +491,7 @@
|
||||||
</div><!-- #widgets-left -->
|
</div><!-- #widgets-left -->
|
||||||
</div><!-- end widget templates -->
|
</div><!-- end widget templates -->
|
||||||
<script src="../../src/wp-includes/js/tinymce/tinymce.js"></script>
|
<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="editor/js/utils.js"></script>
|
||||||
<script src="wp-includes/js/tinymce/plugins/wptextpattern/plugin.js"></script>
|
<script src="wp-includes/js/tinymce/plugins/wptextpattern/plugin.js"></script>
|
||||||
|
|
||||||
|
|
|
@ -155,6 +155,12 @@
|
||||||
selector: '#editor',
|
selector: '#editor',
|
||||||
skin: false,
|
skin: false,
|
||||||
plugins: 'wptextpattern',
|
plugins: 'wptextpattern',
|
||||||
|
wptextpattern: {
|
||||||
|
inline: [
|
||||||
|
{ start: '`', end: '`', format: 'code' },
|
||||||
|
{ start: '``', end: '``', format: 'bold' }
|
||||||
|
]
|
||||||
|
},
|
||||||
init_instance_callback: function() {
|
init_instance_callback: function() {
|
||||||
editor = arguments[0];
|
editor = arguments[0];
|
||||||
editor.focus();
|
editor.focus();
|
||||||
|
@ -299,19 +305,26 @@
|
||||||
}, assert.async() );
|
}, assert.async() );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
QUnit.test( 'Inline: single.', function( assert ) {
|
QUnit.test( 'Inline: single character.', function( assert ) {
|
||||||
type( '`test`', function() {
|
type( '`test`', function() {
|
||||||
assert.equal( editor.getContent(), '<p><code>test</code></p>' );
|
assert.equal( editor.getContent(), '<p><code>test</code></p>' );
|
||||||
assert.equal( editor.selection.getRng().startOffset, 1 );
|
assert.equal( editor.selection.getRng().startOffset, 1 );
|
||||||
}, assert.async() );
|
}, 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 ) {
|
QUnit.test( 'Inline: after typing.', function( assert ) {
|
||||||
editor.setContent( '<p>test test test</p>' );
|
editor.setContent( '<p>test test test</p>' );
|
||||||
editor.selection.setCursorLocation( editor.$( 'p' )[0].firstChild, 5 );
|
editor.selection.setCursorLocation( editor.$( 'p' )[0].firstChild, 5 );
|
||||||
|
|
||||||
type( '`', function() {
|
type( '`', function() {
|
||||||
editor.selection.setCursorLocation( editor.$( 'p' )[0].firstChild, 11 );
|
editor.selection.setCursorLocation( editor.$( 'p' )[0].firstChild, 10 );
|
||||||
}, '`', function() {
|
}, '`', function() {
|
||||||
assert.equal( editor.getContent(), '<p>test <code>test</code> test</p>' );
|
assert.equal( editor.getContent(), '<p>test <code>test</code> test</p>' );
|
||||||
assert.equal( editor.selection.getRng().startOffset, 1 );
|
assert.equal( editor.selection.getRng().startOffset, 1 );
|
||||||
|
@ -323,4 +336,13 @@
|
||||||
assert.equal( editor.getContent(), '<p>test `````</p>' );
|
assert.equal( editor.getContent(), '<p>test `````</p>' );
|
||||||
}, assert.async() );
|
}, 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 );
|
} )( window.jQuery, window.QUnit, window.tinymce, window.setTimeout );
|
||||||
|
|
Loading…
Reference in New Issue