@oscarpalmer/atoms 0.218.0 → 0.220.0
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/array/filter.d.mts +38 -4
- package/dist/array/find.d.mts +34 -0
- package/dist/array/first.d.mts +40 -4
- package/dist/array/last.d.mts +46 -10
- package/dist/array/partition.d.mts +24 -8
- package/dist/array/reverse.d.mts +6 -0
- package/dist/array/reverse.mjs +6 -0
- package/dist/array/select.d.mts +97 -116
- package/dist/array/select.mjs +19 -15
- package/dist/array/single.d.mts +22 -0
- package/dist/array/single.mjs +1 -1
- package/dist/array/sort.d.mts +54 -0
- package/dist/color/space/hex.d.mts +8 -0
- package/dist/color/space/hex.mjs +8 -0
- package/dist/index.d.mts +764 -189
- package/dist/index.mjs +508 -207
- package/dist/internal/array/callbacks.mjs +1 -1
- package/dist/internal/array/find.d.mts +3 -3
- package/dist/internal/array/find.mjs +71 -52
- package/dist/internal/array/shuffle.d.mts +5 -0
- package/dist/internal/array/shuffle.mjs +5 -0
- package/dist/internal/math/aggregate.d.mts +69 -21
- package/dist/internal/math/misc.d.mts +14 -0
- package/dist/internal/math/misc.mjs +14 -0
- package/dist/internal/number.d.mts +18 -0
- package/dist/internal/number.mjs +18 -0
- package/dist/internal/string/case.d.mts +63 -0
- package/dist/internal/string/case.mjs +63 -0
- package/dist/internal/string/misc.d.mts +20 -0
- package/dist/internal/string/misc.mjs +20 -0
- package/dist/logger.d.mts +12 -0
- package/dist/logger.mjs +12 -0
- package/dist/math.d.mts +90 -0
- package/dist/math.mjs +7 -0
- package/dist/models/array/array.find.model.d.mts +26 -0
- package/dist/models/array/array.misc.model.d.mts +2 -4
- package/dist/models/index.d.mts +1 -1
- package/dist/models/string/string.fuzzy.model.d.mts +46 -18
- package/dist/models/string/string.fuzzy.model.mjs +3 -1
- package/dist/models/value/value.merge.model.d.mts +3 -3
- package/dist/promise/misc.d.mts +6 -0
- package/dist/promise/misc.mjs +6 -0
- package/dist/promise/timed.d.mts +3 -0
- package/dist/promise/timed.mjs +3 -0
- package/dist/queue.d.mts +0 -1
- package/dist/queue.mjs +1 -1
- package/dist/string/fuzzy.d.mts +3 -3
- package/dist/string/fuzzy.mjs +171 -97
- package/dist/string/index.d.mts +15 -1
- package/dist/string/index.mjs +15 -1
- package/dist/string/match.d.mts +24 -0
- package/dist/string/match.mjs +24 -0
- package/dist/string/template.d.mts +4 -0
- package/package.json +1 -1
package/dist/promise/misc.d.mts
CHANGED
|
@@ -11,7 +11,13 @@ import { isFulfilled, isRejected } from "./helpers.mjs";
|
|
|
11
11
|
* @returns Cancelable _Promise_
|
|
12
12
|
*/
|
|
13
13
|
export declare function cancelable<Value>(executor: (resolve: (value: Value) => void, reject: (reason: unknown) => void) => void): CancelablePromise<Value>;
|
|
14
|
+
/**
|
|
15
|
+
* @internal
|
|
16
|
+
*/
|
|
14
17
|
export declare function handleResult(status: string, parameters: PromiseParameters): void;
|
|
18
|
+
/**
|
|
19
|
+
* @internal
|
|
20
|
+
*/
|
|
15
21
|
export declare function settlePromise(settler: (value: any) => void, value: unknown, aborter?: Aborter): void;
|
|
16
22
|
/**
|
|
17
23
|
* Converts a _Promise_ to a promised result
|
package/dist/promise/misc.mjs
CHANGED
|
@@ -12,6 +12,9 @@ import { isFulfilled, isRejected } from "./helpers.mjs";
|
|
|
12
12
|
function cancelable(executor) {
|
|
13
13
|
return new CancelablePromise(executor);
|
|
14
14
|
}
|
|
15
|
+
/**
|
|
16
|
+
* @internal
|
|
17
|
+
*/
|
|
15
18
|
function handleResult(status, parameters) {
|
|
16
19
|
const { aborter, complete, data, handlers, index, key, value } = parameters;
|
|
17
20
|
if (aborter?.signal.aborted ?? false) return;
|
|
@@ -35,6 +38,9 @@ function handleResult(status, parameters) {
|
|
|
35
38
|
handlers.resolve(data.result);
|
|
36
39
|
}
|
|
37
40
|
}
|
|
41
|
+
/**
|
|
42
|
+
* @internal
|
|
43
|
+
*/
|
|
38
44
|
function settlePromise(settler, value, aborter) {
|
|
39
45
|
aborter?.cancel();
|
|
40
46
|
settler(value);
|
package/dist/promise/timed.d.mts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { RequiredKeys } from "../models/index.mjs";
|
|
2
2
|
import { PromiseOptions } from "../models/promise.model.mjs";
|
|
3
3
|
//#region src/promise/timed.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* @internal
|
|
6
|
+
*/
|
|
4
7
|
export declare function getTimedPromise<Value>(promise: Promise<Value>, time: number, signal?: AbortSignal): Promise<Value>;
|
|
5
8
|
/**
|
|
6
9
|
* Create a _Promise_ that should be settled within a certain amount of time
|
package/dist/promise/timed.mjs
CHANGED
|
@@ -5,6 +5,9 @@ import { PROMISE_MESSAGE_EXPECTATION_TIMED, PromiseTimeoutError } from "../model
|
|
|
5
5
|
import { createPromiseOptions } from "./helpers.mjs";
|
|
6
6
|
import { settlePromise } from "./misc.mjs";
|
|
7
7
|
//#region src/promise/timed.ts
|
|
8
|
+
/**
|
|
9
|
+
* @internal
|
|
10
|
+
*/
|
|
8
11
|
async function getTimedPromise(promise, time, signal) {
|
|
9
12
|
const aborter = createAborter(signal, () => {
|
|
10
13
|
limiter.cancel();
|
package/dist/queue.d.mts
CHANGED
|
@@ -17,7 +17,6 @@ export declare function isKeyedQueue(value: unknown): value is KeyedQueue<Generi
|
|
|
17
17
|
* @returns `true` if the value is a queue, otherwise `false`
|
|
18
18
|
*/
|
|
19
19
|
export declare function isQueue(value: unknown): value is Queue<GenericCallback | GenericAsyncCallback>;
|
|
20
|
-
export declare function isQueueInstance<Instance>(name: string, value: unknown): value is Instance;
|
|
21
20
|
/**
|
|
22
21
|
* Create a keyed queue for an asynchronous callback function, where each key has its own queue
|
|
23
22
|
*
|
package/dist/queue.mjs
CHANGED
package/dist/string/fuzzy.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { PlainObject } from "../models/index.mjs";
|
|
2
|
-
import { Fuzzy, FuzzyConfiguration,
|
|
2
|
+
import { Fuzzy, FuzzyConfiguration, FuzzyOptions, FuzzyResult, FuzzyState, InternalFuzzy } from "../models/string/string.fuzzy.model.mjs";
|
|
3
3
|
//#region src/string/fuzzy.d.ts
|
|
4
|
-
declare function Fuzzy(this:
|
|
4
|
+
declare function Fuzzy(this: InternalFuzzy, state: FuzzyState<unknown>): void;
|
|
5
5
|
/**
|
|
6
6
|
* Create a fuzzy searcher for an array of items
|
|
7
7
|
*
|
|
@@ -50,4 +50,4 @@ export declare namespace fuzzy {
|
|
|
50
50
|
export var match: typeof fuzzyMatch;
|
|
51
51
|
}
|
|
52
52
|
//#endregion
|
|
53
|
-
export type { Fuzzy,
|
|
53
|
+
export type { Fuzzy, FuzzyOptions, FuzzyResult };
|
package/dist/string/fuzzy.mjs
CHANGED
|
@@ -3,8 +3,7 @@ import { floor } from "../internal/math/misc.mjs";
|
|
|
3
3
|
import { max } from "../internal/math/aggregate.mjs";
|
|
4
4
|
import { getString } from "../internal/string/misc.mjs";
|
|
5
5
|
import { lowerCase } from "../internal/string/case.mjs";
|
|
6
|
-
import { FUZZY_MESSAGE_ARRAY, FUZZY_MESSAGE_HANDLER, FUZZY_PROPERTY, FUZZY_SYMBOL } from "../models/string/string.fuzzy.model.mjs";
|
|
7
|
-
import { includes } from "./match.mjs";
|
|
6
|
+
import { FUZZY_BOUNDARY_SEPARATOR, FUZZY_MESSAGE_ARRAY, FUZZY_MESSAGE_HANDLER, FUZZY_PROPERTY, FUZZY_SYMBOL } from "../models/string/string.fuzzy.model.mjs";
|
|
8
7
|
//#region src/string/fuzzy.ts
|
|
9
8
|
function Fuzzy(state) {
|
|
10
9
|
this[FUZZY_SYMBOL] = state;
|
|
@@ -14,39 +13,76 @@ Fuzzy.prototype.search = search;
|
|
|
14
13
|
Object.defineProperties(Fuzzy.prototype, {
|
|
15
14
|
items: {
|
|
16
15
|
enumerable: true,
|
|
17
|
-
get:
|
|
18
|
-
set:
|
|
16
|
+
get: getItems,
|
|
17
|
+
set: setItems
|
|
19
18
|
},
|
|
20
19
|
strings: {
|
|
21
20
|
enumerable: true,
|
|
22
|
-
get:
|
|
21
|
+
get: getStrings
|
|
23
22
|
}
|
|
24
23
|
});
|
|
25
|
-
function
|
|
26
|
-
return
|
|
24
|
+
function compareItem(sorter) {
|
|
25
|
+
return (first, second) => sorter(first.string.original, second.string.original);
|
|
27
26
|
}
|
|
28
|
-
function
|
|
29
|
-
|
|
30
|
-
|
|
27
|
+
function compareRanked(sorter) {
|
|
28
|
+
return (first, second) => first.rank - second.rank || first.position - second.position || sorter(first.string.original, second.string.original);
|
|
29
|
+
}
|
|
30
|
+
function createItems(state, items) {
|
|
31
|
+
state.items.original = items.map((item) => ({
|
|
32
|
+
data: item,
|
|
33
|
+
string: createString(state.handler(item))
|
|
34
|
+
}));
|
|
35
|
+
state.items.sorted = void 0;
|
|
36
|
+
}
|
|
37
|
+
function createOptions(input, state) {
|
|
38
|
+
const options = {};
|
|
39
|
+
const original = isPlainObject(input) ? input : {};
|
|
40
|
+
const limit = typeof input === "number" ? input : original.limit;
|
|
31
41
|
if (typeof limit === "number" && !Number.isNaN(limit) && limit >= 1) options.limit = floor(limit);
|
|
32
|
-
else options.limit = state?.limit;
|
|
33
|
-
options.tolerance = getTolerance(
|
|
42
|
+
else options.limit = state?.limit ?? Number.POSITIVE_INFINITY;
|
|
43
|
+
options.tolerance = getTolerance(original.tolerance, state);
|
|
34
44
|
return options;
|
|
35
45
|
}
|
|
36
|
-
function
|
|
37
|
-
|
|
38
|
-
|
|
46
|
+
function createRanked(item, needle, position) {
|
|
47
|
+
let boundary = position;
|
|
48
|
+
while (boundary > -1 && !isBoundary(item.string, boundary)) boundary = item.string.lowercase.indexOf(needle, boundary + 1);
|
|
49
|
+
if (boundary === -1) return {
|
|
50
|
+
...item,
|
|
51
|
+
position,
|
|
52
|
+
rank: 2
|
|
53
|
+
};
|
|
39
54
|
return {
|
|
55
|
+
...item,
|
|
56
|
+
position: boundary,
|
|
57
|
+
rank: boundary === 0 ? 0 : 1
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
function createState(items, input) {
|
|
61
|
+
const handler = getHandler(input);
|
|
62
|
+
const options = createOptions(input);
|
|
63
|
+
const sorter = getComparator(input);
|
|
64
|
+
const state = {
|
|
65
|
+
compare: {
|
|
66
|
+
item: compareItem(sorter),
|
|
67
|
+
ranked: compareRanked(sorter)
|
|
68
|
+
},
|
|
40
69
|
handler,
|
|
41
|
-
items:
|
|
70
|
+
items: { original: [] },
|
|
42
71
|
limit: options.limit,
|
|
43
|
-
strings: items.map(handler),
|
|
44
72
|
tolerance: options.tolerance
|
|
45
73
|
};
|
|
74
|
+
createItems(state, items);
|
|
75
|
+
return state;
|
|
76
|
+
}
|
|
77
|
+
function createString(original) {
|
|
78
|
+
return {
|
|
79
|
+
original,
|
|
80
|
+
lowercase: lowerCase(original)
|
|
81
|
+
};
|
|
46
82
|
}
|
|
47
83
|
function fuzzy(items, configuration) {
|
|
48
84
|
if (!Array.isArray(items)) throw new TypeError(FUZZY_MESSAGE_ARRAY);
|
|
49
|
-
return new Fuzzy(
|
|
85
|
+
return new Fuzzy(createState(items, configuration));
|
|
50
86
|
}
|
|
51
87
|
/**
|
|
52
88
|
* Does the needle match the haystack in a fuzzy way?
|
|
@@ -60,53 +96,117 @@ function fuzzy(items, configuration) {
|
|
|
60
96
|
function fuzzyMatch(haystack, needle) {
|
|
61
97
|
if (typeof haystack !== "string" || typeof needle !== "string") return false;
|
|
62
98
|
const trimmed = needle.trim();
|
|
63
|
-
|
|
64
|
-
|
|
99
|
+
const lowercaseHaystack = lowerCase(haystack);
|
|
100
|
+
const lowercaseNeedle = lowerCase(trimmed);
|
|
101
|
+
if (lowercaseHaystack.includes(lowercaseNeedle)) return true;
|
|
102
|
+
return getScore({
|
|
103
|
+
lowercase: lowercaseHaystack,
|
|
104
|
+
original: haystack
|
|
105
|
+
}, lowercaseNeedle) > -1;
|
|
106
|
+
}
|
|
107
|
+
function getComparator(input) {
|
|
108
|
+
if (isPlainObject(input) && typeof input.compare === "function") return input.compare;
|
|
109
|
+
defaultSorter ??= Intl.Collator().compare;
|
|
110
|
+
return defaultSorter;
|
|
65
111
|
}
|
|
66
112
|
function getHandler(input) {
|
|
67
113
|
if (input == null || input === getString) return getString;
|
|
68
114
|
switch (typeof input) {
|
|
69
|
-
case "function": return input;
|
|
70
|
-
case "
|
|
115
|
+
case "function": return (item) => getString(input(item));
|
|
116
|
+
case "number":
|
|
117
|
+
case "string":
|
|
118
|
+
case "symbol": return (item) => getString(item?.[input]);
|
|
71
119
|
default:
|
|
72
120
|
if (isPlainObject(input)) return getHandler(input.key ?? input.handler);
|
|
73
121
|
throw new TypeError(FUZZY_MESSAGE_HANDLER);
|
|
74
122
|
}
|
|
75
123
|
}
|
|
76
|
-
function
|
|
77
|
-
return this[FUZZY_SYMBOL].items.
|
|
78
|
-
}
|
|
79
|
-
function getFuzzyStrings() {
|
|
80
|
-
return this[FUZZY_SYMBOL].strings.slice();
|
|
124
|
+
function getItems() {
|
|
125
|
+
return this[FUZZY_SYMBOL].items.original.map((item) => item.data);
|
|
81
126
|
}
|
|
82
|
-
function
|
|
83
|
-
|
|
84
|
-
const
|
|
85
|
-
const lowerCaseNeedle = lowerCase(needle);
|
|
86
|
-
const needleLength = lowerCaseNeedle.length;
|
|
127
|
+
function getMatchEnd(haystack, needle, cursor) {
|
|
128
|
+
const haystackLength = haystack.length;
|
|
129
|
+
const needleLength = needle.length;
|
|
87
130
|
let needleIndex = 0;
|
|
88
|
-
let
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
131
|
+
for (let index = cursor; index < haystackLength; index += 1) if (haystack[index] === needle[needleIndex]) {
|
|
132
|
+
needleIndex += 1;
|
|
133
|
+
if (needleIndex === needleLength) return index;
|
|
134
|
+
}
|
|
135
|
+
return -1;
|
|
136
|
+
}
|
|
137
|
+
function getResult(state, exact, included, scored, options) {
|
|
138
|
+
const result = {
|
|
139
|
+
exact: [],
|
|
140
|
+
included: [],
|
|
141
|
+
similar: []
|
|
142
|
+
};
|
|
143
|
+
exact.sort(state.compare.item);
|
|
144
|
+
result.exact = exact.slice(0, options.limit).map((item) => item.data);
|
|
145
|
+
included.sort(state.compare.ranked);
|
|
146
|
+
result.included = included.slice(0, options.limit - result.exact.length).map((item) => item.data);
|
|
147
|
+
const remaining = options.limit - result.exact.length - result.included.length;
|
|
148
|
+
if (remaining === 0) return result;
|
|
149
|
+
const keys = Object.keys(scored).map(Number).sort((first, second) => second - first);
|
|
150
|
+
const keysLength = keys.length;
|
|
151
|
+
if (keysLength === 0) return result;
|
|
152
|
+
const maxScore = keys[0];
|
|
153
|
+
outer: for (let index = 0; index < keysLength; index += 1) {
|
|
154
|
+
const key = keys[index];
|
|
155
|
+
if (maxScore - key > options.tolerance) break;
|
|
156
|
+
const keyed = scored[key];
|
|
157
|
+
const keyedLength = keyed.length;
|
|
158
|
+
keyed.sort(state.compare.item);
|
|
159
|
+
for (let keyedIndex = 0; keyedIndex < keyedLength; keyedIndex += 1) {
|
|
160
|
+
result.similar.push(keyed[keyedIndex].data);
|
|
161
|
+
if (result.similar.length >= remaining) break outer;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return result;
|
|
165
|
+
}
|
|
166
|
+
function getScore(item, needle) {
|
|
167
|
+
const haystackLength = item.lowercase.length;
|
|
168
|
+
const needleLength = needle.length;
|
|
169
|
+
if (needleLength > haystackLength) return -1;
|
|
170
|
+
let best = -1;
|
|
171
|
+
let cursor = 0;
|
|
172
|
+
while (cursor < haystackLength) {
|
|
173
|
+
const end = getMatchEnd(item.lowercase, needle, cursor);
|
|
174
|
+
if (end === -1) break;
|
|
175
|
+
let index = end;
|
|
176
|
+
let needleIndex = needleLength - 1;
|
|
177
|
+
let next = -1;
|
|
178
|
+
let score = 0;
|
|
179
|
+
let start = end;
|
|
180
|
+
while (needleIndex >= 0) {
|
|
181
|
+
if (item.lowercase[index] === needle[needleIndex]) {
|
|
182
|
+
score += 1;
|
|
183
|
+
if (next !== -1) score += max([0, 5 - (next - index - 1)]);
|
|
184
|
+
if (isBoundary(item, index)) score += 2;
|
|
185
|
+
next = index;
|
|
186
|
+
start = index;
|
|
187
|
+
needleIndex -= 1;
|
|
97
188
|
}
|
|
98
|
-
|
|
99
|
-
needleIndex += 1;
|
|
189
|
+
index -= 1;
|
|
100
190
|
}
|
|
101
|
-
if (
|
|
191
|
+
if (start === 0) score += 1;
|
|
192
|
+
if (score > best) best = score;
|
|
193
|
+
cursor = start + 1;
|
|
102
194
|
}
|
|
103
|
-
|
|
104
|
-
return max([0,
|
|
195
|
+
if (best === -1) return -1;
|
|
196
|
+
return max([0, best - floor(haystackLength / 3)]);
|
|
197
|
+
}
|
|
198
|
+
function getStrings() {
|
|
199
|
+
return this[FUZZY_SYMBOL].items.original.map((item) => item.string.original);
|
|
105
200
|
}
|
|
106
201
|
function getTolerance(input, state) {
|
|
107
202
|
if (typeof input === "number" && !Number.isNaN(input)) return input < 0 ? 0 : floor(input);
|
|
108
203
|
return state?.tolerance ?? 5;
|
|
109
204
|
}
|
|
205
|
+
function isBoundary(string, index) {
|
|
206
|
+
if (index === 0 || FUZZY_BOUNDARY_SEPARATOR.test(string.lowercase[index - 1])) return true;
|
|
207
|
+
if (string.original.length !== string.lowercase.length) return false;
|
|
208
|
+
return string.original[index] !== string.lowercase[index] && string.original[index - 1] === string.lowercase[index - 1];
|
|
209
|
+
}
|
|
110
210
|
/**
|
|
111
211
|
* Is the value a fuzzy searcher?
|
|
112
212
|
*
|
|
@@ -118,74 +218,48 @@ function getTolerance(input, state) {
|
|
|
118
218
|
function isFuzzy(value) {
|
|
119
219
|
return typeof value === "object" && value !== null && "$fuzzy" in value && value["$fuzzy"] === true;
|
|
120
220
|
}
|
|
121
|
-
function isSubsequence(haystack, needle) {
|
|
122
|
-
const lowerCaseHaystack = lowerCase(haystack);
|
|
123
|
-
const lowerCaseNeedle = lowerCase(needle);
|
|
124
|
-
const haystackLength = lowerCaseHaystack.length;
|
|
125
|
-
const needleLength = lowerCaseNeedle.length;
|
|
126
|
-
let needleIndex = 0;
|
|
127
|
-
for (let haystackIndex = 0; haystackIndex < haystackLength; haystackIndex += 1) {
|
|
128
|
-
if (lowerCaseHaystack[haystackIndex] === lowerCaseNeedle[needleIndex]) needleIndex += 1;
|
|
129
|
-
if (needleIndex === needleLength) return true;
|
|
130
|
-
}
|
|
131
|
-
return false;
|
|
132
|
-
}
|
|
133
221
|
function search(input, option) {
|
|
134
222
|
const state = this[FUZZY_SYMBOL];
|
|
135
|
-
const options = option == null ? state :
|
|
136
|
-
const result = {
|
|
137
|
-
exact: [],
|
|
138
|
-
similar: []
|
|
139
|
-
};
|
|
223
|
+
const options = option == null ? state : createOptions(option, state);
|
|
140
224
|
const value = typeof input === "string" ? input.trim() : "";
|
|
225
|
+
const lowercaseValue = lowerCase(value);
|
|
141
226
|
if (value.length === 0) {
|
|
142
|
-
|
|
143
|
-
return
|
|
227
|
+
state.items.sorted ??= state.items.original.toSorted(state.compare.item);
|
|
228
|
+
return {
|
|
229
|
+
exact: state.items.sorted.slice(0, options.limit).map((item) => item.data),
|
|
230
|
+
included: [],
|
|
231
|
+
similar: []
|
|
232
|
+
};
|
|
144
233
|
}
|
|
145
|
-
let { length } = state.items;
|
|
146
234
|
const exact = [];
|
|
147
|
-
const
|
|
235
|
+
const included = [];
|
|
148
236
|
const scored = {};
|
|
237
|
+
const { length } = state.items.original;
|
|
149
238
|
for (let index = 0; index < length; index += 1) {
|
|
150
|
-
const item = state.items[index];
|
|
151
|
-
const
|
|
152
|
-
if (
|
|
153
|
-
exact.push(
|
|
154
|
-
item,
|
|
155
|
-
haystack
|
|
156
|
-
});
|
|
239
|
+
const item = state.items.original[index];
|
|
240
|
+
const { string } = item;
|
|
241
|
+
if (string.lowercase === lowercaseValue) {
|
|
242
|
+
exact.push(item);
|
|
157
243
|
continue;
|
|
158
244
|
}
|
|
159
|
-
const
|
|
245
|
+
const position = string.lowercase.indexOf(lowercaseValue);
|
|
246
|
+
if (position > -1) {
|
|
247
|
+
included.push(createRanked(item, lowercaseValue, position));
|
|
248
|
+
continue;
|
|
249
|
+
}
|
|
250
|
+
const score = getScore(string, lowercaseValue);
|
|
160
251
|
if (score > -1) {
|
|
161
252
|
scored[score] ??= [];
|
|
162
|
-
scored[score].push(
|
|
163
|
-
item,
|
|
164
|
-
haystack
|
|
165
|
-
});
|
|
253
|
+
scored[score].push(item);
|
|
166
254
|
}
|
|
167
255
|
}
|
|
168
|
-
|
|
169
|
-
length = keys.length;
|
|
170
|
-
if (length > 0 && options.tolerance > 0) {
|
|
171
|
-
const maxScore = keys[0];
|
|
172
|
-
for (let index = 0; index < length; index += 1) {
|
|
173
|
-
const key = keys[index];
|
|
174
|
-
if (maxScore - key > options.tolerance) break;
|
|
175
|
-
similar.push(...createFuzzyItems(scored[key]));
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
result.exact = createFuzzyItems(options.limit == null ? exact : exact.slice(0, options.limit));
|
|
179
|
-
if (options.limit == null) result.similar = similar;
|
|
180
|
-
else result.similar = similar.slice(0, options.limit - result.exact.length);
|
|
181
|
-
return result;
|
|
256
|
+
return getResult(state, exact, included, scored, options);
|
|
182
257
|
}
|
|
183
|
-
function
|
|
258
|
+
function setItems(value) {
|
|
184
259
|
if (!Array.isArray(value)) throw new TypeError(FUZZY_MESSAGE_ARRAY);
|
|
185
|
-
|
|
186
|
-
state.items = value.slice();
|
|
187
|
-
state.strings = value.map((item) => state.handler(item));
|
|
260
|
+
createItems(this[FUZZY_SYMBOL], value);
|
|
188
261
|
}
|
|
262
|
+
let defaultSorter;
|
|
189
263
|
fuzzy.is = isFuzzy;
|
|
190
264
|
fuzzy.match = fuzzyMatch;
|
|
191
265
|
//#endregion
|
package/dist/string/index.d.mts
CHANGED
|
@@ -31,7 +31,7 @@ export declare function getUuid(): string;
|
|
|
31
31
|
*
|
|
32
32
|
* @param value JSON string to parse
|
|
33
33
|
* @param reviver Reviver function to transform the parsed values
|
|
34
|
-
* @returns Parsed value or `undefined` if parsing fails
|
|
34
|
+
* @returns Parsed value, or `undefined` if parsing fails
|
|
35
35
|
*/
|
|
36
36
|
export declare function parse(value: string, reviver?: (this: unknown, key: string, value: unknown) => unknown): unknown;
|
|
37
37
|
/**
|
|
@@ -39,6 +39,13 @@ export declare function parse(value: string, reviver?: (this: unknown, key: stri
|
|
|
39
39
|
*
|
|
40
40
|
* @param value String to trim
|
|
41
41
|
* @returns Trimmed string
|
|
42
|
+
* @example
|
|
43
|
+
* ```typescript
|
|
44
|
+
* trim(' this is a test '); // => 'this is a test'
|
|
45
|
+
* trim('this is a test'); // => 'this is a test'
|
|
46
|
+
* trim(' '); // => ''
|
|
47
|
+
* trim(''); // => ''
|
|
48
|
+
* ```
|
|
42
49
|
*/
|
|
43
50
|
export declare function trim(value: string): string;
|
|
44
51
|
/**
|
|
@@ -48,6 +55,13 @@ export declare function trim(value: string): string;
|
|
|
48
55
|
* @param length Maximum length of the string after truncation
|
|
49
56
|
* @param suffix Suffix to append to the truncated string
|
|
50
57
|
* @returns Truncated string
|
|
58
|
+
* @example
|
|
59
|
+
* ```typescript
|
|
60
|
+
* truncate('this is a test', 7); // => 'this is'
|
|
61
|
+
* truncate('this is a test', 7, '...'); // => 'this ...'
|
|
62
|
+
* truncate('this is a test', 20); // => 'this is a test'
|
|
63
|
+
* truncate('this is a test', 0); // => ''
|
|
64
|
+
* ```
|
|
51
65
|
*/
|
|
52
66
|
export declare function truncate(value: string, length: number, suffix?: string): string;
|
|
53
67
|
//#endregion
|
package/dist/string/index.mjs
CHANGED
|
@@ -57,7 +57,7 @@ function getUuid(html) {
|
|
|
57
57
|
*
|
|
58
58
|
* @param value JSON string to parse
|
|
59
59
|
* @param reviver Reviver function to transform the parsed values
|
|
60
|
-
* @returns Parsed value or `undefined` if parsing fails
|
|
60
|
+
* @returns Parsed value, or `undefined` if parsing fails
|
|
61
61
|
*/
|
|
62
62
|
function parse(value, reviver) {
|
|
63
63
|
try {
|
|
@@ -71,6 +71,13 @@ function parse(value, reviver) {
|
|
|
71
71
|
*
|
|
72
72
|
* @param value String to trim
|
|
73
73
|
* @returns Trimmed string
|
|
74
|
+
* @example
|
|
75
|
+
* ```typescript
|
|
76
|
+
* trim(' this is a test '); // => 'this is a test'
|
|
77
|
+
* trim('this is a test'); // => 'this is a test'
|
|
78
|
+
* trim(' '); // => ''
|
|
79
|
+
* trim(''); // => ''
|
|
80
|
+
* ```
|
|
74
81
|
*/
|
|
75
82
|
function trim(value) {
|
|
76
83
|
return typeof value === "string" ? value.trim() : "";
|
|
@@ -82,6 +89,13 @@ function trim(value) {
|
|
|
82
89
|
* @param length Maximum length of the string after truncation
|
|
83
90
|
* @param suffix Suffix to append to the truncated string
|
|
84
91
|
* @returns Truncated string
|
|
92
|
+
* @example
|
|
93
|
+
* ```typescript
|
|
94
|
+
* truncate('this is a test', 7); // => 'this is'
|
|
95
|
+
* truncate('this is a test', 7, '...'); // => 'this ...'
|
|
96
|
+
* truncate('this is a test', 20); // => 'this is a test'
|
|
97
|
+
* truncate('this is a test', 0); // => ''
|
|
98
|
+
* ```
|
|
85
99
|
*/
|
|
86
100
|
function truncate(value, length, suffix) {
|
|
87
101
|
if (typeof value !== "string" || typeof length !== "number" || length === 0) return "";
|
package/dist/string/match.d.mts
CHANGED
|
@@ -6,6 +6,14 @@
|
|
|
6
6
|
* @param needle String to look for
|
|
7
7
|
* @param ignoreCase Ignore case when matching? _(defaults to `false`)_
|
|
8
8
|
* @returns `true` if the string ends with the given substring, otherwise `false`
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* endsWith('this is a test', 'test'); // => true
|
|
13
|
+
* endsWith('this is a test', 'Test'); // => false
|
|
14
|
+
* endsWith('this is a test', 'Test', true); // => true
|
|
15
|
+
* endsWith('this is a test', 'not'); // => false
|
|
16
|
+
* ```
|
|
9
17
|
*/
|
|
10
18
|
export declare function endsWith(haystack: string, needle: string, ignoreCase?: boolean): boolean;
|
|
11
19
|
/**
|
|
@@ -15,6 +23,14 @@ export declare function endsWith(haystack: string, needle: string, ignoreCase?:
|
|
|
15
23
|
* @param needle String to look for
|
|
16
24
|
* @param ignoreCase Ignore case when matching? _(defaults to `false`)_
|
|
17
25
|
* @returns `true` if the string includes the given substring, otherwise `false`
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```typescript
|
|
29
|
+
* includes('this is a test', 'is'); // => true
|
|
30
|
+
* includes('this is a test', 'Is'); // => false
|
|
31
|
+
* includes('this is a test', 'Is', true); // => true
|
|
32
|
+
* includes('this is a test', 'not'); // => false
|
|
33
|
+
* ```
|
|
18
34
|
*/
|
|
19
35
|
export declare function includes(haystack: string, needle: string, ignoreCase?: boolean): boolean;
|
|
20
36
|
/**
|
|
@@ -24,6 +40,14 @@ export declare function includes(haystack: string, needle: string, ignoreCase?:
|
|
|
24
40
|
* @param needle String to look for
|
|
25
41
|
* @param ignoreCase Ignore case when matching? _(defaults to `false`)_
|
|
26
42
|
* @returns `true` if the string starts with the given substring, otherwise `false`
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```typescript
|
|
46
|
+
* startsWith('this is a test', 'this'); // => true
|
|
47
|
+
* startsWith('this is a test', 'This'); // => false
|
|
48
|
+
* startsWith('this is a test', 'This', true); // => true
|
|
49
|
+
* startsWith('this is a test', 'not'); // => false
|
|
50
|
+
* ```
|
|
27
51
|
*/
|
|
28
52
|
export declare function startsWith(haystack: string, needle: string, ignoreCase?: boolean): boolean;
|
|
29
53
|
//#endregion
|
package/dist/string/match.mjs
CHANGED
|
@@ -8,6 +8,14 @@ import { memoize } from "../internal/function/memoize.mjs";
|
|
|
8
8
|
* @param needle String to look for
|
|
9
9
|
* @param ignoreCase Ignore case when matching? _(defaults to `false`)_
|
|
10
10
|
* @returns `true` if the string ends with the given substring, otherwise `false`
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* endsWith('this is a test', 'test'); // => true
|
|
15
|
+
* endsWith('this is a test', 'Test'); // => false
|
|
16
|
+
* endsWith('this is a test', 'Test', true); // => true
|
|
17
|
+
* endsWith('this is a test', 'not'); // => false
|
|
18
|
+
* ```
|
|
11
19
|
*/
|
|
12
20
|
function endsWith(haystack, needle, ignoreCase) {
|
|
13
21
|
return match(STRING_MATCH_ENDS_WITH, haystack, needle, ignoreCase === true);
|
|
@@ -19,6 +27,14 @@ function endsWith(haystack, needle, ignoreCase) {
|
|
|
19
27
|
* @param needle String to look for
|
|
20
28
|
* @param ignoreCase Ignore case when matching? _(defaults to `false`)_
|
|
21
29
|
* @returns `true` if the string includes the given substring, otherwise `false`
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```typescript
|
|
33
|
+
* includes('this is a test', 'is'); // => true
|
|
34
|
+
* includes('this is a test', 'Is'); // => false
|
|
35
|
+
* includes('this is a test', 'Is', true); // => true
|
|
36
|
+
* includes('this is a test', 'not'); // => false
|
|
37
|
+
* ```
|
|
22
38
|
*/
|
|
23
39
|
function includes(haystack, needle, ignoreCase) {
|
|
24
40
|
return match(STRING_MATCH_INCLUDES, haystack, needle, ignoreCase === true);
|
|
@@ -38,6 +54,14 @@ function matchCallback(haystack, needle, ignoreCase) {
|
|
|
38
54
|
* @param needle String to look for
|
|
39
55
|
* @param ignoreCase Ignore case when matching? _(defaults to `false`)_
|
|
40
56
|
* @returns `true` if the string starts with the given substring, otherwise `false`
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```typescript
|
|
60
|
+
* startsWith('this is a test', 'this'); // => true
|
|
61
|
+
* startsWith('this is a test', 'This'); // => false
|
|
62
|
+
* startsWith('this is a test', 'This', true); // => true
|
|
63
|
+
* startsWith('this is a test', 'not'); // => false
|
|
64
|
+
* ```
|
|
41
65
|
*/
|
|
42
66
|
function startsWith(haystack, needle, ignoreCase) {
|
|
43
67
|
return match(STRING_MATCH_STARTS_WITH, haystack, needle, ignoreCase === true);
|
|
@@ -24,6 +24,10 @@ export declare function template(strings: TemplateStringsArray, ...values: unkno
|
|
|
24
24
|
* @param variables Variables to use
|
|
25
25
|
* @param options Templating options
|
|
26
26
|
* @returns Templated string
|
|
27
|
+
* @example
|
|
28
|
+
* ```typescript
|
|
29
|
+
* template('Hello, {{name}}!', {name: 'World'}); // => 'Hello, World!'
|
|
30
|
+
* ```
|
|
27
31
|
*/
|
|
28
32
|
export declare function template(value: string, variables?: PlainObject, options?: Partial<TemplateOptions>): string;
|
|
29
33
|
export declare namespace template {
|