jenkins-bot has submitted this change and it was merged. ( https://gerrit.wikimedia.org/r/342016 )
Change subject: Use Intl.Collator for all searches if available ...................................................................... Use Intl.Collator for all searches if available Fall back to simple equality / toLowerCase equality if not available (IE9/10). Also by always using the stream search this avoids incorrect offsets caused by doing indexOf on a string that has changed length due to toLowerCase rules. Bug: T159439 Change-Id: Ic849f5f9014203172fa8eaa5316813093da88aa7 --- M src/dm/ve.dm.Document.js M tests/dm/ve.dm.Document.test.js 2 files changed, 41 insertions(+), 29 deletions(-) Approvals: jenkins-bot: Verified Jforrester: Looks good to me, approved diff --git a/src/dm/ve.dm.Document.js b/src/dm/ve.dm.Document.js index 5575365..ee9f097 100644 --- a/src/dm/ve.dm.Document.js +++ b/src/dm/ve.dm.Document.js @@ -1492,16 +1492,19 @@ * @return {ve.Range[]} List of ranges where the string was found */ ve.dm.Document.prototype.findText = function ( query, options ) { - var i, j, l, qLen, match, offset, lines, dataString, sensitivity, compare, - ranges = [], - text = this.data.getText( - true, - new ve.Range( 0, this.getInternalList().getListNode().getOuterRange().start ) - ); + var i, j, l, qLen, match, offset, lines, dataString, sensitivity, compare, text, + data = this.data, + docLen = this.getInternalList().getListNode().getOuterRange().start, + ranges = []; options = options || {}; if ( query instanceof RegExp ) { + // Convert whole doucment to plain-text for regex matching + text = data.getText( + true, + new ve.Range( 0, docLen ) + ); offset = 0; // Avoid multi-line matching by only matching within newlines lines = text.split( '\n' ); @@ -1529,31 +1532,34 @@ } } else { qLen = query.length; - if ( options.diacriticInsensitiveString && ve.supportsIntl ) { - sensitivity = options.caseSensitiveString ? 'case' : 'base'; + if ( ve.supportsIntl ) { + if ( options.diacriticInsensitiveString ) { + sensitivity = options.caseSensitiveString ? 'case' : 'base'; + } else { + sensitivity = options.caseSensitiveString ? 'variant' : 'accent'; + } compare = new Intl.Collator( this.lang, { sensitivity: sensitivity } ).compare; - // Iterate up to (and including) offset textLength - queryLength. Beyond that point - // there is not enough room for the query to exist - for ( offset = 0, l = text.length - qLen; offset <= l; offset++ ) { - j = 0; - while ( compare( text[ offset + j ], query[ j ] ) === 0 ) { - j++; - if ( j === qLen ) { - ranges.push( new ve.Range( offset, offset + qLen ) ); - offset += options.noOverlaps ? qLen - 1 : 0; - break; - } - } - } } else { - if ( !options.caseSensitiveString ) { - text = text.toLowerCase(); - query = query.toLowerCase(); - } - offset = -1; - while ( ( offset = text.indexOf( query, offset ) ) !== -1 ) { - ranges.push( new ve.Range( offset, offset + qLen ) ); - offset += options.noOverlaps ? qLen : 1; + // Support: IE<=10 + compare = options.caseSensitiveString ? + function ( a, b ) { + return a === b ? 0 : 1; + } : + function ( a, b ) { + return a.toLowerCase() === b.toLowerCase() ? 0 : 1; + }; + } + // Iterate up to (and including) offset textLength - queryLength. Beyond that point + // there is not enough room for the query to exist + for ( offset = 0, l = docLen - qLen; offset <= l; offset++ ) { + j = 0; + while ( compare( data.getCharacterData( offset + j ), query[ j ] ) === 0 ) { + j++; + if ( j === qLen ) { + ranges.push( new ve.Range( offset, offset + qLen ) ); + offset += options.noOverlaps ? qLen - 1 : 0; + break; + } } } } diff --git a/tests/dm/ve.dm.Document.test.js b/tests/dm/ve.dm.Document.test.js index 2163f15..1694696 100644 --- a/tests/dm/ve.dm.Document.test.js +++ b/tests/dm/ve.dm.Document.test.js @@ -1041,6 +1041,7 @@ QUnit.test( 'Find text', function ( assert ) { var i, ranges, + supportsIntl = ve.supportsIntl, doc = ve.dm.converter.getModelFromDom( ve.createDocumentFromHtml( // 1 '<p>Foo bar fooq.</p>' + @@ -1245,5 +1246,10 @@ doc.lang = cases[ i ].lang || 'en'; ranges = doc.findText( cases[ i ].query, cases[ i ].options ); assert.deepEqual( ranges, cases[ i ].ranges, cases[ i ].msg ); + if ( !cases[ i ].options.diacriticInsensitiveString ) { + ve.supportsIntl = false; + assert.deepEqual( ranges, cases[ i ].ranges, cases[ i ].msg + ': without Intl API' ); + ve.supportsIntl = supportsIntl; + } } } ); -- To view, visit https://gerrit.wikimedia.org/r/342016 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: Ic849f5f9014203172fa8eaa5316813093da88aa7 Gerrit-PatchSet: 2 Gerrit-Project: VisualEditor/VisualEditor Gerrit-Branch: master Gerrit-Owner: Esanders <esand...@wikimedia.org> Gerrit-Reviewer: Jforrester <jforres...@wikimedia.org> Gerrit-Reviewer: jenkins-bot <> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits