@stacksjs/strings 0.70.22 → 0.70.25
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/README.md +1 -1
- package/dist/index.js +396 -84
- package/dist/{case.d.ts → src/case.d.ts} +74 -19
- package/dist/src/detect-indent.d.ts +2 -0
- package/dist/{detect-newline.d.ts → src/detect-newline.d.ts} +1 -1
- package/dist/src/helpers.d.ts +1 -0
- package/dist/src/index.d.ts +2 -0
- package/dist/src/macro.d.ts +36 -0
- package/dist/src/pluralize.d.ts +20 -0
- package/dist/src/slug.d.ts +13 -0
- package/dist/src/sponge-case.d.ts +2 -0
- package/dist/src/string.d.ts +7 -0
- package/dist/src/swap-case.d.ts +2 -0
- package/dist/{title-case.d.ts → src/title-case.d.ts} +1 -2
- package/dist/src/utils.d.ts +78 -0
- package/dist/{is.d.ts → src/validators.d.ts} +136 -10
- package/package.json +16 -10
- package/dist/detect-indent.d.ts +0 -9
- package/dist/helpers.d.ts +0 -1
- package/dist/index.d.ts +0 -2
- package/dist/macro.d.ts +0 -35
- package/dist/pluralize.d.ts +0 -33
- package/dist/slug.d.ts +0 -16
- package/dist/sponge-case.d.ts +0 -1
- package/dist/string.d.ts +0 -6
- package/dist/swap-case.d.ts +0 -1
- package/dist/utils.d.ts +0 -19
package/README.md
CHANGED
|
@@ -94,7 +94,7 @@ console.log(camelCase('hello world')) // => "helloWorld"
|
|
|
94
94
|
console.log(plural('dog')) // => "dogs"
|
|
95
95
|
```
|
|
96
96
|
|
|
97
|
-
To view the full documentation, please visit [https://stacksjs.
|
|
97
|
+
To view the full documentation, please visit [<https://stacksjs.com/string>s](https://stacksjs.com/strings).
|
|
98
98
|
|
|
99
99
|
## 🧪 Testing
|
|
100
100
|
|
package/dist/index.js
CHANGED
|
@@ -1,63 +1,4 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __export = (target, all) => {
|
|
4
|
-
for (var name in all)
|
|
5
|
-
__defProp(target, name, {
|
|
6
|
-
get: all[name],
|
|
7
|
-
enumerable: true,
|
|
8
|
-
configurable: true,
|
|
9
|
-
set: (newValue) => all[name] = () => newValue
|
|
10
|
-
});
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
// src/string.ts
|
|
14
|
-
var exports_string = {};
|
|
15
|
-
__export(exports_string, {
|
|
16
|
-
urlAlphabet: () => urlAlphabet,
|
|
17
|
-
truncate: () => truncate,
|
|
18
|
-
trainCase: () => trainCase,
|
|
19
|
-
toString: () => toString,
|
|
20
|
-
titleCase: () => titleCase,
|
|
21
|
-
template: () => template,
|
|
22
|
-
swapCase: () => swapCase,
|
|
23
|
-
str: () => str,
|
|
24
|
-
spongeCase: () => spongeCase,
|
|
25
|
-
splitSeparateNumbers: () => splitSeparateNumbers,
|
|
26
|
-
split: () => split,
|
|
27
|
-
snakeCase: () => snakeCase,
|
|
28
|
-
slugify: () => slugify,
|
|
29
|
-
slug: () => slug,
|
|
30
|
-
slash: () => slash,
|
|
31
|
-
singular: () => singular,
|
|
32
|
-
sentenceCase: () => sentenceCase,
|
|
33
|
-
random: () => random,
|
|
34
|
-
pluralize: () => pluralize,
|
|
35
|
-
plural: () => plural,
|
|
36
|
-
pathCase: () => pathCase,
|
|
37
|
-
pascalSnakeCase: () => pascalSnakeCase,
|
|
38
|
-
pascalCase: () => pascalCase,
|
|
39
|
-
paramCase: () => paramCase,
|
|
40
|
-
noCase: () => noCase,
|
|
41
|
-
lowercase: () => lowercase,
|
|
42
|
-
kebabCase: () => kebabCase,
|
|
43
|
-
extendCharMap: () => extendCharMap,
|
|
44
|
-
ensureSuffix: () => ensureSuffix,
|
|
45
|
-
ensurePrefix: () => ensurePrefix,
|
|
46
|
-
dotCase: () => dotCase,
|
|
47
|
-
detectNewlineGraceful: () => detectNewlineGraceful,
|
|
48
|
-
detectNewline: () => detectNewline,
|
|
49
|
-
detectIndent: () => detectIndent,
|
|
50
|
-
constantCase: () => constantCase,
|
|
51
|
-
capitalize: () => capitalize,
|
|
52
|
-
capitalCase: () => capitalCase,
|
|
53
|
-
camelCase: () => camelCase,
|
|
54
|
-
WORD_SEPARATORS: () => WORD_SEPARATORS,
|
|
55
|
-
TITLE_TERMINATORS: () => TITLE_TERMINATORS,
|
|
56
|
-
Str: () => Str,
|
|
57
|
-
SMALL_WORDS: () => SMALL_WORDS,
|
|
58
|
-
SENTENCE_TERMINATORS: () => SENTENCE_TERMINATORS
|
|
59
|
-
});
|
|
60
|
-
|
|
61
2
|
// src/sponge-case.ts
|
|
62
3
|
function spongeCase(input, locale) {
|
|
63
4
|
let result = "";
|
|
@@ -146,6 +87,8 @@ function titleCase(input, options = {}) {
|
|
|
146
87
|
result += whiteSpace;
|
|
147
88
|
continue;
|
|
148
89
|
}
|
|
90
|
+
if (token === undefined)
|
|
91
|
+
continue;
|
|
149
92
|
if (IS_SPECIAL_CASE.test(token)) {
|
|
150
93
|
const acronym = token.match(IS_ACRONYM);
|
|
151
94
|
if (acronym) {
|
|
@@ -161,7 +104,10 @@ function titleCase(input, options = {}) {
|
|
|
161
104
|
let value = token;
|
|
162
105
|
let isSentenceEnd = false;
|
|
163
106
|
for (let i = 0;i < matches.length; i++) {
|
|
164
|
-
const
|
|
107
|
+
const match = matches[i];
|
|
108
|
+
if (!match)
|
|
109
|
+
continue;
|
|
110
|
+
const { 0: word, index: wordIndex = 0 } = match;
|
|
165
111
|
const nextChar = token.charAt(wordIndex + word.length);
|
|
166
112
|
isSentenceEnd = terminators.has(nextChar);
|
|
167
113
|
if (isNewSentence) {
|
|
@@ -226,9 +172,11 @@ function splitSeparateNumbers(value) {
|
|
|
226
172
|
const words = split(value);
|
|
227
173
|
for (let i = 0;i < words.length; i++) {
|
|
228
174
|
const word = words[i];
|
|
175
|
+
if (word === undefined)
|
|
176
|
+
continue;
|
|
229
177
|
const match = SPLIT_SEPARATE_NUMBER_RE.exec(word);
|
|
230
178
|
if (match) {
|
|
231
|
-
const offset = match.index + (match[1] ?? match[2]).length;
|
|
179
|
+
const offset = match.index + (match[1] ?? match[2] ?? "").length;
|
|
232
180
|
words.splice(i, 1, word.slice(0, offset), word.slice(offset));
|
|
233
181
|
}
|
|
234
182
|
}
|
|
@@ -305,11 +253,17 @@ function upperFactory(locale) {
|
|
|
305
253
|
return locale === false ? (input) => input.toUpperCase() : (input) => input.toLocaleUpperCase(locale);
|
|
306
254
|
}
|
|
307
255
|
function capitalCaseTransformFactory(lower, upper) {
|
|
308
|
-
return (word) =>
|
|
256
|
+
return (word) => {
|
|
257
|
+
if (!word)
|
|
258
|
+
return word;
|
|
259
|
+
return `${upper(word[0] ?? "")}${lower(word.slice(1))}`;
|
|
260
|
+
};
|
|
309
261
|
}
|
|
310
262
|
function pascalCaseTransformFactory(lower, upper) {
|
|
311
263
|
return (word, index) => {
|
|
312
|
-
|
|
264
|
+
if (!word)
|
|
265
|
+
return word;
|
|
266
|
+
const char0 = word[0] ?? "";
|
|
313
267
|
const initial = index > 0 && char0 >= "0" && char0 <= "9" ? `_${char0}` : upper(char0);
|
|
314
268
|
return initial + lower(word.slice(1));
|
|
315
269
|
};
|
|
@@ -339,10 +293,12 @@ function splitPrefixSuffix(input, options = {}) {
|
|
|
339
293
|
input.slice(suffixIndex)
|
|
340
294
|
];
|
|
341
295
|
}
|
|
296
|
+
|
|
342
297
|
// src/helpers.ts
|
|
343
298
|
function toString(v) {
|
|
344
299
|
return Object.prototype.toString.call(v);
|
|
345
300
|
}
|
|
301
|
+
|
|
346
302
|
// src/pluralize.ts
|
|
347
303
|
var pluralRules = [];
|
|
348
304
|
var singularRules = [];
|
|
@@ -359,19 +315,20 @@ function restoreCase(word, token) {
|
|
|
359
315
|
return token.toLowerCase();
|
|
360
316
|
if (word === word.toUpperCase())
|
|
361
317
|
return token.toUpperCase();
|
|
362
|
-
|
|
318
|
+
const firstChar = word[0];
|
|
319
|
+
if (firstChar !== undefined && firstChar === firstChar.toUpperCase()) {
|
|
363
320
|
return token.charAt(0).toUpperCase() + token.slice(1).toLowerCase();
|
|
364
321
|
}
|
|
365
322
|
return token.toLowerCase();
|
|
366
323
|
}
|
|
367
324
|
function interpolate(str, ...args) {
|
|
368
|
-
return str.replace(/\$(\d{1,2})/g, (
|
|
325
|
+
return str.replace(/\$(\d{1,2})/g, (_match, index) => args[Number(index)] || "");
|
|
369
326
|
}
|
|
370
327
|
function replace(word, rule) {
|
|
371
328
|
return word.replace(rule[0], (...matchArgs) => {
|
|
372
329
|
const result = interpolate(rule[1], ...matchArgs);
|
|
373
330
|
if (matchArgs[0] === "") {
|
|
374
|
-
return restoreCase(word[matchArgs[matchArgs.length - 2] - 1], result);
|
|
331
|
+
return restoreCase(word[matchArgs[matchArgs.length - 2] - 1] ?? "", result);
|
|
375
332
|
}
|
|
376
333
|
return restoreCase(matchArgs[0], result);
|
|
377
334
|
});
|
|
@@ -382,7 +339,7 @@ function sanitizeWord(token, word, rules) {
|
|
|
382
339
|
}
|
|
383
340
|
for (let i = rules.length - 1;i >= 0; i--) {
|
|
384
341
|
const rule = rules[i];
|
|
385
|
-
if (rule[0].test(word))
|
|
342
|
+
if (rule && rule[0].test(word))
|
|
386
343
|
return replace(word, rule);
|
|
387
344
|
}
|
|
388
345
|
return word;
|
|
@@ -498,7 +455,7 @@ pluralize.addIrregularRule = (single, plural2) => {
|
|
|
498
455
|
["pickaxe", "pickaxes"],
|
|
499
456
|
["passerby", "passersby"],
|
|
500
457
|
["canvas", "canvases"]
|
|
501
|
-
].forEach(([single, plural2]) => pluralize.addIrregularRule(single, plural2));
|
|
458
|
+
].forEach(([single, plural2]) => pluralize.addIrregularRule(single ?? "", plural2 ?? ""));
|
|
502
459
|
[
|
|
503
460
|
[/s?$/i, "s"],
|
|
504
461
|
[/[^\x20-\x7F]$/, "$0"],
|
|
@@ -525,7 +482,11 @@ pluralize.addIrregularRule = (single, plural2) => {
|
|
|
525
482
|
[/eaux$/i, "$0"],
|
|
526
483
|
[/m[ae]n$/i, "men"],
|
|
527
484
|
["thou", "you"]
|
|
528
|
-
].forEach(([rule, replacement]) =>
|
|
485
|
+
].forEach(([rule, replacement]) => {
|
|
486
|
+
if (rule === undefined)
|
|
487
|
+
return;
|
|
488
|
+
pluralize.addPluralRule(rule, replacement);
|
|
489
|
+
});
|
|
529
490
|
[
|
|
530
491
|
[/s$/i, ""],
|
|
531
492
|
[/(ss)$/i, "$1"],
|
|
@@ -551,7 +512,11 @@ pluralize.addIrregularRule = (single, plural2) => {
|
|
|
551
512
|
[/(child)ren$/i, "$1"],
|
|
552
513
|
[/(eau)x?$/i, "$1"],
|
|
553
514
|
[/men$/i, "man"]
|
|
554
|
-
].forEach(([rule, replacement]) =>
|
|
515
|
+
].forEach(([rule, replacement]) => {
|
|
516
|
+
if (rule === undefined)
|
|
517
|
+
return;
|
|
518
|
+
pluralize.addSingularRule(rule, replacement);
|
|
519
|
+
});
|
|
555
520
|
[
|
|
556
521
|
"adulthood",
|
|
557
522
|
"advice",
|
|
@@ -695,7 +660,7 @@ function makeIndentsMap(string, ignoreSingleSpaces = true) {
|
|
|
695
660
|
const indents = new Map;
|
|
696
661
|
let previousSize = 0;
|
|
697
662
|
let previousIndentType;
|
|
698
|
-
let key;
|
|
663
|
+
let key = "";
|
|
699
664
|
for (const line of string.split(/\n/g)) {
|
|
700
665
|
if (!line) {
|
|
701
666
|
continue;
|
|
@@ -773,13 +738,10 @@ function detectIndent(string) {
|
|
|
773
738
|
indents = makeIndentsMap(string, false);
|
|
774
739
|
}
|
|
775
740
|
const keyOfMostUsedIndent = getMostUsedKey(indents);
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
({ type, amount } = decodeIndentsKey(keyOfMostUsedIndent));
|
|
781
|
-
indent = makeIndentString(type, amount);
|
|
782
|
-
}
|
|
741
|
+
const decoded = keyOfMostUsedIndent !== undefined ? decodeIndentsKey(keyOfMostUsedIndent) : undefined;
|
|
742
|
+
const type = decoded?.type;
|
|
743
|
+
const amount = decoded?.amount ?? 0;
|
|
744
|
+
const indent = decoded ? makeIndentString(type, amount) : "";
|
|
783
745
|
return {
|
|
784
746
|
amount,
|
|
785
747
|
type,
|
|
@@ -823,7 +785,7 @@ function ensureSuffix(suffix, str) {
|
|
|
823
785
|
function template(str, ...args) {
|
|
824
786
|
return str.replace(/\{(\d+)\}/g, (match, key) => {
|
|
825
787
|
const index = Number(key);
|
|
826
|
-
return Number.isNaN(index) ? match : args[index];
|
|
788
|
+
return Number.isNaN(index) || args[index] === undefined ? match : args[index];
|
|
827
789
|
});
|
|
828
790
|
}
|
|
829
791
|
function truncate(str, length, end = "...") {
|
|
@@ -832,11 +794,15 @@ function truncate(str, length, end = "...") {
|
|
|
832
794
|
return str.slice(0, length - end.length) + end;
|
|
833
795
|
}
|
|
834
796
|
function random(size = 16, dict = urlAlphabet) {
|
|
835
|
-
let id = "";
|
|
836
|
-
let i = size;
|
|
837
797
|
const len = dict.length;
|
|
838
|
-
|
|
839
|
-
|
|
798
|
+
const g = globalThis;
|
|
799
|
+
if (!g.crypto?.getRandomValues)
|
|
800
|
+
throw new Error("[strings.random] crypto.getRandomValues is not available; cannot generate secure random string.");
|
|
801
|
+
const bytes = new Uint8Array(size);
|
|
802
|
+
g.crypto.getRandomValues(bytes);
|
|
803
|
+
let id = "";
|
|
804
|
+
for (let i = 0;i < size; i++)
|
|
805
|
+
id += dict[(bytes[i] ?? 0) % len];
|
|
840
806
|
return id;
|
|
841
807
|
}
|
|
842
808
|
function slug(str, options) {
|
|
@@ -942,7 +908,312 @@ var Str = {
|
|
|
942
908
|
}
|
|
943
909
|
};
|
|
944
910
|
var str = Str;
|
|
911
|
+
|
|
912
|
+
// src/validators.ts
|
|
913
|
+
function isEmail(email) {
|
|
914
|
+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
915
|
+
return emailRegex.test(email);
|
|
916
|
+
}
|
|
917
|
+
function isStrongPassword(password) {
|
|
918
|
+
if (password.length < 8)
|
|
919
|
+
return false;
|
|
920
|
+
const hasUpperCase = /[A-Z]/.test(password);
|
|
921
|
+
const hasLowerCase = /[a-z]/.test(password);
|
|
922
|
+
const hasNumber = /\d/.test(password);
|
|
923
|
+
const hasSymbol = /[!@#$%^&*()_+\-=[\]{};':"\\|,.<>/?]/.test(password);
|
|
924
|
+
return hasUpperCase && hasLowerCase && hasNumber && hasSymbol;
|
|
925
|
+
}
|
|
926
|
+
function isAlphanumeric(str2) {
|
|
927
|
+
return /^[a-zA-Z0-9]+$/.test(str2);
|
|
928
|
+
}
|
|
929
|
+
function isURL(url) {
|
|
930
|
+
try {
|
|
931
|
+
const parsed = new URL(url);
|
|
932
|
+
return parsed.protocol === "http:" || parsed.protocol === "https:";
|
|
933
|
+
} catch {
|
|
934
|
+
return false;
|
|
935
|
+
}
|
|
936
|
+
}
|
|
937
|
+
function isMobilePhone(phoneNumber) {
|
|
938
|
+
const phoneRegex = /^\+?[1-9]\d{6,14}$/;
|
|
939
|
+
const cleaned = phoneNumber.replace(/[\s()-]/g, "");
|
|
940
|
+
return phoneRegex.test(cleaned);
|
|
941
|
+
}
|
|
942
|
+
function isAlpha(str2) {
|
|
943
|
+
return /^[a-zA-Z]+$/.test(str2);
|
|
944
|
+
}
|
|
945
|
+
function isPostalCode(zipCode) {
|
|
946
|
+
const usZip = /^\d{5}(-\d{4})?$/;
|
|
947
|
+
const ukPostcode = /^[A-Z]{1,2}\d{1,2}[A-Z]?\s?\d[A-Z]{2}$/i;
|
|
948
|
+
const canadaPostcode = /^[A-Z]\d[A-Z]\s?\d[A-Z]\d$/i;
|
|
949
|
+
const generic = /^[a-zA-Z0-9]{3,10}$/;
|
|
950
|
+
return usZip.test(zipCode) || ukPostcode.test(zipCode) || canadaPostcode.test(zipCode) || generic.test(zipCode);
|
|
951
|
+
}
|
|
952
|
+
function isNumeric(str2) {
|
|
953
|
+
return /^\d+$/.test(str2);
|
|
954
|
+
}
|
|
955
|
+
function isHexColor(color) {
|
|
956
|
+
return /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/.test(color);
|
|
957
|
+
}
|
|
958
|
+
function isHexadecimal(hex) {
|
|
959
|
+
return /^[A-Fa-f0-9]+$/.test(hex);
|
|
960
|
+
}
|
|
961
|
+
function isBase64(base64) {
|
|
962
|
+
try {
|
|
963
|
+
return btoa(atob(base64)) === base64;
|
|
964
|
+
} catch {
|
|
965
|
+
return false;
|
|
966
|
+
}
|
|
967
|
+
}
|
|
968
|
+
function isUUID(uuid) {
|
|
969
|
+
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
970
|
+
return uuidRegex.test(uuid);
|
|
971
|
+
}
|
|
972
|
+
function isJSON(json) {
|
|
973
|
+
try {
|
|
974
|
+
JSON.parse(json);
|
|
975
|
+
return true;
|
|
976
|
+
} catch {
|
|
977
|
+
return false;
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
function isCreditCard(creditCard) {
|
|
981
|
+
const cleaned = creditCard.replace(/[\s-]/g, "");
|
|
982
|
+
if (!/^\d{13,19}$/.test(cleaned))
|
|
983
|
+
return false;
|
|
984
|
+
let sum = 0;
|
|
985
|
+
let isEven = false;
|
|
986
|
+
for (let i = cleaned.length - 1;i >= 0; i--) {
|
|
987
|
+
let digit = parseInt(cleaned.charAt(i), 10);
|
|
988
|
+
if (isEven) {
|
|
989
|
+
digit *= 2;
|
|
990
|
+
if (digit > 9)
|
|
991
|
+
digit -= 9;
|
|
992
|
+
}
|
|
993
|
+
sum += digit;
|
|
994
|
+
isEven = !isEven;
|
|
995
|
+
}
|
|
996
|
+
return sum % 10 === 0;
|
|
997
|
+
}
|
|
998
|
+
function isISBN(isbn) {
|
|
999
|
+
const cleaned = isbn.replace(/[\s-]/g, "");
|
|
1000
|
+
if (cleaned.length === 10) {
|
|
1001
|
+
let sum = 0;
|
|
1002
|
+
for (let i = 0;i < 9; i++) {
|
|
1003
|
+
const digit = parseInt(cleaned.charAt(i), 10);
|
|
1004
|
+
if (isNaN(digit))
|
|
1005
|
+
return false;
|
|
1006
|
+
sum += digit * (10 - i);
|
|
1007
|
+
}
|
|
1008
|
+
const checkChar = cleaned.charAt(9);
|
|
1009
|
+
const checkDigit = checkChar === "X" ? 10 : parseInt(checkChar, 10);
|
|
1010
|
+
if (isNaN(checkDigit) && checkChar !== "X")
|
|
1011
|
+
return false;
|
|
1012
|
+
sum += checkDigit;
|
|
1013
|
+
return sum % 11 === 0;
|
|
1014
|
+
}
|
|
1015
|
+
if (cleaned.length === 13) {
|
|
1016
|
+
let sum = 0;
|
|
1017
|
+
for (let i = 0;i < 12; i++) {
|
|
1018
|
+
const digit = parseInt(cleaned.charAt(i), 10);
|
|
1019
|
+
if (isNaN(digit))
|
|
1020
|
+
return false;
|
|
1021
|
+
sum += digit * (i % 2 === 0 ? 1 : 3);
|
|
1022
|
+
}
|
|
1023
|
+
const checkDigit = parseInt(cleaned.charAt(12), 10);
|
|
1024
|
+
if (isNaN(checkDigit))
|
|
1025
|
+
return false;
|
|
1026
|
+
return (10 - sum % 10) % 10 === checkDigit;
|
|
1027
|
+
}
|
|
1028
|
+
return false;
|
|
1029
|
+
}
|
|
1030
|
+
function isIP(ip) {
|
|
1031
|
+
const ipv4Regex = /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
|
|
1032
|
+
if (ipv4Regex.test(ip))
|
|
1033
|
+
return true;
|
|
1034
|
+
const ipv6Regex = /^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/;
|
|
1035
|
+
return ipv6Regex.test(ip);
|
|
1036
|
+
}
|
|
1037
|
+
function isIPRange(ip) {
|
|
1038
|
+
const parts = ip.split("/");
|
|
1039
|
+
if (parts.length !== 2)
|
|
1040
|
+
return false;
|
|
1041
|
+
const [address, cidr] = parts;
|
|
1042
|
+
if (address === undefined || cidr === undefined)
|
|
1043
|
+
return false;
|
|
1044
|
+
const cidrNum = parseInt(cidr, 10);
|
|
1045
|
+
if (!isIP(address))
|
|
1046
|
+
return false;
|
|
1047
|
+
if (address.includes(":")) {
|
|
1048
|
+
return cidrNum >= 0 && cidrNum <= 128;
|
|
1049
|
+
} else {
|
|
1050
|
+
return cidrNum >= 0 && cidrNum <= 32;
|
|
1051
|
+
}
|
|
1052
|
+
}
|
|
1053
|
+
function isMACAddress(macAddress) {
|
|
1054
|
+
const macRegex = /^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$/;
|
|
1055
|
+
return macRegex.test(macAddress);
|
|
1056
|
+
}
|
|
1057
|
+
function isLatLong(latlong) {
|
|
1058
|
+
const parts = latlong.split(",");
|
|
1059
|
+
if (parts.length !== 2)
|
|
1060
|
+
return false;
|
|
1061
|
+
const lat = parseFloat((parts[0] ?? "").trim());
|
|
1062
|
+
const long = parseFloat((parts[1] ?? "").trim());
|
|
1063
|
+
return !isNaN(lat) && !isNaN(long) && lat >= -90 && lat <= 90 && long >= -180 && long <= 180;
|
|
1064
|
+
}
|
|
1065
|
+
function isCurrency(currency) {
|
|
1066
|
+
const currencyRegex = /^[$\u00A3\u20AC\u00A5]?\d{1,3}(,?\d{3})*(\.\d{2})?$/;
|
|
1067
|
+
return currencyRegex.test(currency.trim());
|
|
1068
|
+
}
|
|
1069
|
+
function isDataURI(dataURI) {
|
|
1070
|
+
const dataURIRegex = /^data:([a-z]+\/[a-z0-9-+.]+(;[a-z-]+=[a-z0-9-]+)*)?;base64,([a-z0-9+/]+=*)/i;
|
|
1071
|
+
return dataURIRegex.test(dataURI) || /^data:,/.test(dataURI);
|
|
1072
|
+
}
|
|
1073
|
+
function isMimeType(mimeType) {
|
|
1074
|
+
const mimeTypeRegex = /^[a-z]+\/[a-z0-9\-+.]+$/i;
|
|
1075
|
+
return mimeTypeRegex.test(mimeType);
|
|
1076
|
+
}
|
|
1077
|
+
function isJWT(jwt) {
|
|
1078
|
+
const parts = jwt.split(".");
|
|
1079
|
+
if (parts.length !== 3)
|
|
1080
|
+
return false;
|
|
1081
|
+
try {
|
|
1082
|
+
parts.forEach((part) => {
|
|
1083
|
+
atob(part.replace(/-/g, "+").replace(/_/g, "/"));
|
|
1084
|
+
});
|
|
1085
|
+
return true;
|
|
1086
|
+
} catch {
|
|
1087
|
+
return false;
|
|
1088
|
+
}
|
|
1089
|
+
}
|
|
1090
|
+
function isAscii(ascii) {
|
|
1091
|
+
return /^[\x00-\x7F]*$/.test(ascii);
|
|
1092
|
+
}
|
|
1093
|
+
function isBase32(base32) {
|
|
1094
|
+
return /^[A-Z2-7]+=*$/.test(base32.toUpperCase());
|
|
1095
|
+
}
|
|
1096
|
+
function isByteLength(str2, options) {
|
|
1097
|
+
const min = options?.min ?? 0;
|
|
1098
|
+
const max = options?.max ?? Infinity;
|
|
1099
|
+
const byteLength = new TextEncoder().encode(str2).length;
|
|
1100
|
+
return byteLength >= min && byteLength <= max;
|
|
1101
|
+
}
|
|
1102
|
+
function isFQDN(fqdn) {
|
|
1103
|
+
const fqdnRegex = /^(?=.{1,253}$)((?!-)[A-Za-z0-9-]{1,63}(?<!-)\.)+[A-Za-z]{2,}$/;
|
|
1104
|
+
return fqdnRegex.test(fqdn);
|
|
1105
|
+
}
|
|
1106
|
+
function isFullWidth(fullWidth) {
|
|
1107
|
+
return /^[\uFF00-\uFFEF]+$/.test(fullWidth);
|
|
1108
|
+
}
|
|
1109
|
+
function isHalfWidth(halfWidth) {
|
|
1110
|
+
return /^[\u0020-\u007E\uFF61-\uFF9F]+$/.test(halfWidth);
|
|
1111
|
+
}
|
|
1112
|
+
function isHash(hash, algorithm) {
|
|
1113
|
+
const hashLengths = {
|
|
1114
|
+
md5: 32,
|
|
1115
|
+
sha1: 40,
|
|
1116
|
+
sha256: 64,
|
|
1117
|
+
sha384: 96,
|
|
1118
|
+
sha512: 128
|
|
1119
|
+
};
|
|
1120
|
+
const expectedLength = hashLengths[algorithm];
|
|
1121
|
+
if (!expectedLength)
|
|
1122
|
+
return false;
|
|
1123
|
+
return hash.length === expectedLength && /^[a-f0-9]+$/i.test(hash);
|
|
1124
|
+
}
|
|
1125
|
+
function isHSL(hsl) {
|
|
1126
|
+
const hslRegex = /^hsl\(\s*(\d+)\s*,\s*(\d+(?:\.\d+)?%)\s*,\s*(\d+(?:\.\d+)?%)\s*\)$/;
|
|
1127
|
+
return hslRegex.test(hsl);
|
|
1128
|
+
}
|
|
1129
|
+
function isIBAN(iban) {
|
|
1130
|
+
const cleaned = iban.replace(/\s/g, "").toUpperCase();
|
|
1131
|
+
if (!/^[A-Z]{2}\d{2}[A-Z0-9]+$/.test(cleaned))
|
|
1132
|
+
return false;
|
|
1133
|
+
if (cleaned.length < 15 || cleaned.length > 34)
|
|
1134
|
+
return false;
|
|
1135
|
+
const rearranged = cleaned.slice(4) + cleaned.slice(0, 4);
|
|
1136
|
+
const digits = rearranged.split("").map((char) => {
|
|
1137
|
+
const code = char.charCodeAt(0);
|
|
1138
|
+
return code >= 65 && code <= 90 ? (code - 55).toString() : char;
|
|
1139
|
+
}).join("");
|
|
1140
|
+
let remainder = digits.slice(0, 2);
|
|
1141
|
+
for (let i = 2;i < digits.length; i += 7) {
|
|
1142
|
+
remainder = (parseInt(remainder + digits.slice(i, i + 7), 10) % 97).toString();
|
|
1143
|
+
}
|
|
1144
|
+
return parseInt(remainder, 10) === 1;
|
|
1145
|
+
}
|
|
1146
|
+
function isIdentityCard(identityCard) {
|
|
1147
|
+
const cleaned = identityCard.replace(/[\s-]/g, "");
|
|
1148
|
+
return /^[A-Z0-9]{5,20}$/i.test(cleaned);
|
|
1149
|
+
}
|
|
1150
|
+
function isISIN(isin) {
|
|
1151
|
+
if (!/^[A-Z]{2}[A-Z0-9]{9}\d$/.test(isin))
|
|
1152
|
+
return false;
|
|
1153
|
+
const digits = isin.split("").map((char) => {
|
|
1154
|
+
const code = char.charCodeAt(0);
|
|
1155
|
+
return code >= 65 && code <= 90 ? (code - 55).toString() : char;
|
|
1156
|
+
}).join("");
|
|
1157
|
+
let sum = 0;
|
|
1158
|
+
let isEven = true;
|
|
1159
|
+
for (let i = digits.length - 1;i >= 0; i--) {
|
|
1160
|
+
let digit = parseInt(digits.charAt(i), 10);
|
|
1161
|
+
if (isEven) {
|
|
1162
|
+
digit *= 2;
|
|
1163
|
+
if (digit > 9)
|
|
1164
|
+
digit -= 9;
|
|
1165
|
+
}
|
|
1166
|
+
sum += digit;
|
|
1167
|
+
isEven = !isEven;
|
|
1168
|
+
}
|
|
1169
|
+
return sum % 10 === 0;
|
|
1170
|
+
}
|
|
1171
|
+
function isISO8601(iso8601) {
|
|
1172
|
+
const iso8601Regex = /^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}:\d{2}(\.\d{3})?(Z|[+-]\d{2}:\d{2})?)?$/;
|
|
1173
|
+
if (!iso8601Regex.test(iso8601))
|
|
1174
|
+
return false;
|
|
1175
|
+
try {
|
|
1176
|
+
const date = new Date(iso8601);
|
|
1177
|
+
return !isNaN(date.getTime());
|
|
1178
|
+
} catch {
|
|
1179
|
+
return false;
|
|
1180
|
+
}
|
|
1181
|
+
}
|
|
1182
|
+
function isISRC(isrc) {
|
|
1183
|
+
return /^[A-Z]{2}[A-Z0-9]{3}\d{2}\d{5}$/.test(isrc.replace(/-/g, ""));
|
|
1184
|
+
}
|
|
1185
|
+
function isISSN(issn) {
|
|
1186
|
+
const cleaned = issn.replace(/[\s-]/g, "");
|
|
1187
|
+
if (!/^\d{7}[\dX]$/.test(cleaned))
|
|
1188
|
+
return false;
|
|
1189
|
+
let sum = 0;
|
|
1190
|
+
for (let i = 0;i < 7; i++) {
|
|
1191
|
+
sum += parseInt(cleaned.charAt(i), 10) * (8 - i);
|
|
1192
|
+
}
|
|
1193
|
+
const checkChar = cleaned.charAt(7);
|
|
1194
|
+
const checkDigit = checkChar === "X" ? 10 : parseInt(checkChar, 10);
|
|
1195
|
+
sum += checkDigit;
|
|
1196
|
+
return sum % 11 === 0;
|
|
1197
|
+
}
|
|
1198
|
+
function isISO31661Alpha2(iso31661Alpha2) {
|
|
1199
|
+
return /^[A-Z]{2}$/.test(iso31661Alpha2);
|
|
1200
|
+
}
|
|
1201
|
+
function isISO31661Alpha3(iso31661Alpha3) {
|
|
1202
|
+
return /^[A-Z]{3}$/.test(iso31661Alpha3);
|
|
1203
|
+
}
|
|
1204
|
+
function validateUsername(username) {
|
|
1205
|
+
return isAlphanumeric(username);
|
|
1206
|
+
}
|
|
1207
|
+
function isLatitude(latitude) {
|
|
1208
|
+
const lat = parseFloat(latitude);
|
|
1209
|
+
return !isNaN(lat) && lat >= -90 && lat <= 90;
|
|
1210
|
+
}
|
|
1211
|
+
function isLongitude(longitude) {
|
|
1212
|
+
const long = parseFloat(longitude);
|
|
1213
|
+
return !isNaN(long) && long >= -180 && long <= 180;
|
|
1214
|
+
}
|
|
945
1215
|
export {
|
|
1216
|
+
validateUsername,
|
|
946
1217
|
urlAlphabet,
|
|
947
1218
|
truncate,
|
|
948
1219
|
trainCase,
|
|
@@ -950,7 +1221,7 @@ export {
|
|
|
950
1221
|
titleCase,
|
|
951
1222
|
template,
|
|
952
1223
|
swapCase,
|
|
953
|
-
|
|
1224
|
+
string2 as string,
|
|
954
1225
|
str,
|
|
955
1226
|
spongeCase,
|
|
956
1227
|
splitSeparateNumbers,
|
|
@@ -971,6 +1242,47 @@ export {
|
|
|
971
1242
|
noCase,
|
|
972
1243
|
lowercase,
|
|
973
1244
|
kebabCase,
|
|
1245
|
+
isUUID,
|
|
1246
|
+
isURL,
|
|
1247
|
+
isStrongPassword,
|
|
1248
|
+
isPostalCode,
|
|
1249
|
+
isNumeric,
|
|
1250
|
+
isMobilePhone,
|
|
1251
|
+
isMimeType,
|
|
1252
|
+
isMACAddress,
|
|
1253
|
+
isLongitude,
|
|
1254
|
+
isLatitude,
|
|
1255
|
+
isLatLong,
|
|
1256
|
+
isJWT,
|
|
1257
|
+
isJSON,
|
|
1258
|
+
isIdentityCard,
|
|
1259
|
+
isISSN,
|
|
1260
|
+
isISRC,
|
|
1261
|
+
isISO8601,
|
|
1262
|
+
isISO31661Alpha3,
|
|
1263
|
+
isISO31661Alpha2,
|
|
1264
|
+
isISIN,
|
|
1265
|
+
isISBN,
|
|
1266
|
+
isIPRange,
|
|
1267
|
+
isIP,
|
|
1268
|
+
isIBAN,
|
|
1269
|
+
isHexadecimal,
|
|
1270
|
+
isHexColor,
|
|
1271
|
+
isHash,
|
|
1272
|
+
isHalfWidth,
|
|
1273
|
+
isHSL,
|
|
1274
|
+
isFullWidth,
|
|
1275
|
+
isFQDN,
|
|
1276
|
+
isEmail,
|
|
1277
|
+
isDataURI,
|
|
1278
|
+
isCurrency,
|
|
1279
|
+
isCreditCard,
|
|
1280
|
+
isByteLength,
|
|
1281
|
+
isBase64,
|
|
1282
|
+
isBase32,
|
|
1283
|
+
isAscii,
|
|
1284
|
+
isAlphanumeric,
|
|
1285
|
+
isAlpha,
|
|
974
1286
|
extendCharMap,
|
|
975
1287
|
ensureSuffix,
|
|
976
1288
|
ensurePrefix,
|