complete-common 2.29.0 → 2.31.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/functions/array.d.ts.map +1 -1
- package/dist/functions/assert.d.cts +4 -2
- package/dist/functions/assert.d.mts +4 -2
- package/dist/functions/assert.d.ts +4 -2
- package/dist/functions/assert.d.ts.map +1 -1
- package/dist/functions/enums.d.cts +2 -2
- package/dist/functions/enums.d.mts +2 -2
- package/dist/functions/enums.d.ts +2 -2
- package/dist/functions/set.d.cts +1 -1
- package/dist/functions/set.d.mts +1 -1
- package/dist/functions/set.d.ts +1 -1
- package/dist/functions/set.d.ts.map +1 -1
- package/dist/functions/sort.d.ts.map +1 -1
- package/dist/functions/string.d.ts.map +1 -1
- package/dist/functions/time.d.cts +1 -1
- package/dist/functions/time.d.mts +1 -1
- package/dist/functions/time.d.ts +1 -1
- package/dist/functions/time.d.ts.map +1 -1
- package/dist/functions/tuple.d.cts +2 -2
- package/dist/functions/tuple.d.mts +2 -2
- package/dist/functions/tuple.d.ts +2 -2
- package/dist/functions/types.d.cts +1 -1
- package/dist/functions/types.d.mts +1 -1
- package/dist/functions/types.d.ts +1 -1
- package/dist/functions/utils.d.cts +2 -4
- package/dist/functions/utils.d.mts +2 -4
- package/dist/functions/utils.d.ts +2 -4
- package/dist/functions/utils.d.ts.map +1 -1
- package/dist/index.cjs +44 -44
- package/dist/index.mjs +44 -45
- package/package.json +4 -4
- package/src/functions/array.ts +2 -8
- package/src/functions/assert.ts +16 -4
- package/src/functions/enums.ts +2 -2
- package/src/functions/object.ts +1 -1
- package/src/functions/set.ts +2 -7
- package/src/functions/sort.ts +1 -3
- package/src/functions/string.ts +28 -23
- package/src/functions/time.ts +5 -2
- package/src/functions/tuple.ts +2 -2
- package/src/functions/types.ts +1 -1
- package/src/functions/utils.ts +13 -11
package/src/functions/string.ts
CHANGED
|
@@ -14,25 +14,25 @@ import { parseIntSafe } from "./utils.js";
|
|
|
14
14
|
// they will return inconsistent results due to the `lastIndex` property persisting between calls.
|
|
15
15
|
|
|
16
16
|
/** We use a "*" instead of a "+" so that an empty string will match. */
|
|
17
|
-
|
|
18
|
-
const ASCII_REGEX = /^[\u0000-\u007F]*$/;
|
|
17
|
+
const ASCII_REGEX = /^\p{ASCII}*$/v;
|
|
19
18
|
|
|
20
|
-
const DIACRITIC_REGEX = /\p{Diacritic}/
|
|
19
|
+
const DIACRITIC_REGEX = /\p{Diacritic}/v;
|
|
20
|
+
const FIRST_LETTER_CAPITALIZED_REGEX = /^\p{Lu}/v;
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
|
-
* - We can't use `/\p{Emoji}/
|
|
24
|
-
* - We can't use `/\p{Extended_Pictographic}/
|
|
23
|
+
* - We can't use `/\p{Emoji}/v` because it has a false positive on "#" characters.
|
|
24
|
+
* - We can't use `/\p{Extended_Pictographic}/v` because it has a false negative on keycap emojis.
|
|
25
25
|
*/
|
|
26
|
-
const EMOJI_REGEX =
|
|
26
|
+
const EMOJI_REGEX = /\p{Extended_Pictographic}|[#*0-9]\u{FE0F}?\u{20E3}/v;
|
|
27
27
|
|
|
28
|
-
const
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
const WHITESPACE_REGEX = /\s
|
|
32
|
-
const WHITESPACE_GLOBAL_REGEX = /\s/
|
|
33
|
-
const TITLE_CASE_BOUNDARY_REGEX = /(?<=[\da-z])(?=[A-Z])/
|
|
34
|
-
const UPPERCASE_REGEX = /^[A-Z]
|
|
35
|
-
const LOWERCASE_REGEX = /^[a-z]
|
|
28
|
+
const KEBAB_CASE_REGEX = /^[\da-z]+(?:-[\da-z]+)*$/v;
|
|
29
|
+
const SEMANTIC_VERSION_REGEX =
|
|
30
|
+
/^v*(?<major>\d+)\.(?<minor>\d+)\.(?<patch>\d+)/v;
|
|
31
|
+
const WHITESPACE_REGEX = /\s/v;
|
|
32
|
+
const WHITESPACE_GLOBAL_REGEX = /\s/gv;
|
|
33
|
+
const TITLE_CASE_BOUNDARY_REGEX = /(?<=[\da-z])(?=[A-Z])/gv;
|
|
34
|
+
const UPPERCASE_REGEX = /^[A-Z]*$/v;
|
|
35
|
+
const LOWERCASE_REGEX = /^[a-z]*$/v;
|
|
36
36
|
|
|
37
37
|
/** Helper function to capitalize the first letter of a string. */
|
|
38
38
|
export function capitalizeFirstLetter(string: string): string {
|
|
@@ -124,6 +124,7 @@ export function isASCII(str: string): boolean {
|
|
|
124
124
|
* https://stackoverflow.com/questions/8334606/check-if-first-letter-of-word-is-a-capital-letter
|
|
125
125
|
*/
|
|
126
126
|
export function isFirstLetterCapitalized(string: string): boolean {
|
|
127
|
+
// eslint-disable-next-line @typescript-eslint/prefer-string-starts-ends-with
|
|
127
128
|
return FIRST_LETTER_CAPITALIZED_REGEX.test(string);
|
|
128
129
|
}
|
|
129
130
|
|
|
@@ -157,8 +158,8 @@ export function isUpperCase(string: string): boolean {
|
|
|
157
158
|
|
|
158
159
|
/** Helper function to convert a string from kebab-case to camelCase. */
|
|
159
160
|
export function kebabCaseToCamelCase(string: string): string {
|
|
160
|
-
return string.replaceAll(/-./
|
|
161
|
-
const firstLetterOfWord = match
|
|
161
|
+
return string.replaceAll(/-./gv, (match) => {
|
|
162
|
+
const firstLetterOfWord = match.at(1);
|
|
162
163
|
return firstLetterOfWord === undefined
|
|
163
164
|
? ""
|
|
164
165
|
: firstLetterOfWord.toUpperCase();
|
|
@@ -189,11 +190,11 @@ export function normalizeString(string: string): string {
|
|
|
189
190
|
|
|
190
191
|
// Normalize newlines.
|
|
191
192
|
sanitizedString = sanitizedString.replaceAll("\n\r", "\n");
|
|
192
|
-
sanitizedString = sanitizedString.replaceAll(/\p{Zl}/
|
|
193
|
-
sanitizedString = sanitizedString.replaceAll(/\p{Zp}/
|
|
193
|
+
sanitizedString = sanitizedString.replaceAll(/\p{Zl}/gv, "\n");
|
|
194
|
+
sanitizedString = sanitizedString.replaceAll(/\p{Zp}/gv, "\n");
|
|
194
195
|
|
|
195
196
|
// Normalize spaces.
|
|
196
|
-
sanitizedString = sanitizedString.replaceAll(/\p{Zs}/
|
|
197
|
+
sanitizedString = sanitizedString.replaceAll(/\p{Zs}/gv, " ");
|
|
197
198
|
|
|
198
199
|
// Remove leading/trailing whitespace.
|
|
199
200
|
sanitizedString = sanitizedString.trim();
|
|
@@ -210,7 +211,7 @@ export function normalizeString(string: string): string {
|
|
|
210
211
|
export function parseSemanticVersion(
|
|
211
212
|
versionString: string,
|
|
212
213
|
): SemanticVersion | undefined {
|
|
213
|
-
const match =
|
|
214
|
+
const match = SEMANTIC_VERSION_REGEX.exec(versionString);
|
|
214
215
|
if (match === null || match.groups === undefined) {
|
|
215
216
|
return undefined;
|
|
216
217
|
}
|
|
@@ -232,7 +233,11 @@ export function parseSemanticVersion(
|
|
|
232
233
|
return undefined;
|
|
233
234
|
}
|
|
234
235
|
|
|
235
|
-
return {
|
|
236
|
+
return {
|
|
237
|
+
majorVersion,
|
|
238
|
+
minorVersion,
|
|
239
|
+
patchVersion,
|
|
240
|
+
};
|
|
236
241
|
}
|
|
237
242
|
|
|
238
243
|
/* eslint-disable jsdoc/escape-inline-tags */
|
|
@@ -301,7 +306,7 @@ export function removeLinesMatching(string: string, match: string): string {
|
|
|
301
306
|
* https://stackoverflow.com/questions/11598786/how-to-replace-non-printable-unicode-characters-javascript
|
|
302
307
|
*/
|
|
303
308
|
export function removeNonPrintableCharacters(string: string): string {
|
|
304
|
-
return string.replaceAll(/\p{C}/
|
|
309
|
+
return string.replaceAll(/\p{C}/gv, "");
|
|
305
310
|
}
|
|
306
311
|
|
|
307
312
|
/** Helper function to remove all whitespace characters from a string. */
|
|
@@ -353,7 +358,7 @@ export function satisfiesSemanticVersion(
|
|
|
353
358
|
export function titleCaseToKebabCase(string: string): string {
|
|
354
359
|
return string
|
|
355
360
|
.replaceAll(TITLE_CASE_BOUNDARY_REGEX, "-")
|
|
356
|
-
.replaceAll(/ +/
|
|
361
|
+
.replaceAll(/ +/gv, "-")
|
|
357
362
|
.toLowerCase();
|
|
358
363
|
}
|
|
359
364
|
|
package/src/functions/time.ts
CHANGED
|
@@ -17,10 +17,13 @@
|
|
|
17
17
|
* const elapsedSeconds = getElapsedSeconds(startTime);
|
|
18
18
|
* ```
|
|
19
19
|
*/
|
|
20
|
-
export function getElapsedSeconds(
|
|
20
|
+
export function getElapsedSeconds(
|
|
21
|
+
startTime: number,
|
|
22
|
+
roundToInteger = true,
|
|
23
|
+
): number {
|
|
21
24
|
const endTime = Date.now();
|
|
22
25
|
const elapsedMilliseconds = endTime - startTime;
|
|
23
26
|
const elapsedSeconds = elapsedMilliseconds / 1000;
|
|
24
27
|
|
|
25
|
-
return Math.floor(elapsedSeconds);
|
|
28
|
+
return roundToInteger ? Math.floor(elapsedSeconds) : elapsedSeconds;
|
|
26
29
|
}
|
package/src/functions/tuple.ts
CHANGED
|
@@ -13,7 +13,7 @@ type TupleValue<T extends readonly unknown[]> = T[0];
|
|
|
13
13
|
type TupleEntry<T extends readonly unknown[]> = [TupleKey<T>, TupleValue<T>]; // eslint-disable-line perfectionist/sort-modules
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
|
-
* Helper function to get the entries (i.e
|
|
16
|
+
* Helper function to get the entries (i.e., indexes and values) of a tuple in a type-safe way.
|
|
17
17
|
*
|
|
18
18
|
* This is useful because the vanilla `Array.entries` method will always have the keys be of type
|
|
19
19
|
* `number`.
|
|
@@ -25,7 +25,7 @@ export function* tupleEntries<T extends readonly unknown[]>(
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
|
-
* Helper function to get the keys (i.e
|
|
28
|
+
* Helper function to get the keys (i.e., indexes) of a tuple in a type-safe way.
|
|
29
29
|
*
|
|
30
30
|
* This is useful because the vanilla `Array.keys` method will always have the keys be of type
|
|
31
31
|
* `number`.
|
package/src/functions/types.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
* Helper function to narrow an unknown value to an object (i.e
|
|
8
|
+
* Helper function to narrow an unknown value to an object (i.e., a TypeScript record).
|
|
9
9
|
*
|
|
10
10
|
* Under the hood, this checks for `typeof variable === "object"`, `variable !== null`, and
|
|
11
11
|
* `!Array.isArray(variable)`.
|
package/src/functions/utils.ts
CHANGED
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
// When regexes are located at the root instead of inside the function, the functions are tested to
|
|
8
8
|
// perform 11% faster.
|
|
9
9
|
|
|
10
|
-
const FLOAT_REGEX =
|
|
11
|
-
const INTEGER_REGEX = /^-?\d
|
|
10
|
+
const FLOAT_REGEX = /^-?(?:\d+(?:\.\d+)?|\.\d+)$/v;
|
|
11
|
+
const INTEGER_REGEX = /^-?\d+$/v;
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* Helper function to get an iterator of integers with the specified range, inclusive on the lower
|
|
@@ -99,7 +99,7 @@ export function isKeyOf<T extends object>(
|
|
|
99
99
|
key: PropertyKey,
|
|
100
100
|
target: T,
|
|
101
101
|
): key is keyof T {
|
|
102
|
-
return key
|
|
102
|
+
return Object.hasOwn(target, key);
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
/**
|
|
@@ -115,10 +115,8 @@ export function noop(): void {}
|
|
|
115
115
|
* - `undefined` is returned instead of `Number.NaN`, which is helpful in conjunction with
|
|
116
116
|
* TypeScript type narrowing patterns.
|
|
117
117
|
* - Strings that are a mixture of numbers and letters will result in undefined instead of the part
|
|
118
|
-
* of the string that is the number. (e.g
|
|
118
|
+
* of the string that is the number. (e.g., "1a" --> undefined instead of "1a" --> 1)
|
|
119
119
|
* - Non-strings will result in undefined instead of being coerced to a number.
|
|
120
|
-
*
|
|
121
|
-
* @param string A string to convert to an integer.
|
|
122
120
|
*/
|
|
123
121
|
export function parseFloatSafe(string: string): number | undefined {
|
|
124
122
|
if (typeof string !== "string") {
|
|
@@ -128,11 +126,13 @@ export function parseFloatSafe(string: string): number | undefined {
|
|
|
128
126
|
const trimmedString = string.trim();
|
|
129
127
|
|
|
130
128
|
// If the string does not entirely consist of numbers, return undefined.
|
|
131
|
-
if (FLOAT_REGEX.
|
|
129
|
+
if (!FLOAT_REGEX.test(trimmedString)) {
|
|
132
130
|
return undefined;
|
|
133
131
|
}
|
|
134
132
|
|
|
135
|
-
|
|
133
|
+
// The "Number" constructor is used instead of "Number.parseFloat":
|
|
134
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-number-coercion.md
|
|
135
|
+
const number = Number(trimmedString);
|
|
136
136
|
return Number.isNaN(number) ? undefined : number;
|
|
137
137
|
}
|
|
138
138
|
|
|
@@ -142,7 +142,7 @@ export function parseFloatSafe(string: string): number | undefined {
|
|
|
142
142
|
* - `undefined` is returned instead of `Number.NaN`, which is helpful in conjunction with
|
|
143
143
|
* TypeScript type narrowing patterns.
|
|
144
144
|
* - Strings that are a mixture of numbers and letters will result in undefined instead of the part
|
|
145
|
-
* of the string that is the number. (e.g
|
|
145
|
+
* of the string that is the number. (e.g., "1a" --> undefined instead of "1a" --> 1)
|
|
146
146
|
* - Non-strings will result in undefined instead of being coerced to a number.
|
|
147
147
|
*
|
|
148
148
|
* If you have to use a radix other than 10, use the vanilla `Number.parseInt` function instead,
|
|
@@ -156,11 +156,13 @@ export function parseIntSafe(string: string): number | undefined {
|
|
|
156
156
|
const trimmedString = string.trim();
|
|
157
157
|
|
|
158
158
|
// If the string does not entirely consist of numbers, return undefined.
|
|
159
|
-
if (INTEGER_REGEX.
|
|
159
|
+
if (!INTEGER_REGEX.test(trimmedString)) {
|
|
160
160
|
return undefined;
|
|
161
161
|
}
|
|
162
162
|
|
|
163
|
-
|
|
163
|
+
// The "Number" constructor is used instead of "Number.parseInt":
|
|
164
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-number-coercion.md
|
|
165
|
+
const number = Math.trunc(Number(trimmedString));
|
|
164
166
|
return Number.isNaN(number) ? undefined : number;
|
|
165
167
|
}
|
|
166
168
|
|