diff --git a/wp-includes/js/tinymce/plugins/wptextpattern/plugin.js b/wp-includes/js/tinymce/plugins/wptextpattern/plugin.js index e85a4857c2..236775034c 100644 --- a/wp-includes/js/tinymce/plugins/wptextpattern/plugin.js +++ b/wp-includes/js/tinymce/plugins/wptextpattern/plugin.js @@ -3,12 +3,46 @@ * * @since 4.3.0 * - * This plugin can automatically format text patterns as you type. It includes two patterns: + * This plugin can automatically format text patterns as you type. It includes several groups of patterns. + * + * Start of line patterns: + * As-you-type: * - Unordered list (`* ` and `- `). * - Ordered list (`1. ` and `1) `). * + * On enter: + * - h2 (## ). + * - h3 (### ). + * - h4 (#### ). + * - h5 (##### ). + * - h6 (###### ). + * - blockquote (> ). + * - hr (---). + * + * Inline patterns: + * - (`) (backtick). + * * If the transformation in unwanted, the user can undo the change by pressing backspace, * using the undo shortcut, or the undo button in the toolbar. + * + * Setting for the patterns can be overridden by plugins by using the `tiny_mce_before_init` PHP filter. + * The setting name is `wptextpattern` and the value is an object containing override arrays for each + * patterns group. There are three groups: "space", "enter", and "inline". Example (PHP): + * + * add_filter( 'tiny_mce_before_init', 'my_mce_init_wptextpattern' ); + * function my_mce_init_wptextpattern( $init ) { + * $init['wptextpattern'] = wp_json_encode( array( + * 'inline' => array( + * array( 'delimiter' => '**', 'format' => 'bold' ), + * array( 'delimiter' => '__', 'format' => 'italic' ), + * ), + * ) ); + * + * return $init; + * } + * + * Note that setting this will override the default text patterns. You will need to include them + * in your settings array if you want to keep them working. */ ( function( tinymce, setTimeout ) { if ( tinymce.Env.ie && tinymce.Env.ie < 9 ) { @@ -46,19 +80,10 @@ ]; var inlinePatterns = settings.inline || [ - { start: '`', end: '`', format: 'code' } + { delimiter: '`', format: 'code' } ]; var canUndo; - var chars = []; - - tinymce.each( inlinePatterns, function( pattern ) { - tinymce.each( ( pattern.start + pattern.end ).split( '' ), function( c ) { - if ( tinymce.inArray( chars, c ) === -1 ) { - chars.push( c ); - } - } ); - } ); editor.on( 'selectionchange', function() { canUndo = null; @@ -100,28 +125,44 @@ return; } - // The ending character should exist in the patterns registered. - if ( tinymce.inArray( chars, node.data.charAt( offset - 1 ) ) === -1 ) { - return; - } - var string = node.data.slice( 0, offset ); + var lastChar = node.data.charAt( offset - 1 ); tinymce.each( inlinePatterns, function( p ) { - var regExp = new RegExp( escapeRegExp( p.start ) + '\\S+' + escapeRegExp( p.end ) + '$' ); + // Character before selection should be delimiter. + if ( lastChar !== p.delimiter.slice( -1 ) ) { + return; + } + + var escDelimiter = escapeRegExp( p.delimiter ); + var delimiterFirstChar = p.delimiter.charAt( 0 ); + var regExp = new RegExp( '(.*)' + escDelimiter + '.+' + escDelimiter + '$' ); var match = string.match( regExp ); if ( ! match ) { return; } - // 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 ) { + startOffset = match[1].length; + endOffset = offset - p.delimiter.length; + + var before = string.charAt( startOffset - 1 ); + var after = string.charAt( startOffset + p.delimiter.length ); + + // test*test* => format applied + // test *test* => applied + // test* test* => not applied + if ( startOffset && /\S/.test( before ) ) { + if ( /\s/.test( after ) || before === delimiterFirstChar ) { + return; + } + } + + // Do not replace when only whitespace and delimiter characters. + if ( ( new RegExp( '^[\\s' + escapeRegExp( delimiterFirstChar ) + ']+$' ) ).test( string.slice( startOffset, endOffset ) ) ) { return; } - startOffset = match.index; - endOffset = offset - p.end.length; pattern = p; return false; @@ -142,8 +183,8 @@ node = node.splitText( startOffset ); zero = node.splitText( offset - startOffset ); - node.deleteData( 0, pattern.start.length ); - node.deleteData( node.data.length - pattern.end.length, pattern.end.length ); + node.deleteData( 0, pattern.delimiter.length ); + node.deleteData( node.data.length - pattern.delimiter.length, pattern.delimiter.length ); editor.formatter.apply( pattern.format, {}, node ); diff --git a/wp-includes/js/tinymce/plugins/wptextpattern/plugin.min.js b/wp-includes/js/tinymce/plugins/wptextpattern/plugin.min.js index 3622f4d7ab..c4e7cbba50 100644 --- a/wp-includes/js/tinymce/plugins/wptextpattern/plugin.min.js +++ b/wp-includes/js/tinymce/plugins/wptextpattern/plugin.min.js @@ -1 +1 @@ -!function(a,b){function c(a){return a.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&")}a.Env.ie&&a.Env.ie<9||a.PluginManager.add("wptextpattern",function(d){function e(){var e,f,g,h,i,k=d.selection.getRng(),l=k.startContainer,m=k.startOffset;if(l&&3===l.nodeType&&l.data.length&&m&&a.inArray(p,l.data.charAt(m-1))!==-1){var n=l.data.slice(0,m);a.each(o,function(a){var b=new RegExp(c(a.start)+"\\S+"+c(a.end)+"$"),d=n.match(b);if(d&&l.data.slice(d.index+a.start.length,m-a.end.length).indexOf(a.start.slice(0,1))===-1)return e=d.index,f=m-a.end.length,g=a,!1}),g&&(h=d.formatter.get(g.format),h&&h[0].inline&&(d.undoManager.add(),d.undoManager.transact(function(){l.insertData(m,"\ufeff"),l=l.splitText(e),i=l.splitText(m-e),l.deleteData(0,g.start.length),l.deleteData(l.data.length-g.end.length,g.end.length),d.formatter.apply(g.format,{},l),d.selection.setCursorLocation(i,1)}),b(function(){j="space",d.once("selectionchange",function(){var a;i&&(a=i.data.indexOf("\ufeff"),a!==-1&&i.deleteData(a,a+1))})})))}}function f(a){var b,c=d.dom.getParent(a,"p");if(c){for(;(b=c.firstChild)&&3!==b.nodeType;)c=b;if(b)return b.data||(b=b.nextSibling&&3===b.nextSibling.nodeType?b.nextSibling:null),b}}function g(){var c,e,g=d.selection.getRng(),h=g.startContainer;h&&f(h)===h&&(c=h.parentNode,e=h.data,a.each(m,function(a){var f=e.match(a.regExp);if(f&&g.startOffset===f[0].length)return d.undoManager.add(),d.undoManager.transact(function(){h.deleteData(0,f[0].length),c.innerHTML||c.appendChild(document.createElement("br")),d.selection.setCursorLocation(c),d.execCommand(a.cmd)}),b(function(){j="space"}),!1}))}function h(){var c,e,g,h=d.selection.getRng(),k=h.startContainer,l=f(k),m=n.length;if(l){for(c=l.data;m--;)if(n[m].start){if(0===c.indexOf(n[m].start)){e=n[m];break}}else if(n[m].regExp&&n[m].regExp.test(c)){e=n[m];break}e&&(l===k&&a.trim(c)===e.start||d.once("keyup",function(){d.undoManager.add(),d.undoManager.transact(function(){e.format?(d.formatter.apply(e.format,{},l),l.replaceData(0,l.data.length,i(l.data.slice(e.start.length)))):e.element&&(g=l.parentNode&&l.parentNode.parentNode,g&&g.replaceChild(document.createElement(e.element),l.parentNode))}),b(function(){j="enter"})}))}}function i(a){return a?a.replace(/^\s+/,""):""}var j,k=a.util.VK,l=d.settings.wptextpattern||{},m=l.space||[{regExp:/^[*-]\s/,cmd:"InsertUnorderedList"},{regExp:/^1[.)]\s/,cmd:"InsertOrderedList"}],n=l.enter||[{start:"##",format:"h2"},{start:"###",format:"h3"},{start:"####",format:"h4"},{start:"#####",format:"h5"},{start:"######",format:"h6"},{start:">",format:"blockquote"},{regExp:/^(-){3,}$/,element:"hr"}],o=l.inline||[{start:"`",end:"`",format:"code"}],p=[];a.each(o,function(b){a.each((b.start+b.end).split(""),function(b){a.inArray(p,b)===-1&&p.push(b)})}),d.on("selectionchange",function(){j=null}),d.on("keydown",function(a){(j&&27===a.keyCode||"space"===j&&a.keyCode===k.BACKSPACE)&&(d.undoManager.undo(),a.preventDefault(),a.stopImmediatePropagation()),k.metaKeyPressed(a)||(a.keyCode===k.ENTER?h():a.keyCode===k.SPACEBAR?b(g):a.keyCode>47&&!(a.keyCode>=91&&a.keyCode<=93)&&b(e))},!0)})}(window.tinymce,window.setTimeout); \ No newline at end of file +!function(a,b){function c(a){return a.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&")}a.Env.ie&&a.Env.ie<9||a.PluginManager.add("wptextpattern",function(d){function e(){var e,f,g,h,i,k=d.selection.getRng(),l=k.startContainer,m=k.startOffset;if(l&&3===l.nodeType&&l.data.length&&m){var n=l.data.slice(0,m),p=l.data.charAt(m-1);a.each(o,function(a){if(p===a.delimiter.slice(-1)){var b=c(a.delimiter),d=a.delimiter.charAt(0),h=new RegExp("(.*)"+b+".+"+b+"$"),i=n.match(h);if(i){e=i[1].length,f=m-a.delimiter.length;var j=n.charAt(e-1),k=n.charAt(e+a.delimiter.length);if(!(e&&/\S/.test(j)&&(/\s/.test(k)||j===d)||new RegExp("^[\\s"+c(d)+"]+$").test(n.slice(e,f))))return g=a,!1}}}),g&&(h=d.formatter.get(g.format),h&&h[0].inline&&(d.undoManager.add(),d.undoManager.transact(function(){l.insertData(m,"\ufeff"),l=l.splitText(e),i=l.splitText(m-e),l.deleteData(0,g.delimiter.length),l.deleteData(l.data.length-g.delimiter.length,g.delimiter.length),d.formatter.apply(g.format,{},l),d.selection.setCursorLocation(i,1)}),b(function(){j="space",d.once("selectionchange",function(){var a;i&&(a=i.data.indexOf("\ufeff"),a!==-1&&i.deleteData(a,a+1))})})))}}function f(a){var b,c=d.dom.getParent(a,"p");if(c){for(;(b=c.firstChild)&&3!==b.nodeType;)c=b;if(b)return b.data||(b=b.nextSibling&&3===b.nextSibling.nodeType?b.nextSibling:null),b}}function g(){var c,e,g=d.selection.getRng(),h=g.startContainer;h&&f(h)===h&&(c=h.parentNode,e=h.data,a.each(m,function(a){var f=e.match(a.regExp);if(f&&g.startOffset===f[0].length)return d.undoManager.add(),d.undoManager.transact(function(){h.deleteData(0,f[0].length),c.innerHTML||c.appendChild(document.createElement("br")),d.selection.setCursorLocation(c),d.execCommand(a.cmd)}),b(function(){j="space"}),!1}))}function h(){var c,e,g,h=d.selection.getRng(),k=h.startContainer,l=f(k),m=n.length;if(l){for(c=l.data;m--;)if(n[m].start){if(0===c.indexOf(n[m].start)){e=n[m];break}}else if(n[m].regExp&&n[m].regExp.test(c)){e=n[m];break}e&&(l===k&&a.trim(c)===e.start||d.once("keyup",function(){d.undoManager.add(),d.undoManager.transact(function(){e.format?(d.formatter.apply(e.format,{},l),l.replaceData(0,l.data.length,i(l.data.slice(e.start.length)))):e.element&&(g=l.parentNode&&l.parentNode.parentNode,g&&g.replaceChild(document.createElement(e.element),l.parentNode))}),b(function(){j="enter"})}))}}function i(a){return a?a.replace(/^\s+/,""):""}var j,k=a.util.VK,l=d.settings.wptextpattern||{},m=l.space||[{regExp:/^[*-]\s/,cmd:"InsertUnorderedList"},{regExp:/^1[.)]\s/,cmd:"InsertOrderedList"}],n=l.enter||[{start:"##",format:"h2"},{start:"###",format:"h3"},{start:"####",format:"h4"},{start:"#####",format:"h5"},{start:"######",format:"h6"},{start:">",format:"blockquote"},{regExp:/^(-){3,}$/,element:"hr"}],o=l.inline||[{delimiter:"`",format:"code"}];d.on("selectionchange",function(){j=null}),d.on("keydown",function(a){(j&&27===a.keyCode||"space"===j&&a.keyCode===k.BACKSPACE)&&(d.undoManager.undo(),a.preventDefault(),a.stopImmediatePropagation()),k.metaKeyPressed(a)||(a.keyCode===k.ENTER?h():a.keyCode===k.SPACEBAR?b(g):a.keyCode>47&&!(a.keyCode>=91&&a.keyCode<=93)&&b(e))},!0)})}(window.tinymce,window.setTimeout); \ No newline at end of file diff --git a/wp-includes/js/tinymce/wp-tinymce.js.gz b/wp-includes/js/tinymce/wp-tinymce.js.gz index c212d1feb4..5f02c27425 100644 Binary files a/wp-includes/js/tinymce/wp-tinymce.js.gz and b/wp-includes/js/tinymce/wp-tinymce.js.gz differ diff --git a/wp-includes/version.php b/wp-includes/version.php index 6703fe25f9..d934c047ae 100644 --- a/wp-includes/version.php +++ b/wp-includes/version.php @@ -4,7 +4,7 @@ * * @global string $wp_version */ -$wp_version = '4.7-beta2-39149'; +$wp_version = '4.7-beta2-39150'; /** * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.