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.
Files changed (42) hide show
  1. package/dist/functions/array.d.ts.map +1 -1
  2. package/dist/functions/assert.d.cts +4 -2
  3. package/dist/functions/assert.d.mts +4 -2
  4. package/dist/functions/assert.d.ts +4 -2
  5. package/dist/functions/assert.d.ts.map +1 -1
  6. package/dist/functions/enums.d.cts +2 -2
  7. package/dist/functions/enums.d.mts +2 -2
  8. package/dist/functions/enums.d.ts +2 -2
  9. package/dist/functions/set.d.cts +1 -1
  10. package/dist/functions/set.d.mts +1 -1
  11. package/dist/functions/set.d.ts +1 -1
  12. package/dist/functions/set.d.ts.map +1 -1
  13. package/dist/functions/sort.d.ts.map +1 -1
  14. package/dist/functions/string.d.ts.map +1 -1
  15. package/dist/functions/time.d.cts +1 -1
  16. package/dist/functions/time.d.mts +1 -1
  17. package/dist/functions/time.d.ts +1 -1
  18. package/dist/functions/time.d.ts.map +1 -1
  19. package/dist/functions/tuple.d.cts +2 -2
  20. package/dist/functions/tuple.d.mts +2 -2
  21. package/dist/functions/tuple.d.ts +2 -2
  22. package/dist/functions/types.d.cts +1 -1
  23. package/dist/functions/types.d.mts +1 -1
  24. package/dist/functions/types.d.ts +1 -1
  25. package/dist/functions/utils.d.cts +2 -4
  26. package/dist/functions/utils.d.mts +2 -4
  27. package/dist/functions/utils.d.ts +2 -4
  28. package/dist/functions/utils.d.ts.map +1 -1
  29. package/dist/index.cjs +44 -44
  30. package/dist/index.mjs +44 -45
  31. package/package.json +4 -4
  32. package/src/functions/array.ts +2 -8
  33. package/src/functions/assert.ts +16 -4
  34. package/src/functions/enums.ts +2 -2
  35. package/src/functions/object.ts +1 -1
  36. package/src/functions/set.ts +2 -7
  37. package/src/functions/sort.ts +1 -3
  38. package/src/functions/string.ts +28 -23
  39. package/src/functions/time.ts +5 -2
  40. package/src/functions/tuple.ts +2 -2
  41. package/src/functions/types.ts +1 -1
  42. package/src/functions/utils.ts +13 -11
@@ -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
- // eslint-disable-next-line no-control-regex
18
- const ASCII_REGEX = /^[\u0000-\u007F]*$/;
17
+ const ASCII_REGEX = /^\p{ASCII}*$/v;
19
18
 
20
- const DIACRITIC_REGEX = /\p{Diacritic}/u;
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}/u` because it has a false positive on "#" characters.
24
- * - We can't use `/\p{Extended_Pictographic}/u` because it has a false negative on keycap emojis.
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 = /(\p{Extended_Pictographic}|[#*0-9]\uFE0F?\u20E3)/u;
26
+ const EMOJI_REGEX = /\p{Extended_Pictographic}|[#*0-9]\u{FE0F}?\u{20E3}/v;
27
27
 
28
- const FIRST_LETTER_CAPITALIZED_REGEX = /^\p{Lu}/u;
29
- const KEBAB_CASE_REGEX = /^[\da-z]+(?:-[\da-z]+)*$/;
30
- const SEMANTIC_VERSION_REGEX = /^v*(?<major>\d+)\.(?<minor>\d+)\.(?<patch>\d+)/;
31
- const WHITESPACE_REGEX = /\s/;
32
- const WHITESPACE_GLOBAL_REGEX = /\s/g;
33
- const TITLE_CASE_BOUNDARY_REGEX = /(?<=[\da-z])(?=[A-Z])/g;
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(/-./g, (match) => {
161
- const firstLetterOfWord = match[1];
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}/gu, "\n");
193
- sanitizedString = sanitizedString.replaceAll(/\p{Zp}/gu, "\n");
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}/gu, " ");
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 = versionString.match(SEMANTIC_VERSION_REGEX);
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 { majorVersion, minorVersion, patchVersion };
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}/gu, "");
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(/ +/g, "-")
361
+ .replaceAll(/ +/gv, "-")
357
362
  .toLowerCase();
358
363
  }
359
364
 
@@ -17,10 +17,13 @@
17
17
  * const elapsedSeconds = getElapsedSeconds(startTime);
18
18
  * ```
19
19
  */
20
- export function getElapsedSeconds(startTime: number): number {
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
  }
@@ -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. indexes and values) of a tuple in a type-safe way.
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. indexes) of a tuple in a type-safe way.
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`.
@@ -5,7 +5,7 @@
5
5
  */
6
6
 
7
7
  /**
8
- * Helper function to narrow an unknown value to an object (i.e. a TypeScript record).
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)`.
@@ -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 = /^-?\d*\.?\d+$/;
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 in target;
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. "1a" --> undefined instead of "1a" --> 1)
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.exec(trimmedString) === null) {
129
+ if (!FLOAT_REGEX.test(trimmedString)) {
132
130
  return undefined;
133
131
  }
134
132
 
135
- const number = Number.parseFloat(trimmedString);
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. "1a" --> undefined instead of "1a" --> 1)
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.exec(trimmedString) === null) {
159
+ if (!INTEGER_REGEX.test(trimmedString)) {
160
160
  return undefined;
161
161
  }
162
162
 
163
- const number = Number.parseInt(trimmedString, 10);
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