reg-cli 0.19.0-rc0 → 0.19.0-rc2
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.
- package/dist/cli.cjs +1 -2
- package/dist/cli.mjs +1 -1
- package/dist/index.cjs +59 -58
- package/dist/index.mjs +58 -56
- package/dist/reg.wasm +0 -0
- package/dist/runner.cjs +235 -0
- package/dist/runner.mjs +235 -0
- package/dist/shared/report-worker.js +697 -1078
- package/dist/{tracing-7HO8hac9.mjs → tracing-Bo38b9aR.mjs} +45 -1
- package/dist/{tracing-DlLL541f.cjs → tracing-Cf9TNPXQ.cjs} +100 -2
- package/dist/{ximgdiff-wmW1BH1H.cjs → ximgdiff-B16oe7EL.cjs} +2 -2
- package/package.json +27 -10
- package/dist/entry.cjs +0 -119
- package/dist/entry.d.cts +0 -15
- package/dist/entry.d.mts +0 -15
- package/dist/entry.mjs +0 -118
- package/dist/progress-BB7D-xke.mjs +0 -28
- package/dist/progress-UOiKHaTY.cjs +0 -33
- package/dist/rolldown-runtime-D_mwlA32.cjs +0 -43
- package/dist/worker.cjs +0 -143
- package/dist/worker.mjs +0 -142
- /package/dist/{worker.d.cts → runner.d.cts} +0 -0
- /package/dist/{worker.d.mts → runner.d.mts} +0 -0
- /package/dist/{ximgdiff-DzkRRnkW.mjs → ximgdiff-D8GAJaxA.mjs} +0 -0
|
@@ -4,12 +4,8 @@
|
|
|
4
4
|
return !Array.isArray ? getTag(value) === "[object Array]" : Array.isArray(value);
|
|
5
5
|
}
|
|
6
6
|
function baseToString(value) {
|
|
7
|
-
if (typeof value == "string")
|
|
8
|
-
|
|
9
|
-
}
|
|
10
|
-
if (typeof value === "bigint") {
|
|
11
|
-
return value.toString();
|
|
12
|
-
}
|
|
7
|
+
if (typeof value == "string") return value;
|
|
8
|
+
if (typeof value === "bigint") return value.toString();
|
|
13
9
|
const result = value + "";
|
|
14
10
|
return result == "0" && 1 / value == -Infinity ? "-0" : result;
|
|
15
11
|
}
|
|
@@ -41,12 +37,14 @@
|
|
|
41
37
|
return value == null ? value === void 0 ? "[object Undefined]" : "[object Null]" : Object.prototype.toString.call(value);
|
|
42
38
|
}
|
|
43
39
|
const INCORRECT_INDEX_TYPE = "Incorrect 'index' type";
|
|
40
|
+
const INVALID_DOC_INDEX = "Invalid doc index: must be a non-negative integer within the bounds of the docs array";
|
|
44
41
|
const LOGICAL_SEARCH_INVALID_QUERY_FOR_KEY = (key) => `Invalid value for key ${key}`;
|
|
45
42
|
const PATTERN_LENGTH_TOO_LARGE = (max) => `Pattern length exceeds max of ${max}.`;
|
|
46
43
|
const MISSING_KEY_PROPERTY = (name) => `Missing ${name} property in key`;
|
|
47
44
|
const INVALID_KEY_WEIGHT_VALUE = (key) => `Property 'weight' in key '${key}' must be a positive integer`;
|
|
45
|
+
const FUSE_MATCH_TOKEN_SEARCH_UNSUPPORTED = "Fuse.match does not support useTokenSearch: token search requires corpus-level statistics (df, fieldCount) that a one-off string comparison does not have. Use new Fuse(...).search(...) instead.";
|
|
48
46
|
const hasOwn = Object.prototype.hasOwnProperty;
|
|
49
|
-
|
|
47
|
+
var KeyStore = class {
|
|
50
48
|
constructor(keys) {
|
|
51
49
|
this._keys = [];
|
|
52
50
|
this._keyMap = {};
|
|
@@ -70,7 +68,7 @@
|
|
|
70
68
|
toJSON() {
|
|
71
69
|
return JSON.stringify(this._keys);
|
|
72
70
|
}
|
|
73
|
-
}
|
|
71
|
+
};
|
|
74
72
|
function createKey(key) {
|
|
75
73
|
let path = null;
|
|
76
74
|
let id = null;
|
|
@@ -82,20 +80,16 @@
|
|
|
82
80
|
path = createKeyPath(key);
|
|
83
81
|
id = createKeyId(key);
|
|
84
82
|
} else {
|
|
85
|
-
if (!hasOwn.call(key, "name"))
|
|
86
|
-
throw new Error(MISSING_KEY_PROPERTY("name"));
|
|
87
|
-
}
|
|
83
|
+
if (!hasOwn.call(key, "name")) throw new Error(MISSING_KEY_PROPERTY("name"));
|
|
88
84
|
const name = key.name;
|
|
89
85
|
src = name;
|
|
90
|
-
if (hasOwn.call(key, "weight")) {
|
|
86
|
+
if (hasOwn.call(key, "weight") && key.weight !== void 0) {
|
|
91
87
|
weight = key.weight;
|
|
92
|
-
if (weight <= 0)
|
|
93
|
-
throw new Error(INVALID_KEY_WEIGHT_VALUE(name));
|
|
94
|
-
}
|
|
88
|
+
if (weight <= 0) throw new Error(INVALID_KEY_WEIGHT_VALUE(createKeyId(name)));
|
|
95
89
|
}
|
|
96
90
|
path = createKeyPath(name);
|
|
97
91
|
id = createKeyId(name);
|
|
98
|
-
getFn = key.getFn;
|
|
92
|
+
getFn = key.getFn ?? null;
|
|
99
93
|
}
|
|
100
94
|
return {
|
|
101
95
|
path,
|
|
@@ -115,33 +109,22 @@
|
|
|
115
109
|
const list = [];
|
|
116
110
|
let arr = false;
|
|
117
111
|
const deepGet = (obj2, path2, index, arrayIndex) => {
|
|
118
|
-
if (!isDefined(obj2))
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
112
|
+
if (!isDefined(obj2)) return;
|
|
113
|
+
if (!path2[index]) list.push(arrayIndex !== void 0 ? {
|
|
114
|
+
v: obj2,
|
|
115
|
+
i: arrayIndex
|
|
116
|
+
} : obj2);
|
|
117
|
+
else {
|
|
118
|
+
const value = obj2[path2[index]];
|
|
119
|
+
if (!isDefined(value)) return;
|
|
120
|
+
if (index === path2.length - 1 && (isString(value) || isNumber(value) || isBoolean(value) || typeof value === "bigint")) list.push(arrayIndex !== void 0 ? {
|
|
121
|
+
v: toString(value),
|
|
124
122
|
i: arrayIndex
|
|
125
|
-
} :
|
|
126
|
-
|
|
127
|
-
const key = path2[index];
|
|
128
|
-
const value = obj2[key];
|
|
129
|
-
if (!isDefined(value)) {
|
|
130
|
-
return;
|
|
131
|
-
}
|
|
132
|
-
if (index === path2.length - 1 && (isString(value) || isNumber(value) || isBoolean(value) || typeof value === "bigint")) {
|
|
133
|
-
list.push(arrayIndex !== void 0 ? {
|
|
134
|
-
v: toString(value),
|
|
135
|
-
i: arrayIndex
|
|
136
|
-
} : toString(value));
|
|
137
|
-
} else if (isArray(value)) {
|
|
123
|
+
} : toString(value));
|
|
124
|
+
else if (isArray(value)) {
|
|
138
125
|
arr = true;
|
|
139
|
-
for (let i = 0, len = value.length; i < len; i += 1)
|
|
140
|
-
|
|
141
|
-
}
|
|
142
|
-
} else if (path2.length) {
|
|
143
|
-
deepGet(value, path2, index + 1, arrayIndex);
|
|
144
|
-
}
|
|
126
|
+
for (let i = 0, len = value.length; i < len; i += 1) deepGet(value[i], path2, index + 1, i);
|
|
127
|
+
} else if (path2.length) deepGet(value, path2, index + 1, arrayIndex);
|
|
145
128
|
}
|
|
146
129
|
};
|
|
147
130
|
deepGet(obj, isString(path) ? path.split(".") : path, 0);
|
|
@@ -168,6 +151,8 @@
|
|
|
168
151
|
const AdvancedOptions = {
|
|
169
152
|
useExtendedSearch: false,
|
|
170
153
|
useTokenSearch: false,
|
|
154
|
+
tokenize: void 0,
|
|
155
|
+
tokenMatch: "any",
|
|
171
156
|
getFn: get,
|
|
172
157
|
ignoreLocation: false,
|
|
173
158
|
ignoreFieldNorm: false,
|
|
@@ -179,18 +164,25 @@
|
|
|
179
164
|
...FuzzyOptions,
|
|
180
165
|
...AdvancedOptions
|
|
181
166
|
});
|
|
182
|
-
|
|
167
|
+
function isWordSeparator(code) {
|
|
168
|
+
return code >= 9 && code <= 13 || code === 32 || code === 160;
|
|
169
|
+
}
|
|
183
170
|
function norm(weight = 1, mantissa = 3) {
|
|
184
171
|
const cache = /* @__PURE__ */ new Map();
|
|
185
172
|
const m = Math.pow(10, mantissa);
|
|
186
173
|
return {
|
|
187
174
|
get(value) {
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
175
|
+
let numTokens = 0;
|
|
176
|
+
let inWord = false;
|
|
177
|
+
for (let i = 0; i < value.length; i++) if (!isWordSeparator(value.charCodeAt(i))) {
|
|
178
|
+
if (!inWord) {
|
|
179
|
+
numTokens++;
|
|
180
|
+
inWord = true;
|
|
181
|
+
}
|
|
182
|
+
} else inWord = false;
|
|
183
|
+
if (numTokens === 0) numTokens = 1;
|
|
184
|
+
if (cache.has(numTokens)) return cache.get(numTokens);
|
|
185
|
+
const n = Math.round(m / Math.pow(numTokens, 0.5 * weight)) / m;
|
|
194
186
|
cache.set(numTokens, n);
|
|
195
187
|
return n;
|
|
196
188
|
},
|
|
@@ -199,11 +191,8 @@
|
|
|
199
191
|
}
|
|
200
192
|
};
|
|
201
193
|
}
|
|
202
|
-
|
|
203
|
-
constructor({
|
|
204
|
-
getFn = Config.getFn,
|
|
205
|
-
fieldNormWeight = Config.fieldNormWeight
|
|
206
|
-
} = {}) {
|
|
194
|
+
var FuseIndex = class {
|
|
195
|
+
constructor({ getFn = Config.getFn, fieldNormWeight = Config.fieldNormWeight } = {}) {
|
|
207
196
|
this.norm = norm(fieldNormWeight, 3);
|
|
208
197
|
this.getFn = getFn;
|
|
209
198
|
this.isCreated = false;
|
|
@@ -226,44 +215,53 @@
|
|
|
226
215
|
});
|
|
227
216
|
}
|
|
228
217
|
create() {
|
|
229
|
-
if (this.isCreated || !this.docs.length)
|
|
230
|
-
return;
|
|
231
|
-
}
|
|
218
|
+
if (this.isCreated || !this.docs.length) return;
|
|
232
219
|
this.isCreated = true;
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
this.
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
220
|
+
const len = this.docs.length;
|
|
221
|
+
this.records = new Array(len);
|
|
222
|
+
let recordCount = 0;
|
|
223
|
+
if (isString(this.docs[0])) for (let i = 0; i < len; i++) {
|
|
224
|
+
const record = this._createStringRecord(this.docs[i], i);
|
|
225
|
+
if (record) this.records[recordCount++] = record;
|
|
226
|
+
}
|
|
227
|
+
else for (let i = 0; i < len; i++) this.records[recordCount++] = this._createObjectRecord(this.docs[i], i);
|
|
228
|
+
this.records.length = recordCount;
|
|
242
229
|
this.norm.clear();
|
|
243
230
|
}
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
const idx = this.size();
|
|
231
|
+
add(doc, docIndex) {
|
|
232
|
+
if (!Number.isInteger(docIndex) || docIndex < 0) throw new Error(INVALID_DOC_INDEX);
|
|
247
233
|
if (isString(doc)) {
|
|
248
|
-
this.
|
|
249
|
-
|
|
250
|
-
|
|
234
|
+
const record2 = this._createStringRecord(doc, docIndex);
|
|
235
|
+
if (record2) this.records.push(record2);
|
|
236
|
+
return record2;
|
|
251
237
|
}
|
|
238
|
+
const record = this._createObjectRecord(doc, docIndex);
|
|
239
|
+
this.records.push(record);
|
|
240
|
+
return record;
|
|
252
241
|
}
|
|
253
|
-
// Removes the doc at the specified index of the index
|
|
254
242
|
removeAt(idx) {
|
|
255
|
-
|
|
256
|
-
for (let i =
|
|
257
|
-
this.records
|
|
243
|
+
if (!Number.isInteger(idx) || idx < 0) throw new Error(INVALID_DOC_INDEX);
|
|
244
|
+
for (let i = 0, len = this.records.length; i < len; i += 1) if (this.records[i].i === idx) {
|
|
245
|
+
this.records.splice(i, 1);
|
|
246
|
+
break;
|
|
258
247
|
}
|
|
248
|
+
for (let i = 0, len = this.records.length; i < len; i += 1) if (this.records[i].i > idx) this.records[i].i -= 1;
|
|
259
249
|
}
|
|
260
|
-
// Removes docs at the specified indices (must be sorted ascending)
|
|
261
250
|
removeAll(indices) {
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
251
|
+
const toRemove = /* @__PURE__ */ new Set();
|
|
252
|
+
for (const v of indices) if (Number.isInteger(v) && v >= 0) toRemove.add(v);
|
|
253
|
+
if (toRemove.size === 0) return;
|
|
254
|
+
this.records = this.records.filter((r) => !toRemove.has(r.i));
|
|
255
|
+
const sorted = Array.from(toRemove).sort((a, b) => a - b);
|
|
256
|
+
for (const record of this.records) {
|
|
257
|
+
let lo = 0;
|
|
258
|
+
let hi = sorted.length;
|
|
259
|
+
while (lo < hi) {
|
|
260
|
+
const mid = lo + hi >>> 1;
|
|
261
|
+
if (sorted[mid] < record.i) lo = mid + 1;
|
|
262
|
+
else hi = mid;
|
|
263
|
+
}
|
|
264
|
+
record.i -= lo;
|
|
267
265
|
}
|
|
268
266
|
}
|
|
269
267
|
getValueForItemAtKeyId(item, keyId) {
|
|
@@ -272,34 +270,28 @@
|
|
|
272
270
|
size() {
|
|
273
271
|
return this.records.length;
|
|
274
272
|
}
|
|
275
|
-
|
|
276
|
-
if (!isDefined(doc) || isBlank(doc))
|
|
277
|
-
|
|
278
|
-
}
|
|
279
|
-
const record = {
|
|
273
|
+
_createStringRecord(doc, docIndex) {
|
|
274
|
+
if (!isDefined(doc) || isBlank(doc)) return null;
|
|
275
|
+
return {
|
|
280
276
|
v: doc,
|
|
281
277
|
i: docIndex,
|
|
282
278
|
n: this.norm.get(doc)
|
|
283
279
|
};
|
|
284
|
-
this.records.push(record);
|
|
285
280
|
}
|
|
286
|
-
|
|
281
|
+
_createObjectRecord(doc, docIndex) {
|
|
287
282
|
const record = {
|
|
288
283
|
i: docIndex,
|
|
289
284
|
$: {}
|
|
290
285
|
};
|
|
291
|
-
this.keys.
|
|
286
|
+
for (let keyIndex = 0, keyLen = this.keys.length; keyIndex < keyLen; keyIndex++) {
|
|
287
|
+
const key = this.keys[keyIndex];
|
|
292
288
|
const value = key.getFn ? key.getFn(doc) : this.getFn(doc, key.path);
|
|
293
|
-
if (!isDefined(value))
|
|
294
|
-
return;
|
|
295
|
-
}
|
|
289
|
+
if (!isDefined(value)) continue;
|
|
296
290
|
if (isArray(value)) {
|
|
297
291
|
const subRecords = [];
|
|
298
292
|
for (let i = 0, len = value.length; i < len; i += 1) {
|
|
299
293
|
const item = value[i];
|
|
300
|
-
if (!isDefined(item))
|
|
301
|
-
continue;
|
|
302
|
-
}
|
|
294
|
+
if (!isDefined(item)) continue;
|
|
303
295
|
if (isString(item)) {
|
|
304
296
|
if (!isBlank(item)) {
|
|
305
297
|
const subRecord = {
|
|
@@ -329,24 +321,17 @@
|
|
|
329
321
|
};
|
|
330
322
|
record.$[keyIndex] = subRecord;
|
|
331
323
|
}
|
|
332
|
-
}
|
|
333
|
-
|
|
324
|
+
}
|
|
325
|
+
return record;
|
|
334
326
|
}
|
|
335
327
|
toJSON() {
|
|
336
328
|
return {
|
|
337
|
-
|
|
338
|
-
keys: this.keys.map(({
|
|
339
|
-
getFn,
|
|
340
|
-
...key
|
|
341
|
-
}) => key),
|
|
329
|
+
keys: this.keys.map(({ getFn, ...key }) => key),
|
|
342
330
|
records: this.records
|
|
343
331
|
};
|
|
344
332
|
}
|
|
345
|
-
}
|
|
346
|
-
function createIndex(keys, docs, {
|
|
347
|
-
getFn = Config.getFn,
|
|
348
|
-
fieldNormWeight = Config.fieldNormWeight
|
|
349
|
-
} = {}) {
|
|
333
|
+
};
|
|
334
|
+
function createIndex(keys, docs, { getFn = Config.getFn, fieldNormWeight = Config.fieldNormWeight } = {}) {
|
|
350
335
|
const myIndex = new FuseIndex({
|
|
351
336
|
getFn,
|
|
352
337
|
fieldNormWeight
|
|
@@ -356,14 +341,8 @@
|
|
|
356
341
|
myIndex.create();
|
|
357
342
|
return myIndex;
|
|
358
343
|
}
|
|
359
|
-
function parseIndex(data, {
|
|
360
|
-
|
|
361
|
-
fieldNormWeight = Config.fieldNormWeight
|
|
362
|
-
} = {}) {
|
|
363
|
-
const {
|
|
364
|
-
keys,
|
|
365
|
-
records
|
|
366
|
-
} = data;
|
|
344
|
+
function parseIndex(data, { getFn = Config.getFn, fieldNormWeight = Config.fieldNormWeight } = {}) {
|
|
345
|
+
const { keys, records } = data;
|
|
367
346
|
const myIndex = new FuseIndex({
|
|
368
347
|
getFn,
|
|
369
348
|
fieldNormWeight
|
|
@@ -379,34 +358,18 @@
|
|
|
379
358
|
let i = 0;
|
|
380
359
|
for (let len = matchmask.length; i < len; i += 1) {
|
|
381
360
|
const match = matchmask[i];
|
|
382
|
-
if (match && start === -1)
|
|
383
|
-
|
|
384
|
-
} else if (!match && start !== -1) {
|
|
361
|
+
if (match && start === -1) start = i;
|
|
362
|
+
else if (!match && start !== -1) {
|
|
385
363
|
end = i - 1;
|
|
386
|
-
if (end - start + 1 >= minMatchCharLength)
|
|
387
|
-
indices.push([start, end]);
|
|
388
|
-
}
|
|
364
|
+
if (end - start + 1 >= minMatchCharLength) indices.push([start, end]);
|
|
389
365
|
start = -1;
|
|
390
366
|
}
|
|
391
367
|
}
|
|
392
|
-
if (matchmask[i - 1] && i - start >= minMatchCharLength)
|
|
393
|
-
indices.push([start, i - 1]);
|
|
394
|
-
}
|
|
368
|
+
if (matchmask[i - 1] && i - start >= minMatchCharLength) indices.push([start, i - 1]);
|
|
395
369
|
return indices;
|
|
396
370
|
}
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
location = Config.location,
|
|
400
|
-
distance = Config.distance,
|
|
401
|
-
threshold = Config.threshold,
|
|
402
|
-
findAllMatches = Config.findAllMatches,
|
|
403
|
-
minMatchCharLength = Config.minMatchCharLength,
|
|
404
|
-
includeMatches = Config.includeMatches,
|
|
405
|
-
ignoreLocation = Config.ignoreLocation
|
|
406
|
-
} = {}) {
|
|
407
|
-
if (pattern.length > MAX_BITS) {
|
|
408
|
-
throw new Error(PATTERN_LENGTH_TOO_LARGE(MAX_BITS));
|
|
409
|
-
}
|
|
371
|
+
function search(text, pattern, patternAlphabet, { location = Config.location, distance = Config.distance, threshold = Config.threshold, findAllMatches = Config.findAllMatches, minMatchCharLength = Config.minMatchCharLength, includeMatches = Config.includeMatches, ignoreLocation = Config.ignoreLocation } = {}) {
|
|
372
|
+
if (pattern.length > 32) throw new Error(PATTERN_LENGTH_TOO_LARGE(32));
|
|
410
373
|
const patternLen = pattern.length;
|
|
411
374
|
const textLen = text.length;
|
|
412
375
|
const expectedLocation = Math.max(0, Math.min(location, textLen));
|
|
@@ -437,18 +400,15 @@
|
|
|
437
400
|
bestLocation = -1;
|
|
438
401
|
let lastBitArr = [];
|
|
439
402
|
let finalScore = 1;
|
|
403
|
+
let bestErrors = 0;
|
|
440
404
|
let binMax = patternLen + textLen;
|
|
441
405
|
const mask = 1 << patternLen - 1;
|
|
442
406
|
for (let i = 0; i < patternLen; i += 1) {
|
|
443
407
|
let binMin = 0;
|
|
444
408
|
let binMid = binMax;
|
|
445
409
|
while (binMin < binMid) {
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
binMin = binMid;
|
|
449
|
-
} else {
|
|
450
|
-
binMax = binMid;
|
|
451
|
-
}
|
|
410
|
+
if (calcScore(i, expectedLocation + binMid) <= currentThreshold) binMin = binMid;
|
|
411
|
+
else binMax = binMid;
|
|
452
412
|
binMid = Math.floor((binMax - binMin) / 2 + binMin);
|
|
453
413
|
}
|
|
454
414
|
binMax = binMid;
|
|
@@ -459,43 +419,34 @@
|
|
|
459
419
|
for (let j = finish; j >= start; j -= 1) {
|
|
460
420
|
const currentLocation = j - 1;
|
|
461
421
|
const charMatch = patternAlphabet[text[currentLocation]];
|
|
462
|
-
if (computeMatches) {
|
|
463
|
-
matchMask[currentLocation] = +!!charMatch;
|
|
464
|
-
}
|
|
465
422
|
bitArr[j] = (bitArr[j + 1] << 1 | 1) & charMatch;
|
|
466
|
-
if (i)
|
|
467
|
-
bitArr[j] |= (lastBitArr[j + 1] | lastBitArr[j]) << 1 | 1 | lastBitArr[j + 1];
|
|
468
|
-
}
|
|
423
|
+
if (i) bitArr[j] |= (lastBitArr[j + 1] | lastBitArr[j]) << 1 | 1 | lastBitArr[j + 1];
|
|
469
424
|
if (bitArr[j] & mask) {
|
|
470
425
|
finalScore = calcScore(i, currentLocation);
|
|
471
426
|
if (finalScore <= currentThreshold) {
|
|
472
427
|
currentThreshold = finalScore;
|
|
473
428
|
bestLocation = currentLocation;
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
}
|
|
429
|
+
bestErrors = i;
|
|
430
|
+
if (bestLocation <= expectedLocation) break;
|
|
477
431
|
start = Math.max(1, 2 * expectedLocation - bestLocation);
|
|
478
432
|
}
|
|
479
433
|
}
|
|
480
434
|
}
|
|
481
|
-
|
|
482
|
-
if (score > currentThreshold) {
|
|
483
|
-
break;
|
|
484
|
-
}
|
|
435
|
+
if (calcScore(i + 1, expectedLocation) > currentThreshold) break;
|
|
485
436
|
lastBitArr = bitArr;
|
|
486
437
|
}
|
|
438
|
+
if (computeMatches && bestLocation >= 0) {
|
|
439
|
+
const matchEnd = Math.min(textLen - 1, bestLocation + patternLen - 1 + bestErrors);
|
|
440
|
+
for (let k = bestLocation; k <= matchEnd; k += 1) if (patternAlphabet[text[k]]) matchMask[k] = 1;
|
|
441
|
+
}
|
|
487
442
|
const result = {
|
|
488
443
|
isMatch: bestLocation >= 0,
|
|
489
|
-
// Count exact matches (those with a score of 0) to be "almost" exact
|
|
490
444
|
score: Math.max(1e-3, finalScore)
|
|
491
445
|
};
|
|
492
446
|
if (computeMatches) {
|
|
493
447
|
const indices = convertMaskToIndices(matchMask, minMatchCharLength);
|
|
494
|
-
if (!indices.length)
|
|
495
|
-
|
|
496
|
-
} else if (includeMatches) {
|
|
497
|
-
result.indices = indices;
|
|
498
|
-
}
|
|
448
|
+
if (!indices.length) result.isMatch = false;
|
|
449
|
+
else if (includeMatches) result.indices = indices;
|
|
499
450
|
}
|
|
500
451
|
return result;
|
|
501
452
|
}
|
|
@@ -514,54 +465,29 @@
|
|
|
514
465
|
for (let i = 1, len = indices.length; i < len; i += 1) {
|
|
515
466
|
const last = merged[merged.length - 1];
|
|
516
467
|
const curr = indices[i];
|
|
517
|
-
if (curr[0] <= last[1] + 1)
|
|
518
|
-
|
|
519
|
-
} else {
|
|
520
|
-
merged.push(curr);
|
|
521
|
-
}
|
|
468
|
+
if (curr[0] <= last[1] + 1) last[1] = Math.max(last[1], curr[1]);
|
|
469
|
+
else merged.push(curr);
|
|
522
470
|
}
|
|
523
471
|
return merged;
|
|
524
472
|
}
|
|
525
473
|
const NON_DECOMPOSABLE_MAP = {
|
|
526
474
|
"ł": "l",
|
|
527
|
-
// ł
|
|
528
475
|
"Ł": "L",
|
|
529
|
-
// Ł
|
|
530
476
|
"đ": "d",
|
|
531
|
-
// đ
|
|
532
477
|
"Đ": "D",
|
|
533
|
-
// Đ
|
|
534
478
|
"ø": "o",
|
|
535
|
-
// ø
|
|
536
479
|
"Ø": "O",
|
|
537
|
-
// Ø
|
|
538
480
|
"ħ": "h",
|
|
539
|
-
// ħ
|
|
540
481
|
"Ħ": "H",
|
|
541
|
-
// Ħ
|
|
542
482
|
"ŧ": "t",
|
|
543
|
-
// ŧ
|
|
544
483
|
"Ŧ": "T",
|
|
545
|
-
// Ŧ
|
|
546
484
|
"ı": "i",
|
|
547
|
-
// ı
|
|
548
485
|
"ß": "ss"
|
|
549
|
-
// ß
|
|
550
486
|
};
|
|
551
487
|
const NON_DECOMPOSABLE_RE = new RegExp("[" + Object.keys(NON_DECOMPOSABLE_MAP).join("") + "]", "g");
|
|
552
|
-
const stripDiacritics = String.prototype.normalize ? (str) => str.normalize("NFD").replace(/[\u0300-\u036F\u0483-\u0489\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u0610-\u061A\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7\u06E8\u06EA-\u06ED\u0711\u0730-\u074A\u07A6-\u07B0\u07EB-\u07F3\u07FD\u0816-\u0819\u081B-\u0823\u0825-\u0827\u0829-\u082D\u0859-\u085B\u08D3-\u08E1\u08E3-\u0903\u093A-\u093C\u093E-\u094F\u0951-\u0957\u0962\u0963\u0981-\u0983\u09BC\u09BE-\u09C4\u09C7\u09C8\u09CB-\u09CD\u09D7\u09E2\u09E3\u09FE\u0A01-\u0A03\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A70\u0A71\u0A75\u0A81-\u0A83\u0ABC\u0ABE-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AE2\u0AE3\u0AFA-\u0AFF\u0B01-\u0B03\u0B3C\u0B3E-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B62\u0B63\u0B82\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD7\u0C00-\u0C04\u0C3E-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C62\u0C63\u0C81-\u0C83\u0CBC\u0CBE-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CE2\u0CE3\u0D00-\u0D03\u0D3B\u0D3C\u0D3E-\u0D44\u0D46-\u0D48\u0D4A-\u0D4D\u0D57\u0D62\u0D63\u0D82\u0D83\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DF2\u0DF3\u0E31\u0E34-\u0E3A\u0E47-\u0E4E\u0EB1\u0EB4-\u0EB9\u0EBB\u0EBC\u0EC8-\u0ECD\u0F18\u0F19\u0F35\u0F37\u0F39\u0F3E\u0F3F\u0F71-\u0F84\u0F86\u0F87\u0F8D-\u0F97\u0F99-\u0FBC\u0FC6\u102B-\u103E\u1056-\u1059\u105E-\u1060\u1062-\u1064\u1067-\u106D\u1071-\u1074\u1082-\u108D\u108F\u109A-\u109D\u135D-\u135F\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17B4-\u17D3\u17DD\u180B-\u180D\u1885\u1886\u18A9\u1920-\u192B\u1930-\u193B\u1A17-\u1A1B\u1A55-\u1A5E\u1A60-\u1A7C\u1A7F\u1AB0-\u1ABE\u1B00-\u1B04\u1B34-\u1B44\u1B6B-\u1B73\u1B80-\u1B82\u1BA1-\u1BAD\u1BE6-\u1BF3\u1C24-\u1C37\u1CD0-\u1CD2\u1CD4-\u1CE8\u1CED\u1CF2-\u1CF4\u1CF7-\u1CF9\u1DC0-\u1DF9\u1DFB-\u1DFF\u20D0-\u20F0\u2CEF-\u2CF1\u2D7F\u2DE0-\u2DFF\u302A-\u302F\u3099\u309A\uA66F-\uA672\uA674-\uA67D\uA69E\uA69F\uA6F0\uA6F1\uA802\uA806\uA80B\uA823-\uA827\uA880\uA881\uA8B4-\uA8C5\uA8E0-\uA8F1\uA8FF\uA926-\uA92D\uA947-\uA953\uA980-\uA983\uA9B3-\uA9C0\uA9E5\uAA29-\uAA36\uAA43\uAA4C\uAA4D\uAA7B-\uAA7D\uAAB0\uAAB2-\uAAB4\uAAB7\uAAB8\uAABE\uAABF\uAAC1\uAAEB-\uAAEF\uAAF5\uAAF6\uABE3-\uABEA\uABEC\uABED\uFB1E\uFE00-\uFE0F\uFE20-\uFE2F]/g, "").replace(NON_DECOMPOSABLE_RE, (ch) => NON_DECOMPOSABLE_MAP[ch]) : (str) => str;
|
|
553
|
-
|
|
554
|
-
constructor(pattern, {
|
|
555
|
-
location = Config.location,
|
|
556
|
-
threshold = Config.threshold,
|
|
557
|
-
distance = Config.distance,
|
|
558
|
-
includeMatches = Config.includeMatches,
|
|
559
|
-
findAllMatches = Config.findAllMatches,
|
|
560
|
-
minMatchCharLength = Config.minMatchCharLength,
|
|
561
|
-
isCaseSensitive = Config.isCaseSensitive,
|
|
562
|
-
ignoreDiacritics = Config.ignoreDiacritics,
|
|
563
|
-
ignoreLocation = Config.ignoreLocation
|
|
564
|
-
} = {}) {
|
|
488
|
+
const stripDiacritics = typeof String.prototype.normalize === "function" ? (str) => str.normalize("NFD").replace(/[\u0300-\u036F\u0483-\u0489\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u0610-\u061A\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7\u06E8\u06EA-\u06ED\u0711\u0730-\u074A\u07A6-\u07B0\u07EB-\u07F3\u07FD\u0816-\u0819\u081B-\u0823\u0825-\u0827\u0829-\u082D\u0859-\u085B\u08D3-\u08E1\u08E3-\u0903\u093A-\u093C\u093E-\u094F\u0951-\u0957\u0962\u0963\u0981-\u0983\u09BC\u09BE-\u09C4\u09C7\u09C8\u09CB-\u09CD\u09D7\u09E2\u09E3\u09FE\u0A01-\u0A03\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A70\u0A71\u0A75\u0A81-\u0A83\u0ABC\u0ABE-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AE2\u0AE3\u0AFA-\u0AFF\u0B01-\u0B03\u0B3C\u0B3E-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B62\u0B63\u0B82\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD7\u0C00-\u0C04\u0C3E-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C62\u0C63\u0C81-\u0C83\u0CBC\u0CBE-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CE2\u0CE3\u0D00-\u0D03\u0D3B\u0D3C\u0D3E-\u0D44\u0D46-\u0D48\u0D4A-\u0D4D\u0D57\u0D62\u0D63\u0D82\u0D83\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DF2\u0DF3\u0E31\u0E34-\u0E3A\u0E47-\u0E4E\u0EB1\u0EB4-\u0EB9\u0EBB\u0EBC\u0EC8-\u0ECD\u0F18\u0F19\u0F35\u0F37\u0F39\u0F3E\u0F3F\u0F71-\u0F84\u0F86\u0F87\u0F8D-\u0F97\u0F99-\u0FBC\u0FC6\u102B-\u103E\u1056-\u1059\u105E-\u1060\u1062-\u1064\u1067-\u106D\u1071-\u1074\u1082-\u108D\u108F\u109A-\u109D\u135D-\u135F\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17B4-\u17D3\u17DD\u180B-\u180D\u1885\u1886\u18A9\u1920-\u192B\u1930-\u193B\u1A17-\u1A1B\u1A55-\u1A5E\u1A60-\u1A7C\u1A7F\u1AB0-\u1ABE\u1B00-\u1B04\u1B34-\u1B44\u1B6B-\u1B73\u1B80-\u1B82\u1BA1-\u1BAD\u1BE6-\u1BF3\u1C24-\u1C37\u1CD0-\u1CD2\u1CD4-\u1CE8\u1CED\u1CF2-\u1CF4\u1CF7-\u1CF9\u1DC0-\u1DF9\u1DFB-\u1DFF\u20D0-\u20F0\u2CEF-\u2CF1\u2D7F\u2DE0-\u2DFF\u302A-\u302F\u3099\u309A\uA66F-\uA672\uA674-\uA67D\uA69E\uA69F\uA6F0\uA6F1\uA802\uA806\uA80B\uA823-\uA827\uA880\uA881\uA8B4-\uA8C5\uA8E0-\uA8F1\uA8FF\uA926-\uA92D\uA947-\uA953\uA980-\uA983\uA9B3-\uA9C0\uA9E5\uAA29-\uAA36\uAA43\uAA4C\uAA4D\uAA7B-\uAA7D\uAAB0\uAAB2-\uAAB4\uAAB7\uAAB8\uAABE\uAABF\uAAC1\uAAEB-\uAAEF\uAAF5\uAAF6\uABE3-\uABEA\uABEC\uABED\uFB1E\uFE00-\uFE0F\uFE20-\uFE2F]/g, "").replace(NON_DECOMPOSABLE_RE, (ch) => NON_DECOMPOSABLE_MAP[ch]) : (str) => str;
|
|
489
|
+
var BitapSearch = class {
|
|
490
|
+
constructor(pattern, { location = Config.location, threshold = Config.threshold, distance = Config.distance, includeMatches = Config.includeMatches, findAllMatches = Config.findAllMatches, minMatchCharLength = Config.minMatchCharLength, isCaseSensitive = Config.isCaseSensitive, ignoreDiacritics = Config.ignoreDiacritics, ignoreLocation = Config.ignoreLocation } = {}) {
|
|
565
491
|
this.options = {
|
|
566
492
|
location,
|
|
567
493
|
threshold,
|
|
@@ -577,9 +503,7 @@
|
|
|
577
503
|
pattern = ignoreDiacritics ? stripDiacritics(pattern) : pattern;
|
|
578
504
|
this.pattern = pattern;
|
|
579
505
|
this.chunks = [];
|
|
580
|
-
if (!this.pattern.length)
|
|
581
|
-
return;
|
|
582
|
-
}
|
|
506
|
+
if (!this.pattern.length) return;
|
|
583
507
|
const addChunk = (pattern2, startIndex) => {
|
|
584
508
|
this.chunks.push({
|
|
585
509
|
pattern: pattern2,
|
|
@@ -588,61 +512,42 @@
|
|
|
588
512
|
});
|
|
589
513
|
};
|
|
590
514
|
const len = this.pattern.length;
|
|
591
|
-
if (len >
|
|
515
|
+
if (len > 32) {
|
|
592
516
|
let i = 0;
|
|
593
|
-
const remainder = len %
|
|
517
|
+
const remainder = len % 32;
|
|
594
518
|
const end = len - remainder;
|
|
595
519
|
while (i < end) {
|
|
596
|
-
addChunk(this.pattern.substr(i,
|
|
597
|
-
i +=
|
|
520
|
+
addChunk(this.pattern.substr(i, 32), i);
|
|
521
|
+
i += 32;
|
|
598
522
|
}
|
|
599
523
|
if (remainder) {
|
|
600
|
-
const startIndex = len -
|
|
524
|
+
const startIndex = len - 32;
|
|
601
525
|
addChunk(this.pattern.substr(startIndex), startIndex);
|
|
602
526
|
}
|
|
603
|
-
} else
|
|
604
|
-
addChunk(this.pattern, 0);
|
|
605
|
-
}
|
|
527
|
+
} else addChunk(this.pattern, 0);
|
|
606
528
|
}
|
|
607
529
|
searchIn(text) {
|
|
608
|
-
const {
|
|
609
|
-
isCaseSensitive,
|
|
610
|
-
ignoreDiacritics,
|
|
611
|
-
includeMatches
|
|
612
|
-
} = this.options;
|
|
530
|
+
const { isCaseSensitive, ignoreDiacritics, includeMatches } = this.options;
|
|
613
531
|
text = isCaseSensitive ? text : text.toLowerCase();
|
|
614
532
|
text = ignoreDiacritics ? stripDiacritics(text) : text;
|
|
615
533
|
if (this.pattern === text) {
|
|
534
|
+
if (text.length < this.options.minMatchCharLength) return {
|
|
535
|
+
isMatch: false,
|
|
536
|
+
score: 1
|
|
537
|
+
};
|
|
616
538
|
const result2 = {
|
|
617
539
|
isMatch: true,
|
|
618
540
|
score: 0
|
|
619
541
|
};
|
|
620
|
-
if (includeMatches)
|
|
621
|
-
result2.indices = [[0, text.length - 1]];
|
|
622
|
-
}
|
|
542
|
+
if (includeMatches) result2.indices = [[0, text.length - 1]];
|
|
623
543
|
return result2;
|
|
624
544
|
}
|
|
625
|
-
const {
|
|
626
|
-
location,
|
|
627
|
-
distance,
|
|
628
|
-
threshold,
|
|
629
|
-
findAllMatches,
|
|
630
|
-
minMatchCharLength,
|
|
631
|
-
ignoreLocation
|
|
632
|
-
} = this.options;
|
|
545
|
+
const { location, distance, threshold, findAllMatches, minMatchCharLength, ignoreLocation } = this.options;
|
|
633
546
|
const allIndices = [];
|
|
634
547
|
let totalScore = 0;
|
|
635
548
|
let hasMatches = false;
|
|
636
|
-
this.chunks.forEach(({
|
|
637
|
-
pattern,
|
|
638
|
-
alphabet,
|
|
639
|
-
startIndex
|
|
640
|
-
}) => {
|
|
641
|
-
const {
|
|
642
|
-
isMatch,
|
|
643
|
-
score,
|
|
644
|
-
indices
|
|
645
|
-
} = search(text, pattern, alphabet, {
|
|
549
|
+
this.chunks.forEach(({ pattern, alphabet, startIndex }) => {
|
|
550
|
+
const { isMatch, score, indices } = search(text, pattern, alphabet, {
|
|
646
551
|
location: location + startIndex,
|
|
647
552
|
distance,
|
|
648
553
|
threshold,
|
|
@@ -651,249 +556,169 @@
|
|
|
651
556
|
includeMatches,
|
|
652
557
|
ignoreLocation
|
|
653
558
|
});
|
|
654
|
-
if (isMatch)
|
|
655
|
-
hasMatches = true;
|
|
656
|
-
}
|
|
559
|
+
if (isMatch) hasMatches = true;
|
|
657
560
|
totalScore += score;
|
|
658
|
-
if (isMatch && indices)
|
|
659
|
-
allIndices.push(...indices);
|
|
660
|
-
}
|
|
561
|
+
if (isMatch && indices) allIndices.push(...indices);
|
|
661
562
|
});
|
|
662
563
|
const result = {
|
|
663
564
|
isMatch: hasMatches,
|
|
664
565
|
score: hasMatches ? totalScore / this.chunks.length : 1
|
|
665
566
|
};
|
|
666
|
-
if (hasMatches && includeMatches)
|
|
667
|
-
result.indices = mergeIndices(allIndices);
|
|
668
|
-
}
|
|
567
|
+
if (hasMatches && includeMatches) result.indices = mergeIndices(allIndices);
|
|
669
568
|
return result;
|
|
670
569
|
}
|
|
570
|
+
};
|
|
571
|
+
const MULTI_MATCH_TYPES = /* @__PURE__ */ new Set(["fuzzy", "include"]);
|
|
572
|
+
function isInverse(type) {
|
|
573
|
+
return type.startsWith("inverse");
|
|
671
574
|
}
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
}
|
|
688
|
-
}
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
}
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
}
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
static get singleRegex() {
|
|
816
|
-
return /^!(.*)\$$/;
|
|
817
|
-
}
|
|
818
|
-
search(text) {
|
|
819
|
-
const isMatch = !text.endsWith(this.pattern);
|
|
820
|
-
return {
|
|
821
|
-
isMatch,
|
|
822
|
-
score: isMatch ? 0 : 1,
|
|
823
|
-
indices: [0, text.length - 1]
|
|
824
|
-
};
|
|
825
|
-
}
|
|
826
|
-
}
|
|
827
|
-
class FuzzyMatch extends BaseMatch {
|
|
828
|
-
constructor(pattern, {
|
|
829
|
-
location = Config.location,
|
|
830
|
-
threshold = Config.threshold,
|
|
831
|
-
distance = Config.distance,
|
|
832
|
-
includeMatches = Config.includeMatches,
|
|
833
|
-
findAllMatches = Config.findAllMatches,
|
|
834
|
-
minMatchCharLength = Config.minMatchCharLength,
|
|
835
|
-
isCaseSensitive = Config.isCaseSensitive,
|
|
836
|
-
ignoreDiacritics = Config.ignoreDiacritics,
|
|
837
|
-
ignoreLocation = Config.ignoreLocation
|
|
838
|
-
} = {}) {
|
|
839
|
-
super(pattern);
|
|
840
|
-
this._bitapSearch = new BitapSearch(pattern, {
|
|
841
|
-
location,
|
|
842
|
-
threshold,
|
|
843
|
-
distance,
|
|
844
|
-
includeMatches,
|
|
845
|
-
findAllMatches,
|
|
846
|
-
minMatchCharLength,
|
|
847
|
-
isCaseSensitive,
|
|
848
|
-
ignoreDiacritics,
|
|
849
|
-
ignoreLocation
|
|
850
|
-
});
|
|
851
|
-
}
|
|
852
|
-
static get type() {
|
|
853
|
-
return "fuzzy";
|
|
854
|
-
}
|
|
855
|
-
static get multiRegex() {
|
|
856
|
-
return /^"(.*)"$/;
|
|
857
|
-
}
|
|
858
|
-
static get singleRegex() {
|
|
859
|
-
return /^(.*)$/;
|
|
860
|
-
}
|
|
861
|
-
search(text) {
|
|
862
|
-
return this._bitapSearch.searchIn(text);
|
|
863
|
-
}
|
|
864
|
-
}
|
|
865
|
-
class IncludeMatch extends BaseMatch {
|
|
866
|
-
constructor(pattern) {
|
|
867
|
-
super(pattern);
|
|
868
|
-
}
|
|
869
|
-
static get type() {
|
|
870
|
-
return "include";
|
|
871
|
-
}
|
|
872
|
-
static get multiRegex() {
|
|
873
|
-
return /^'"(.*)"$/;
|
|
874
|
-
}
|
|
875
|
-
static get singleRegex() {
|
|
876
|
-
return /^'(.*)$/;
|
|
877
|
-
}
|
|
878
|
-
search(text) {
|
|
879
|
-
let location = 0;
|
|
880
|
-
let index;
|
|
881
|
-
const indices = [];
|
|
882
|
-
const patternLen = this.pattern.length;
|
|
883
|
-
while ((index = text.indexOf(this.pattern, location)) > -1) {
|
|
884
|
-
location = index + patternLen;
|
|
885
|
-
indices.push([index, location - 1]);
|
|
575
|
+
const matchers = [
|
|
576
|
+
{
|
|
577
|
+
type: "exact",
|
|
578
|
+
multiRegex: /^="(.*)"$/,
|
|
579
|
+
singleRegex: /^=(.*)$/,
|
|
580
|
+
create: (pattern) => ({
|
|
581
|
+
type: "exact",
|
|
582
|
+
search(text) {
|
|
583
|
+
const isMatch = text === pattern;
|
|
584
|
+
return {
|
|
585
|
+
isMatch,
|
|
586
|
+
score: isMatch ? 0 : 1,
|
|
587
|
+
indices: [0, pattern.length - 1]
|
|
588
|
+
};
|
|
589
|
+
}
|
|
590
|
+
})
|
|
591
|
+
},
|
|
592
|
+
{
|
|
593
|
+
type: "include",
|
|
594
|
+
multiRegex: /^'"(.*)"$/,
|
|
595
|
+
singleRegex: /^'(.*)$/,
|
|
596
|
+
create: (pattern) => ({
|
|
597
|
+
type: "include",
|
|
598
|
+
search(text) {
|
|
599
|
+
let location = 0;
|
|
600
|
+
let index;
|
|
601
|
+
const indices = [];
|
|
602
|
+
const patternLen = pattern.length;
|
|
603
|
+
while ((index = text.indexOf(pattern, location)) > -1) {
|
|
604
|
+
location = index + patternLen;
|
|
605
|
+
indices.push([index, location - 1]);
|
|
606
|
+
}
|
|
607
|
+
const isMatch = !!indices.length;
|
|
608
|
+
return {
|
|
609
|
+
isMatch,
|
|
610
|
+
score: isMatch ? 0 : 1,
|
|
611
|
+
indices
|
|
612
|
+
};
|
|
613
|
+
}
|
|
614
|
+
})
|
|
615
|
+
},
|
|
616
|
+
{
|
|
617
|
+
type: "prefix-exact",
|
|
618
|
+
multiRegex: /^\^"(.*)"$/,
|
|
619
|
+
singleRegex: /^\^(.*)$/,
|
|
620
|
+
create: (pattern) => ({
|
|
621
|
+
type: "prefix-exact",
|
|
622
|
+
search(text) {
|
|
623
|
+
const isMatch = text.startsWith(pattern);
|
|
624
|
+
return {
|
|
625
|
+
isMatch,
|
|
626
|
+
score: isMatch ? 0 : 1,
|
|
627
|
+
indices: [0, pattern.length - 1]
|
|
628
|
+
};
|
|
629
|
+
}
|
|
630
|
+
})
|
|
631
|
+
},
|
|
632
|
+
{
|
|
633
|
+
type: "inverse-prefix-exact",
|
|
634
|
+
multiRegex: /^!\^"(.*)"$/,
|
|
635
|
+
singleRegex: /^!\^(.*)$/,
|
|
636
|
+
create: (pattern) => ({
|
|
637
|
+
type: "inverse-prefix-exact",
|
|
638
|
+
search(text) {
|
|
639
|
+
const isMatch = !text.startsWith(pattern);
|
|
640
|
+
return {
|
|
641
|
+
isMatch,
|
|
642
|
+
score: isMatch ? 0 : 1,
|
|
643
|
+
indices: [0, text.length - 1]
|
|
644
|
+
};
|
|
645
|
+
}
|
|
646
|
+
})
|
|
647
|
+
},
|
|
648
|
+
{
|
|
649
|
+
type: "inverse-suffix-exact",
|
|
650
|
+
multiRegex: /^!"(.*)"\$$/,
|
|
651
|
+
singleRegex: /^!(.*)\$$/,
|
|
652
|
+
create: (pattern) => ({
|
|
653
|
+
type: "inverse-suffix-exact",
|
|
654
|
+
search(text) {
|
|
655
|
+
const isMatch = !text.endsWith(pattern);
|
|
656
|
+
return {
|
|
657
|
+
isMatch,
|
|
658
|
+
score: isMatch ? 0 : 1,
|
|
659
|
+
indices: [0, text.length - 1]
|
|
660
|
+
};
|
|
661
|
+
}
|
|
662
|
+
})
|
|
663
|
+
},
|
|
664
|
+
{
|
|
665
|
+
type: "suffix-exact",
|
|
666
|
+
multiRegex: /^"(.*)"\$$/,
|
|
667
|
+
singleRegex: /^(.*)\$$/,
|
|
668
|
+
create: (pattern) => ({
|
|
669
|
+
type: "suffix-exact",
|
|
670
|
+
search(text) {
|
|
671
|
+
const isMatch = text.endsWith(pattern);
|
|
672
|
+
return {
|
|
673
|
+
isMatch,
|
|
674
|
+
score: isMatch ? 0 : 1,
|
|
675
|
+
indices: [text.length - pattern.length, text.length - 1]
|
|
676
|
+
};
|
|
677
|
+
}
|
|
678
|
+
})
|
|
679
|
+
},
|
|
680
|
+
{
|
|
681
|
+
type: "inverse-exact",
|
|
682
|
+
multiRegex: /^!"(.*)"$/,
|
|
683
|
+
singleRegex: /^!(.*)$/,
|
|
684
|
+
create: (pattern) => ({
|
|
685
|
+
type: "inverse-exact",
|
|
686
|
+
search(text) {
|
|
687
|
+
const isMatch = text.indexOf(pattern) === -1;
|
|
688
|
+
return {
|
|
689
|
+
isMatch,
|
|
690
|
+
score: isMatch ? 0 : 1,
|
|
691
|
+
indices: [0, text.length - 1]
|
|
692
|
+
};
|
|
693
|
+
}
|
|
694
|
+
})
|
|
695
|
+
},
|
|
696
|
+
{
|
|
697
|
+
type: "fuzzy",
|
|
698
|
+
multiRegex: /^"(.*)"$/,
|
|
699
|
+
singleRegex: /^(.*)$/,
|
|
700
|
+
create: (pattern, options = {}) => {
|
|
701
|
+
const bitap = new BitapSearch(pattern, {
|
|
702
|
+
location: options.location ?? Config.location,
|
|
703
|
+
threshold: options.threshold ?? Config.threshold,
|
|
704
|
+
distance: options.distance ?? Config.distance,
|
|
705
|
+
includeMatches: options.includeMatches ?? Config.includeMatches,
|
|
706
|
+
findAllMatches: options.findAllMatches ?? Config.findAllMatches,
|
|
707
|
+
minMatchCharLength: options.minMatchCharLength ?? Config.minMatchCharLength,
|
|
708
|
+
isCaseSensitive: options.isCaseSensitive ?? Config.isCaseSensitive,
|
|
709
|
+
ignoreDiacritics: options.ignoreDiacritics ?? Config.ignoreDiacritics,
|
|
710
|
+
ignoreLocation: options.ignoreLocation ?? Config.ignoreLocation
|
|
711
|
+
});
|
|
712
|
+
return {
|
|
713
|
+
type: "fuzzy",
|
|
714
|
+
search(text) {
|
|
715
|
+
return bitap.searchIn(text);
|
|
716
|
+
}
|
|
717
|
+
};
|
|
886
718
|
}
|
|
887
|
-
const isMatch = !!indices.length;
|
|
888
|
-
return {
|
|
889
|
-
isMatch,
|
|
890
|
-
score: isMatch ? 0 : 1,
|
|
891
|
-
indices
|
|
892
|
-
};
|
|
893
719
|
}
|
|
894
|
-
|
|
895
|
-
const
|
|
896
|
-
const searchersLen = searchers.length;
|
|
720
|
+
];
|
|
721
|
+
const matchersLen = matchers.length;
|
|
897
722
|
const ESCAPED_PIPE = "\0";
|
|
898
723
|
const OR_TOKEN = "|";
|
|
899
724
|
function tokenize(pattern) {
|
|
@@ -931,33 +756,33 @@
|
|
|
931
756
|
}
|
|
932
757
|
return tokens;
|
|
933
758
|
}
|
|
759
|
+
function getMatch(pattern, exp) {
|
|
760
|
+
const matches = pattern.match(exp);
|
|
761
|
+
return matches ? matches[1] : null;
|
|
762
|
+
}
|
|
934
763
|
function parseQuery(pattern, options = {}) {
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
const restored = item.replace(/\u0000/g, "|");
|
|
938
|
-
const query = tokenize(restored.trim()).filter((item2) => item2 && !!item2.trim());
|
|
764
|
+
return pattern.replace(/\\\|/g, ESCAPED_PIPE).split(OR_TOKEN).map((item) => {
|
|
765
|
+
const query = tokenize(item.replace(/\u0000/g, "|").trim()).filter((item2) => item2 && !!item2.trim());
|
|
939
766
|
const results = [];
|
|
940
767
|
for (let i = 0, len = query.length; i < len; i += 1) {
|
|
941
768
|
const queryItem = query[i];
|
|
942
769
|
let found = false;
|
|
943
770
|
let idx = -1;
|
|
944
|
-
while (!found && ++idx <
|
|
945
|
-
const
|
|
946
|
-
const token =
|
|
771
|
+
while (!found && ++idx < matchersLen) {
|
|
772
|
+
const def = matchers[idx];
|
|
773
|
+
const token = getMatch(queryItem, def.multiRegex);
|
|
947
774
|
if (token) {
|
|
948
|
-
results.push(
|
|
775
|
+
results.push(def.create(token, options));
|
|
949
776
|
found = true;
|
|
950
777
|
}
|
|
951
778
|
}
|
|
952
|
-
if (found)
|
|
953
|
-
continue;
|
|
954
|
-
}
|
|
779
|
+
if (found) continue;
|
|
955
780
|
idx = -1;
|
|
956
|
-
while (++idx <
|
|
957
|
-
const
|
|
958
|
-
const token =
|
|
781
|
+
while (++idx < matchersLen) {
|
|
782
|
+
const def = matchers[idx];
|
|
783
|
+
const token = getMatch(queryItem, def.singleRegex);
|
|
959
784
|
if (token) {
|
|
960
|
-
results.push(
|
|
785
|
+
results.push(def.create(token, options));
|
|
961
786
|
break;
|
|
962
787
|
}
|
|
963
788
|
}
|
|
@@ -965,19 +790,8 @@
|
|
|
965
790
|
return results;
|
|
966
791
|
});
|
|
967
792
|
}
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
constructor(pattern, {
|
|
971
|
-
isCaseSensitive = Config.isCaseSensitive,
|
|
972
|
-
ignoreDiacritics = Config.ignoreDiacritics,
|
|
973
|
-
includeMatches = Config.includeMatches,
|
|
974
|
-
minMatchCharLength = Config.minMatchCharLength,
|
|
975
|
-
ignoreLocation = Config.ignoreLocation,
|
|
976
|
-
findAllMatches = Config.findAllMatches,
|
|
977
|
-
location = Config.location,
|
|
978
|
-
threshold = Config.threshold,
|
|
979
|
-
distance = Config.distance
|
|
980
|
-
} = {}) {
|
|
793
|
+
var ExtendedSearch = class {
|
|
794
|
+
constructor(pattern, { isCaseSensitive = Config.isCaseSensitive, ignoreDiacritics = Config.ignoreDiacritics, includeMatches = Config.includeMatches, minMatchCharLength = Config.minMatchCharLength, ignoreLocation = Config.ignoreLocation, findAllMatches = Config.findAllMatches, location = Config.location, threshold = Config.threshold, distance = Config.distance } = {}) {
|
|
981
795
|
this.query = null;
|
|
982
796
|
this.options = {
|
|
983
797
|
isCaseSensitive,
|
|
@@ -998,22 +812,13 @@
|
|
|
998
812
|
static condition(_, options) {
|
|
999
813
|
return options.useExtendedSearch;
|
|
1000
814
|
}
|
|
1001
|
-
// Note: searchIn operates on a single text value and sets hasInverse on the
|
|
1002
|
-
// result when inverse patterns are involved. _searchObjectList uses this to
|
|
1003
|
-
// switch from "ANY key" to "ALL keys" aggregation. See #712.
|
|
1004
815
|
searchIn(text) {
|
|
1005
816
|
const query = this.query;
|
|
1006
|
-
if (!query) {
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
}
|
|
1012
|
-
const {
|
|
1013
|
-
includeMatches,
|
|
1014
|
-
isCaseSensitive,
|
|
1015
|
-
ignoreDiacritics
|
|
1016
|
-
} = this.options;
|
|
817
|
+
if (!query) return {
|
|
818
|
+
isMatch: false,
|
|
819
|
+
score: 1
|
|
820
|
+
};
|
|
821
|
+
const { includeMatches, isCaseSensitive, ignoreDiacritics } = this.options;
|
|
1017
822
|
text = isCaseSensitive ? text : text.toLowerCase();
|
|
1018
823
|
text = ignoreDiacritics ? stripDiacritics(text) : text;
|
|
1019
824
|
let numMatches = 0;
|
|
@@ -1021,31 +826,19 @@
|
|
|
1021
826
|
let totalScore = 0;
|
|
1022
827
|
let hasInverse = false;
|
|
1023
828
|
for (let i = 0, qLen = query.length; i < qLen; i += 1) {
|
|
1024
|
-
const
|
|
829
|
+
const searchers = query[i];
|
|
1025
830
|
allIndices.length = 0;
|
|
1026
831
|
numMatches = 0;
|
|
1027
832
|
hasInverse = false;
|
|
1028
|
-
for (let j = 0, pLen =
|
|
1029
|
-
const
|
|
1030
|
-
const {
|
|
1031
|
-
isMatch,
|
|
1032
|
-
indices,
|
|
1033
|
-
score
|
|
1034
|
-
} = searcher.search(text);
|
|
833
|
+
for (let j = 0, pLen = searchers.length; j < pLen; j += 1) {
|
|
834
|
+
const matcher = searchers[j];
|
|
835
|
+
const { isMatch, indices, score } = matcher.search(text);
|
|
1035
836
|
if (isMatch) {
|
|
1036
837
|
numMatches += 1;
|
|
1037
838
|
totalScore += score;
|
|
1038
|
-
|
|
1039
|
-
if (
|
|
1040
|
-
|
|
1041
|
-
}
|
|
1042
|
-
if (includeMatches) {
|
|
1043
|
-
if (MultiMatchSet.has(type)) {
|
|
1044
|
-
allIndices.push(...indices);
|
|
1045
|
-
} else {
|
|
1046
|
-
allIndices.push(indices);
|
|
1047
|
-
}
|
|
1048
|
-
}
|
|
839
|
+
if (isInverse(matcher.type)) hasInverse = true;
|
|
840
|
+
if (includeMatches) if (MULTI_MATCH_TYPES.has(matcher.type)) allIndices.push(...indices);
|
|
841
|
+
else allIndices.push(indices);
|
|
1049
842
|
} else {
|
|
1050
843
|
totalScore = 0;
|
|
1051
844
|
numMatches = 0;
|
|
@@ -1059,12 +852,8 @@
|
|
|
1059
852
|
isMatch: true,
|
|
1060
853
|
score: totalScore / numMatches
|
|
1061
854
|
};
|
|
1062
|
-
if (hasInverse)
|
|
1063
|
-
|
|
1064
|
-
}
|
|
1065
|
-
if (includeMatches) {
|
|
1066
|
-
result.indices = mergeIndices(allIndices);
|
|
1067
|
-
}
|
|
855
|
+
if (hasInverse) result.hasInverse = true;
|
|
856
|
+
if (includeMatches) result.indices = mergeIndices(allIndices);
|
|
1068
857
|
return result;
|
|
1069
858
|
}
|
|
1070
859
|
}
|
|
@@ -1073,7 +862,7 @@
|
|
|
1073
862
|
score: 1
|
|
1074
863
|
};
|
|
1075
864
|
}
|
|
1076
|
-
}
|
|
865
|
+
};
|
|
1077
866
|
const registeredSearchers = [];
|
|
1078
867
|
function register(...args) {
|
|
1079
868
|
registeredSearchers.push(...args);
|
|
@@ -1081,9 +870,7 @@
|
|
|
1081
870
|
function createSearcher(pattern, options) {
|
|
1082
871
|
for (let i = 0, len = registeredSearchers.length; i < len; i += 1) {
|
|
1083
872
|
const searcherClass = registeredSearchers[i];
|
|
1084
|
-
if (searcherClass.condition(pattern, options))
|
|
1085
|
-
return new searcherClass(pattern, options);
|
|
1086
|
-
}
|
|
873
|
+
if (searcherClass.condition(pattern, options)) return new searcherClass(pattern, options);
|
|
1087
874
|
}
|
|
1088
875
|
return new BitapSearch(pattern, options);
|
|
1089
876
|
}
|
|
@@ -1098,43 +885,29 @@
|
|
|
1098
885
|
const isExpression = (query) => !!(query[LogicalOperator.AND] || query[LogicalOperator.OR]);
|
|
1099
886
|
const isPath = (query) => !!query[KeyType.PATH];
|
|
1100
887
|
const isLeaf = (query) => !isArray(query) && isObject(query) && !isExpression(query);
|
|
1101
|
-
const convertToExplicit = (query) => ({
|
|
1102
|
-
|
|
1103
|
-
[key]: query[key]
|
|
1104
|
-
}))
|
|
1105
|
-
});
|
|
1106
|
-
function parse(query, options, {
|
|
1107
|
-
auto = true
|
|
1108
|
-
} = {}) {
|
|
888
|
+
const convertToExplicit = (query) => ({ [LogicalOperator.AND]: Object.keys(query).map((key) => ({ [key]: query[key] })) });
|
|
889
|
+
function parse(query, options, { auto = true } = {}) {
|
|
1109
890
|
const next = (query2) => {
|
|
1110
891
|
if (isString(query2)) {
|
|
1111
892
|
const obj = {
|
|
1112
893
|
keyId: null,
|
|
1113
894
|
pattern: query2
|
|
1114
895
|
};
|
|
1115
|
-
if (auto)
|
|
1116
|
-
obj.searcher = createSearcher(query2, options);
|
|
1117
|
-
}
|
|
896
|
+
if (auto) obj.searcher = createSearcher(query2, options);
|
|
1118
897
|
return obj;
|
|
1119
898
|
}
|
|
1120
899
|
const keys = Object.keys(query2);
|
|
1121
900
|
const isQueryPath = isPath(query2);
|
|
1122
|
-
if (!isQueryPath && keys.length > 1 && !isExpression(query2))
|
|
1123
|
-
return next(convertToExplicit(query2));
|
|
1124
|
-
}
|
|
901
|
+
if (!isQueryPath && keys.length > 1 && !isExpression(query2)) return next(convertToExplicit(query2));
|
|
1125
902
|
if (isLeaf(query2)) {
|
|
1126
903
|
const key = isQueryPath ? query2[KeyType.PATH] : keys[0];
|
|
1127
904
|
const pattern = isQueryPath ? query2[KeyType.PATTERN] : query2[key];
|
|
1128
|
-
if (!isString(pattern))
|
|
1129
|
-
throw new Error(LOGICAL_SEARCH_INVALID_QUERY_FOR_KEY(key));
|
|
1130
|
-
}
|
|
905
|
+
if (!isString(pattern)) throw new Error(LOGICAL_SEARCH_INVALID_QUERY_FOR_KEY(key));
|
|
1131
906
|
const obj = {
|
|
1132
907
|
keyId: createKeyId(key),
|
|
1133
908
|
pattern
|
|
1134
909
|
};
|
|
1135
|
-
if (auto)
|
|
1136
|
-
obj.searcher = createSearcher(pattern, options);
|
|
1137
|
-
}
|
|
910
|
+
if (auto) obj.searcher = createSearcher(pattern, options);
|
|
1138
911
|
return obj;
|
|
1139
912
|
}
|
|
1140
913
|
const node = {
|
|
@@ -1143,70 +916,54 @@
|
|
|
1143
916
|
};
|
|
1144
917
|
keys.forEach((key) => {
|
|
1145
918
|
const value = query2[key];
|
|
1146
|
-
if (isArray(value)) {
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
});
|
|
1150
|
-
}
|
|
919
|
+
if (isArray(value)) value.forEach((item) => {
|
|
920
|
+
node.children.push(next(item));
|
|
921
|
+
});
|
|
1151
922
|
});
|
|
1152
923
|
return node;
|
|
1153
924
|
};
|
|
1154
|
-
if (!isExpression(query))
|
|
1155
|
-
query = convertToExplicit(query);
|
|
1156
|
-
}
|
|
925
|
+
if (!isExpression(query)) query = convertToExplicit(query);
|
|
1157
926
|
return next(query);
|
|
1158
927
|
}
|
|
1159
|
-
function computeScoreSingle(matches, {
|
|
1160
|
-
ignoreFieldNorm = Config.ignoreFieldNorm
|
|
1161
|
-
}) {
|
|
928
|
+
function computeScoreSingle(matches, { ignoreFieldNorm = Config.ignoreFieldNorm }) {
|
|
1162
929
|
let totalScore = 1;
|
|
1163
|
-
matches.forEach(({
|
|
1164
|
-
key,
|
|
1165
|
-
norm: norm2,
|
|
1166
|
-
score
|
|
1167
|
-
}) => {
|
|
930
|
+
matches.forEach(({ key, norm: norm2, score }) => {
|
|
1168
931
|
const weight = key ? key.weight : null;
|
|
1169
932
|
totalScore *= Math.pow(score === 0 && weight ? Number.EPSILON : score, (weight || 1) * (ignoreFieldNorm ? 1 : norm2));
|
|
1170
933
|
});
|
|
1171
934
|
return totalScore;
|
|
1172
935
|
}
|
|
1173
|
-
function computeScore(results, {
|
|
1174
|
-
ignoreFieldNorm = Config.ignoreFieldNorm
|
|
1175
|
-
}) {
|
|
936
|
+
function computeScore(results, { ignoreFieldNorm = Config.ignoreFieldNorm }) {
|
|
1176
937
|
results.forEach((result) => {
|
|
1177
|
-
result.score = computeScoreSingle(result.matches, {
|
|
1178
|
-
ignoreFieldNorm
|
|
1179
|
-
});
|
|
938
|
+
result.score = computeScoreSingle(result.matches, { ignoreFieldNorm });
|
|
1180
939
|
});
|
|
1181
940
|
}
|
|
1182
|
-
|
|
1183
|
-
constructor(limit) {
|
|
941
|
+
var MaxHeap = class {
|
|
942
|
+
constructor(limit, comparator) {
|
|
1184
943
|
this.limit = limit;
|
|
1185
944
|
this.heap = [];
|
|
945
|
+
this.comparator = comparator;
|
|
1186
946
|
}
|
|
1187
947
|
get size() {
|
|
1188
948
|
return this.heap.length;
|
|
1189
949
|
}
|
|
1190
|
-
shouldInsert(score) {
|
|
1191
|
-
return this.size < this.limit || score < this.heap[0].score;
|
|
1192
|
-
}
|
|
1193
950
|
insert(item) {
|
|
1194
951
|
if (this.size < this.limit) {
|
|
1195
952
|
this.heap.push(item);
|
|
1196
953
|
this._bubbleUp(this.size - 1);
|
|
1197
|
-
} else if (item
|
|
954
|
+
} else if (this.comparator(item, this.heap[0]) < 0) {
|
|
1198
955
|
this.heap[0] = item;
|
|
1199
956
|
this._sinkDown(0);
|
|
1200
957
|
}
|
|
1201
958
|
}
|
|
1202
|
-
extractSorted(
|
|
1203
|
-
return this.heap.sort(
|
|
959
|
+
extractSorted() {
|
|
960
|
+
return this.heap.sort(this.comparator);
|
|
1204
961
|
}
|
|
1205
962
|
_bubbleUp(i) {
|
|
1206
963
|
const heap = this.heap;
|
|
1207
964
|
while (i > 0) {
|
|
1208
965
|
const parent = i - 1 >> 1;
|
|
1209
|
-
if (heap[i]
|
|
966
|
+
if (this.comparator(heap[i], heap[parent]) <= 0) break;
|
|
1210
967
|
const tmp = heap[i];
|
|
1211
968
|
heap[i] = heap[parent];
|
|
1212
969
|
heap[parent] = tmp;
|
|
@@ -1221,12 +978,8 @@
|
|
|
1221
978
|
i = largest;
|
|
1222
979
|
const left = 2 * i + 1;
|
|
1223
980
|
const right = 2 * i + 2;
|
|
1224
|
-
if (left < len && heap[left]
|
|
1225
|
-
|
|
1226
|
-
}
|
|
1227
|
-
if (right < len && heap[right].score > heap[largest].score) {
|
|
1228
|
-
largest = right;
|
|
1229
|
-
}
|
|
981
|
+
if (left < len && this.comparator(heap[left], heap[largest]) > 0) largest = left;
|
|
982
|
+
if (right < len && this.comparator(heap[right], heap[largest]) > 0) largest = right;
|
|
1230
983
|
if (largest !== i) {
|
|
1231
984
|
const tmp = heap[i];
|
|
1232
985
|
heap[i] = heap[largest];
|
|
@@ -1234,201 +987,223 @@
|
|
|
1234
987
|
}
|
|
1235
988
|
} while (largest !== i);
|
|
1236
989
|
}
|
|
1237
|
-
}
|
|
1238
|
-
function
|
|
1239
|
-
const matches =
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
return;
|
|
1243
|
-
}
|
|
1244
|
-
matches.forEach((match) => {
|
|
1245
|
-
if (!isDefined(match.indices) || !match.indices.length) {
|
|
1246
|
-
return;
|
|
1247
|
-
}
|
|
1248
|
-
const {
|
|
1249
|
-
indices,
|
|
1250
|
-
value
|
|
1251
|
-
} = match;
|
|
990
|
+
};
|
|
991
|
+
function formatMatches(result) {
|
|
992
|
+
const matches = [];
|
|
993
|
+
result.matches.forEach((match) => {
|
|
994
|
+
if (!isDefined(match.indices) || !match.indices.length) return;
|
|
1252
995
|
const obj = {
|
|
1253
|
-
indices,
|
|
1254
|
-
value
|
|
996
|
+
indices: match.indices,
|
|
997
|
+
value: match.value
|
|
1255
998
|
};
|
|
1256
|
-
if (match.key)
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
if (match.idx > -1) {
|
|
1260
|
-
obj.refIndex = match.idx;
|
|
1261
|
-
}
|
|
1262
|
-
data.matches.push(obj);
|
|
999
|
+
if (match.key) obj.key = match.key.id;
|
|
1000
|
+
if (match.idx > -1) obj.refIndex = match.idx;
|
|
1001
|
+
matches.push(obj);
|
|
1263
1002
|
});
|
|
1003
|
+
return matches;
|
|
1264
1004
|
}
|
|
1265
|
-
function
|
|
1266
|
-
data.score = result.score;
|
|
1267
|
-
}
|
|
1268
|
-
function format(results, docs, {
|
|
1269
|
-
includeMatches = Config.includeMatches,
|
|
1270
|
-
includeScore = Config.includeScore
|
|
1271
|
-
} = {}) {
|
|
1272
|
-
const transformers = [];
|
|
1273
|
-
if (includeMatches) transformers.push(transformMatches);
|
|
1274
|
-
if (includeScore) transformers.push(transformScore);
|
|
1005
|
+
function format(results, docs, { includeMatches = Config.includeMatches, includeScore = Config.includeScore } = {}) {
|
|
1275
1006
|
return results.map((result) => {
|
|
1276
|
-
const {
|
|
1277
|
-
idx
|
|
1278
|
-
} = result;
|
|
1007
|
+
const { idx } = result;
|
|
1279
1008
|
const data = {
|
|
1280
1009
|
item: docs[idx],
|
|
1281
1010
|
refIndex: idx
|
|
1282
1011
|
};
|
|
1283
|
-
if (
|
|
1284
|
-
|
|
1285
|
-
transformer(result, data);
|
|
1286
|
-
});
|
|
1287
|
-
}
|
|
1012
|
+
if (includeMatches) data.matches = formatMatches(result);
|
|
1013
|
+
if (includeScore) data.score = result.score;
|
|
1288
1014
|
return data;
|
|
1289
1015
|
});
|
|
1290
1016
|
}
|
|
1291
|
-
const
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
if (!isCaseSensitive) {
|
|
1299
|
-
text = text.toLowerCase();
|
|
1300
|
-
}
|
|
1301
|
-
if (ignoreDiacritics) {
|
|
1302
|
-
text = stripDiacritics(text);
|
|
1303
|
-
}
|
|
1304
|
-
return text.match(WORD) || [];
|
|
1305
|
-
}
|
|
1306
|
-
};
|
|
1017
|
+
const DEFAULT_TOKEN = /[\p{L}\p{M}\p{N}_]+/gu;
|
|
1018
|
+
const warned = /* @__PURE__ */ new WeakSet();
|
|
1019
|
+
function warnNonGlobal(regex) {
|
|
1020
|
+
if (!warned.has(regex)) {
|
|
1021
|
+
warned.add(regex);
|
|
1022
|
+
console.warn(`[Fuse] tokenize regex ${regex} lacks the global flag; only the first match per text will be returned. Add the 'g' flag.`);
|
|
1023
|
+
}
|
|
1307
1024
|
}
|
|
1308
|
-
function
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
const termFreqs = /* @__PURE__ */ new Map();
|
|
1317
|
-
for (const token of tokens) {
|
|
1318
|
-
termFreqs.set(token, (termFreqs.get(token) || 0) + 1);
|
|
1319
|
-
}
|
|
1320
|
-
for (const [term, tf] of termFreqs) {
|
|
1321
|
-
const posting = {
|
|
1322
|
-
docIdx,
|
|
1323
|
-
keyIdx,
|
|
1324
|
-
subIdx,
|
|
1325
|
-
tf
|
|
1326
|
-
};
|
|
1327
|
-
let postings = terms.get(term);
|
|
1328
|
-
if (!postings) {
|
|
1329
|
-
postings = [];
|
|
1330
|
-
terms.set(term, postings);
|
|
1025
|
+
function resolveTokenize(tokenize2) {
|
|
1026
|
+
if (typeof tokenize2 === "function") {
|
|
1027
|
+
let validated = false;
|
|
1028
|
+
return (text) => {
|
|
1029
|
+
const result = tokenize2(text);
|
|
1030
|
+
if (!validated) {
|
|
1031
|
+
validated = true;
|
|
1032
|
+
if (!Array.isArray(result) || result.some((t) => typeof t !== "string")) throw new Error(`[Fuse] tokenize function must return string[]; received ${Array.isArray(result) ? "array containing non-strings" : typeof result}.`);
|
|
1331
1033
|
}
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
}
|
|
1034
|
+
return result;
|
|
1035
|
+
};
|
|
1335
1036
|
}
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
v,
|
|
1340
|
-
$: fields
|
|
1341
|
-
} = record;
|
|
1342
|
-
if (v !== void 0) {
|
|
1343
|
-
addField(v, docIdx, -1, -1);
|
|
1344
|
-
continue;
|
|
1345
|
-
}
|
|
1346
|
-
if (fields) {
|
|
1347
|
-
for (let keyIdx = 0; keyIdx < keyCount; keyIdx++) {
|
|
1348
|
-
const value = fields[keyIdx];
|
|
1349
|
-
if (!value) continue;
|
|
1350
|
-
if (Array.isArray(value)) {
|
|
1351
|
-
for (const sub of value) {
|
|
1352
|
-
addField(sub.v, docIdx, keyIdx, sub.i ?? -1);
|
|
1353
|
-
}
|
|
1354
|
-
} else {
|
|
1355
|
-
addField(value.v, docIdx, keyIdx, -1);
|
|
1356
|
-
}
|
|
1357
|
-
}
|
|
1358
|
-
}
|
|
1037
|
+
if (tokenize2 instanceof RegExp) {
|
|
1038
|
+
if (!tokenize2.global) warnNonGlobal(tokenize2);
|
|
1039
|
+
return (text) => text.match(tokenize2) || [];
|
|
1359
1040
|
}
|
|
1360
|
-
return
|
|
1361
|
-
terms,
|
|
1362
|
-
fieldCount,
|
|
1363
|
-
df
|
|
1364
|
-
};
|
|
1041
|
+
return (text) => text.match(DEFAULT_TOKEN) || [];
|
|
1365
1042
|
}
|
|
1366
|
-
function
|
|
1367
|
-
const
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1043
|
+
function createAnalyzer({ isCaseSensitive = false, ignoreDiacritics = false, tokenize: tokenize2 } = {}) {
|
|
1044
|
+
const tokenizeFn = resolveTokenize(tokenize2);
|
|
1045
|
+
return { tokenize(text) {
|
|
1046
|
+
if (!isCaseSensitive) text = text.toLowerCase();
|
|
1047
|
+
if (ignoreDiacritics) text = stripDiacritics(text);
|
|
1048
|
+
return tokenizeFn(text);
|
|
1049
|
+
} };
|
|
1050
|
+
}
|
|
1051
|
+
var TokenSearch = class {
|
|
1052
|
+
static condition(_, options) {
|
|
1053
|
+
return options.useTokenSearch;
|
|
1054
|
+
}
|
|
1055
|
+
constructor(pattern, options) {
|
|
1056
|
+
this.options = options;
|
|
1057
|
+
this.analyzer = createAnalyzer({
|
|
1058
|
+
isCaseSensitive: options.isCaseSensitive,
|
|
1059
|
+
ignoreDiacritics: options.ignoreDiacritics,
|
|
1060
|
+
tokenize: options.tokenize
|
|
1061
|
+
});
|
|
1062
|
+
const queryTerms = this.analyzer.tokenize(pattern);
|
|
1063
|
+
const { df, fieldCount } = options._invertedIndex;
|
|
1064
|
+
this.termSearchers = [];
|
|
1065
|
+
this.idfWeights = [];
|
|
1066
|
+
for (const term of queryTerms) {
|
|
1067
|
+
this.termSearchers.push(new BitapSearch(term, {
|
|
1068
|
+
location: options.location,
|
|
1069
|
+
threshold: options.threshold,
|
|
1070
|
+
distance: options.distance,
|
|
1071
|
+
includeMatches: options.includeMatches,
|
|
1072
|
+
findAllMatches: options.findAllMatches,
|
|
1073
|
+
minMatchCharLength: options.minMatchCharLength,
|
|
1074
|
+
isCaseSensitive: options.isCaseSensitive,
|
|
1075
|
+
ignoreDiacritics: options.ignoreDiacritics,
|
|
1076
|
+
ignoreLocation: true
|
|
1077
|
+
}));
|
|
1078
|
+
const docFreq = df.get(term) || 0;
|
|
1079
|
+
const idf = Math.log(1 + (fieldCount - docFreq + 0.5) / (docFreq + 0.5));
|
|
1080
|
+
this.idfWeights.push(idf);
|
|
1379
1081
|
}
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1082
|
+
this.combineAll = options.tokenMatch === "all";
|
|
1083
|
+
this.numTerms = this.termSearchers.length;
|
|
1084
|
+
this.useMask = this.numTerms <= 31;
|
|
1085
|
+
}
|
|
1086
|
+
searchIn(text) {
|
|
1087
|
+
if (!this.termSearchers.length) return {
|
|
1088
|
+
isMatch: false,
|
|
1089
|
+
score: 1
|
|
1090
|
+
};
|
|
1091
|
+
const allIndices = [];
|
|
1092
|
+
let weightedScore = 0;
|
|
1093
|
+
let maxPossibleScore = 0;
|
|
1094
|
+
let matchedCount = 0;
|
|
1095
|
+
let matchedMask = 0;
|
|
1096
|
+
const matchedTerms = this.combineAll && !this.useMask ? /* @__PURE__ */ new Set() : null;
|
|
1097
|
+
for (let i = 0; i < this.termSearchers.length; i++) {
|
|
1098
|
+
const result = this.termSearchers[i].searchIn(text);
|
|
1099
|
+
const idf = this.idfWeights[i];
|
|
1100
|
+
maxPossibleScore += idf;
|
|
1101
|
+
if (result.isMatch) {
|
|
1102
|
+
matchedCount++;
|
|
1103
|
+
weightedScore += idf * (1 - result.score);
|
|
1104
|
+
if (result.indices) allIndices.push(...result.indices);
|
|
1105
|
+
if (this.combineAll) if (this.useMask) matchedMask |= 1 << i;
|
|
1106
|
+
else matchedTerms.add(i);
|
|
1391
1107
|
}
|
|
1392
|
-
postings.push(posting);
|
|
1393
|
-
index.df.set(term, (index.df.get(term) || 0) + 1);
|
|
1394
1108
|
}
|
|
1109
|
+
if (matchedCount === 0) return {
|
|
1110
|
+
isMatch: false,
|
|
1111
|
+
score: 1
|
|
1112
|
+
};
|
|
1113
|
+
const normalized = maxPossibleScore > 0 ? 1 - weightedScore / maxPossibleScore : 0;
|
|
1114
|
+
const searchResult = {
|
|
1115
|
+
isMatch: true,
|
|
1116
|
+
score: Math.max(1e-3, normalized)
|
|
1117
|
+
};
|
|
1118
|
+
if (this.options.includeMatches && allIndices.length) searchResult.indices = mergeIndices(allIndices);
|
|
1119
|
+
if (this.combineAll) {
|
|
1120
|
+
if (this.useMask) searchResult.matchedMask = matchedMask;
|
|
1121
|
+
else searchResult.matchedTerms = matchedTerms;
|
|
1122
|
+
searchResult.termCount = this.numTerms;
|
|
1123
|
+
}
|
|
1124
|
+
return searchResult;
|
|
1125
|
+
}
|
|
1126
|
+
};
|
|
1127
|
+
function addField(index, text, docIdx, analyzer) {
|
|
1128
|
+
const tokens = analyzer.tokenize(text);
|
|
1129
|
+
if (!tokens.length) return;
|
|
1130
|
+
index.fieldCount++;
|
|
1131
|
+
index.docFieldCount.set(docIdx, (index.docFieldCount.get(docIdx) || 0) + 1);
|
|
1132
|
+
const distinctTerms = new Set(tokens);
|
|
1133
|
+
let perDocTerms = index.docTermFieldHits.get(docIdx);
|
|
1134
|
+
if (!perDocTerms) {
|
|
1135
|
+
perDocTerms = /* @__PURE__ */ new Map();
|
|
1136
|
+
index.docTermFieldHits.set(docIdx, perDocTerms);
|
|
1137
|
+
}
|
|
1138
|
+
for (const term of distinctTerms) {
|
|
1139
|
+
perDocTerms.set(term, (perDocTerms.get(term) || 0) + 1);
|
|
1140
|
+
index.df.set(term, (index.df.get(term) || 0) + 1);
|
|
1395
1141
|
}
|
|
1142
|
+
}
|
|
1143
|
+
function ingestRecord(index, record, keyCount, analyzer) {
|
|
1144
|
+
const { i: docIdx, v, $: fields } = record;
|
|
1396
1145
|
if (v !== void 0) {
|
|
1397
|
-
addField(v,
|
|
1146
|
+
addField(index, v, docIdx, analyzer);
|
|
1398
1147
|
return;
|
|
1399
1148
|
}
|
|
1400
|
-
if (fields)
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
addField(sub.v, keyIdx, sub.i ?? -1);
|
|
1407
|
-
}
|
|
1408
|
-
} else {
|
|
1409
|
-
addField(value.v, keyIdx, -1);
|
|
1410
|
-
}
|
|
1411
|
-
}
|
|
1149
|
+
if (!fields) return;
|
|
1150
|
+
for (let keyIdx = 0; keyIdx < keyCount; keyIdx++) {
|
|
1151
|
+
const value = fields[keyIdx];
|
|
1152
|
+
if (!value) continue;
|
|
1153
|
+
if (Array.isArray(value)) for (const sub of value) addField(index, sub.v, docIdx, analyzer);
|
|
1154
|
+
else addField(index, value.v, docIdx, analyzer);
|
|
1412
1155
|
}
|
|
1413
1156
|
}
|
|
1157
|
+
function buildInvertedIndex(records, keyCount, analyzer) {
|
|
1158
|
+
const index = {
|
|
1159
|
+
fieldCount: 0,
|
|
1160
|
+
df: /* @__PURE__ */ new Map(),
|
|
1161
|
+
docFieldCount: /* @__PURE__ */ new Map(),
|
|
1162
|
+
docTermFieldHits: /* @__PURE__ */ new Map()
|
|
1163
|
+
};
|
|
1164
|
+
for (const record of records) ingestRecord(index, record, keyCount, analyzer);
|
|
1165
|
+
return index;
|
|
1166
|
+
}
|
|
1167
|
+
function addToInvertedIndex(index, record, keyCount, analyzer) {
|
|
1168
|
+
ingestRecord(index, record, keyCount, analyzer);
|
|
1169
|
+
}
|
|
1414
1170
|
function removeFromInvertedIndex(index, docIdx) {
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
}
|
|
1428
|
-
}
|
|
1171
|
+
const fieldCount = index.docFieldCount.get(docIdx);
|
|
1172
|
+
if (fieldCount === void 0) return;
|
|
1173
|
+
index.fieldCount -= fieldCount;
|
|
1174
|
+
index.docFieldCount.delete(docIdx);
|
|
1175
|
+
const perDocTerms = index.docTermFieldHits.get(docIdx);
|
|
1176
|
+
if (!perDocTerms) return;
|
|
1177
|
+
for (const [term, hits] of perDocTerms) {
|
|
1178
|
+
const next = (index.df.get(term) || 0) - hits;
|
|
1179
|
+
if (next <= 0) index.df.delete(term);
|
|
1180
|
+
else index.df.set(term, next);
|
|
1181
|
+
}
|
|
1182
|
+
index.docTermFieldHits.delete(docIdx);
|
|
1429
1183
|
}
|
|
1430
|
-
|
|
1431
|
-
|
|
1184
|
+
function removeAndShiftInvertedIndex(index, removedIndices) {
|
|
1185
|
+
if (removedIndices.length === 0) return;
|
|
1186
|
+
const sorted = Array.from(new Set(removedIndices)).sort((a, b) => a - b);
|
|
1187
|
+
for (const idx of sorted) removeFromInvertedIndex(index, idx);
|
|
1188
|
+
const shift = (oldIdx) => {
|
|
1189
|
+
let lo = 0;
|
|
1190
|
+
let hi = sorted.length;
|
|
1191
|
+
while (lo < hi) {
|
|
1192
|
+
const mid = lo + hi >>> 1;
|
|
1193
|
+
if (sorted[mid] < oldIdx) lo = mid + 1;
|
|
1194
|
+
else hi = mid;
|
|
1195
|
+
}
|
|
1196
|
+
return oldIdx - lo;
|
|
1197
|
+
};
|
|
1198
|
+
const firstRemoved = sorted[0];
|
|
1199
|
+
const shiftedDocFieldCount = /* @__PURE__ */ new Map();
|
|
1200
|
+
for (const [oldKey, count] of index.docFieldCount) shiftedDocFieldCount.set(oldKey > firstRemoved ? shift(oldKey) : oldKey, count);
|
|
1201
|
+
index.docFieldCount = shiftedDocFieldCount;
|
|
1202
|
+
const shiftedDocTermFieldHits = /* @__PURE__ */ new Map();
|
|
1203
|
+
for (const [oldKey, terms] of index.docTermFieldHits) shiftedDocTermFieldHits.set(oldKey > firstRemoved ? shift(oldKey) : oldKey, terms);
|
|
1204
|
+
index.docTermFieldHits = shiftedDocTermFieldHits;
|
|
1205
|
+
}
|
|
1206
|
+
var Fuse = class {
|
|
1432
1207
|
constructor(docs, options, index) {
|
|
1433
1208
|
this.options = {
|
|
1434
1209
|
...Config,
|
|
@@ -1445,23 +1220,18 @@
|
|
|
1445
1220
|
this._lastSearcher = null;
|
|
1446
1221
|
}
|
|
1447
1222
|
_getSearcher(query) {
|
|
1448
|
-
if (this._lastQuery === query)
|
|
1449
|
-
|
|
1450
|
-
}
|
|
1451
|
-
const opts = this._invertedIndex ? {
|
|
1223
|
+
if (this._lastQuery === query) return this._lastSearcher;
|
|
1224
|
+
const searcher = createSearcher(query, this._invertedIndex ? {
|
|
1452
1225
|
...this.options,
|
|
1453
1226
|
_invertedIndex: this._invertedIndex
|
|
1454
|
-
} : this.options;
|
|
1455
|
-
const searcher = createSearcher(query, opts);
|
|
1227
|
+
} : this.options);
|
|
1456
1228
|
this._lastQuery = query;
|
|
1457
1229
|
this._lastSearcher = searcher;
|
|
1458
1230
|
return searcher;
|
|
1459
1231
|
}
|
|
1460
1232
|
setCollection(docs, index) {
|
|
1461
1233
|
this._docs = docs;
|
|
1462
|
-
if (index && !(index instanceof FuseIndex))
|
|
1463
|
-
throw new Error(INCORRECT_INDEX_TYPE);
|
|
1464
|
-
}
|
|
1234
|
+
if (index && !(index instanceof FuseIndex)) throw new Error(INCORRECT_INDEX_TYPE);
|
|
1465
1235
|
this._myIndex = index || createIndex(this.options.keys, this._docs, {
|
|
1466
1236
|
getFn: this.options.getFn,
|
|
1467
1237
|
fieldNormWeight: this.options.fieldNormWeight
|
|
@@ -1469,155 +1239,129 @@
|
|
|
1469
1239
|
if (this.options.useTokenSearch) {
|
|
1470
1240
|
const analyzer = createAnalyzer({
|
|
1471
1241
|
isCaseSensitive: this.options.isCaseSensitive,
|
|
1472
|
-
ignoreDiacritics: this.options.ignoreDiacritics
|
|
1242
|
+
ignoreDiacritics: this.options.ignoreDiacritics,
|
|
1243
|
+
tokenize: this.options.tokenize
|
|
1473
1244
|
});
|
|
1474
1245
|
this._invertedIndex = buildInvertedIndex(this._myIndex.records, this._myIndex.keys.length, analyzer);
|
|
1475
1246
|
}
|
|
1247
|
+
this._invalidateSearcherCache();
|
|
1476
1248
|
}
|
|
1477
1249
|
add(doc) {
|
|
1478
|
-
if (!isDefined(doc))
|
|
1479
|
-
return;
|
|
1480
|
-
}
|
|
1250
|
+
if (!isDefined(doc)) return;
|
|
1481
1251
|
this._docs.push(doc);
|
|
1482
|
-
this._myIndex.add(doc);
|
|
1483
|
-
if (this._invertedIndex) {
|
|
1484
|
-
const record = this._myIndex.records[this._myIndex.records.length - 1];
|
|
1252
|
+
const record = this._myIndex.add(doc, this._docs.length - 1);
|
|
1253
|
+
if (this._invertedIndex && record) {
|
|
1485
1254
|
const analyzer = createAnalyzer({
|
|
1486
1255
|
isCaseSensitive: this.options.isCaseSensitive,
|
|
1487
|
-
ignoreDiacritics: this.options.ignoreDiacritics
|
|
1256
|
+
ignoreDiacritics: this.options.ignoreDiacritics,
|
|
1257
|
+
tokenize: this.options.tokenize
|
|
1488
1258
|
});
|
|
1489
1259
|
addToInvertedIndex(this._invertedIndex, record, this._myIndex.keys.length, analyzer);
|
|
1490
1260
|
}
|
|
1261
|
+
this._invalidateSearcherCache();
|
|
1491
1262
|
}
|
|
1492
1263
|
remove(predicate = () => false) {
|
|
1493
1264
|
const results = [];
|
|
1494
1265
|
const indicesToRemove = [];
|
|
1495
|
-
for (let i = 0, len = this._docs.length; i < len; i += 1) {
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
indicesToRemove.push(i);
|
|
1499
|
-
}
|
|
1266
|
+
for (let i = 0, len = this._docs.length; i < len; i += 1) if (predicate(this._docs[i], i)) {
|
|
1267
|
+
results.push(this._docs[i]);
|
|
1268
|
+
indicesToRemove.push(i);
|
|
1500
1269
|
}
|
|
1501
1270
|
if (indicesToRemove.length) {
|
|
1502
|
-
if (this._invertedIndex)
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
}
|
|
1506
|
-
}
|
|
1507
|
-
for (let i = indicesToRemove.length - 1; i >= 0; i -= 1) {
|
|
1508
|
-
this._docs.splice(indicesToRemove[i], 1);
|
|
1509
|
-
}
|
|
1271
|
+
if (this._invertedIndex) removeAndShiftInvertedIndex(this._invertedIndex, indicesToRemove);
|
|
1272
|
+
const toRemove = new Set(indicesToRemove);
|
|
1273
|
+
this._docs = this._docs.filter((_, i) => !toRemove.has(i));
|
|
1510
1274
|
this._myIndex.removeAll(indicesToRemove);
|
|
1275
|
+
this._invalidateSearcherCache();
|
|
1511
1276
|
}
|
|
1512
1277
|
return results;
|
|
1513
1278
|
}
|
|
1514
1279
|
removeAt(idx) {
|
|
1515
|
-
if (this.
|
|
1516
|
-
|
|
1517
|
-
}
|
|
1280
|
+
if (!Number.isInteger(idx) || idx < 0 || idx >= this._docs.length) throw new Error(INVALID_DOC_INDEX);
|
|
1281
|
+
if (this._invertedIndex) removeAndShiftInvertedIndex(this._invertedIndex, [idx]);
|
|
1518
1282
|
const doc = this._docs.splice(idx, 1)[0];
|
|
1519
1283
|
this._myIndex.removeAt(idx);
|
|
1284
|
+
this._invalidateSearcherCache();
|
|
1520
1285
|
return doc;
|
|
1521
1286
|
}
|
|
1287
|
+
_invalidateSearcherCache() {
|
|
1288
|
+
this._lastQuery = null;
|
|
1289
|
+
this._lastSearcher = null;
|
|
1290
|
+
}
|
|
1522
1291
|
getIndex() {
|
|
1523
1292
|
return this._myIndex;
|
|
1524
1293
|
}
|
|
1294
|
+
_normalizedKeys() {
|
|
1295
|
+
return this._myIndex.keys.map((key) => this._keyStore.get(key.id) || key);
|
|
1296
|
+
}
|
|
1525
1297
|
search(query, options) {
|
|
1526
|
-
const {
|
|
1527
|
-
|
|
1528
|
-
} = options || {};
|
|
1529
|
-
const {
|
|
1530
|
-
includeMatches,
|
|
1531
|
-
includeScore,
|
|
1532
|
-
shouldSort,
|
|
1533
|
-
sortFn,
|
|
1534
|
-
ignoreFieldNorm
|
|
1535
|
-
} = this.options;
|
|
1298
|
+
const { limit = -1 } = options || {};
|
|
1299
|
+
const { includeMatches, includeScore, shouldSort, sortFn, ignoreFieldNorm } = this.options;
|
|
1536
1300
|
if (isString(query) && !query.trim()) {
|
|
1537
1301
|
let docs = this._docs.map((item, idx) => ({
|
|
1538
1302
|
item,
|
|
1539
1303
|
refIndex: idx
|
|
1540
1304
|
}));
|
|
1541
|
-
if (isNumber(limit) && limit > -1)
|
|
1542
|
-
docs = docs.slice(0, limit);
|
|
1543
|
-
}
|
|
1305
|
+
if (isNumber(limit) && limit > -1) docs = docs.slice(0, limit);
|
|
1544
1306
|
return docs;
|
|
1545
1307
|
}
|
|
1546
|
-
const useHeap = isNumber(limit) && limit > 0 && isString(query);
|
|
1308
|
+
const useHeap = shouldSort && isNumber(limit) && limit > 0 && isString(query);
|
|
1309
|
+
const comparator = sortFn;
|
|
1310
|
+
const stable = (a, b) => comparator(a, b) || a.idx - b.idx;
|
|
1547
1311
|
let results;
|
|
1548
1312
|
if (useHeap) {
|
|
1549
|
-
const heap = new MaxHeap(limit);
|
|
1550
|
-
if (isString(this._docs[0])) {
|
|
1551
|
-
|
|
1552
|
-
heap,
|
|
1553
|
-
ignoreFieldNorm
|
|
1554
|
-
});
|
|
1555
|
-
} else {
|
|
1556
|
-
this._searchObjectList(query, {
|
|
1557
|
-
heap,
|
|
1558
|
-
ignoreFieldNorm
|
|
1559
|
-
});
|
|
1560
|
-
}
|
|
1561
|
-
results = heap.extractSorted(sortFn);
|
|
1562
|
-
} else {
|
|
1563
|
-
results = isString(query) ? isString(this._docs[0]) ? this._searchStringList(query) : this._searchObjectList(query) : this._searchLogical(query);
|
|
1564
|
-
computeScore(results, {
|
|
1313
|
+
const heap = new MaxHeap(limit, stable);
|
|
1314
|
+
if (isString(this._docs[0])) this._searchStringList(query, {
|
|
1315
|
+
heap,
|
|
1565
1316
|
ignoreFieldNorm
|
|
1566
1317
|
});
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1318
|
+
else this._searchObjectList(query, {
|
|
1319
|
+
heap,
|
|
1320
|
+
ignoreFieldNorm
|
|
1321
|
+
});
|
|
1322
|
+
results = heap.extractSorted();
|
|
1323
|
+
} else {
|
|
1324
|
+
results = isString(query) ? isString(this._docs[0]) ? this._searchStringList(query) : this._searchObjectList(query) : this._searchLogical(query);
|
|
1325
|
+
computeScore(results, { ignoreFieldNorm });
|
|
1326
|
+
if (shouldSort) results.sort(isString(query) ? stable : comparator);
|
|
1327
|
+
if (isNumber(limit) && limit > -1) results = results.slice(0, limit);
|
|
1573
1328
|
}
|
|
1574
1329
|
return format(results, this._docs, {
|
|
1575
1330
|
includeMatches,
|
|
1576
1331
|
includeScore
|
|
1577
1332
|
});
|
|
1578
1333
|
}
|
|
1579
|
-
_searchStringList(query, {
|
|
1580
|
-
heap,
|
|
1581
|
-
ignoreFieldNorm
|
|
1582
|
-
} = {}) {
|
|
1334
|
+
_searchStringList(query, { heap, ignoreFieldNorm } = {}) {
|
|
1583
1335
|
const searcher = this._getSearcher(query);
|
|
1584
|
-
const
|
|
1585
|
-
|
|
1586
|
-
} = this._myIndex;
|
|
1336
|
+
const requireAllTokens = this.options.useTokenSearch && this.options.tokenMatch === "all";
|
|
1337
|
+
const { records } = this._myIndex;
|
|
1587
1338
|
const results = heap ? null : [];
|
|
1588
|
-
records.forEach(({
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
isMatch,
|
|
1598
|
-
score,
|
|
1599
|
-
indices
|
|
1600
|
-
} = searcher.searchIn(text);
|
|
1601
|
-
if (isMatch) {
|
|
1602
|
-
const result = {
|
|
1603
|
-
item: text,
|
|
1604
|
-
idx,
|
|
1605
|
-
matches: [{
|
|
1606
|
-
score,
|
|
1607
|
-
value: text,
|
|
1608
|
-
norm: norm2,
|
|
1609
|
-
indices
|
|
1610
|
-
}]
|
|
1339
|
+
records.forEach(({ v: text, i: idx, n: norm2 }) => {
|
|
1340
|
+
if (!isDefined(text)) return;
|
|
1341
|
+
const searchResult = searcher.searchIn(text);
|
|
1342
|
+
if (searchResult.isMatch) {
|
|
1343
|
+
const match = {
|
|
1344
|
+
score: searchResult.score,
|
|
1345
|
+
value: text,
|
|
1346
|
+
norm: norm2,
|
|
1347
|
+
indices: searchResult.indices
|
|
1611
1348
|
};
|
|
1612
|
-
if (
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1349
|
+
if (requireAllTokens) {
|
|
1350
|
+
match.matchedMask = searchResult.matchedMask;
|
|
1351
|
+
match.matchedTerms = searchResult.matchedTerms;
|
|
1352
|
+
match.termCount = searchResult.termCount;
|
|
1353
|
+
}
|
|
1354
|
+
const matches = [match];
|
|
1355
|
+
if (!requireAllTokens || this._coversAllTokens(matches)) {
|
|
1356
|
+
const result = {
|
|
1357
|
+
item: text,
|
|
1358
|
+
idx,
|
|
1359
|
+
matches
|
|
1360
|
+
};
|
|
1361
|
+
if (heap) {
|
|
1362
|
+
result.score = computeScoreSingle(result.matches, { ignoreFieldNorm });
|
|
1617
1363
|
heap.insert(result);
|
|
1618
|
-
}
|
|
1619
|
-
} else {
|
|
1620
|
-
results.push(result);
|
|
1364
|
+
} else results.push(result);
|
|
1621
1365
|
}
|
|
1622
1366
|
}
|
|
1623
1367
|
});
|
|
@@ -1625,61 +1369,46 @@
|
|
|
1625
1369
|
}
|
|
1626
1370
|
_searchLogical(query) {
|
|
1627
1371
|
const expression = parse(query, this.options);
|
|
1372
|
+
const keys = this._normalizedKeys();
|
|
1628
1373
|
const evaluate = (node, item, idx) => {
|
|
1629
1374
|
if (!("children" in node)) {
|
|
1630
|
-
const {
|
|
1631
|
-
keyId,
|
|
1632
|
-
searcher
|
|
1633
|
-
} = node;
|
|
1375
|
+
const { keyId, searcher } = node;
|
|
1634
1376
|
let matches;
|
|
1635
1377
|
if (keyId === null) {
|
|
1636
1378
|
matches = [];
|
|
1637
|
-
|
|
1379
|
+
keys.forEach((key, keyIndex) => {
|
|
1638
1380
|
matches.push(...this._findMatches({
|
|
1639
1381
|
key,
|
|
1640
1382
|
value: item[keyIndex],
|
|
1641
1383
|
searcher
|
|
1642
1384
|
}));
|
|
1643
1385
|
});
|
|
1644
|
-
} else {
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
item,
|
|
1655
|
-
matches
|
|
1656
|
-
}];
|
|
1657
|
-
}
|
|
1386
|
+
} else matches = this._findMatches({
|
|
1387
|
+
key: this._keyStore.get(keyId),
|
|
1388
|
+
value: this._myIndex.getValueForItemAtKeyId(item, keyId),
|
|
1389
|
+
searcher
|
|
1390
|
+
});
|
|
1391
|
+
if (matches && matches.length) return [{
|
|
1392
|
+
idx,
|
|
1393
|
+
item,
|
|
1394
|
+
matches
|
|
1395
|
+
}];
|
|
1658
1396
|
return [];
|
|
1659
1397
|
}
|
|
1660
|
-
const {
|
|
1661
|
-
children,
|
|
1662
|
-
operator
|
|
1663
|
-
} = node;
|
|
1398
|
+
const { children, operator } = node;
|
|
1664
1399
|
const res = [];
|
|
1665
1400
|
for (let i = 0, len = children.length; i < len; i += 1) {
|
|
1666
1401
|
const child = children[i];
|
|
1667
1402
|
const result = evaluate(child, item, idx);
|
|
1668
|
-
if (result.length)
|
|
1669
|
-
|
|
1670
|
-
} else if (operator === LogicalOperator.AND) {
|
|
1671
|
-
return [];
|
|
1672
|
-
}
|
|
1403
|
+
if (result.length) res.push(...result);
|
|
1404
|
+
else if (operator === LogicalOperator.AND) return [];
|
|
1673
1405
|
}
|
|
1674
1406
|
return res;
|
|
1675
1407
|
};
|
|
1676
1408
|
const records = this._myIndex.records;
|
|
1677
1409
|
const resultMap = /* @__PURE__ */ new Map();
|
|
1678
1410
|
const results = [];
|
|
1679
|
-
records.forEach(({
|
|
1680
|
-
$: item,
|
|
1681
|
-
i: idx
|
|
1682
|
-
}) => {
|
|
1411
|
+
records.forEach(({ $: item, i: idx }) => {
|
|
1683
1412
|
if (isDefined(item)) {
|
|
1684
1413
|
const expResults = evaluate(expression, item, idx);
|
|
1685
1414
|
if (expResults.length) {
|
|
@@ -1691,9 +1420,7 @@
|
|
|
1691
1420
|
});
|
|
1692
1421
|
results.push(resultMap.get(idx));
|
|
1693
1422
|
}
|
|
1694
|
-
expResults.forEach(({
|
|
1695
|
-
matches
|
|
1696
|
-
}) => {
|
|
1423
|
+
expResults.forEach(({ matches }) => {
|
|
1697
1424
|
resultMap.get(idx).matches.push(...matches);
|
|
1698
1425
|
});
|
|
1699
1426
|
}
|
|
@@ -1701,31 +1428,14 @@
|
|
|
1701
1428
|
});
|
|
1702
1429
|
return results;
|
|
1703
1430
|
}
|
|
1704
|
-
|
|
1705
|
-
// across keys switches from "ANY key matches" to "ALL keys must match."
|
|
1706
|
-
// This is signaled by hasInverse on the SearchResult from ExtendedSearch.
|
|
1707
|
-
//
|
|
1708
|
-
// For mixed patterns like "^hello !Syrup", a key failure is ambiguous —
|
|
1709
|
-
// it could be the positive or inverse term that failed. In that case we
|
|
1710
|
-
// conservatively exclude the item, which is strictly better than the old
|
|
1711
|
-
// behavior of including it. See: https://github.com/krisk/Fuse/issues/712
|
|
1712
|
-
_searchObjectList(query, {
|
|
1713
|
-
heap,
|
|
1714
|
-
ignoreFieldNorm
|
|
1715
|
-
} = {}) {
|
|
1431
|
+
_searchObjectList(query, { heap, ignoreFieldNorm } = {}) {
|
|
1716
1432
|
const searcher = this._getSearcher(query);
|
|
1717
|
-
const
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
} = this._myIndex;
|
|
1433
|
+
const requireAllTokens = this.options.useTokenSearch && this.options.tokenMatch === "all";
|
|
1434
|
+
const { records } = this._myIndex;
|
|
1435
|
+
const keys = this._normalizedKeys();
|
|
1721
1436
|
const results = heap ? null : [];
|
|
1722
|
-
records.forEach(({
|
|
1723
|
-
|
|
1724
|
-
i: idx
|
|
1725
|
-
}) => {
|
|
1726
|
-
if (!isDefined(item)) {
|
|
1727
|
-
return;
|
|
1728
|
-
}
|
|
1437
|
+
records.forEach(({ $: item, i: idx }) => {
|
|
1438
|
+
if (!isDefined(item)) return;
|
|
1729
1439
|
const matches = [];
|
|
1730
1440
|
let anyKeyFailed = false;
|
|
1731
1441
|
let hasInverse = false;
|
|
@@ -1737,195 +1447,104 @@
|
|
|
1737
1447
|
});
|
|
1738
1448
|
if (keyMatches.length) {
|
|
1739
1449
|
matches.push(...keyMatches);
|
|
1740
|
-
if (keyMatches[0].hasInverse)
|
|
1741
|
-
|
|
1742
|
-
}
|
|
1743
|
-
} else {
|
|
1744
|
-
anyKeyFailed = true;
|
|
1745
|
-
}
|
|
1450
|
+
if (keyMatches[0].hasInverse) hasInverse = true;
|
|
1451
|
+
} else anyKeyFailed = true;
|
|
1746
1452
|
});
|
|
1747
|
-
if (hasInverse && anyKeyFailed)
|
|
1748
|
-
|
|
1749
|
-
}
|
|
1750
|
-
if (matches.length) {
|
|
1453
|
+
if (hasInverse && anyKeyFailed) return;
|
|
1454
|
+
if (matches.length && (!requireAllTokens || this._coversAllTokens(matches))) {
|
|
1751
1455
|
const result = {
|
|
1752
1456
|
idx,
|
|
1753
1457
|
item,
|
|
1754
1458
|
matches
|
|
1755
1459
|
};
|
|
1756
1460
|
if (heap) {
|
|
1757
|
-
result.score = computeScoreSingle(result.matches, {
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
if (heap.shouldInsert(result.score)) {
|
|
1761
|
-
heap.insert(result);
|
|
1762
|
-
}
|
|
1763
|
-
} else {
|
|
1764
|
-
results.push(result);
|
|
1765
|
-
}
|
|
1461
|
+
result.score = computeScoreSingle(result.matches, { ignoreFieldNorm });
|
|
1462
|
+
heap.insert(result);
|
|
1463
|
+
} else results.push(result);
|
|
1766
1464
|
}
|
|
1767
1465
|
});
|
|
1768
1466
|
return results;
|
|
1769
1467
|
}
|
|
1770
|
-
_findMatches({
|
|
1771
|
-
|
|
1772
|
-
value,
|
|
1773
|
-
searcher
|
|
1774
|
-
}) {
|
|
1775
|
-
if (!isDefined(value)) {
|
|
1776
|
-
return [];
|
|
1777
|
-
}
|
|
1468
|
+
_findMatches({ key, value, searcher }) {
|
|
1469
|
+
if (!isDefined(value)) return [];
|
|
1778
1470
|
const matches = [];
|
|
1779
|
-
if (isArray(value)) {
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
if (!isDefined(text)) {
|
|
1786
|
-
return;
|
|
1787
|
-
}
|
|
1788
|
-
const {
|
|
1789
|
-
isMatch,
|
|
1790
|
-
score,
|
|
1791
|
-
indices,
|
|
1792
|
-
hasInverse
|
|
1793
|
-
} = searcher.searchIn(text);
|
|
1794
|
-
if (isMatch) {
|
|
1795
|
-
matches.push({
|
|
1796
|
-
score,
|
|
1797
|
-
key,
|
|
1798
|
-
value: text,
|
|
1799
|
-
idx,
|
|
1800
|
-
norm: norm2,
|
|
1801
|
-
indices,
|
|
1802
|
-
hasInverse
|
|
1803
|
-
});
|
|
1804
|
-
}
|
|
1805
|
-
});
|
|
1806
|
-
} else {
|
|
1807
|
-
const {
|
|
1808
|
-
v: text,
|
|
1809
|
-
n: norm2
|
|
1810
|
-
} = value;
|
|
1811
|
-
const {
|
|
1812
|
-
isMatch,
|
|
1813
|
-
score,
|
|
1814
|
-
indices,
|
|
1815
|
-
hasInverse
|
|
1816
|
-
} = searcher.searchIn(text);
|
|
1817
|
-
if (isMatch) {
|
|
1818
|
-
matches.push({
|
|
1819
|
-
score,
|
|
1471
|
+
if (isArray(value)) value.forEach(({ v: text, i: idx, n: norm2 }) => {
|
|
1472
|
+
if (!isDefined(text)) return;
|
|
1473
|
+
const searchResult = searcher.searchIn(text);
|
|
1474
|
+
if (searchResult.isMatch) {
|
|
1475
|
+
const match = {
|
|
1476
|
+
score: searchResult.score,
|
|
1820
1477
|
key,
|
|
1821
1478
|
value: text,
|
|
1479
|
+
idx,
|
|
1822
1480
|
norm: norm2,
|
|
1823
|
-
indices,
|
|
1824
|
-
hasInverse
|
|
1825
|
-
}
|
|
1481
|
+
indices: searchResult.indices,
|
|
1482
|
+
hasInverse: searchResult.hasInverse
|
|
1483
|
+
};
|
|
1484
|
+
if (searchResult.termCount !== void 0) {
|
|
1485
|
+
match.matchedMask = searchResult.matchedMask;
|
|
1486
|
+
match.matchedTerms = searchResult.matchedTerms;
|
|
1487
|
+
match.termCount = searchResult.termCount;
|
|
1488
|
+
}
|
|
1489
|
+
matches.push(match);
|
|
1826
1490
|
}
|
|
1827
|
-
}
|
|
1828
|
-
return matches;
|
|
1829
|
-
}
|
|
1830
|
-
}
|
|
1831
|
-
class TokenSearch {
|
|
1832
|
-
static condition(_, options) {
|
|
1833
|
-
return options.useTokenSearch;
|
|
1834
|
-
}
|
|
1835
|
-
constructor(pattern, options) {
|
|
1836
|
-
this.options = options;
|
|
1837
|
-
this.analyzer = createAnalyzer({
|
|
1838
|
-
isCaseSensitive: options.isCaseSensitive,
|
|
1839
|
-
ignoreDiacritics: options.ignoreDiacritics
|
|
1840
1491
|
});
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
isCaseSensitive: options.isCaseSensitive,
|
|
1858
|
-
ignoreDiacritics: options.ignoreDiacritics,
|
|
1859
|
-
ignoreLocation: true
|
|
1860
|
-
}));
|
|
1861
|
-
const docFreq = df.get(term) || 0;
|
|
1862
|
-
const idf = Math.log(1 + (fieldCount - docFreq + 0.5) / (docFreq + 0.5));
|
|
1863
|
-
this.idfWeights.push(idf);
|
|
1864
|
-
}
|
|
1865
|
-
}
|
|
1866
|
-
searchIn(text) {
|
|
1867
|
-
if (!this.termSearchers.length) {
|
|
1868
|
-
return {
|
|
1869
|
-
isMatch: false,
|
|
1870
|
-
score: 1
|
|
1871
|
-
};
|
|
1872
|
-
}
|
|
1873
|
-
const allIndices = [];
|
|
1874
|
-
let weightedScore = 0;
|
|
1875
|
-
let maxPossibleScore = 0;
|
|
1876
|
-
let matchedCount = 0;
|
|
1877
|
-
for (let i = 0; i < this.termSearchers.length; i++) {
|
|
1878
|
-
const result = this.termSearchers[i].searchIn(text);
|
|
1879
|
-
const idf = this.idfWeights[i];
|
|
1880
|
-
maxPossibleScore += idf;
|
|
1881
|
-
if (result.isMatch) {
|
|
1882
|
-
matchedCount++;
|
|
1883
|
-
weightedScore += idf * (1 - result.score);
|
|
1884
|
-
if (result.indices) {
|
|
1885
|
-
allIndices.push(...result.indices);
|
|
1492
|
+
else {
|
|
1493
|
+
const { v: text, n: norm2 } = value;
|
|
1494
|
+
const searchResult = searcher.searchIn(text);
|
|
1495
|
+
if (searchResult.isMatch) {
|
|
1496
|
+
const match = {
|
|
1497
|
+
score: searchResult.score,
|
|
1498
|
+
key,
|
|
1499
|
+
value: text,
|
|
1500
|
+
norm: norm2,
|
|
1501
|
+
indices: searchResult.indices,
|
|
1502
|
+
hasInverse: searchResult.hasInverse
|
|
1503
|
+
};
|
|
1504
|
+
if (searchResult.termCount !== void 0) {
|
|
1505
|
+
match.matchedMask = searchResult.matchedMask;
|
|
1506
|
+
match.matchedTerms = searchResult.matchedTerms;
|
|
1507
|
+
match.termCount = searchResult.termCount;
|
|
1886
1508
|
}
|
|
1509
|
+
matches.push(match);
|
|
1887
1510
|
}
|
|
1888
1511
|
}
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1512
|
+
return matches;
|
|
1513
|
+
}
|
|
1514
|
+
_coversAllTokens(matches) {
|
|
1515
|
+
const termCount = matches.length ? matches[0].termCount : void 0;
|
|
1516
|
+
if (termCount === void 0) return true;
|
|
1517
|
+
if (termCount <= 31) {
|
|
1518
|
+
let coverage2 = 0;
|
|
1519
|
+
for (let i = 0; i < matches.length; i++) coverage2 |= matches[i].matchedMask || 0;
|
|
1520
|
+
return coverage2 === 2 ** termCount - 1;
|
|
1894
1521
|
}
|
|
1895
|
-
const
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
};
|
|
1900
|
-
if (this.options.includeMatches && allIndices.length) {
|
|
1901
|
-
searchResult.indices = mergeIndices(allIndices);
|
|
1522
|
+
const coverage = /* @__PURE__ */ new Set();
|
|
1523
|
+
for (let i = 0; i < matches.length; i++) {
|
|
1524
|
+
const terms = matches[i].matchedTerms;
|
|
1525
|
+
if (terms) for (const t of terms) coverage.add(t);
|
|
1902
1526
|
}
|
|
1903
|
-
return
|
|
1527
|
+
return coverage.size === termCount;
|
|
1904
1528
|
}
|
|
1905
|
-
}
|
|
1906
|
-
Fuse.version = "7.
|
|
1529
|
+
};
|
|
1530
|
+
Fuse.version = "7.5.0";
|
|
1907
1531
|
Fuse.createIndex = createIndex;
|
|
1908
1532
|
Fuse.parseIndex = parseIndex;
|
|
1909
1533
|
Fuse.config = Config;
|
|
1910
1534
|
Fuse.match = function(pattern, text, options) {
|
|
1911
|
-
|
|
1535
|
+
if (options && options.useTokenSearch) throw new Error(FUSE_MATCH_TOKEN_SEARCH_UNSUPPORTED);
|
|
1536
|
+
return createSearcher(pattern, {
|
|
1912
1537
|
...Config,
|
|
1913
1538
|
...options
|
|
1914
|
-
});
|
|
1915
|
-
return searcher.searchIn(text);
|
|
1539
|
+
}).searchIn(text);
|
|
1916
1540
|
};
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
{
|
|
1921
|
-
register(ExtendedSearch);
|
|
1922
|
-
}
|
|
1923
|
-
{
|
|
1924
|
-
register(TokenSearch);
|
|
1925
|
-
}
|
|
1541
|
+
Fuse.parseQuery = parse;
|
|
1542
|
+
register(ExtendedSearch);
|
|
1543
|
+
register(TokenSearch);
|
|
1926
1544
|
Fuse.use = function(...plugins) {
|
|
1927
1545
|
plugins.forEach((plugin) => register(plugin));
|
|
1928
1546
|
};
|
|
1547
|
+
var entry_default = Fuse;
|
|
1929
1548
|
const version = "0.3.5";
|
|
1930
1549
|
const packageJson = {
|
|
1931
1550
|
version
|
|
@@ -2090,7 +1709,7 @@
|
|
|
2090
1709
|
});
|
|
2091
1710
|
}
|
|
2092
1711
|
const search2 = (entities) => {
|
|
2093
|
-
const fuse = new
|
|
1712
|
+
const fuse = new entry_default(entities, {
|
|
2094
1713
|
shouldSort: false,
|
|
2095
1714
|
isCaseSensitive: false,
|
|
2096
1715
|
findAllMatches: true,
|