@itwin/appui-abstract 4.3.0-dev.8 → 4.4.0-dev.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/CHANGELOG.md +38 -1
  2. package/lib/cjs/appui-abstract/UiAdmin.d.ts.map +1 -1
  3. package/lib/cjs/appui-abstract/UiAdmin.js +5 -4
  4. package/lib/cjs/appui-abstract/UiAdmin.js.map +1 -1
  5. package/lib/cjs/appui-abstract/UiItemsManager.d.ts.map +1 -1
  6. package/lib/cjs/appui-abstract/UiItemsManager.js +4 -4
  7. package/lib/cjs/appui-abstract/UiItemsManager.js.map +1 -1
  8. package/lib/cjs/appui-abstract/common/KeyboardKey.d.ts +3 -3
  9. package/lib/cjs/appui-abstract/common/KeyboardKey.d.ts.map +1 -1
  10. package/lib/cjs/appui-abstract/common/KeyboardKey.js +4 -3
  11. package/lib/cjs/appui-abstract/common/KeyboardKey.js.map +1 -1
  12. package/lib/cjs/appui-abstract/utils/IconSpecUtilities.d.ts +3 -3
  13. package/lib/cjs/appui-abstract/utils/IconSpecUtilities.d.ts.map +1 -1
  14. package/lib/cjs/appui-abstract/utils/IconSpecUtilities.js +4 -3
  15. package/lib/cjs/appui-abstract/utils/IconSpecUtilities.js.map +1 -1
  16. package/lib/cjs/appui-abstract/utils/UiError.d.ts +1 -1
  17. package/lib/cjs/appui-abstract/utils/UiError.js +1 -1
  18. package/lib/cjs/appui-abstract/utils/UiError.js.map +1 -1
  19. package/lib/cjs/appui-abstract/utils/filter/filters.d.ts +2 -80
  20. package/lib/cjs/appui-abstract/utils/filter/filters.d.ts.map +1 -1
  21. package/lib/cjs/appui-abstract/utils/filter/filters.js +13 -621
  22. package/lib/cjs/appui-abstract/utils/filter/filters.js.map +1 -1
  23. package/lib/cjs/appui-abstract/utils/misc.d.ts +1 -4
  24. package/lib/cjs/appui-abstract/utils/misc.d.ts.map +1 -1
  25. package/lib/cjs/appui-abstract/utils/misc.js +2 -10
  26. package/lib/cjs/appui-abstract/utils/misc.js.map +1 -1
  27. package/lib/cjs/appui-abstract.d.ts +0 -2
  28. package/lib/cjs/appui-abstract.d.ts.map +1 -1
  29. package/lib/cjs/appui-abstract.js +0 -2
  30. package/lib/cjs/appui-abstract.js.map +1 -1
  31. package/lib/esm/appui-abstract/UiAdmin.d.ts.map +1 -1
  32. package/lib/esm/appui-abstract/UiAdmin.js +6 -5
  33. package/lib/esm/appui-abstract/UiAdmin.js.map +1 -1
  34. package/lib/esm/appui-abstract/UiItemsManager.d.ts.map +1 -1
  35. package/lib/esm/appui-abstract/UiItemsManager.js +4 -4
  36. package/lib/esm/appui-abstract/UiItemsManager.js.map +1 -1
  37. package/lib/esm/appui-abstract/common/KeyboardKey.d.ts +3 -3
  38. package/lib/esm/appui-abstract/common/KeyboardKey.d.ts.map +1 -1
  39. package/lib/esm/appui-abstract/common/KeyboardKey.js +4 -3
  40. package/lib/esm/appui-abstract/common/KeyboardKey.js.map +1 -1
  41. package/lib/esm/appui-abstract/utils/IconSpecUtilities.d.ts +3 -3
  42. package/lib/esm/appui-abstract/utils/IconSpecUtilities.d.ts.map +1 -1
  43. package/lib/esm/appui-abstract/utils/IconSpecUtilities.js +4 -3
  44. package/lib/esm/appui-abstract/utils/IconSpecUtilities.js.map +1 -1
  45. package/lib/esm/appui-abstract/utils/UiError.d.ts +1 -1
  46. package/lib/esm/appui-abstract/utils/UiError.js +1 -1
  47. package/lib/esm/appui-abstract/utils/UiError.js.map +1 -1
  48. package/lib/esm/appui-abstract/utils/filter/filters.d.ts +2 -80
  49. package/lib/esm/appui-abstract/utils/filter/filters.d.ts.map +1 -1
  50. package/lib/esm/appui-abstract/utils/filter/filters.js +12 -609
  51. package/lib/esm/appui-abstract/utils/filter/filters.js.map +1 -1
  52. package/lib/esm/appui-abstract/utils/misc.d.ts +1 -4
  53. package/lib/esm/appui-abstract/utils/misc.d.ts.map +1 -1
  54. package/lib/esm/appui-abstract/utils/misc.js +1 -8
  55. package/lib/esm/appui-abstract/utils/misc.js.map +1 -1
  56. package/lib/esm/appui-abstract.d.ts +0 -2
  57. package/lib/esm/appui-abstract.d.ts.map +1 -1
  58. package/lib/esm/appui-abstract.js +0 -2
  59. package/lib/esm/appui-abstract.js.map +1 -1
  60. package/package.json +5 -6
  61. package/lib/cjs/appui-abstract/utils/filter/charCode.d.ts +0 -417
  62. package/lib/cjs/appui-abstract/utils/filter/charCode.d.ts.map +0 -1
  63. package/lib/cjs/appui-abstract/utils/filter/charCode.js +0 -7
  64. package/lib/cjs/appui-abstract/utils/filter/charCode.js.map +0 -1
  65. package/lib/cjs/appui-abstract/utils/filter/map.d.ts +0 -60
  66. package/lib/cjs/appui-abstract/utils/filter/map.d.ts.map +0 -1
  67. package/lib/cjs/appui-abstract/utils/filter/map.js +0 -403
  68. package/lib/cjs/appui-abstract/utils/filter/map.js.map +0 -1
  69. package/lib/cjs/appui-abstract/utils/filter/strings.d.ts +0 -21
  70. package/lib/cjs/appui-abstract/utils/filter/strings.d.ts.map +0 -1
  71. package/lib/cjs/appui-abstract/utils/filter/strings.js +0 -79
  72. package/lib/cjs/appui-abstract/utils/filter/strings.js.map +0 -1
  73. package/lib/esm/appui-abstract/utils/filter/charCode.d.ts +0 -417
  74. package/lib/esm/appui-abstract/utils/filter/charCode.d.ts.map +0 -1
  75. package/lib/esm/appui-abstract/utils/filter/charCode.js +0 -6
  76. package/lib/esm/appui-abstract/utils/filter/charCode.js.map +0 -1
  77. package/lib/esm/appui-abstract/utils/filter/map.d.ts +0 -60
  78. package/lib/esm/appui-abstract/utils/filter/map.d.ts.map +0 -1
  79. package/lib/esm/appui-abstract/utils/filter/map.js +0 -398
  80. package/lib/esm/appui-abstract/utils/filter/map.js.map +0 -1
  81. package/lib/esm/appui-abstract/utils/filter/strings.d.ts +0 -21
  82. package/lib/esm/appui-abstract/utils/filter/strings.d.ts.map +0 -1
  83. package/lib/esm/appui-abstract/utils/filter/strings.js +0 -71
  84. package/lib/esm/appui-abstract/utils/filter/strings.js.map +0 -1
@@ -7,104 +7,19 @@
7
7
  * @module Utilities
8
8
  */
9
9
  Object.defineProperty(exports, "__esModule", { value: true });
10
- exports.fuzzyScoreGraceful = exports.fuzzyScoreGracefulAggressive = exports.fuzzyScore = exports.FuzzyScore = exports.isPatternInWord = exports.createMatches = exports.matchesFuzzy2 = exports.matchesFuzzy = exports.matchesWords = exports.matchesCamelCase = exports.matchesSubString = exports.matchesContiguousSubString = exports.matchesPrefix = exports.matchesStrictPrefix = exports.or = void 0;
11
- const map_1 = require("./map");
12
- const strings = require("./strings");
13
- // Combined filters
14
- /**
15
- * @returns A filter which combines the provided set
16
- * of filters with an or. The *first* filters that
17
- * matches defined the return value of the returned
18
- * filter.
19
- * @internal
20
- */
21
- function or(...filter) {
22
- return function (word, wordToMatchAgainst) {
23
- for (let i = 0, len = filter.length; i < len; i++) {
24
- const match = filter[i](word, wordToMatchAgainst);
25
- if (match) {
26
- return match;
27
- }
28
- }
29
- return null;
30
- };
31
- }
32
- exports.or = or;
33
- // Prefix
34
- /** @internal */
35
- exports.matchesStrictPrefix = _matchesPrefix.bind(undefined, false);
36
- /** @internal */
37
- exports.matchesPrefix = _matchesPrefix.bind(undefined, true);
38
- function _matchesPrefix(ignoreCase, word, wordToMatchAgainst) {
39
- if (!wordToMatchAgainst || wordToMatchAgainst.length < word.length) {
40
- return null;
41
- }
42
- let matches;
43
- if (ignoreCase) {
44
- matches = strings.startsWithIgnoreCase(wordToMatchAgainst, word);
45
- }
46
- else {
47
- matches = wordToMatchAgainst.indexOf(word) === 0;
48
- }
49
- if (!matches) {
50
- return null;
51
- }
52
- return word.length > 0 ? [{ start: 0, end: word.length }] : [];
53
- }
54
- // Contiguous Substring
55
- /** @internal */
56
- function matchesContiguousSubString(word, wordToMatchAgainst) {
57
- const index = wordToMatchAgainst.toLowerCase().indexOf(word.toLowerCase());
58
- if (index === -1) {
59
- return null;
60
- }
61
- return [{ start: index, end: index + word.length }];
62
- }
63
- exports.matchesContiguousSubString = matchesContiguousSubString;
64
- // Substring
65
- /**
66
- * Return case insensitive substring matches
67
- * @param word filter string
68
- * @param wordToMatchAgainst string to test
69
- * @internal
70
- */
71
- function matchesSubString(word, wordToMatchAgainst) {
72
- return _matchesSubString(word.toLowerCase(), wordToMatchAgainst.toLowerCase(), 0, 0);
73
- }
74
- exports.matchesSubString = matchesSubString;
75
- function _matchesSubString(word, wordToMatchAgainst, i, j) {
76
- if (i === word.length) {
77
- return [];
78
- }
79
- else if (j === wordToMatchAgainst.length) {
80
- return null;
81
- }
82
- else {
83
- if (word[i] === wordToMatchAgainst[j]) {
84
- let result = null;
85
- if (result = _matchesSubString(word, wordToMatchAgainst, i + 1, j + 1)) {
86
- return join({ start: j, end: j + 1 }, result);
87
- }
88
- return null;
89
- }
90
- return _matchesSubString(word, wordToMatchAgainst, i, j + 1);
91
- }
92
- }
93
- // CamelCase
94
- function isLower(code) {
95
- return 97 /* CharCode.a */ <= code && code <= 122 /* CharCode.z */;
96
- }
97
- function isUpper(code) {
98
- return 65 /* CharCode.A */ <= code && code <= 90 /* CharCode.Z */;
99
- }
100
- function isNumber(code) {
101
- return 48 /* CharCode.Digit0 */ <= code && code <= 57 /* CharCode.Digit9 */;
102
- }
10
+ exports.matchesWords = void 0;
11
+ var CharCode;
12
+ (function (CharCode) {
13
+ CharCode[CharCode["Space"] = 32] = "Space";
14
+ CharCode[CharCode["Tab"] = 9] = "Tab";
15
+ CharCode[CharCode["LineFeed"] = 10] = "LineFeed";
16
+ CharCode[CharCode["CarriageReturn"] = 13] = "CarriageReturn";
17
+ })(CharCode || (CharCode = {}));
103
18
  function isWhitespace(code) {
104
- return (code === 32 /* CharCode.Space */
105
- || code === 9 /* CharCode.Tab */
106
- || code === 10 /* CharCode.LineFeed */
107
- || code === 13 /* CharCode.CarriageReturn */);
19
+ return (code === CharCode.Space
20
+ || code === CharCode.Tab
21
+ || code === CharCode.LineFeed
22
+ || code === CharCode.CarriageReturn);
108
23
  }
109
24
  const wordSeparators = new Set();
110
25
  '`~!@#$%^&*()-=+[{]}\\|;:\'",.<>/?'
@@ -116,9 +31,6 @@ function isWordSeparator(code) {
116
31
  function charactersMatch(codeA, codeB) {
117
32
  return (codeA === codeB) || (isWordSeparator(codeA) && isWordSeparator(codeB));
118
33
  }
119
- function isAlphanumeric(code) {
120
- return isLower(code) || isUpper(code) || isNumber(code);
121
- }
122
34
  function join(head, tail) {
123
35
  if (tail.length === 0) {
124
36
  tail = [head];
@@ -131,129 +43,6 @@ function join(head, tail) {
131
43
  }
132
44
  return tail;
133
45
  }
134
- function nextAnchor(camelCaseWord, start) {
135
- for (let i = start; i < camelCaseWord.length; i++) {
136
- const c = camelCaseWord.charCodeAt(i);
137
- if (isUpper(c) || isNumber(c) || (i > 0 && !isAlphanumeric(camelCaseWord.charCodeAt(i - 1)))) {
138
- return i;
139
- }
140
- }
141
- return camelCaseWord.length;
142
- }
143
- function _matchesCamelCase(word, camelCaseWord, i, j) {
144
- if (i === word.length) {
145
- return [];
146
- }
147
- else if (j === camelCaseWord.length) {
148
- return null;
149
- }
150
- else if (word[i] !== camelCaseWord[j].toLowerCase()) {
151
- return null;
152
- }
153
- else {
154
- let result = null;
155
- let nextUpperIndex = j + 1;
156
- result = _matchesCamelCase(word, camelCaseWord, i + 1, j + 1);
157
- while (!result && (nextUpperIndex = nextAnchor(camelCaseWord, nextUpperIndex)) < camelCaseWord.length) {
158
- result = _matchesCamelCase(word, camelCaseWord, i + 1, nextUpperIndex);
159
- nextUpperIndex++;
160
- }
161
- return result === null ? null : join({ start: j, end: j + 1 }, result);
162
- }
163
- }
164
- // Heuristic to avoid computing camel case matcher for words that don't
165
- // look like camelCaseWords.
166
- function analyzeCamelCaseWord(word) {
167
- let upper = 0, lower = 0, alpha = 0, numeric = 0, code = 0;
168
- for (let i = 0; i < word.length; i++) {
169
- code = word.charCodeAt(i);
170
- if (isUpper(code)) {
171
- upper++;
172
- }
173
- if (isLower(code)) {
174
- lower++;
175
- }
176
- if (isAlphanumeric(code)) {
177
- alpha++;
178
- }
179
- if (isNumber(code)) {
180
- numeric++;
181
- }
182
- }
183
- const upperPercent = upper / word.length;
184
- const lowerPercent = lower / word.length;
185
- const alphaPercent = alpha / word.length;
186
- const numericPercent = numeric / word.length;
187
- return { upperPercent, lowerPercent, alphaPercent, numericPercent };
188
- }
189
- function isUpperCaseWord(analysis) {
190
- const { upperPercent, lowerPercent } = analysis;
191
- return lowerPercent === 0 && upperPercent > 0.6;
192
- }
193
- function isCamelCaseWord(analysis) {
194
- const { upperPercent, lowerPercent, alphaPercent, numericPercent } = analysis;
195
- return lowerPercent > 0.2 && upperPercent < 0.8 && alphaPercent > 0.6 && numericPercent < 0.2;
196
- }
197
- // Heuristic to avoid computing camel case matcher for words that don't
198
- // look like camel case patterns.
199
- function isCamelCasePattern(word) {
200
- let upper = 0, lower = 0, code = 0, whitespace = 0;
201
- for (let i = 0; i < word.length; i++) {
202
- code = word.charCodeAt(i);
203
- if (isUpper(code)) {
204
- upper++;
205
- }
206
- if (isLower(code)) {
207
- lower++;
208
- }
209
- if (isWhitespace(code)) {
210
- whitespace++;
211
- }
212
- }
213
- if ((upper === 0 || lower === 0) && whitespace === 0) {
214
- return word.length <= 30;
215
- }
216
- else {
217
- return upper <= 5;
218
- }
219
- }
220
- /**
221
- * Return matches treating "camelCase" words separately. For example the filter string "gp" would return two matches in string "Git Pull".
222
- * @param word filter string
223
- * @param wordToMatchAgainst string to test
224
- * @internal
225
- */
226
- function matchesCamelCase(word, camelCaseWord) {
227
- if (!camelCaseWord) {
228
- return null;
229
- }
230
- camelCaseWord = camelCaseWord.trim();
231
- if (camelCaseWord.length === 0) {
232
- return null;
233
- }
234
- if (!isCamelCasePattern(camelCaseWord)) {
235
- return null;
236
- }
237
- if (camelCaseWord.length > 60) {
238
- return null;
239
- }
240
- const analysis = analyzeCamelCaseWord(camelCaseWord);
241
- if (!isCamelCaseWord(analysis)) {
242
- // istanbul ignore next
243
- if (!isUpperCaseWord(analysis)) {
244
- return null;
245
- }
246
- camelCaseWord = camelCaseWord.toLowerCase();
247
- }
248
- let result = null;
249
- let i = 0;
250
- word = word.toLowerCase();
251
- while (i < camelCaseWord.length && (result = _matchesCamelCase(word, camelCaseWord, 0, i)) === null) {
252
- i = nextAnchor(camelCaseWord, i + 1);
253
- }
254
- return result;
255
- }
256
- exports.matchesCamelCase = matchesCamelCase;
257
46
  /**
258
47
  * Matches beginning of words supporting non-ASCII languages.
259
48
  * @param word Filter string
@@ -261,7 +50,7 @@ exports.matchesCamelCase = matchesCamelCase;
261
50
  * @param contiguous - If true the filter string must be found "contiguous" in the searched string (E.g. "pul" will match "Git: Pull").
262
51
  * Otherwise also matches sub string of the word with beginnings of the words in the target (e.g. "gp" or "g p" will match "Git: Pull").
263
52
  * Useful in cases where the target is words (e.g. command labels)
264
- * @internal
53
+ * @internal @deprecated in 4.3. Use `matchesWords` from @itwin/core-react instead. Though internal, this requires deprecation due to known public usage in @itwin/core-react.
265
54
  */
266
55
  function matchesWords(word, target, contiguous = false) {
267
56
  if (!target || target.length === 0) {
@@ -310,401 +99,4 @@ function nextWord(word, start) {
310
99
  }
311
100
  return word.length;
312
101
  }
313
- // Fuzzy
314
- const fuzzyContiguousFilter = or(exports.matchesPrefix, matchesCamelCase, matchesContiguousSubString);
315
- const fuzzySeparateFilter = or(exports.matchesPrefix, matchesCamelCase, matchesSubString);
316
- const fuzzyRegExpCache = new map_1.LRUCache(10000); // bounded to 10000 elements
317
- /**
318
- * Match pattern against word in a fuzzy way. This will only return a single match.
319
- * @internal
320
- */
321
- function matchesFuzzy(word, wordToMatchAgainst, enableSeparateSubstringMatching = false) {
322
- // istanbul ignore next
323
- if (typeof word !== "string" || typeof wordToMatchAgainst !== "string") {
324
- return null; // return early for invalid input
325
- }
326
- // Form RegExp for wildcard matches
327
- let regexp = fuzzyRegExpCache.get(word);
328
- if (!regexp) {
329
- regexp = new RegExp(strings.convertSimple2RegExpPattern(word), "i");
330
- fuzzyRegExpCache.set(word, regexp);
331
- }
332
- // RegExp Filter
333
- const match = regexp.exec(wordToMatchAgainst);
334
- if (match) {
335
- return [{ start: match.index, end: match.index + match[0].length }];
336
- }
337
- // Default Filter
338
- return enableSeparateSubstringMatching ? /* istanbul ignore next */ fuzzySeparateFilter(word, wordToMatchAgainst) : fuzzyContiguousFilter(word, wordToMatchAgainst);
339
- }
340
- exports.matchesFuzzy = matchesFuzzy;
341
- /**
342
- * Match pattern against word in a fuzzy way. As in IntelliSense and faster and more
343
- * powerful than `matchesFuzzy`. This will only return a single match.
344
- * @internal
345
- */
346
- function matchesFuzzy2(pattern, word) {
347
- const score = fuzzyScore(pattern, pattern.toLowerCase(), 0, word, word.toLowerCase(), 0, true);
348
- return score ? createMatches(score) : null;
349
- }
350
- exports.matchesFuzzy2 = matchesFuzzy2;
351
- // #region --- fuzzyScore ---
352
- /**
353
- * @internal
354
- */
355
- function createMatches(score) {
356
- // istanbul ignore next
357
- if (typeof score === "undefined") {
358
- return [];
359
- }
360
- const matches = score[1].toString(2);
361
- const wordStart = score[2];
362
- const res = [];
363
- for (let pos = wordStart; pos < _maxLen; pos++) {
364
- if (matches[matches.length - (pos + 1)] === "1") {
365
- const last = res[res.length - 1];
366
- if (last && last.end === pos) {
367
- last.end = pos + 1;
368
- }
369
- else {
370
- res.push({ start: pos, end: pos + 1 });
371
- }
372
- }
373
- }
374
- return res;
375
- }
376
- exports.createMatches = createMatches;
377
- const _maxLen = 128;
378
- function initTable() {
379
- const table = [];
380
- const row = [0];
381
- for (let i = 1; i <= _maxLen; i++) {
382
- row.push(-i);
383
- }
384
- for (let i = 0; i <= _maxLen; i++) {
385
- const thisRow = row.slice(0);
386
- thisRow[0] = -i;
387
- table.push(thisRow);
388
- }
389
- return table;
390
- }
391
- const _table = initTable();
392
- const _scores = initTable();
393
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
394
- const _arrows = initTable();
395
- const _debug = false;
396
- function isSeparatorAtPos(value, index) {
397
- if (index < 0 || index >= value.length) {
398
- return false;
399
- }
400
- const code = value.charCodeAt(index);
401
- switch (code) {
402
- case 95 /* CharCode.Underline */:
403
- case 45 /* CharCode.Dash */:
404
- case 46 /* CharCode.Period */:
405
- case 32 /* CharCode.Space */:
406
- case 47 /* CharCode.Slash */:
407
- case 92 /* CharCode.Backslash */:
408
- case 39 /* CharCode.SingleQuote */:
409
- case 34 /* CharCode.DoubleQuote */:
410
- case 58 /* CharCode.Colon */:
411
- case 36 /* CharCode.DollarSign */:
412
- return true;
413
- default:
414
- return false;
415
- }
416
- }
417
- function isWhitespaceAtPos(value, index) {
418
- if (index < 0 || index >= value.length) {
419
- return false;
420
- }
421
- const code = value.charCodeAt(index);
422
- switch (code) {
423
- // istanbul ignore next
424
- case 32 /* CharCode.Space */:
425
- case 9 /* CharCode.Tab */:
426
- return true;
427
- default:
428
- return false;
429
- }
430
- }
431
- function isUpperCaseAtPos(pos, word, wordLow) {
432
- return word[pos] !== wordLow[pos];
433
- }
434
- /** @internal */
435
- function isPatternInWord(patternLow, patternPos, patternLen, wordLow, wordPos, wordLen) {
436
- while (patternPos < patternLen && wordPos < wordLen) {
437
- if (patternLow[patternPos] === wordLow[wordPos]) {
438
- patternPos += 1;
439
- }
440
- wordPos += 1;
441
- }
442
- return patternPos === patternLen; // pattern must be exhausted
443
- }
444
- exports.isPatternInWord = isPatternInWord;
445
- /** @internal */
446
- var FuzzyScore;
447
- (function (FuzzyScore) {
448
- /**
449
- * No matches and value `-100`
450
- * @internal
451
- */
452
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
453
- FuzzyScore.Default = Object.freeze([-100, 0, 0]);
454
- // istanbul ignore next
455
- /** @internal */
456
- function isDefault(score) {
457
- return !score || (score[0] === -100 && score[1] === 0 && score[2] === 0);
458
- }
459
- FuzzyScore.isDefault = isDefault;
460
- })(FuzzyScore = exports.FuzzyScore || (exports.FuzzyScore = {}));
461
- /** @internal */
462
- function fuzzyScore(pattern, patternLow, patternStart, word, wordLow, wordStart, firstMatchCanBeWeak) {
463
- // istanbul ignore next
464
- const patternLen = pattern.length > _maxLen ? _maxLen : pattern.length;
465
- const wordLen = word.length > _maxLen ? _maxLen : word.length;
466
- if (patternStart >= patternLen || wordStart >= wordLen || (patternLen - patternStart) > (wordLen - wordStart)) {
467
- return undefined;
468
- }
469
- // Run a simple check if the characters of pattern occur
470
- // (in order) at all in word. If that isn't the case we
471
- // stop because no match will be possible
472
- if (!isPatternInWord(patternLow, patternStart, patternLen, wordLow, wordStart, wordLen)) {
473
- return undefined;
474
- }
475
- let row = 1;
476
- let column = 1;
477
- let patternPos = patternStart;
478
- let wordPos = wordStart;
479
- let hasStrongFirstMatch = false;
480
- // There will be a match, fill in tables
481
- for (row = 1, patternPos = patternStart; patternPos < patternLen; row++, patternPos++) {
482
- for (column = 1, wordPos = wordStart; wordPos < wordLen; column++, wordPos++) {
483
- const score = _doScore(pattern, patternLow, patternPos, patternStart, word, wordLow, wordPos);
484
- if (patternPos === patternStart && score > 1) {
485
- hasStrongFirstMatch = true;
486
- }
487
- _scores[row][column] = score;
488
- const diag = _table[row - 1][column - 1] + (score > 1 ? 1 : score);
489
- const top = _table[row - 1][column] + -1;
490
- const left = _table[row][column - 1] + -1;
491
- if (left >= top) {
492
- // left or diag
493
- if (left > diag) {
494
- _table[row][column] = left;
495
- _arrows[row][column] = 4 /* Arrow.Left */;
496
- }
497
- else if (left === diag) {
498
- _table[row][column] = left;
499
- _arrows[row][column] = 4 /* Arrow.Left */ | 2 /* Arrow.Diag */;
500
- }
501
- else {
502
- _table[row][column] = diag;
503
- _arrows[row][column] = 2 /* Arrow.Diag */;
504
- }
505
- }
506
- else {
507
- // top or diag
508
- if (top > diag) {
509
- _table[row][column] = top;
510
- _arrows[row][column] = 1 /* Arrow.Top */;
511
- }
512
- else if (top === diag) {
513
- _table[row][column] = top;
514
- _arrows[row][column] = 1 /* Arrow.Top */ | 2 /* Arrow.Diag */;
515
- }
516
- else {
517
- _table[row][column] = diag;
518
- _arrows[row][column] = 2 /* Arrow.Diag */;
519
- }
520
- }
521
- }
522
- }
523
- if (!hasStrongFirstMatch && !firstMatchCanBeWeak) {
524
- return undefined;
525
- }
526
- _matchesCount = 0;
527
- _topScore = -100;
528
- _wordStart = wordStart;
529
- _firstMatchCanBeWeak = firstMatchCanBeWeak;
530
- _findAllMatches2(row - 1, column - 1, patternLen === wordLen ? 1 : 0, 0, false);
531
- if (_matchesCount === 0) {
532
- return undefined;
533
- }
534
- return [_topScore, _topMatch2, wordStart];
535
- }
536
- exports.fuzzyScore = fuzzyScore;
537
- function _doScore(pattern, patternLow, patternPos, patternStart, word, wordLow, wordPos) {
538
- if (patternLow[patternPos] !== wordLow[wordPos]) {
539
- return -1;
540
- }
541
- if (wordPos === (patternPos - patternStart)) {
542
- // common prefix: `foobar <-> foobaz`
543
- // ^^^^^
544
- if (pattern[patternPos] === word[wordPos]) {
545
- return 7;
546
- }
547
- else {
548
- return 5;
549
- }
550
- }
551
- else if (isUpperCaseAtPos(wordPos, word, wordLow) && (wordPos === 0 || !isUpperCaseAtPos(wordPos - 1, word, wordLow))) {
552
- // hitting upper-case: `foo <-> forOthers`
553
- // ^^ ^
554
- if (pattern[patternPos] === word[wordPos]) {
555
- return 7;
556
- }
557
- else {
558
- return 5;
559
- }
560
- }
561
- else if (isSeparatorAtPos(wordLow, wordPos) && (wordPos === 0 || !isSeparatorAtPos(wordLow, wordPos - 1))) {
562
- // hitting a separator: `. <-> foo.bar`
563
- // ^
564
- return 5;
565
- }
566
- else if (isSeparatorAtPos(wordLow, wordPos - 1) || isWhitespaceAtPos(wordLow, wordPos - 1)) {
567
- // post separator: `foo <-> bar_foo`
568
- // ^^^
569
- return 5;
570
- }
571
- else {
572
- return 1;
573
- }
574
- }
575
- let _matchesCount = 0;
576
- let _topMatch2 = 0;
577
- let _topScore = 0;
578
- let _wordStart = 0;
579
- let _firstMatchCanBeWeak = false;
580
- function _findAllMatches2(row, column, total, matches, lastMatched) {
581
- if (_matchesCount >= 10 || total < -25) {
582
- // stop when having already 10 results, or
583
- // when a potential alignment as already 5 gaps
584
- return;
585
- }
586
- let simpleMatchCount = 0;
587
- while (row > 0 && column > 0) {
588
- const score = _scores[row][column];
589
- const arrow = _arrows[row][column];
590
- if (arrow === 4 /* Arrow.Left */) {
591
- // left -> no match, skip a word character
592
- column -= 1;
593
- if (lastMatched) {
594
- total -= 5; // new gap penalty
595
- }
596
- else if (matches !== 0) {
597
- total -= 1; // gap penalty after first match
598
- }
599
- lastMatched = false;
600
- simpleMatchCount = 0;
601
- }
602
- else {
603
- /* istanbul ignore else */
604
- if (arrow & 2 /* Arrow.Diag */) {
605
- if (arrow & 4 /* Arrow.Left */) {
606
- // left
607
- _findAllMatches2(row, column - 1, matches !== 0 ? total - 1 : total, // gap penalty after first match
608
- matches, lastMatched);
609
- }
610
- // diag
611
- total += score;
612
- row -= 1;
613
- column -= 1;
614
- lastMatched = true;
615
- // match -> set a 1 at the word pos
616
- matches += 2 ** (column + _wordStart);
617
- // count simple matches and boost a row of
618
- // simple matches when they yield in a
619
- // strong match.
620
- if (score === 1) {
621
- simpleMatchCount += 1;
622
- if (row === 0 && !_firstMatchCanBeWeak) {
623
- // when the first match is a weak
624
- // match we discard it
625
- return undefined;
626
- }
627
- }
628
- else {
629
- // boost
630
- total += 1 + (simpleMatchCount * (score - 1));
631
- simpleMatchCount = 0;
632
- }
633
- }
634
- else {
635
- // istanbul ignore next
636
- return undefined;
637
- }
638
- }
639
- }
640
- total -= column >= 3 ? 9 : column * 3; // late start penalty
641
- // dynamically keep track of the current top score
642
- // and insert the current best score at head, the rest at tail
643
- _matchesCount += 1;
644
- if (total > _topScore) {
645
- _topScore = total;
646
- _topMatch2 = matches;
647
- }
648
- }
649
- // #endregion
650
- // #region --- graceful ---
651
- /** @internal */
652
- function fuzzyScoreGracefulAggressive(pattern, lowPattern, patternPos, word, lowWord, wordPos, firstMatchCanBeWeak) {
653
- return fuzzyScoreWithPermutations(pattern, lowPattern, patternPos, word, lowWord, wordPos, true, firstMatchCanBeWeak);
654
- }
655
- exports.fuzzyScoreGracefulAggressive = fuzzyScoreGracefulAggressive;
656
- /** @internal */
657
- function fuzzyScoreGraceful(pattern, lowPattern, patternPos, word, lowWord, wordPos, firstMatchCanBeWeak) {
658
- return fuzzyScoreWithPermutations(pattern, lowPattern, patternPos, word, lowWord, wordPos, false, firstMatchCanBeWeak);
659
- }
660
- exports.fuzzyScoreGraceful = fuzzyScoreGraceful;
661
- function fuzzyScoreWithPermutations(pattern, lowPattern, patternPos, word, lowWord, wordPos, aggressive, firstMatchCanBeWeak) {
662
- let top = fuzzyScore(pattern, lowPattern, patternPos, word, lowWord, wordPos, firstMatchCanBeWeak);
663
- if (top && !aggressive) {
664
- // when using the original pattern yield a result we`
665
- // return it unless we are aggressive and try to find
666
- // a better alignment, e.g. `cno` -> `^co^ns^ole` or `^c^o^nsole`.
667
- return top;
668
- }
669
- // istanbul ignore else
670
- if (pattern.length >= 3) {
671
- // When the pattern is long enough then try a few (max 7)
672
- // permutations of the pattern to find a better match. The
673
- // permutations only swap neighbouring characters, e.g
674
- // `cnoso` becomes `conso`, `cnsoo`, `cnoos`.
675
- const tries = Math.min(7, pattern.length - 1);
676
- for (let movingPatternPos = patternPos + 1; movingPatternPos < tries; movingPatternPos++) {
677
- const newPattern = nextTypoPermutation(pattern, movingPatternPos);
678
- // istanbul ignore else
679
- if (newPattern) {
680
- const candidate = fuzzyScore(newPattern, newPattern.toLowerCase(), patternPos, word, lowWord, wordPos, firstMatchCanBeWeak);
681
- if (candidate) {
682
- candidate[0] -= 3; // permutation penalty
683
- // istanbul ignore else
684
- if (!top || candidate[0] > top[0]) {
685
- top = candidate;
686
- }
687
- }
688
- }
689
- }
690
- }
691
- return top;
692
- }
693
- function nextTypoPermutation(pattern, patternPos) {
694
- // istanbul ignore next
695
- if (patternPos + 1 >= pattern.length) {
696
- return undefined;
697
- }
698
- const swap1 = pattern[patternPos];
699
- const swap2 = pattern[patternPos + 1];
700
- // istanbul ignore next
701
- if (swap1 === swap2) {
702
- return undefined;
703
- }
704
- return pattern.slice(0, patternPos)
705
- + swap2
706
- + swap1
707
- + pattern.slice(patternPos + 2);
708
- }
709
- // #endregion
710
102
  //# sourceMappingURL=filters.js.map