@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.
Files changed (54) hide show
  1. package/dist/array/filter.d.mts +38 -4
  2. package/dist/array/find.d.mts +34 -0
  3. package/dist/array/first.d.mts +40 -4
  4. package/dist/array/last.d.mts +46 -10
  5. package/dist/array/partition.d.mts +24 -8
  6. package/dist/array/reverse.d.mts +6 -0
  7. package/dist/array/reverse.mjs +6 -0
  8. package/dist/array/select.d.mts +97 -116
  9. package/dist/array/select.mjs +19 -15
  10. package/dist/array/single.d.mts +22 -0
  11. package/dist/array/single.mjs +1 -1
  12. package/dist/array/sort.d.mts +54 -0
  13. package/dist/color/space/hex.d.mts +8 -0
  14. package/dist/color/space/hex.mjs +8 -0
  15. package/dist/index.d.mts +764 -189
  16. package/dist/index.mjs +508 -207
  17. package/dist/internal/array/callbacks.mjs +1 -1
  18. package/dist/internal/array/find.d.mts +3 -3
  19. package/dist/internal/array/find.mjs +71 -52
  20. package/dist/internal/array/shuffle.d.mts +5 -0
  21. package/dist/internal/array/shuffle.mjs +5 -0
  22. package/dist/internal/math/aggregate.d.mts +69 -21
  23. package/dist/internal/math/misc.d.mts +14 -0
  24. package/dist/internal/math/misc.mjs +14 -0
  25. package/dist/internal/number.d.mts +18 -0
  26. package/dist/internal/number.mjs +18 -0
  27. package/dist/internal/string/case.d.mts +63 -0
  28. package/dist/internal/string/case.mjs +63 -0
  29. package/dist/internal/string/misc.d.mts +20 -0
  30. package/dist/internal/string/misc.mjs +20 -0
  31. package/dist/logger.d.mts +12 -0
  32. package/dist/logger.mjs +12 -0
  33. package/dist/math.d.mts +90 -0
  34. package/dist/math.mjs +7 -0
  35. package/dist/models/array/array.find.model.d.mts +26 -0
  36. package/dist/models/array/array.misc.model.d.mts +2 -4
  37. package/dist/models/index.d.mts +1 -1
  38. package/dist/models/string/string.fuzzy.model.d.mts +46 -18
  39. package/dist/models/string/string.fuzzy.model.mjs +3 -1
  40. package/dist/models/value/value.merge.model.d.mts +3 -3
  41. package/dist/promise/misc.d.mts +6 -0
  42. package/dist/promise/misc.mjs +6 -0
  43. package/dist/promise/timed.d.mts +3 -0
  44. package/dist/promise/timed.mjs +3 -0
  45. package/dist/queue.d.mts +0 -1
  46. package/dist/queue.mjs +1 -1
  47. package/dist/string/fuzzy.d.mts +3 -3
  48. package/dist/string/fuzzy.mjs +171 -97
  49. package/dist/string/index.d.mts +15 -1
  50. package/dist/string/index.mjs +15 -1
  51. package/dist/string/match.d.mts +24 -0
  52. package/dist/string/match.mjs +24 -0
  53. package/dist/string/template.d.mts +4 -0
  54. package/package.json +1 -1
@@ -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
@@ -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);
@@ -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
@@ -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
@@ -360,4 +360,4 @@ async function run(state) {
360
360
  }
361
361
  queue.keyed = keyedQueue;
362
362
  //#endregion
363
- export { isKeyedQueue, isQueue, isQueueInstance, keyedQueue, queue };
363
+ export { isKeyedQueue, isQueue, keyedQueue, queue };
@@ -1,7 +1,7 @@
1
1
  import { PlainObject } from "../models/index.mjs";
2
- import { Fuzzy, FuzzyConfiguration, FuzzyItem, FuzzyOptions, FuzzyResult, FuzzyState } from "../models/string/string.fuzzy.model.mjs";
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: any, state: FuzzyState<unknown>): void;
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, FuzzyItem, FuzzyOptions, FuzzyResult };
53
+ export type { Fuzzy, FuzzyOptions, FuzzyResult };
@@ -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: getFuzzyItems,
18
- set: setFuzzyItems
16
+ get: getItems,
17
+ set: setItems
19
18
  },
20
19
  strings: {
21
20
  enumerable: true,
22
- get: getFuzzyStrings
21
+ get: getStrings
23
22
  }
24
23
  });
25
- function createFuzzyItems(items) {
26
- return items.toSorted((first, second) => first.haystack.localeCompare(second.haystack)).map(({ item }) => item);
24
+ function compareItem(sorter) {
25
+ return (first, second) => sorter(first.string.original, second.string.original);
27
26
  }
28
- function createFuzzyOptions(input, state) {
29
- const options = isPlainObject(input) ? input : {};
30
- const limit = typeof input === "number" ? input : options.limit;
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(options.tolerance, state);
42
+ else options.limit = state?.limit ?? Number.POSITIVE_INFINITY;
43
+ options.tolerance = getTolerance(original.tolerance, state);
34
44
  return options;
35
45
  }
36
- function createFuzzyState(items, input) {
37
- const handler = getHandler(input);
38
- const options = createFuzzyOptions(input);
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: items.slice(),
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(createFuzzyState(items, configuration));
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
- if (includes(haystack, trimmed, true)) return true;
64
- return getScore(haystack, trimmed) > -1;
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 "string": return (item) => item[input];
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 getFuzzyItems() {
77
- return this[FUZZY_SYMBOL].items.slice();
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 getScore(haystack, needle) {
83
- if (!isSubsequence(haystack, needle)) return -1;
84
- const lowerCaseHaystack = lowerCase(haystack);
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 previousMatchIndex = -1;
89
- let score = 0;
90
- for (let haystackIndex = 0; haystackIndex < lowerCaseHaystack.length; haystackIndex += 1) {
91
- if (lowerCaseHaystack[haystackIndex] === lowerCaseNeedle[needleIndex]) {
92
- score += 1;
93
- if (haystackIndex === 0) score += 1;
94
- if (previousMatchIndex !== -1) {
95
- const gap = haystackIndex - previousMatchIndex - 1;
96
- score += max([0, 5 - gap]);
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
- previousMatchIndex = haystackIndex;
99
- needleIndex += 1;
189
+ index -= 1;
100
190
  }
101
- if (needleIndex === needleLength) break;
191
+ if (start === 0) score += 1;
192
+ if (score > best) best = score;
193
+ cursor = start + 1;
102
194
  }
103
- score -= floor(lowerCaseHaystack.length / 3);
104
- return max([0, score]);
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 : createFuzzyOptions(option, 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
- result.exact = state.items.slice(0, options.limit);
143
- return result;
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 similar = [];
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 haystack = state.strings[index];
152
- if (includes(haystack, value, true)) {
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 score = getScore(haystack, value);
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
- const keys = Object.keys(scored).map(Number).sort((first, second) => second - first);
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 setFuzzyItems(value) {
258
+ function setItems(value) {
184
259
  if (!Array.isArray(value)) throw new TypeError(FUZZY_MESSAGE_ARRAY);
185
- const state = this[FUZZY_SYMBOL];
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
@@ -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
@@ -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 "";
@@ -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
@@ -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 {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oscarpalmer/atoms",
3
- "version": "0.218.0",
3
+ "version": "0.220.0",
4
4
  "description": "Atomic utilities for making your JavaScript better.",
5
5
  "keywords": [
6
6
  "array",