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

Reply via email to