@stacksjs/strings 0.70.57 → 0.70.58

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.
@@ -0,0 +1,272 @@
1
+ export function isEmail(email) {
2
+ return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
3
+ }
4
+ export function isStrongPassword(password) {
5
+ if (password.length < 8)
6
+ return !1;
7
+ const hasUpperCase = /[A-Z]/.test(password), hasLowerCase = /[a-z]/.test(password), hasNumber = /\d/.test(password), hasSymbol = /[!@#$%^&*()_+\-=[\]{};':"\\|,.<>/?]/.test(password);
8
+ return hasUpperCase && hasLowerCase && hasNumber && hasSymbol;
9
+ }
10
+ export function isAlphanumeric(str) {
11
+ return /^[a-zA-Z0-9]+$/.test(str);
12
+ }
13
+ export function isURL(url) {
14
+ try {
15
+ const parsed = new URL(url);
16
+ return parsed.protocol === "http:" || parsed.protocol === "https:";
17
+ } catch {
18
+ return !1;
19
+ }
20
+ }
21
+ export function isMobilePhone(phoneNumber) {
22
+ const phoneRegex = /^\+?[1-9]\d{6,14}$/, cleaned = phoneNumber.replace(/[\s()-]/g, "");
23
+ return phoneRegex.test(cleaned);
24
+ }
25
+ export function isAlpha(str) {
26
+ return /^[a-zA-Z]+$/.test(str);
27
+ }
28
+ export function isPostalCode(zipCode) {
29
+ const usZip = /^\d{5}(?:-\d{4})?$/, ukPostcode = /^[A-Z]{1,2}\d{1,2}[A-Z]?\s?\d[A-Z]{2}$/i, canadaPostcode = /^[A-Z]\d[A-Z]\s?\d[A-Z]\d$/i, generic = /^[a-zA-Z0-9]{3,10}$/;
30
+ return usZip.test(zipCode) || ukPostcode.test(zipCode) || canadaPostcode.test(zipCode) || generic.test(zipCode);
31
+ }
32
+ export function isNumeric(str) {
33
+ return /^\d+$/.test(str);
34
+ }
35
+ export function isHexColor(color) {
36
+ return /^#(?:[A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/.test(color);
37
+ }
38
+ export function isHexadecimal(hex) {
39
+ return /^[A-Fa-f0-9]+$/.test(hex);
40
+ }
41
+ export function isBase64(base64) {
42
+ try {
43
+ return btoa(atob(base64)) === base64;
44
+ } catch {
45
+ return !1;
46
+ }
47
+ }
48
+ export function isUUID(uuid) {
49
+ return /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(uuid);
50
+ }
51
+ export function isJSON(json) {
52
+ try {
53
+ JSON.parse(json);
54
+ return !0;
55
+ } catch {
56
+ return !1;
57
+ }
58
+ }
59
+ export function isCreditCard(creditCard) {
60
+ const cleaned = creditCard.replace(/[\s-]/g, "");
61
+ if (!/^\d{13,19}$/.test(cleaned))
62
+ return !1;
63
+ let sum = 0, isEven = !1;
64
+ for (let i = cleaned.length - 1;i >= 0; i--) {
65
+ let digit = parseInt(cleaned.charAt(i), 10);
66
+ if (isEven) {
67
+ digit *= 2;
68
+ if (digit > 9)
69
+ digit -= 9;
70
+ }
71
+ sum += digit;
72
+ isEven = !isEven;
73
+ }
74
+ return sum % 10 === 0;
75
+ }
76
+ export function isISBN(isbn) {
77
+ const cleaned = isbn.replace(/[\s-]/g, "");
78
+ if (cleaned.length === 10) {
79
+ let sum = 0;
80
+ for (let i = 0;i < 9; i++) {
81
+ const digit = parseInt(cleaned.charAt(i), 10);
82
+ if (isNaN(digit))
83
+ return !1;
84
+ sum += digit * (10 - i);
85
+ }
86
+ const checkChar = cleaned.charAt(9), checkDigit = checkChar === "X" ? 10 : parseInt(checkChar, 10);
87
+ if (isNaN(checkDigit) && checkChar !== "X")
88
+ return !1;
89
+ sum += checkDigit;
90
+ return sum % 11 === 0;
91
+ }
92
+ if (cleaned.length === 13) {
93
+ let sum = 0;
94
+ for (let i = 0;i < 12; i++) {
95
+ const digit = parseInt(cleaned.charAt(i), 10);
96
+ if (isNaN(digit))
97
+ return !1;
98
+ sum += digit * (i % 2 === 0 ? 1 : 3);
99
+ }
100
+ const checkDigit = parseInt(cleaned.charAt(12), 10);
101
+ if (isNaN(checkDigit))
102
+ return !1;
103
+ return (10 - sum % 10) % 10 === checkDigit;
104
+ }
105
+ return !1;
106
+ }
107
+ export function isIP(ip) {
108
+ if (/^(?: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]?)$/.test(ip))
109
+ return !0;
110
+ return /^(?:(?:[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]))$/.test(ip);
111
+ }
112
+ export function isIPRange(ip) {
113
+ const parts = ip.split("/");
114
+ if (parts.length !== 2)
115
+ return !1;
116
+ const [address, cidr] = parts;
117
+ if (address === void 0 || cidr === void 0)
118
+ return !1;
119
+ const cidrNum = parseInt(cidr, 10);
120
+ if (!isIP(address))
121
+ return !1;
122
+ if (address.includes(":"))
123
+ return cidrNum >= 0 && cidrNum <= 128;
124
+ else
125
+ return cidrNum >= 0 && cidrNum <= 32;
126
+ }
127
+ export function isMACAddress(macAddress) {
128
+ return /^(?:[0-9A-Fa-f]{2}[:-]){5}(?:[0-9A-Fa-f]{2})$/.test(macAddress);
129
+ }
130
+ export function isLatLong(latlong) {
131
+ const parts = latlong.split(",");
132
+ if (parts.length !== 2)
133
+ return !1;
134
+ const lat = parseFloat((parts[0] ?? "").trim()), long = parseFloat((parts[1] ?? "").trim());
135
+ return !isNaN(lat) && !isNaN(long) && lat >= -90 && lat <= 90 && long >= -180 && long <= 180;
136
+ }
137
+ export function isCurrency(currency) {
138
+ return /^[$\u00A3\u20AC\u00A5]?\d{1,3}(?:,?\d{3})*(?:\.\d{2})?$/.test(currency.trim());
139
+ }
140
+ export function isDataURI(dataURI) {
141
+ return /^data:(?:[a-z]+\/[a-z0-9-+.]+(?:;[a-z-]+=[a-z0-9-]+)*)?;base64,(?:[a-z0-9+/]+=*)/i.test(dataURI) || /^data:,/.test(dataURI);
142
+ }
143
+ export function isMimeType(mimeType) {
144
+ return /^[a-z]+\/[a-z0-9\-+.]+$/i.test(mimeType);
145
+ }
146
+ export function isJWT(jwt) {
147
+ const parts = jwt.split(".");
148
+ if (parts.length !== 3)
149
+ return !1;
150
+ try {
151
+ parts.forEach((part) => {
152
+ atob(part.replace(/-/g, "+").replace(/_/g, "/"));
153
+ });
154
+ return !0;
155
+ } catch {
156
+ return !1;
157
+ }
158
+ }
159
+ export function isAscii(ascii) {
160
+ return /^[\x00-\x7F]*$/.test(ascii);
161
+ }
162
+ export function isBase32(base32) {
163
+ return /^[A-Z2-7]+=*$/.test(base32.toUpperCase());
164
+ }
165
+ export function isByteLength(str, options) {
166
+ const min = options?.min ?? 0, max = options?.max ?? 1 / 0, byteLength = new TextEncoder().encode(str).length;
167
+ return byteLength >= min && byteLength <= max;
168
+ }
169
+ export function isFQDN(fqdn) {
170
+ return /^(?=.{1,253}$)(?:(?!-)[A-Za-z0-9-]{1,63}(?<!-)\.)+[A-Za-z]{2,}$/.test(fqdn);
171
+ }
172
+ export function isFullWidth(fullWidth) {
173
+ return /^[\uFF00-\uFFEF]+$/.test(fullWidth);
174
+ }
175
+ export function isHalfWidth(halfWidth) {
176
+ return /^[\u0020-\u007E\uFF61-\uFF9F]+$/.test(halfWidth);
177
+ }
178
+ export function isHash(hash, algorithm) {
179
+ const expectedLength = {
180
+ md5: 32,
181
+ sha1: 40,
182
+ sha256: 64,
183
+ sha384: 96,
184
+ sha512: 128
185
+ }[algorithm];
186
+ if (!expectedLength)
187
+ return !1;
188
+ return hash.length === expectedLength && /^[a-f0-9]+$/i.test(hash);
189
+ }
190
+ export function isHSL(hsl) {
191
+ return /^hsl\(?:\s*(?:\d+)\s*,\s*(?:\d+(?:\.\d+)?%)\s*,\s*(?:\d+(?:\.\d+)?%)\s*\)$/.test(hsl);
192
+ }
193
+ export function isIBAN(iban) {
194
+ const cleaned = iban.replace(/\s/g, "").toUpperCase();
195
+ if (!/^[A-Z]{2}\d{2}[A-Z0-9]+$/.test(cleaned))
196
+ return !1;
197
+ if (cleaned.length < 15 || cleaned.length > 34)
198
+ return !1;
199
+ const digits = (cleaned.slice(4) + cleaned.slice(0, 4)).split("").map((char) => {
200
+ const code = char.charCodeAt(0);
201
+ return code >= 65 && code <= 90 ? (code - 55).toString() : char;
202
+ }).join("");
203
+ let remainder = digits.slice(0, 2);
204
+ for (let i = 2;i < digits.length; i += 7)
205
+ remainder = (parseInt(remainder + digits.slice(i, i + 7), 10) % 97).toString();
206
+ return parseInt(remainder, 10) === 1;
207
+ }
208
+ export function isIdentityCard(identityCard) {
209
+ const cleaned = identityCard.replace(/[\s-]/g, "");
210
+ return /^[A-Z0-9]{5,20}$/i.test(cleaned);
211
+ }
212
+ export function isISIN(isin) {
213
+ if (!/^[A-Z]{2}[A-Z0-9]{9}\d$/.test(isin))
214
+ return !1;
215
+ const digits = isin.split("").map((char) => {
216
+ const code = char.charCodeAt(0);
217
+ return code >= 65 && code <= 90 ? (code - 55).toString() : char;
218
+ }).join("");
219
+ let sum = 0, isEven = !0;
220
+ for (let i = digits.length - 1;i >= 0; i--) {
221
+ let digit = parseInt(digits.charAt(i), 10);
222
+ if (isEven) {
223
+ digit *= 2;
224
+ if (digit > 9)
225
+ digit -= 9;
226
+ }
227
+ sum += digit;
228
+ isEven = !isEven;
229
+ }
230
+ return sum % 10 === 0;
231
+ }
232
+ export function isISO8601(iso8601) {
233
+ if (!/^\d{4}-\d{2}-\d{2}(?:T\d{2}:\d{2}:\d{2}(?:\.\d{3})?(?:Z|[+-]\d{2}:\d{2})?)?$/.test(iso8601))
234
+ return !1;
235
+ try {
236
+ const date = new Date(iso8601);
237
+ return !isNaN(date.getTime());
238
+ } catch {
239
+ return !1;
240
+ }
241
+ }
242
+ export function isISRC(isrc) {
243
+ return /^[A-Z]{2}[A-Z0-9]{3}\d{2}\d{5}$/.test(isrc.replace(/-/g, ""));
244
+ }
245
+ export function isISSN(issn) {
246
+ const cleaned = issn.replace(/[\s-]/g, "");
247
+ if (!/^\d{7}[\dX]$/.test(cleaned))
248
+ return !1;
249
+ let sum = 0;
250
+ for (let i = 0;i < 7; i++)
251
+ sum += parseInt(cleaned.charAt(i), 10) * (8 - i);
252
+ const checkChar = cleaned.charAt(7), checkDigit = checkChar === "X" ? 10 : parseInt(checkChar, 10);
253
+ sum += checkDigit;
254
+ return sum % 11 === 0;
255
+ }
256
+ export function isISO31661Alpha2(iso31661Alpha2) {
257
+ return /^[A-Z]{2}$/.test(iso31661Alpha2);
258
+ }
259
+ export function isISO31661Alpha3(iso31661Alpha3) {
260
+ return /^[A-Z]{3}$/.test(iso31661Alpha3);
261
+ }
262
+ export function validateUsername(username) {
263
+ return isAlphanumeric(username);
264
+ }
265
+ export function isLatitude(latitude) {
266
+ const lat = parseFloat(latitude);
267
+ return !isNaN(lat) && lat >= -90 && lat <= 90;
268
+ }
269
+ export function isLongitude(longitude) {
270
+ const long = parseFloat(longitude);
271
+ return !isNaN(long) && long >= -180 && long <= 180;
272
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@stacksjs/strings",
3
3
  "type": "module",
4
- "version": "0.70.57",
4
+ "version": "0.70.58",
5
5
  "description": "The Stacks string utilities.",
6
6
  "author": "Chris Breuer",
7
7
  "contributors": [
@@ -64,9 +64,9 @@
64
64
  "prepublishOnly": "bun run build"
65
65
  },
66
66
  "devDependencies": {
67
- "@stacksjs/alias": "0.70.57",
67
+ "@stacksjs/alias": "0.70.58",
68
68
  "better-dx": "^0.2.12",
69
- "@stacksjs/types": "0.70.57"
69
+ "@stacksjs/types": "0.70.58"
70
70
  },
71
71
  "sideEffects": false
72
72
  }