@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 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.org/strings](https://stacksjs.org/strings).
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 { 0: word, index: wordIndex = 0 } = matches[i];
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) => `${upper(word[0])}${lower(word.slice(1))}`;
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
- const char0 = word[0];
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
- if (word[0] === word[0].toUpperCase()) {
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, (match, index) => args[Number(index)] || "");
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]) => pluralize.addPluralRule(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]) => pluralize.addSingularRule(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
- let type;
777
- let amount = 0;
778
- let indent = "";
779
- if (keyOfMostUsedIndent !== undefined) {
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
- while (i--)
839
- id += dict[Math.random() * len | 0];
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
- exports_string as string,
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,