@@ -87,18 +87,23 @@ export class SearchRequest {
87
87
*/
88
88
static tokenizeSearchText ( searchText : string ) : string [ ] {
89
89
// based on code generated by gemini
90
- const regex = / " ( [ ^ " ] * ) " | \S + / g; // tokenizes all words between double quotes as well as every word outside of quotes
91
- let tokens = [ ] ;
92
- let match ;
93
-
94
- while ( ( match = regex . exec ( searchText ) ) !== null ) {
95
- if ( match [ 1 ] ) {
96
- tokens . push ( match [ 1 ] ) ; // Add the content within quotes
97
- } else {
98
- tokens . push ( match [ 0 ] ) ; // Add the non-quoted token
90
+ let matches = SearchRequest . extractQuotedStrings ( searchText ) ;
91
+ // filter out ',' tokens
92
+ matches = matches . flatMap ( item => item === ',' ? [ ] : item ) ;
93
+
94
+ // Process each match to unescape characters in quoted strings.
95
+ return matches . map ( match => {
96
+ // Check if the match is a quoted string.
97
+ if ( match . startsWith ( '"' ) && match . endsWith ( '"' ) ) {
98
+ // Remove leading/trailing quotes and then unescape the characters.
99
+ let unescaped = match . slice ( 1 , - 1 ) ;
100
+ unescaped = unescaped . replace ( / \\ " / g, '"' ) ;
101
+ unescaped = unescaped . replace ( / \\ \\ / g, '\\' ) ;
102
+ return unescaped ;
99
103
}
100
- }
101
- return tokens ;
104
+ // For unquoted words, return as-is.
105
+ return match ;
106
+ } ) ;
102
107
}
103
108
104
109
@@ -403,6 +408,25 @@ export class SearchRequest {
403
408
}
404
409
405
410
411
+ /** returns true iff searchText is a quoted string
412
+ */
413
+ static isQuotedString = ( searchText : string ) : boolean => {
414
+ return new RegExp ( / " ( [ ^ " ] * ) " / g) . test ( searchText ) ;
415
+ // return new RegExp(/"(?:[^"\\]|\\.)+"|[^\s,]+/g).test(searchText);
416
+ } ;
417
+
418
+
419
+ static extractQuotedStrings = ( searchText : string ) : string [ ] => {
420
+ // based on code generated by gemini
421
+ // Regex to find tokens: quoted strings with escaped quotes, or unquoted words.
422
+ const regex = / " [ ^ " ] * " | [ \S ] + / g
423
+ // const regex = /"([^"]*)"/g;
424
+ const matches = searchText . match ( regex ) ;
425
+ return matches ?? [ ] ;
426
+ }
427
+
428
+
429
+
406
430
/**
407
431
* determine the SearchReuestTypeId based on searchText
408
432
* @param searchText the search text
@@ -414,7 +438,12 @@ export class SearchRequest {
414
438
if ( searchText . includes ( '{' ) ) {
415
439
return 'SEARCH_STRING_CANNOT_CONTAIN_RESERVED_CHARACTERS'
416
440
}
417
- // disallow wildcards
441
+ // else if (searchText[0] == '"' && searchText[searchText.length - 1] == '"') {
442
+ // else if (new RegExp(/"([^"]*)"/g).test(searchText)) {
443
+ // else if (new RegExp(/"(?:[^"\\]|\\.)+"|[^\s,]+/g).test(searchText)) {
444
+ else if ( SearchRequest . isQuotedString ( searchText ) ) {
445
+ return 'SEARCH_PHRASE' ;
446
+ }
418
447
else if ( searchText . includes ( '*' ) ) {
419
448
return 'SEARCH_AS_WILDCARD_ASTERISK'
420
449
}
@@ -429,11 +458,6 @@ export class SearchRequest {
429
458
else if ( searchText . includes ( '%' ) ) {
430
459
return 'WILDCARD_PERCENT_SEARCH_NOT_SUPPORTED'
431
460
}
432
- // else if (searchText[0] == '"' && searchText[searchText.length - 1] == '"') {
433
- else if ( new RegExp ( / " ( [ ^ " ] * ) " / g) . test ( searchText ) ) {
434
- return 'SEARCH_PHRASE'
435
- }
436
-
437
461
// process urls
438
462
else if ( SearchRequest . isUrl ( searchText ) ) {
439
463
// original from https://jsfiddle.net/DanielD/8S4nq/
0 commit comments