@hichchi/utils 0.0.1-beta.2 → 0.0.2

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 (90) hide show
  1. package/index.cjs.default.js +1 -0
  2. package/index.cjs.js +3645 -0
  3. package/index.cjs.mjs +2 -0
  4. package/index.d.ts +1 -5
  5. package/index.esm.js +3575 -0
  6. package/package.json +13 -8
  7. package/src/index.d.ts +5 -0
  8. package/{interfaces → src/interfaces}/infinite-object.interface.d.ts +3 -3
  9. package/{interfaces → src/interfaces}/path-value-set.interface.d.ts +12 -12
  10. package/{types → src/types}/deep-partial.type.d.ts +6 -0
  11. package/{types → src/types}/literal-object.type.d.ts +2 -2
  12. package/{utils → src/utils}/index.d.ts +1 -0
  13. package/{utils → src/utils}/object.utils.d.ts +23 -19
  14. package/CHANGELOG.md +0 -19
  15. package/README.md +0 -7944
  16. package/constants/constants.js +0 -227
  17. package/constants/constants.js.map +0 -1
  18. package/constants/english-inflection-rules.js +0 -360
  19. package/constants/english-inflection-rules.js.map +0 -1
  20. package/constants/index.js +0 -6
  21. package/constants/index.js.map +0 -1
  22. package/enums/index.js +0 -5
  23. package/enums/index.js.map +0 -1
  24. package/enums/template-tag.enum.js +0 -39
  25. package/enums/template-tag.enum.js.map +0 -1
  26. package/index.js +0 -9
  27. package/index.js.map +0 -1
  28. package/interfaces/index.js +0 -7
  29. package/interfaces/index.js.map +0 -1
  30. package/interfaces/infinite-object.interface.js +0 -3
  31. package/interfaces/infinite-object.interface.js.map +0 -1
  32. package/interfaces/inflection-rule.interfaces.js +0 -3
  33. package/interfaces/inflection-rule.interfaces.js.map +0 -1
  34. package/interfaces/path-value-set.interface.js +0 -3
  35. package/interfaces/path-value-set.interface.js.map +0 -1
  36. package/readme-top.md +0 -187
  37. package/types/deep-partial.type.js +0 -3
  38. package/types/deep-partial.type.js.map +0 -1
  39. package/types/index.js +0 -38
  40. package/types/index.js.map +0 -1
  41. package/types/is-already-in-path.type.js +0 -3
  42. package/types/is-already-in-path.type.js.map +0 -1
  43. package/types/is-empty.type.js +0 -3
  44. package/types/is-empty.type.js.map +0 -1
  45. package/types/is-primitive.type.js +0 -4
  46. package/types/is-primitive.type.js.map +0 -1
  47. package/types/literal-object.type.js +0 -3
  48. package/types/literal-object.type.js.map +0 -1
  49. package/types/loose-autocomplete.type.js +0 -3
  50. package/types/loose-autocomplete.type.js.map +0 -1
  51. package/types/partial-with-null.type.js +0 -3
  52. package/types/partial-with-null.type.js.map +0 -1
  53. package/types/prettify.type.js +0 -3
  54. package/types/prettify.type.js.map +0 -1
  55. package/types/type.type.js +0 -3
  56. package/types/type.type.js.map +0 -1
  57. package/utils/assertions.utils.js +0 -163
  58. package/utils/assertions.utils.js.map +0 -1
  59. package/utils/file.utils.js +0 -1315
  60. package/utils/file.utils.js.map +0 -1
  61. package/utils/index.js +0 -9
  62. package/utils/index.js.map +0 -1
  63. package/utils/object.utils.js +0 -1069
  64. package/utils/object.utils.js.map +0 -1
  65. package/utils/string-template.utils.js +0 -269
  66. package/utils/string-template.utils.js.map +0 -1
  67. package/utils/string.utils.js +0 -1255
  68. package/utils/string.utils.js.map +0 -1
  69. package/utils/url.utils.js +0 -112
  70. package/utils/url.utils.js.map +0 -1
  71. /package/{constants → src/constants}/constants.d.ts +0 -0
  72. /package/{constants → src/constants}/english-inflection-rules.d.ts +0 -0
  73. /package/{constants → src/constants}/index.d.ts +0 -0
  74. /package/{enums → src/enums}/index.d.ts +0 -0
  75. /package/{enums → src/enums}/template-tag.enum.d.ts +0 -0
  76. /package/{interfaces → src/interfaces}/index.d.ts +0 -0
  77. /package/{interfaces → src/interfaces}/inflection-rule.interfaces.d.ts +0 -0
  78. /package/{types → src/types}/index.d.ts +0 -0
  79. /package/{types → src/types}/is-already-in-path.type.d.ts +0 -0
  80. /package/{types → src/types}/is-empty.type.d.ts +0 -0
  81. /package/{types → src/types}/is-primitive.type.d.ts +0 -0
  82. /package/{types → src/types}/loose-autocomplete.type.d.ts +0 -0
  83. /package/{types → src/types}/partial-with-null.type.d.ts +0 -0
  84. /package/{types → src/types}/prettify.type.d.ts +0 -0
  85. /package/{types → src/types}/type.type.d.ts +0 -0
  86. /package/{utils → src/utils}/assertions.utils.d.ts +0 -0
  87. /package/{utils → src/utils}/file.utils.d.ts +0 -0
  88. /package/{utils → src/utils}/string-template.utils.d.ts +0 -0
  89. /package/{utils → src/utils}/string.utils.d.ts +0 -0
  90. /package/{utils → src/utils}/url.utils.d.ts +0 -0
@@ -1,1255 +0,0 @@
1
- "use strict";
2
- // noinspection JSUnusedGlobalSymbols
3
- Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.breakToWords = breakToWords;
5
- exports.toLowerCase = toLowerCase;
6
- exports.toLowerCaseBreak = toLowerCaseBreak;
7
- exports.toUpperCase = toUpperCase;
8
- exports.stringSimilarity = stringSimilarity;
9
- exports.slugify = slugify;
10
- exports.extractEmails = extractEmails;
11
- exports.extractUrls = extractUrls;
12
- exports.hashString = hashString;
13
- exports.randomString = randomString;
14
- exports.maskString = maskString;
15
- exports.toFirstCase = toFirstCase;
16
- exports.toVariableName = toVariableName;
17
- exports.wordWrap = wordWrap;
18
- exports.createExcerpt = createExcerpt;
19
- exports.normalizeString = normalizeString;
20
- exports.toUpperCaseBreak = toUpperCaseBreak;
21
- exports.toFirstCaseBreak = toFirstCaseBreak;
22
- exports.toTitleCase = toTitleCase;
23
- exports.toCamelCase = toCamelCase;
24
- exports.toPascalCase = toPascalCase;
25
- exports.toSentenceCase = toSentenceCase;
26
- exports.toSnakeCase = toSnakeCase;
27
- exports.toKebabCase = toKebabCase;
28
- exports.toNumber = toNumber;
29
- exports.htmlToText = htmlToText;
30
- exports.plural = plural;
31
- exports.truncate = truncate;
32
- exports.padString = padString;
33
- exports.escapeRegExp = escapeRegExp;
34
- exports.toProperTitleCase = toProperTitleCase;
35
- exports.format = format;
36
- exports.countOccurrences = countOccurrences;
37
- exports.reverse = reverse;
38
- exports.isAlphanumeric = isAlphanumeric;
39
- exports.removeWhitespace = removeWhitespace;
40
- exports.singular = singular;
41
- const constants_1 = require("../constants");
42
- function breakToWords(str, format) {
43
- if (!str) {
44
- return format ? "" : [];
45
- }
46
- try {
47
- const words = str
48
- .match(/[A-Z]{2,}(?=[A-Z][a-z]+\d*|\b)|[A-Z]?[a-z]+\d*|[A-Z]+|\d+/g)
49
- ?.map((s) => s.toLowerCase()) ?? [];
50
- return format ? words.map(format).join(" ") : words;
51
- }
52
- catch {
53
- return format ? "" : [];
54
- }
55
- }
56
- /**
57
- * Converts a string to lowercase with safe handling of undefined or null values.
58
- *
59
- * This utility function provides a safe way to convert strings to lowercase, automatically
60
- * handling edge cases where the input might be undefined, null, or empty. Unlike the native
61
- * String.prototype.toLowerCase() method, this function won't throw an error when called
62
- * with undefined or null values, instead returning an empty string.
63
- *
64
- * This is particularly useful when working with user input, API responses, or any scenario
65
- * where string values might be optional or potentially undefined. It's commonly used for
66
- * case-insensitive comparisons, search functionality, or normalizing text data.
67
- *
68
- * @param {string} [str] - The string to convert to lowercase. Can be undefined or null.
69
- * @returns {string} The lowercase version of the input string, or an empty string if input is falsy
70
- *
71
- * @example
72
- * ```typescript
73
- * // Basic string conversion
74
- * const result1 = toLowerCase("Hello World");
75
- * // Returns: "hello world"
76
- *
77
- * const result2 = toLowerCase("JAVASCRIPT");
78
- * // Returns: "javascript"
79
- * ```
80
- *
81
- * @example
82
- * ```typescript
83
- * // Safe handling of undefined/null values
84
- * const result1 = toLowerCase(undefined);
85
- * // Returns: ""
86
- *
87
- * const result2 = toLowerCase(null);
88
- * // Returns: ""
89
- *
90
- * const result3 = toLowerCase("");
91
- * // Returns: ""
92
- * ```
93
- *
94
- * @example
95
- * ```typescript
96
- * // Use in case-insensitive search
97
- * function searchUsers(users: User[], searchTerm: string): User[] {
98
- * const normalizedSearch = toLowerCase(searchTerm);
99
- * return users.filter(user =>
100
- * toLowerCase(user.name).includes(normalizedSearch) ||
101
- * toLowerCase(user.email).includes(normalizedSearch)
102
- * );
103
- * }
104
- * ```
105
- *
106
- * @example
107
- * ```typescript
108
- * // Use in form validation
109
- * function validateEmail(email?: string): boolean {
110
- * const normalizedEmail = toLowerCase(email);
111
- * const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
112
- * return emailRegex.test(normalizedEmail);
113
- * }
114
- * ```
115
- *
116
- * @remarks
117
- * - Returns an empty string for any falsy input (undefined, null, empty string)
118
- * - Uses the native String.prototype.toLowerCase() method for actual conversion
119
- * - Does not modify the original string (strings are immutable in JavaScript)
120
- * - Handles all Unicode characters correctly, following locale-independent rules
121
- * - More robust than direct .toLowerCase() calls when input might be undefined
122
- *
123
- * @see {@link toUpperCase} Function for converting strings to uppercase
124
- * @see {@link toLowerCaseBreak} Function for converting to lowercase and breaking into words
125
- */
126
- function toLowerCase(str) {
127
- if (!str) {
128
- return "";
129
- }
130
- return str.toLowerCase();
131
- }
132
- /**
133
- * Converts a string to lowercase and breaks it into words, joining them with a specified separator.
134
- *
135
- * This utility function combines word breaking and case conversion in a single operation.
136
- * It first breaks the input string into individual words using intelligent pattern recognition
137
- * (handling camelCase, snake_case, kebab-case, etc.), converts each word to lowercase,
138
- * and then joins them with the specified separator or a space by default.
139
- *
140
- * This is particularly useful for converting various naming conventions to a consistent
141
- * lowercase format, creating readable labels from variable names, generating search-friendly
142
- * text, or preparing strings for further processing where consistent word separation is needed.
143
- *
144
- * @param {string} [str] - The string to convert and break into words. Can be undefined or null.
145
- * @param {string} [join=" "] - The separator to use when joining the words. Defaults to a single space.
146
- * @returns {string} A lowercase string with words separated by the specified join character,
147
- * or an empty string if input is falsy
148
- *
149
- * @example
150
- * ```typescript
151
- * // Basic camelCase conversion
152
- * const result1 = toLowerCaseBreak("HelloWorld");
153
- * // Returns: "hello world"
154
- *
155
- * const result2 = toLowerCaseBreak("getUserProfile");
156
- * // Returns: "get user profile"
157
- * ```
158
- *
159
- * @example
160
- * ```typescript
161
- * // Custom separators
162
- * const result1 = toLowerCaseBreak("HelloWorld", "-");
163
- * // Returns: "hello-world"
164
- *
165
- * const result2 = toLowerCaseBreak("APIResponseHandler", "_");
166
- * // Returns: "api_response_handler"
167
- *
168
- * const result3 = toLowerCaseBreak("userAccountSettings", " | ");
169
- * // Returns: "user | account | settings"
170
- * ```
171
- *
172
- * @example
173
- * ```typescript
174
- * // Various input formats
175
- * const result1 = toLowerCaseBreak("snake_case_example");
176
- * // Returns: "snake case example"
177
- *
178
- * const result2 = toLowerCaseBreak("kebab-case-example");
179
- * // Returns: "kebab case example"
180
- *
181
- * const result3 = toLowerCaseBreak("CONSTANT_VALUE");
182
- * // Returns: "constant value"
183
- * ```
184
- *
185
- * @example
186
- * ```typescript
187
- * // Creating user-friendly labels
188
- * function createLabel(fieldName: string): string {
189
- * return toLowerCaseBreak(fieldName)
190
- * .split(' ')
191
- * .map(word => word.charAt(0).toUpperCase() + word.slice(1))
192
- * .join(' ');
193
- * }
194
- *
195
- * createLabel("firstName"); // "First Name"
196
- * createLabel("emailAddress"); // "Email Address"
197
- * ```
198
- *
199
- * @example
200
- * ```typescript
201
- * // Safe handling of edge cases
202
- * const result1 = toLowerCaseBreak(undefined);
203
- * // Returns: ""
204
- *
205
- * const result2 = toLowerCaseBreak("", "-");
206
- * // Returns: ""
207
- *
208
- * const result3 = toLowerCaseBreak("singleword");
209
- * // Returns: "singleword"
210
- * ```
211
- *
212
- * @remarks
213
- * - Returns an empty string for any falsy input (undefined, null, empty string)
214
- * - Uses the same intelligent word-breaking algorithm as the breakToWords function
215
- * - Handles camelCase, PascalCase, snake_case, kebab-case, and mixed formats
216
- * - Preserves numbers as separate words when they appear in the string
217
- * - The join parameter can be any string, including empty string for concatenation
218
- * - More efficient than calling breakToWords and toLowerCase separately
219
- *
220
- * @see {@link breakToWords} Function for breaking strings into word arrays
221
- * @see {@link toLowerCase} Function for simple lowercase conversion
222
- * @see {@link toUpperCaseBreak} Function for uppercase word breaking
223
- */
224
- function toLowerCaseBreak(str, join) {
225
- if (!str) {
226
- return "";
227
- }
228
- return breakToWords(str)
229
- .map(s => s.toLowerCase())
230
- .join(join ?? " ");
231
- }
232
- /**
233
- * Converts a string to uppercase with safe handling of undefined or null values.
234
- *
235
- * This utility function provides a safe way to convert strings to uppercase, automatically
236
- * handling edge cases where the input might be undefined, null, or empty. Unlike the native
237
- * String.prototype.toUpperCase() method, this function won't throw an error when called
238
- * with undefined or null values, instead returning an empty string.
239
- *
240
- * This is particularly useful when working with user input, API responses, or any scenario
241
- * where string values might be optional or potentially undefined. It's commonly used for
242
- * creating constants, formatting display text, generating identifiers, or normalizing text
243
- * data that needs to be in uppercase format.
244
- *
245
- * @param {string} [str] - The string to convert to uppercase. Can be undefined or null.
246
- * @returns {string} The uppercase version of the input string, or an empty string if input is falsy
247
- *
248
- * @example
249
- * ```typescript
250
- * // Basic string conversion
251
- * const result1 = toUpperCase("hello world");
252
- * // Returns: "HELLO WORLD"
253
- *
254
- * const result2 = toUpperCase("javascript");
255
- * // Returns: "JAVASCRIPT"
256
- * ```
257
- *
258
- * @example
259
- * ```typescript
260
- * // Safe handling of undefined/null values
261
- * const result1 = toUpperCase(undefined);
262
- * // Returns: ""
263
- *
264
- * const result2 = toUpperCase(null);
265
- * // Returns: ""
266
- *
267
- * const result3 = toUpperCase("");
268
- * // Returns: ""
269
- * ```
270
- *
271
- * @example
272
- * ```typescript
273
- * // Creating constants or identifiers
274
- * function generateConstantName(variableName: string): string {
275
- * return toUpperCase(variableName.replace(/[^a-zA-Z0-9]/g, '_'));
276
- * }
277
- *
278
- * generateConstantName("user-profile"); // "USER_PROFILE"
279
- * generateConstantName("api.endpoint"); // "API_ENDPOINT"
280
- * ```
281
- *
282
- * @example
283
- * ```typescript
284
- * // Use in text formatting
285
- * function formatTitle(title?: string): string {
286
- * if (!title) return "UNTITLED";
287
- * return toUpperCase(title.trim());
288
- * }
289
- *
290
- * formatTitle("my document"); // "MY DOCUMENT"
291
- * formatTitle(undefined); // "UNTITLED"
292
- * ```
293
- *
294
- * @example
295
- * ```typescript
296
- * // Use in case-insensitive comparisons
297
- * function compareIgnoreCase(str1?: string, str2?: string): boolean {
298
- * return toUpperCase(str1) === toUpperCase(str2);
299
- * }
300
- *
301
- * compareIgnoreCase("Hello", "HELLO"); // true
302
- * compareIgnoreCase("Test", "test"); // true
303
- * ```
304
- *
305
- * @remarks
306
- * - Returns an empty string for any falsy input (undefined, null, empty string)
307
- * - Uses the native String.prototype.toUpperCase() method for actual conversion
308
- * - Does not modify the original string (strings are immutable in JavaScript)
309
- * - Handles all Unicode characters correctly, following locale-independent rules
310
- * - More robust than direct .toUpperCase() calls when input might be undefined
311
- * - Particularly useful for creating constants, headers, or display text
312
- *
313
- * @see {@link toLowerCase} Function for converting strings to lowercase
314
- * @see {@link toUpperCaseBreak} Function for converting to uppercase and breaking into words
315
- */
316
- function toUpperCase(str) {
317
- if (!str) {
318
- return "";
319
- }
320
- return str.toUpperCase();
321
- }
322
- /**
323
- * Compares two strings for similarity using Levenshtein distance algorithm.
324
- *
325
- * The Levenshtein distance is a measure of the difference between two strings
326
- * by counting the minimum number of single-character edits (insertions, deletions,
327
- * or substitutions) required to change one string into another.
328
- *
329
- * @param {string} str1 - First string to compare
330
- * @param {string} str2 - Second string to compare
331
- * @returns {number} - A value between 0 and 1, where 1 means identical strings
332
- *
333
- * @example
334
- * ```typescript
335
- * stringSimilarity("hello", "hallo"); // 0.8 (4/5 characters match)
336
- * stringSimilarity("kitten", "sitting"); // ~0.57 (higher distance)
337
- * stringSimilarity("same", "same"); // 1.0 (identical)
338
- * ```
339
- */
340
- function stringSimilarity(str1, str2) {
341
- if (str1 === str2)
342
- return 1.0;
343
- if (!str1 || !str2)
344
- return 0.0;
345
- const len1 = str1.length;
346
- const len2 = str2.length;
347
- // Initialize the distance matrix
348
- const matrix = Array(len1 + 1)
349
- .fill(null)
350
- .map(() => Array(len2 + 1).fill(0));
351
- // Fill the first row and column
352
- for (let i = 0; i <= len1; i++)
353
- matrix[i][0] = i;
354
- for (let j = 0; j <= len2; j++)
355
- matrix[0][j] = j;
356
- // Fill the rest of the matrix
357
- for (let i = 1; i <= len1; i++) {
358
- for (let j = 1; j <= len2; j++) {
359
- const cost = str1[i - 1] === str2[j - 1] ? 0 : 1;
360
- matrix[i][j] = Math.min(matrix[i - 1][j] + 1, // deletion
361
- matrix[i][j - 1] + 1, // insertion
362
- matrix[i - 1][j - 1] + cost);
363
- }
364
- }
365
- // Calculate similarity from Levenshtein distance
366
- const maxLen = Math.max(len1, len2);
367
- if (maxLen === 0)
368
- return 1.0;
369
- return 1.0 - matrix[len1][len2] / maxLen;
370
- }
371
- /**
372
- * Generates a slug from a string, suitable for URLs or file names.
373
- *
374
- * @param {string} str - The string to convert to a slug
375
- * @param {string} [separator="-"] - The character to use as separator
376
- * @returns {string} - The slug string
377
- *
378
- * @example
379
- * ```typescript
380
- * slugify("Hello World"); // "hello-world"
381
- * slugify("10 Tips & Tricks!"); // "10-tips-tricks"
382
- * slugify("My Product (2023 Edition)"); // "my-product-2023-edition"
383
- * slugify("Über résumé"); // "uber-resume"
384
- * slugify("Blog Post", "_"); // "blog_post"
385
- * ```
386
- */
387
- function slugify(str, separator = "-") {
388
- if (!str)
389
- return "";
390
- return str
391
- .normalize("NFD") // Normalize to decomposed form for handling accents
392
- .replace(/[\u0300-\u036f]/g, "") // Remove accents/diacritics
393
- .toLowerCase() // Convert to lowercase
394
- .trim() // Trim whitespace
395
- .replace(/[^\w\s-]/g, "") // Remove non-word chars (except spaces and hyphens)
396
- .replace(/[\s_]+/g, separator) // Replace spaces and underscores with separator
397
- .replace(new RegExp(`${separator}+`, "g"), separator) // Replace multiple separators with single
398
- .replace(new RegExp(`^${separator}|${separator}$`, "g"), ""); // Remove leading/trailing separators
399
- }
400
- /**
401
- * Extracts all email addresses from a string.
402
- *
403
- * @param {string} str - The string to extract emails from
404
- * @returns {string[]} - Array of found email addresses
405
- *
406
- * @example
407
- * ```typescript
408
- * extractEmails("Contact us at support@example.com or sales@example.com");
409
- * // ["support@example.com", "sales@example.com"]
410
- * ```
411
- */
412
- function extractEmails(str) {
413
- if (!str)
414
- return [];
415
- const emailRegex = /([a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9._-]+)/gi;
416
- return str.match(emailRegex) || [];
417
- }
418
- /**
419
- * Extracts all URLs from a string.
420
- *
421
- * @param {string} str - The string to extract URLs from
422
- * @returns {string[]} - Array of found URLs
423
- *
424
- * @example
425
- * ```typescript
426
- * extractUrls("Visit https://example.com or http://test.org/page?id=5");
427
- * // ["https://example.com", "http://test.org/page?id=5"]
428
- * ```
429
- */
430
- function extractUrls(str) {
431
- if (!str)
432
- return [];
433
- // noinspection RegExpSimplifiable
434
- const urlRegex = /(https?:\/\/[^\s]+)/g;
435
- return str.match(urlRegex) || [];
436
- }
437
- /**
438
- * Converts a string to a secure hash using SHA-256.
439
- *
440
- * Note: This is a browser-compatible implementation using the Web Crypto API.
441
- * For Node.js environments, you might want to use the crypto module instead.
442
- *
443
- * @param {string} str - The string to hash
444
- * @returns {Promise<string>} - Promise resolving to the hex hash string
445
- *
446
- * @example
447
- * ```typescript
448
- * // Browser usage
449
- * await hashString("password123");
450
- * // "ef92b778bafe771e89245b89ecbc08a44a4e166c06659911881f383d4473e94f"
451
- * ```
452
- */
453
- async function hashString(str) {
454
- if (!str)
455
- return "";
456
- // Convert string to Uint8Array
457
- const encoder = new TextEncoder();
458
- const data = encoder.encode(str);
459
- // Hash the data
460
- const hashBuffer = await crypto.subtle.digest("SHA-256", data);
461
- // Convert ArrayBuffer to hex string
462
- const hashArray = Array.from(new Uint8Array(hashBuffer));
463
- return hashArray.map(b => b.toString(constants_1.HEX_RADIX).padStart(constants_1.HEX_PADDING_LENGTH, constants_1.HEX_PADDING_CHAR)).join("");
464
- }
465
- /**
466
- * Generates a random string with specified length and character set.
467
- *
468
- * @param {number} length - The length of the random string
469
- * @param {string} [charset] - The characters to use (defaults to alphanumeric)
470
- * @returns {string} - The generated random string
471
- *
472
- * @example
473
- * ```typescript
474
- * // Default alphanumeric string
475
- * randomString(8);
476
- * // e.g. "A7bC9Df3"
477
- *
478
- * // Hex string
479
- * randomString(6, "0123456789abcdef");
480
- * // e.g. "a3f9d2"
481
- *
482
- * // PIN code
483
- * randomString(4, "0123456789");
484
- * // e.g. "8302"
485
- * ```
486
- */
487
- function randomString(length, charset) {
488
- if (length <= 0)
489
- return "";
490
- const chars = charset || "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
491
- let result = "";
492
- // Generate cryptographically secure random values if available
493
- if (typeof crypto !== "undefined" && crypto.getRandomValues) {
494
- const values = new Uint32Array(length);
495
- crypto.getRandomValues(values);
496
- for (let i = 0; i < length; i++) {
497
- result += chars[values[i] % chars.length];
498
- }
499
- }
500
- else {
501
- // Fallback to Math.random (less secure)
502
- for (let i = 0; i < length; i++) {
503
- result += chars.charAt(Math.floor(Math.random() * chars.length));
504
- }
505
- }
506
- return result;
507
- }
508
- /**
509
- * Masks a portion of a string, useful for displaying sensitive information.
510
- *
511
- * @param {string} str - The string to mask
512
- * @param {number} [visibleStart=0] - Number of characters to show at the beginning
513
- * @param {number} [visibleEnd=0] - Number of characters to show at the end
514
- * @param {string} [maskChar="*"] - Character to use for masking
515
- * @returns {string} - The masked string
516
- *
517
- * @example
518
- * ```typescript
519
- * // Mask credit card
520
- * maskString("4111111111111111", 4, 4);
521
- * // "4111********1111"
522
- *
523
- * // Mask email
524
- * maskString("user@example.com", 2, 4, "x");
525
- * // "usxxxxxx.com"
526
- *
527
- * // Mask phone number
528
- * maskString("+1-555-123-4567", 0, 4);
529
- * // "*********4567"
530
- * ```
531
- */
532
- function maskString(str, visibleStart = 0, visibleEnd = 0, maskChar = "*") {
533
- if (!str)
534
- return "";
535
- const length = str.length;
536
- if (visibleStart + visibleEnd >= length)
537
- return str;
538
- const start = str.substring(0, visibleStart);
539
- const middle = maskChar.repeat(length - visibleStart - visibleEnd);
540
- const end = str.substring(length - visibleEnd);
541
- return start + middle + end;
542
- }
543
- /**
544
- * Convert a string to first case (Capitalize first letter of the string).
545
- * @param {string} [str] Optional string to join the words with.
546
- * @returns {string} String in first case.
547
- *
548
- * @example
549
- * ```TypeScript
550
- * toFirstCase("hello world"); // "Hello world"
551
- * ```
552
- */
553
- function toFirstCase(str) {
554
- if (!str) {
555
- return "";
556
- }
557
- return (str[0]?.toUpperCase() || "") + str.slice(1).toLowerCase();
558
- }
559
- /**
560
- * Converts a string to a camelCase or PascalCase variable name.
561
- *
562
- * @param {string} str - The string to convert
563
- * @param {boolean} [pascalCase=false] - Whether to use PascalCase (true) or camelCase (false)
564
- * @returns {string} - The variable name
565
- *
566
- * @example
567
- * ```typescript
568
- * toVariableName("Hello World"); // "helloWorld"
569
- * toVariableName("API Response"); // "apiResponse"
570
- * toVariableName("first-name"); // "firstName"
571
- * toVariableName("user_id", true); // "UserId"
572
- * ```
573
- */
574
- function toVariableName(str, pascalCase = false) {
575
- if (!str)
576
- return "";
577
- // Remove special characters and replace with spaces
578
- const cleaned = str.replace(/[^\w\s]/g, " ");
579
- // Break into words and process
580
- return breakToWords(cleaned)
581
- .map((word, index) => {
582
- // Skip first word for camelCase unless it's PascalCase
583
- if (index === 0 && !pascalCase) {
584
- return word.toLowerCase();
585
- }
586
- // Capitalize first letter
587
- return toFirstCase(word);
588
- })
589
- .join("");
590
- }
591
- /**
592
- * Wraps words in a string to ensure each line is no longer than a specified length.
593
- *
594
- * @param {string} str - The string to wrap
595
- * @param {number} [lineLength=80] - Maximum length of each line
596
- * @param {string} [breakChar="\n"] - Character(s) to insert at line breaks
597
- * @returns {string} - The wrapped string
598
- *
599
- * @example
600
- * ```typescript
601
- * const text = "This is a long sentence that needs to be wrapped to fit within a certain width.";
602
- *
603
- * wordWrap(text, 20);
604
- * // "This is a long\nsentence that needs\nto be wrapped to\nfit within a\ncertain width."
605
- *
606
- * wordWrap(text, 30, "<br>");
607
- * // "This is a long sentence that<br>needs to be wrapped to fit<br>within a certain width."
608
- * ```
609
- */
610
- function wordWrap(str, lineLength = constants_1.DEFAULT_LINE_LENGTH, breakChar = constants_1.DEFAULT_BREAK_CHAR) {
611
- if (!str)
612
- return "";
613
- if (str.length <= lineLength)
614
- return str;
615
- const words = str.split(" ");
616
- let result = "";
617
- let currentLine = "";
618
- for (const word of words) {
619
- // If adding this word exceeds line length, start a new line
620
- if (currentLine.length + word.length + 1 > lineLength) {
621
- result += currentLine.trim() + breakChar;
622
- currentLine = `${word} `;
623
- }
624
- else {
625
- currentLine += `${word} `;
626
- }
627
- }
628
- // Add the last line
629
- result += currentLine.trim();
630
- return result;
631
- }
632
- /**
633
- * Creates an excerpt from a longer text by extracting a portion around a search term.
634
- * Useful for search result highlighting or previews.
635
- *
636
- * @param {string} text - The full text to create an excerpt from
637
- * @param {string} searchTerm - The search term to find in the text
638
- * @param {number} [contextLength=40] - Number of characters to include before and after the search term
639
- * @param {string} [ellipsis="..."] - Characters to use for indicating truncated text
640
- * @returns {string} - The excerpt with the search term in context
641
- *
642
- * @example
643
- * ```typescript
644
- * const article = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam in dui mauris.";
645
- *
646
- * createExcerpt(article, "dolor", 10);
647
- * // "...ipsum dolor sit amet..."
648
- *
649
- * createExcerpt(article, "consectetur", 15, "[...]");
650
- * // "[...]sit amet, consectetur adipiscing[...]"
651
- * ```
652
- */
653
- function createExcerpt(text, searchTerm, contextLength = constants_1.DEFAULT_CONTEXT_LENGTH, ellipsis = constants_1.DEFAULT_ELLIPSIS) {
654
- if (!text || !searchTerm)
655
- return text || "";
656
- // Case-insensitive search
657
- const lowerText = text.toLowerCase();
658
- const lowerSearchTerm = searchTerm.toLowerCase();
659
- const index = lowerText.indexOf(lowerSearchTerm);
660
- if (index === -1) {
661
- // If search term not found, return beginning of text
662
- return text.length > contextLength * constants_1.CONTEXT_MULTIPLIER
663
- ? text.substring(0, contextLength * constants_1.CONTEXT_MULTIPLIER) + ellipsis
664
- : text;
665
- }
666
- // Calculate the start and end positions for the excerpt
667
- const startPos = Math.max(0, index - contextLength);
668
- const endPos = Math.min(text.length, index + searchTerm.length + contextLength);
669
- // Add ellipsis if we're not at the beginning or end
670
- const prefix = startPos > 0 ? ellipsis : "";
671
- const suffix = endPos < text.length ? ellipsis : "";
672
- // Extract the excerpt
673
- return prefix + text.substring(startPos, endPos) + suffix;
674
- }
675
- /**
676
- * Normalizes a string by removing accents, diacritics, and converting to lowercase.
677
- *
678
- * @param {string} str - The string to normalize
679
- * @returns {string} - The normalized string
680
- *
681
- * @example
682
- * ```typescript
683
- * normalizeString("Café"); // "cafe"
684
- * normalizeString("Über"); // "uber"
685
- * normalizeString("résumé"); // "resume"
686
- * normalizeString("ESPAÑA"); // "espana"
687
- * ```
688
- */
689
- function normalizeString(str) {
690
- if (!str)
691
- return "";
692
- return str
693
- .normalize("NFD") // Decompose accented characters
694
- .replace(/[\u0300-\u036f]/g, "") // Remove accent marks
695
- .toLowerCase(); // Convert to lowercase
696
- }
697
- /**
698
- * Convert a string to upper cases and break into words with optional join or space.
699
- * @param {string} [str] String to convert to upper cases and break into words.
700
- * @param {string} [join] Optional string to join the words with.
701
- * @returns {string} String in upper cases and broken into words.
702
- *
703
- * @example
704
- * ```TypeScript
705
- * toUpperCaseBreak("HelloWorld"); // "HELLO WORLD"
706
- * ```
707
- *
708
- * @example
709
- * ```TypeScript
710
- * toUpperCaseBreak("HelloWorld", "! "); // "HELLO! WORLD"
711
- */
712
- function toUpperCaseBreak(str, join) {
713
- if (!str) {
714
- return "";
715
- }
716
- return breakToWords(str)
717
- .map(s => s.toUpperCase())
718
- .join(join ?? " ");
719
- }
720
- /**
721
- * Converts a string to Sentence case (first word capitalized, rest lowercase) with customizable word separators.
722
- *
723
- * This function breaks a string into words, capitalizes the first word, converts remaining
724
- * words to lowercase, and then joins them using a custom separator (or space by default).
725
- *
726
- * Unlike `toFirstCase()` which works on a single word, this function processes multi-word
727
- * strings from various formats (camelCase, snake_case, etc.) and gives control over how
728
- * the words are joined back together.
729
- *
730
- * @param {string} [str] - The input string to convert
731
- * @param {string} [join] - Optional separator to join words (defaults to space)
732
- * @returns {string} - The formatted string with first word capitalized and custom separators,
733
- * or empty string if input is falsy
734
- *
735
- * @example
736
- * ```typescript
737
- * // With default space separator
738
- * toFirstCaseBreak("helloWorld"); // "Hello world"
739
- * toFirstCaseBreak("SYSTEM_ERROR"); // "System error"
740
- * toFirstCaseBreak("api-request-log"); // "Api request log"
741
- *
742
- * // With custom separators
743
- * toFirstCaseBreak("hello_world", "-"); // "Hello-world"
744
- * toFirstCaseBreak("userAuthConfig", "."); // "User.auth.config"
745
- * toFirstCaseBreak("GET_USER_DATA", "/"); // "Get/user/data"
746
- * ```
747
- *
748
- * @see {@link toFirstCase} For capitalizing a single word
749
- * @see {@link toTitleCase} For capitalizing the first letter of every word
750
- * @see {@link breakToWords} The underlying function used to split input into words
751
- */
752
- function toFirstCaseBreak(str, join) {
753
- if (!str) {
754
- return "";
755
- }
756
- return breakToWords(str)
757
- .map((s, i) => (i === 0 ? toFirstCase(s) : s.toLowerCase()))
758
- .join(join ?? " ");
759
- }
760
- /**
761
- * Convert a string to title case (Capitalize first letter of each word).
762
- * @param {string} [str] String to convert to title case.
763
- * @returns {string} String in title case.
764
- *
765
- * @example
766
- * ```TypeScript
767
- * toTitleCase("hello world"); // "Hello World"
768
- * ```
769
- */
770
- function toTitleCase(str) {
771
- if (!str) {
772
- return "";
773
- }
774
- return breakToWords(str)
775
- .map(s => toFirstCase(s))
776
- .join(" ");
777
- }
778
- /**
779
- * Convert a string to camel case.
780
- * @param {string} [str] String to convert to camel case.
781
- * @returns {string} String in camel case.
782
- *
783
- * @example
784
- * ```TypeScript
785
- * toCamelCase("hello world"); // "helloWorld"
786
- * ```
787
- */
788
- function toCamelCase(str) {
789
- if (!str) {
790
- return "";
791
- }
792
- return breakToWords(str)
793
- .map((s, i) => (i === 0 ? s.toLowerCase() : toFirstCase(s)))
794
- .join("");
795
- }
796
- /**
797
- * Convert a string to pascal case.
798
- * @param {string} [str] String to convert to pascal case.
799
- * @returns {string} String in pascal case.
800
- *
801
- * @example
802
- * ```TypeScript
803
- * toPascalCase("hello world"); // "HelloWorld"
804
- * ```
805
- */
806
- function toPascalCase(str) {
807
- if (!str) {
808
- return "";
809
- }
810
- return breakToWords(str)
811
- .map(s => toFirstCase(s))
812
- .join("");
813
- }
814
- /**
815
- * Convert a string to sentence case. (Capitalize first letter of every sentence).
816
- * @param {string} [str] String to convert to sentence case.
817
- * @returns {string} String in sentence case.
818
- *
819
- * @example
820
- * ```TypeScript
821
- * toSentenceCase("hello world. how are you?"); // "Hello world. How are you?"
822
- * ```
823
- */
824
- function toSentenceCase(str) {
825
- return str
826
- .split(".")
827
- .map(s => toFirstCase(s.trim()))
828
- .join(". ");
829
- }
830
- /**
831
- * Converts a string to snake_case format.
832
- *
833
- * This function transforms a string from any common case format (camel, pascal, kebab, etc.)
834
- * into snake_case, where words are lowercase and separated by underscores.
835
- *
836
- * When the optional `caps` parameter is set to true, the result will be UPPER_SNAKE_CASE
837
- * (also known as SCREAMING_SNAKE_CASE or CONSTANT_CASE).
838
- *
839
- * @param {string} [str] - The input string to convert
840
- * @param {boolean} [caps=false] - When true, converts to UPPER_SNAKE_CASE
841
- * @returns {string} - The converted snake_case string, or empty string if input is falsy
842
- *
843
- * @example
844
- * ```typescript
845
- * // From various formats to snake_case
846
- * toSnakeCase("hello world"); // "hello_world"
847
- * toSnakeCase("HelloWorld"); // "hello_world"
848
- * toSnakeCase("hello-world"); // "hello_world"
849
- * toSnakeCase("HELLO WORLD"); // "hello_world"
850
- *
851
- * // To UPPER_SNAKE_CASE (CONSTANT_CASE)
852
- * toSnakeCase("hello world", true); // "HELLO_WORLD"
853
- * toSnakeCase("helloWorld", true); // "HELLO_WORLD"
854
- * ```
855
- *
856
- * @remarks
857
- * This function first splits the string into words using `breakToWords()`,
858
- * then joins them with underscores, applying the requested case transformation.
859
- */
860
- function toSnakeCase(str, caps) {
861
- if (!str) {
862
- return "";
863
- }
864
- const snake = breakToWords(str).join("_");
865
- return caps ? snake.toUpperCase() : snake.toLowerCase();
866
- }
867
- /**
868
- * Convert a string to kebab case.
869
- * @param {string} [str] String to convert to kebab case.
870
- * @param {boolean} [caps] Whether to convert to upper case.
871
- * @returns {string} String in kebab case.
872
- *
873
- * @example
874
- * ```TypeScript
875
- * toKebabCase("hello world"); // "hello-world"
876
- * ```
877
- *
878
- * @example
879
- * ```TypeScript
880
- * toKebabCase("hello world", true); // "HELLO-WORLD"
881
- * ```
882
- */
883
- function toKebabCase(str, caps) {
884
- if (!str) {
885
- return "";
886
- }
887
- const kebab = breakToWords(str).join("-");
888
- return caps ? kebab.toUpperCase() : kebab.toLowerCase();
889
- }
890
- /**
891
- * Converts a string to a number.
892
- * @param {number|string} str String to convert to a number.
893
- * @returns {number|undefined} Number or undefined.
894
- *
895
- * @example
896
- * ```TypeScript
897
- * toNumber("123"); // 123
898
- * ```
899
- */
900
- function toNumber(str) {
901
- return !isNaN(Number(str)) ? Number(str) : undefined;
902
- }
903
- /**
904
- * Remove HTML tags from a string and return plain text.
905
- * @param {string} str String to remove HTML tags from.
906
- * @returns {string} Plain text.
907
- *
908
- * @example
909
- * ```TypeScript
910
- * htmlToText("<h1>Hello World</h1>"); // "Hello World"
911
- * ```
912
- */
913
- function htmlToText(str) {
914
- return str.replace(/<[^>]*>?/gm, "");
915
- }
916
- /**
917
- * Converts a singular English word to its plural form.
918
- *
919
- * This function applies common English pluralization rules to transform
920
- * singular words into their plural equivalents. It handles regular patterns
921
- * as well as many irregular cases and special rules for different word endings.
922
- *
923
- * @param {string} str - The singular word to convert to plural form
924
- * @returns {string} - The plural form of the word, or the original string if:
925
- * - Input is empty/falsy
926
- * - The word is already plural
927
- *
928
- * @example
929
- * ```typescript
930
- * // Regular plurals
931
- * plural("cat"); // "cats"
932
- * plural("dog"); // "dogs"
933
- *
934
- * // Words ending in -y
935
- * plural("party"); // "parties"
936
- * plural("day"); // "days"
937
- *
938
- * // Words ending in -f or -fe
939
- * plural("wolf"); // "wolves"
940
- * plural("knife"); // "knives"
941
- *
942
- * // Words ending in -o
943
- * plural("potato"); // "potatoes"
944
- * plural("photo"); // "photos"
945
- *
946
- * // Irregular plurals
947
- * plural("child"); // "children"
948
- * plural("man"); // "men"
949
- * plural("foot"); // "feet"
950
- *
951
- * // Latin/Greek words
952
- * plural("cactus"); // "cacti"
953
- * plural("analysis"); // "analyses"
954
- * ```
955
- *
956
- * @remarks
957
- * - This function is designed for English language words only
958
- * - It pairs well with the `singular()` function for round-trip conversion
959
- */
960
- function plural(str) {
961
- if (!str)
962
- return str;
963
- // Combine all rules in priority order
964
- const rules = [
965
- ...constants_1.EnglishInflectionRules.INVARIANT,
966
- ...constants_1.EnglishInflectionRules.IRREGULAR.toPlural,
967
- ...constants_1.EnglishInflectionRules.LATIN_GREEK.toPlural,
968
- ...constants_1.EnglishInflectionRules.PATTERN_RULES.toPlural,
969
- ...constants_1.EnglishInflectionRules.DEFAULT.toPlural,
970
- ];
971
- // Apply the first matching rule
972
- for (const rule of rules) {
973
- if (rule.regex.test(str)) {
974
- return str.replace(rule.regex, typeof rule.replacement === "string" ? rule.replacement : rule.replacement(str));
975
- }
976
- }
977
- return str;
978
- }
979
- /**
980
- * Truncates a string to a specified length and adds an ellipsis if needed.
981
- *
982
- * @param {string} str - The string to truncate
983
- * @param {number} length - Maximum length of the truncated string (excluding ellipsis)
984
- * @param {string} [ellipsis="..."] - The ellipsis to add to truncated strings
985
- * @returns {string} - The truncated string with ellipsis if needed
986
- *
987
- * @example
988
- * ```typescript
989
- * truncate("This is a long sentence", 10); // "This is a..."
990
- * truncate("Short", 10); // "Short"
991
- * truncate("Custom ellipsis", 6, " [more]"); // "Custom [more]"
992
- * ```
993
- */
994
- function truncate(str, length, ellipsis = "...") {
995
- if (!str)
996
- return "";
997
- if (str.length <= length)
998
- return str;
999
- return str.substring(0, length) + ellipsis;
1000
- }
1001
- /**
1002
- * Pads a string to a specified length with a specified character.
1003
- *
1004
- * @param {string} str - The string to pad
1005
- * @param {number} length - The target length of the resulting string
1006
- * @param {string} [char=" "] - The character to pad with (defaults to space)
1007
- * @param {boolean} [padEnd=true] - Whether to pad at the end (true) or beginning (false)
1008
- * @returns {string} - The padded string
1009
- *
1010
- * @example
1011
- * ```typescript
1012
- * padString("Hello", 10); // "Hello "
1013
- * padString("Hello", 10, "*"); // "Hello*****"
1014
- * padString("Hello", 10, "0", false); // "00000Hello"
1015
- * ```
1016
- */
1017
- function padString(str, length, char = " ", padEnd = true) {
1018
- if (!str)
1019
- return "";
1020
- if (str.length >= length)
1021
- return str;
1022
- const padding = char.repeat(length - str.length);
1023
- return padEnd ? str + padding : padding + str;
1024
- }
1025
- /**
1026
- * Escapes special characters in a string for use in regular expressions.
1027
- *
1028
- * @param {string} str - The string to escape
1029
- * @returns {string} - The escaped string safe for use in RegExp
1030
- *
1031
- * @example
1032
- * ```typescript
1033
- * escapeRegExp("hello.world*"); // "hello\.world\*"
1034
- *
1035
- * // Usage in RegExp:
1036
- * const userInput = "hello.world*";
1037
- * const regex = new RegExp(escapeRegExp(userInput));
1038
- * ```
1039
- */
1040
- function escapeRegExp(str) {
1041
- return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1042
- }
1043
- /**
1044
- * Capitalizes each word in a string according to title case rules.
1045
- *
1046
- * This function implements proper title case rules, where:
1047
- * - The first and last words are always capitalized
1048
- * - All other major words are capitalized
1049
- * - Minor words (articles, conjunctions, short prepositions) are not capitalized
1050
- * unless they are the first or last word
1051
- *
1052
- * @param {string} str - The string to convert to title case
1053
- * @returns {string} - The string in proper title case format
1054
- *
1055
- * @example
1056
- * ```typescript
1057
- * toProperTitleCase("the quick brown fox jumps over the lazy dog");
1058
- * // "The Quick Brown Fox Jumps over the Lazy Dog"
1059
- *
1060
- * toProperTitleCase("a tale of two cities");
1061
- * // "A Tale of Two Cities"
1062
- * ```
1063
- */
1064
- function toProperTitleCase(str) {
1065
- if (!str)
1066
- return "";
1067
- const minorWords = [
1068
- "a",
1069
- "an",
1070
- "and",
1071
- "as",
1072
- "at",
1073
- "but",
1074
- "by",
1075
- "for",
1076
- "in",
1077
- "nor",
1078
- "of",
1079
- "on",
1080
- "or",
1081
- "per",
1082
- "the",
1083
- "to",
1084
- "via",
1085
- "vs",
1086
- ];
1087
- const words = str.toLowerCase().split(/\s+/);
1088
- const result = words.map((word, index) => {
1089
- // Always capitalize first and last word
1090
- if (index === 0 || index === words.length - 1) {
1091
- return toFirstCase(word);
1092
- }
1093
- // Don't capitalize minor words
1094
- if (minorWords.includes(word.toLowerCase())) {
1095
- return word.toLowerCase();
1096
- }
1097
- // Capitalize major words
1098
- return toFirstCase(word);
1099
- });
1100
- return result.join(" ");
1101
- }
1102
- /**
1103
- * Implementation of the format function that handles both overloads.
1104
- */
1105
- function format(template, ...values) {
1106
- if (!template)
1107
- return "";
1108
- // If the first value is an object (for named placeholders), use it directly
1109
- if (values.length === 1 && typeof values[0] === "object" && values[0] !== null && !Array.isArray(values[0])) {
1110
- const replacements = values[0];
1111
- return template.replace(/{([^{}]+)}/g, (match, key) => {
1112
- const value = replacements[key];
1113
- return value !== undefined ? String(value) : match;
1114
- });
1115
- }
1116
- // Otherwise use indexed placeholders
1117
- return template.replace(/{(\d+)}/g, (match, index) => {
1118
- const value = values[Number(index)];
1119
- return value !== undefined ? String(value) : match;
1120
- });
1121
- }
1122
- /**
1123
- * Counts the occurrences of a substring within a string.
1124
- *
1125
- * @param {string} str - The string to search within
1126
- * @param {string} searchValue - The substring to search for
1127
- * @param {boolean} [caseSensitive=true] - Whether the search should be case-sensitive
1128
- * @returns {number} - The number of occurrences
1129
- *
1130
- * @example
1131
- * ```typescript
1132
- * countOccurrences("hello hello world", "hello"); // 2
1133
- * countOccurrences("Hello hello", "hello", false); // 2
1134
- * countOccurrences("Hello hello", "hello", true); // 1
1135
- * ```
1136
- */
1137
- function countOccurrences(str, searchValue, caseSensitive = true) {
1138
- if (!str || !searchValue)
1139
- return 0;
1140
- const regex = new RegExp(escapeRegExp(searchValue), caseSensitive ? "g" : "gi");
1141
- const matches = str.match(regex);
1142
- return matches ? matches.length : 0;
1143
- }
1144
- /**
1145
- * Reverses a string.
1146
- *
1147
- * @param {string} str - The string to reverse
1148
- * @returns {string} - The reversed string
1149
- *
1150
- * @example
1151
- * ```typescript
1152
- * reverse("hello"); // "olleh"
1153
- * reverse("12345"); // "54321"
1154
- * ```
1155
- */
1156
- function reverse(str) {
1157
- if (!str)
1158
- return "";
1159
- return str.split("").reverse().join("");
1160
- }
1161
- /**
1162
- * Checks if a string contains only alphanumeric characters.
1163
- *
1164
- * @param {string} str - The string to check
1165
- * @returns {boolean} - True if the string contains only alphanumeric characters
1166
- *
1167
- * @example
1168
- * ```typescript
1169
- * isAlphanumeric("abc123"); // true
1170
- * isAlphanumeric("abc-123"); // false
1171
- * ```
1172
- */
1173
- function isAlphanumeric(str) {
1174
- if (!str)
1175
- return false;
1176
- return /^[a-zA-Z0-9]+$/.test(str);
1177
- }
1178
- /**
1179
- * Removes all whitespace from a string.
1180
- *
1181
- * @param {string} str - The string to process
1182
- * @returns {string} - The string with all whitespace removed
1183
- *
1184
- * @example
1185
- * ```typescript
1186
- * removeWhitespace("hello world"); // "helloworld"
1187
- * removeWhitespace(" spaces tabs "); // "spacestabs"
1188
- * ```
1189
- */
1190
- function removeWhitespace(str) {
1191
- if (!str)
1192
- return "";
1193
- return str.replace(/\s+/g, "");
1194
- }
1195
- /**
1196
- * Converts plural English words to their singular form.
1197
- *
1198
- * This function applies a series of linguistic rules and exceptions to transform
1199
- * plural English words into their singular equivalents. It handles irregular plurals
1200
- * (e.g., "children" → "child"), common suffix patterns (e.g., "parties" → "party"),
1201
- * and Latin-derived words (e.g., "cacti" → "cactus").
1202
- *
1203
- * The function applies rules in priority order, from most specific to most general,
1204
- * to ensure correct handling of special cases.
1205
- *
1206
- * @param {string} str - The plural word to convert to singular form
1207
- * @returns {string} - The singular form of the word, or the original string if:
1208
- * - Input is empty/falsy
1209
- * - No singular form is recognized
1210
- * - The word is already singular
1211
- *
1212
- * @example
1213
- * ```typescript
1214
- * // Irregular plurals
1215
- * singular("children"); // "child"
1216
- * singular("men"); // "man"
1217
- * singular("feet"); // "foot"
1218
- *
1219
- * // Common patterns
1220
- * singular("cats"); // "cat"
1221
- * singular("boxes"); // "box"
1222
- * singular("parties"); // "party"
1223
- * singular("wolves"); // "wolf"
1224
- *
1225
- * // Latin-derived words
1226
- * singular("cacti"); // "cactus"
1227
- * singular("phenomena"); // "phenomenon"
1228
- * ```
1229
- *
1230
- * @remarks
1231
- * - This function is designed for English language words only
1232
- * - It handles many common cases but isn't exhaustive for all English plurals
1233
- * - Words that are identical in singular and plural form (e.g., "sheep") are returned unchanged
1234
- */
1235
- function singular(str) {
1236
- if (!str)
1237
- return str;
1238
- // Combine all rules in priority order
1239
- const rules = [
1240
- ...constants_1.EnglishInflectionRules.INVARIANT,
1241
- ...constants_1.EnglishInflectionRules.IRREGULAR.toSingular,
1242
- ...constants_1.EnglishInflectionRules.LATIN_GREEK.toSingular,
1243
- ...constants_1.EnglishInflectionRules.PATTERN_RULES.toSingular,
1244
- ...constants_1.EnglishInflectionRules.DEFAULT.toSingular,
1245
- ];
1246
- // Iterate over rules and apply the first matching one
1247
- for (const rule of rules) {
1248
- if (rule.regex.test(str)) {
1249
- return str.replace(rule.regex, typeof rule.replacement === "string" ? rule.replacement : rule.replacement(str));
1250
- }
1251
- }
1252
- // Return the original string if no rules match
1253
- return str;
1254
- }
1255
- //# sourceMappingURL=string.utils.js.map