From cccc4c11865d75b28eee1b2cc92a2bb98717e953 Mon Sep 17 00:00:00 2001 From: Arkadiusz Filipczak Date: Fri, 20 Aug 2021 13:55:44 +0200 Subject: [PATCH 1/4] Use look{ahead,behind} assertion in whole-word search --- packages/ckeditor5-find-and-replace/src/utils.js | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/packages/ckeditor5-find-and-replace/src/utils.js b/packages/ckeditor5-find-and-replace/src/utils.js index a06289fdab6..315e18dd135 100644 --- a/packages/ckeditor5-find-and-replace/src/utils.js +++ b/packages/ckeditor5-find-and-replace/src/utils.js @@ -104,12 +104,7 @@ function findInsertIndex( resultsList, markerToInsert ) { function regexpMatchToFindResult( matchResult ) { const lastGroupIndex = matchResult.length - 1; - let startOffset = matchResult.index; - - // Searches with match all flag have an extra matching group with empty string or white space matched before the word. - if ( matchResult.length === 3 ) { - startOffset += matchResult[ 1 ].length; - } + const startOffset = matchResult.index; return { label: matchResult[ lastGroupIndex ], @@ -138,7 +133,7 @@ export function findByTextCallback( searchTerm, options ) { if ( options.wholeWords ) { const nonLetterGroup = '[^a-zA-Z\u00C0-\u024F\u1E00-\u1EFF]'; - regExpQuery = `(^|${ nonLetterGroup }|_)` + regExpQuery + `(?:_|${ nonLetterGroup }|$)`; + regExpQuery = `(?<=^|${ nonLetterGroup }|_)` + regExpQuery + `(?=_|${ nonLetterGroup }|$)`; } const regExp = new RegExp( regExpQuery, flags ); From 3901b9f8d464f93d9978f3ff797e5400920b53e8 Mon Sep 17 00:00:00 2001 From: Arkadiusz Filipczak Date: Fri, 20 Aug 2021 14:11:34 +0200 Subject: [PATCH 2/4] Whole-word search should return results if it start/end with a space --- .../ckeditor5-find-and-replace/src/utils.js | 10 +++++++- .../tests/findcommand.js | 24 +++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/packages/ckeditor5-find-and-replace/src/utils.js b/packages/ckeditor5-find-and-replace/src/utils.js index 315e18dd135..29ea5722a08 100644 --- a/packages/ckeditor5-find-and-replace/src/utils.js +++ b/packages/ckeditor5-find-and-replace/src/utils.js @@ -133,7 +133,15 @@ export function findByTextCallback( searchTerm, options ) { if ( options.wholeWords ) { const nonLetterGroup = '[^a-zA-Z\u00C0-\u024F\u1E00-\u1EFF]'; - regExpQuery = `(?<=^|${ nonLetterGroup }|_)` + regExpQuery + `(?=_|${ nonLetterGroup }|$)`; + if ( !new RegExp( '^' + nonLetterGroup ).test( searchTerm ) ) + { + regExpQuery = `(?<=^|${ nonLetterGroup }|_)${ regExpQuery }`; + } + + if ( !new RegExp( nonLetterGroup + '$' ).test( searchTerm ) ) + { + regExpQuery = `${ regExpQuery }(?=_|${ nonLetterGroup }|$)`; + } } const regExp = new RegExp( regExpQuery, flags ); diff --git a/packages/ckeditor5-find-and-replace/tests/findcommand.js b/packages/ckeditor5-find-and-replace/tests/findcommand.js index 2a4b8b66aa1..7b92e2dcfb4 100644 --- a/packages/ckeditor5-find-and-replace/tests/findcommand.js +++ b/packages/ckeditor5-find-and-replace/tests/findcommand.js @@ -233,6 +233,30 @@ describe( 'FindCommand', () => { expect( results.length ).to.equal( 1 ); } ); + it( 'set to true matches a text ending with a space ', () => { + editor.setData( '

foo bar baz

' ); + + const { results } = command.execute( 'bar ', { wholeWords: true } ); + + expect( results.length ).to.equal( 1 ); + } ); + + it( 'set to true matches a text starting with a space ', () => { + editor.setData( '

foo bar baz

' ); + + const { results } = command.execute( ' bar', { wholeWords: true } ); + + expect( results.length ).to.equal( 1 ); + } ); + + it( 'set to true matches a text starting and ending with a space ', () => { + editor.setData( '

foo bar baz

' ); + + const { results } = command.execute( ' bar ', { wholeWords: true } ); + + expect( results.length ).to.equal( 1 ); + } ); + it( 'set to true doesn\'t match a word including diacritic characters', () => { editor.setData( '

foo łbarę and Äbarè

' ); From f16e275eb94b4821badb5bab9bb2dcfc027141f0 Mon Sep 17 00:00:00 2001 From: Arkadiusz Filipczak Date: Mon, 23 Aug 2021 15:02:00 +0200 Subject: [PATCH 3/4] Remove look{ahead,behind} assertions from whole-word search --- packages/ckeditor5-find-and-replace/src/utils.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/ckeditor5-find-and-replace/src/utils.js b/packages/ckeditor5-find-and-replace/src/utils.js index 29ea5722a08..53c46c63186 100644 --- a/packages/ckeditor5-find-and-replace/src/utils.js +++ b/packages/ckeditor5-find-and-replace/src/utils.js @@ -104,7 +104,13 @@ function findInsertIndex( resultsList, markerToInsert ) { function regexpMatchToFindResult( matchResult ) { const lastGroupIndex = matchResult.length - 1; - const startOffset = matchResult.index; + let startOffset = matchResult.index; + + // Searches with match all flag have an extra matching group with empty string or white space matched before the word. + // If the search term starts with the space already, there is no extra group even with match all flag on. + if ( matchResult.length === 3 ) { + startOffset += matchResult[ 1 ].length; + } return { label: matchResult[ lastGroupIndex ], @@ -135,12 +141,12 @@ export function findByTextCallback( searchTerm, options ) { if ( !new RegExp( '^' + nonLetterGroup ).test( searchTerm ) ) { - regExpQuery = `(?<=^|${ nonLetterGroup }|_)${ regExpQuery }`; + regExpQuery = `(^|${ nonLetterGroup }|_)${ regExpQuery }`; } if ( !new RegExp( nonLetterGroup + '$' ).test( searchTerm ) ) { - regExpQuery = `${ regExpQuery }(?=_|${ nonLetterGroup }|$)`; + regExpQuery = `${ regExpQuery }(?:_|${ nonLetterGroup }|$)`; } } From fc4e74ec0b7f2c03ee1306ea0415daa457e0017d Mon Sep 17 00:00:00 2001 From: Kuba Niegowski <1232187+niegowski@users.noreply.github.com> Date: Mon, 23 Aug 2021 15:48:23 +0200 Subject: [PATCH 4/4] Apply review comment. --- packages/ckeditor5-find-and-replace/src/utils.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/ckeditor5-find-and-replace/src/utils.js b/packages/ckeditor5-find-and-replace/src/utils.js index 53c46c63186..8f71cd042cf 100644 --- a/packages/ckeditor5-find-and-replace/src/utils.js +++ b/packages/ckeditor5-find-and-replace/src/utils.js @@ -139,13 +139,11 @@ export function findByTextCallback( searchTerm, options ) { if ( options.wholeWords ) { const nonLetterGroup = '[^a-zA-Z\u00C0-\u024F\u1E00-\u1EFF]'; - if ( !new RegExp( '^' + nonLetterGroup ).test( searchTerm ) ) - { + if ( !new RegExp( '^' + nonLetterGroup ).test( searchTerm ) ) { regExpQuery = `(^|${ nonLetterGroup }|_)${ regExpQuery }`; } - if ( !new RegExp( nonLetterGroup + '$' ).test( searchTerm ) ) - { + if ( !new RegExp( nonLetterGroup + '$' ).test( searchTerm ) ) { regExpQuery = `${ regExpQuery }(?:_|${ nonLetterGroup }|$)`; } }