@utilix-tech/sdk 0.8.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/README.md +15 -3
- package/dist/{chunk-V5JKVDBA.js → chunk-OB56VNKJ.js} +177 -2
- package/dist/{chunk-QJE743LY.js → chunk-YVFM5WYI.js} +62 -1
- package/dist/index.cjs +237 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/{network-DwyAjwJS.d.cts → network-DaNoZ5ER.d.cts} +77 -2
- package/dist/{network-DwyAjwJS.d.ts → network-DaNoZ5ER.d.ts} +77 -2
- package/dist/tools/network.cjs +175 -0
- package/dist/tools/network.d.cts +1 -1
- package/dist/tools/network.d.ts +1 -1
- package/dist/tools/network.js +1 -1
- package/dist/tools/units.cjs +61 -0
- package/dist/tools/units.d.cts +1 -1
- package/dist/tools/units.d.ts +1 -1
- package/dist/tools/units.js +1 -1
- package/dist/{units-6lwDYBvX.d.ts → units-DRT6W-vu.d.cts} +19 -2
- package/dist/{units-6lwDYBvX.d.cts → units-DRT6W-vu.d.ts} +19 -2
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
Full release notes for all Utilix surfaces (browser tools, REST API, SDKs, MCP server) live at [utilix.tech/changelog](https://utilix.tech/changelog). This file tracks just this package.
|
|
4
4
|
|
|
5
|
+
## 0.10.0
|
|
6
|
+
- Added robots.txt Validator and Credit Card Number Validator.
|
|
7
|
+
|
|
8
|
+
## 0.9.0
|
|
9
|
+
- Added Sitemap.xml Validator.
|
|
10
|
+
|
|
5
11
|
## 0.8.0
|
|
6
12
|
- Added ID3 Tag Reader and .env.example Diff Checker.
|
|
7
13
|
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @utilix-tech/sdk
|
|
2
2
|
|
|
3
|
-
**
|
|
3
|
+
**531 developer utility functions for Node.js: runs locally, no API key required.**
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/@utilix-tech/sdk)
|
|
6
6
|
[](https://www.npmjs.com/package/@utilix-tech/sdk)
|
|
@@ -242,7 +242,7 @@ getNextRuns("*/5 * * * *", 5); // next 5 run timestamps
|
|
|
242
242
|
### `/units`: Conversions
|
|
243
243
|
|
|
244
244
|
```ts
|
|
245
|
-
import { convertBytes, pxToAll, convert, formatValue } from "@utilix-tech/sdk/units";
|
|
245
|
+
import { convertBytes, pxToAll, convert, formatValue, validateCardNumber } from "@utilix-tech/sdk/units";
|
|
246
246
|
|
|
247
247
|
// File sizes
|
|
248
248
|
convertBytes(1073741824, "GB"); // 1
|
|
@@ -260,6 +260,10 @@ convert("11111111", 2, 10); // "255"
|
|
|
260
260
|
// Currency / locale formatting
|
|
261
261
|
formatValue(1234567.89, { locale: "en-US", currency: "USD" });
|
|
262
262
|
// "$1,234,567.89"
|
|
263
|
+
|
|
264
|
+
// Credit card Luhn checksum + network detection
|
|
265
|
+
validateCardNumber("4111 1111 1111 1111");
|
|
266
|
+
// { valid: true, network: "Visa", length: 16, formatted: "4111 1111 1111 1111" }
|
|
263
267
|
```
|
|
264
268
|
|
|
265
269
|
---
|
|
@@ -269,7 +273,7 @@ formatValue(1234567.89, { locale: "en-US", currency: "USD" });
|
|
|
269
273
|
```ts
|
|
270
274
|
import { getStatusCode, isValidIp, isValidIpv4, isValidIpv6,
|
|
271
275
|
searchStatusCodes, buildGeoUrl, countryCodeToFlag,
|
|
272
|
-
parseHar } from "@utilix-tech/sdk/network";
|
|
276
|
+
parseHar, validateSitemap, validateRobotsTxt } from "@utilix-tech/sdk/network";
|
|
273
277
|
|
|
274
278
|
getStatusCode(404);
|
|
275
279
|
// { code: 404, text: "Not Found", description: "...", category: "Client Error" }
|
|
@@ -286,6 +290,14 @@ countryCodeToFlag("US"); // "🇺🇸"
|
|
|
286
290
|
const har = await fs.promises.readFile("network.har", "utf-8");
|
|
287
291
|
parseHar(har);
|
|
288
292
|
// { version: "1.2", entries: [...], summary: { totalRequests, totalSize, failedRequests, ... } }
|
|
293
|
+
|
|
294
|
+
// Validate a sitemap.xml (or sitemap index) against the sitemaps.org protocol
|
|
295
|
+
validateSitemap('<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"><url><loc>https://example.com/</loc></url></urlset>');
|
|
296
|
+
// { type: "urlset", urlCount: 1, entries: [...], issues: [...], valid: true }
|
|
297
|
+
|
|
298
|
+
// Validate a robots.txt file: User-agent groups, rules, and syntax mistakes
|
|
299
|
+
validateRobotsTxt("User-agent: *\nDisallow: /admin\nSitemap: https://example.com/sitemap.xml");
|
|
300
|
+
// { groups: [...], sitemaps: [...], issues: [...], valid: true }
|
|
289
301
|
```
|
|
290
302
|
|
|
291
303
|
---
|
|
@@ -32,7 +32,9 @@ __export(network_exports, {
|
|
|
32
32
|
typeNumberToLabel: () => typeNumberToLabel,
|
|
33
33
|
validateDomain: () => validateDomain,
|
|
34
34
|
validateHeaderName: () => validateHeaderName,
|
|
35
|
-
validateHeaderValue: () => validateHeaderValue
|
|
35
|
+
validateHeaderValue: () => validateHeaderValue,
|
|
36
|
+
validateRobotsTxt: () => validateRobotsTxt,
|
|
37
|
+
validateSitemap: () => validateSitemap
|
|
36
38
|
});
|
|
37
39
|
var DNS_RECORD_TYPES = ["A", "AAAA", "CNAME", "MX", "TXT", "NS", "SOA", "PTR", "SRV", "CAA"];
|
|
38
40
|
function buildDnsQueryUrl(domain, type) {
|
|
@@ -1440,5 +1442,178 @@ function parseHar(input) {
|
|
|
1440
1442
|
summary: { totalRequests, totalSize, totalTime, avgTime, failedRequests, methods, statusCodes }
|
|
1441
1443
|
};
|
|
1442
1444
|
}
|
|
1445
|
+
var VALID_CHANGEFREQ = /* @__PURE__ */ new Set(["always", "hourly", "daily", "weekly", "monthly", "yearly", "never"]);
|
|
1446
|
+
function sitemapLineNumber(xml, index) {
|
|
1447
|
+
let line = 1;
|
|
1448
|
+
for (let i = 0; i < index; i++) {
|
|
1449
|
+
if (xml[i] === "\n") line++;
|
|
1450
|
+
}
|
|
1451
|
+
return line;
|
|
1452
|
+
}
|
|
1453
|
+
function extractSitemapTag(block, tag) {
|
|
1454
|
+
const m = block.match(new RegExp(`<${tag}[^>]*>([\\s\\S]*?)</${tag}>`, "i"));
|
|
1455
|
+
return m ? m[1].trim() : void 0;
|
|
1456
|
+
}
|
|
1457
|
+
function isValidW3CDatetime(s) {
|
|
1458
|
+
return /^\d{4}(-\d{2}(-\d{2}(T\d{2}:\d{2}(:\d{2}(\.\d+)?)?(Z|[+-]\d{2}:\d{2}))?)?)?$/.test(s);
|
|
1459
|
+
}
|
|
1460
|
+
function isAbsoluteHttpUrl(s) {
|
|
1461
|
+
return /^https?:\/\//i.test(s);
|
|
1462
|
+
}
|
|
1463
|
+
function validateSitemap(xml) {
|
|
1464
|
+
if (!xml || !xml.trim()) return { error: "Input is empty" };
|
|
1465
|
+
const trimmed = xml.trim();
|
|
1466
|
+
const issues = [];
|
|
1467
|
+
if (!/^\s*<\?xml/i.test(trimmed)) {
|
|
1468
|
+
issues.push({ severity: "warning", line: 1, message: 'Missing XML declaration (<?xml version="1.0" encoding="UTF-8"?>)' });
|
|
1469
|
+
}
|
|
1470
|
+
const isUrlset = /<urlset[\s>]/i.test(trimmed);
|
|
1471
|
+
const isSitemapIndex = /<sitemapindex[\s>]/i.test(trimmed);
|
|
1472
|
+
if (!isUrlset && !isSitemapIndex) {
|
|
1473
|
+
return { error: "Not a valid sitemap: root element must be <urlset> or <sitemapindex>" };
|
|
1474
|
+
}
|
|
1475
|
+
if (isUrlset && isSitemapIndex) {
|
|
1476
|
+
return { error: "Ambiguous file: contains both <urlset> and <sitemapindex> root elements" };
|
|
1477
|
+
}
|
|
1478
|
+
const type = isUrlset ? "urlset" : "sitemapindex";
|
|
1479
|
+
if (isUrlset && !/xmlns\s*=\s*["']http:\/\/www\.sitemaps\.org\/schemas\/sitemap\/0\.9["']/i.test(trimmed)) {
|
|
1480
|
+
issues.push({ severity: "warning", line: 1, message: "Missing or non-standard xmlns namespace (expected http://www.sitemaps.org/schemas/sitemap/0.9)" });
|
|
1481
|
+
}
|
|
1482
|
+
const blockTag = isUrlset ? "url" : "sitemap";
|
|
1483
|
+
const blockRe = new RegExp(`<${blockTag}>([\\s\\S]*?)</${blockTag}>`, "gi");
|
|
1484
|
+
const seenLocs = /* @__PURE__ */ new Set();
|
|
1485
|
+
const entries = [];
|
|
1486
|
+
let match;
|
|
1487
|
+
while ((match = blockRe.exec(trimmed)) !== null) {
|
|
1488
|
+
const block = match[1];
|
|
1489
|
+
const line = sitemapLineNumber(trimmed, match.index);
|
|
1490
|
+
const loc = extractSitemapTag(block, "loc");
|
|
1491
|
+
if (!loc) {
|
|
1492
|
+
issues.push({ severity: "error", line, message: `<${blockTag}> entry is missing required <loc>` });
|
|
1493
|
+
continue;
|
|
1494
|
+
}
|
|
1495
|
+
if (!isAbsoluteHttpUrl(loc)) {
|
|
1496
|
+
issues.push({ severity: "error", line, message: `<loc>${loc}</loc> must be an absolute URL starting with http:// or https://` });
|
|
1497
|
+
}
|
|
1498
|
+
if (/&(?!amp;|lt;|gt;|apos;|quot;|#\d+;)/.test(loc)) {
|
|
1499
|
+
issues.push({ severity: "error", line, message: `<loc>${loc}</loc> contains an unescaped '&' (use & instead)` });
|
|
1500
|
+
}
|
|
1501
|
+
if (seenLocs.has(loc)) {
|
|
1502
|
+
issues.push({ severity: "warning", line, message: `Duplicate <loc>${loc}</loc>` });
|
|
1503
|
+
}
|
|
1504
|
+
seenLocs.add(loc);
|
|
1505
|
+
const lastmod = extractSitemapTag(block, "lastmod");
|
|
1506
|
+
if (lastmod !== void 0 && !isValidW3CDatetime(lastmod)) {
|
|
1507
|
+
issues.push({ severity: "warning", line, message: `<lastmod>${lastmod}</lastmod> is not a valid W3C datetime` });
|
|
1508
|
+
}
|
|
1509
|
+
if (type === "urlset") {
|
|
1510
|
+
const changefreq = extractSitemapTag(block, "changefreq");
|
|
1511
|
+
if (changefreq !== void 0 && !VALID_CHANGEFREQ.has(changefreq.toLowerCase())) {
|
|
1512
|
+
issues.push({ severity: "error", line, message: `<changefreq>${changefreq}</changefreq> must be one of: ${[...VALID_CHANGEFREQ].join(", ")}` });
|
|
1513
|
+
}
|
|
1514
|
+
const priority = extractSitemapTag(block, "priority");
|
|
1515
|
+
if (priority !== void 0) {
|
|
1516
|
+
const p = Number(priority);
|
|
1517
|
+
if (Number.isNaN(p) || p < 0 || p > 1) {
|
|
1518
|
+
issues.push({ severity: "error", line, message: `<priority>${priority}</priority> must be a number between 0.0 and 1.0` });
|
|
1519
|
+
}
|
|
1520
|
+
}
|
|
1521
|
+
entries.push({ loc, lastmod, changefreq, priority, line });
|
|
1522
|
+
} else {
|
|
1523
|
+
entries.push({ loc, lastmod, line });
|
|
1524
|
+
}
|
|
1525
|
+
}
|
|
1526
|
+
if (entries.length === 0) {
|
|
1527
|
+
issues.push({ severity: "error", line: 1, message: `No <${blockTag}> entries found` });
|
|
1528
|
+
}
|
|
1529
|
+
if (type === "urlset" && entries.length > 5e4) {
|
|
1530
|
+
issues.push({ severity: "error", line: 1, message: `Sitemap contains ${entries.length} URLs, exceeding the 50,000 URL limit per the sitemaps.org spec` });
|
|
1531
|
+
}
|
|
1532
|
+
const valid = !issues.some((i) => i.severity === "error");
|
|
1533
|
+
return { type, urlCount: entries.length, entries, issues, valid };
|
|
1534
|
+
}
|
|
1535
|
+
var KNOWN_ROBOTS_DIRECTIVES = /* @__PURE__ */ new Set(["user-agent", "disallow", "allow", "sitemap", "crawl-delay", "host"]);
|
|
1536
|
+
function validateRobotsTxt(text) {
|
|
1537
|
+
if (!text || !text.trim()) return { error: "Input is empty" };
|
|
1538
|
+
const lines = text.split("\n");
|
|
1539
|
+
const issues = [];
|
|
1540
|
+
const groups = [];
|
|
1541
|
+
const sitemaps = [];
|
|
1542
|
+
let currentGroup = null;
|
|
1543
|
+
for (let i = 0; i < lines.length; i++) {
|
|
1544
|
+
const rawLine = lines[i];
|
|
1545
|
+
const lineNum = i + 1;
|
|
1546
|
+
const commentIdx = rawLine.indexOf("#");
|
|
1547
|
+
const line = (commentIdx >= 0 ? rawLine.slice(0, commentIdx) : rawLine).trim();
|
|
1548
|
+
if (!line) continue;
|
|
1549
|
+
const colonIdx = line.indexOf(":");
|
|
1550
|
+
if (colonIdx === -1) {
|
|
1551
|
+
issues.push({ severity: "error", line: lineNum, message: `Malformed line (missing ':'): "${line}"` });
|
|
1552
|
+
continue;
|
|
1553
|
+
}
|
|
1554
|
+
const directive = line.slice(0, colonIdx).trim().toLowerCase();
|
|
1555
|
+
const value = line.slice(colonIdx + 1).trim();
|
|
1556
|
+
if (!KNOWN_ROBOTS_DIRECTIVES.has(directive)) {
|
|
1557
|
+
issues.push({ severity: "warning", line: lineNum, message: `Unknown directive "${directive}"` });
|
|
1558
|
+
continue;
|
|
1559
|
+
}
|
|
1560
|
+
if (directive === "sitemap") {
|
|
1561
|
+
if (!/^https?:\/\//i.test(value)) {
|
|
1562
|
+
issues.push({ severity: "error", line: lineNum, message: `Sitemap URL "${value}" must be absolute (start with http:// or https://)` });
|
|
1563
|
+
}
|
|
1564
|
+
sitemaps.push(value);
|
|
1565
|
+
continue;
|
|
1566
|
+
}
|
|
1567
|
+
if (directive === "user-agent") {
|
|
1568
|
+
if (!value) {
|
|
1569
|
+
issues.push({ severity: "error", line: lineNum, message: "User-agent directive is missing a value" });
|
|
1570
|
+
}
|
|
1571
|
+
if (currentGroup && currentGroup.rules.length === 0 && currentGroup.crawlDelay === void 0) {
|
|
1572
|
+
currentGroup.userAgents.push(value);
|
|
1573
|
+
} else {
|
|
1574
|
+
currentGroup = { userAgents: [value], rules: [], line: lineNum };
|
|
1575
|
+
groups.push(currentGroup);
|
|
1576
|
+
}
|
|
1577
|
+
continue;
|
|
1578
|
+
}
|
|
1579
|
+
if (!currentGroup) {
|
|
1580
|
+
issues.push({ severity: "error", line: lineNum, message: `"${directive}" directive found before any User-agent line` });
|
|
1581
|
+
continue;
|
|
1582
|
+
}
|
|
1583
|
+
if (directive === "disallow" || directive === "allow") {
|
|
1584
|
+
if (value !== "" && !value.startsWith("/") && !value.startsWith("*")) {
|
|
1585
|
+
issues.push({ severity: "warning", line: lineNum, message: `${directive === "disallow" ? "Disallow" : "Allow"} value "${value}" should start with "/" (or be empty)` });
|
|
1586
|
+
}
|
|
1587
|
+
if (currentGroup.rules.some((r) => r.type === directive && r.value === value)) {
|
|
1588
|
+
issues.push({ severity: "warning", line: lineNum, message: `Duplicate ${directive} rule for "${value}" in this group` });
|
|
1589
|
+
}
|
|
1590
|
+
currentGroup.rules.push({ type: directive, value, line: lineNum });
|
|
1591
|
+
} else if (directive === "crawl-delay") {
|
|
1592
|
+
const n = Number(value);
|
|
1593
|
+
if (Number.isNaN(n) || n < 0) {
|
|
1594
|
+
issues.push({ severity: "error", line: lineNum, message: `Crawl-delay "${value}" must be a non-negative number` });
|
|
1595
|
+
} else {
|
|
1596
|
+
currentGroup.crawlDelay = n;
|
|
1597
|
+
}
|
|
1598
|
+
}
|
|
1599
|
+
}
|
|
1600
|
+
if (groups.length === 0) {
|
|
1601
|
+
issues.push({ severity: "error", line: 1, message: "No User-agent groups found" });
|
|
1602
|
+
}
|
|
1603
|
+
const seenUA = /* @__PURE__ */ new Map();
|
|
1604
|
+
for (const g of groups) {
|
|
1605
|
+
for (const ua of g.userAgents) {
|
|
1606
|
+
const key = ua.toLowerCase();
|
|
1607
|
+
const firstLine = seenUA.get(key);
|
|
1608
|
+
if (firstLine !== void 0) {
|
|
1609
|
+
issues.push({ severity: "warning", line: g.line, message: `Duplicate User-agent "${ua}" (first seen on line ${firstLine})` });
|
|
1610
|
+
} else {
|
|
1611
|
+
seenUA.set(key, g.line);
|
|
1612
|
+
}
|
|
1613
|
+
}
|
|
1614
|
+
}
|
|
1615
|
+
const valid = !issues.some((i) => i.severity === "error");
|
|
1616
|
+
return { groups, sitemaps, issues, valid };
|
|
1617
|
+
}
|
|
1443
1618
|
|
|
1444
|
-
export { DNS_RECORD_TYPES, HTTP_HEADERS, STATUS_CODES, buildDnsQueryUrl, buildGeoUrl, buildMapUrl, countryCodeToFlag, formatCoordinates, formatTtl, getByCategory, getHeader, getHeadersByCategory, getStatusByCategory, getStatusCode, isClientError, isServerError, isSuccess, isValidIp, isValidIpv4, isValidIpv6, network_exports, parseDnsResponse, parseGeoResponse, parseHar, searchHeaders, searchStatusCodes, statusCodeToText, typeNumberToLabel, validateDomain, validateHeaderName, validateHeaderValue };
|
|
1619
|
+
export { DNS_RECORD_TYPES, HTTP_HEADERS, STATUS_CODES, buildDnsQueryUrl, buildGeoUrl, buildMapUrl, countryCodeToFlag, formatCoordinates, formatTtl, getByCategory, getHeader, getHeadersByCategory, getStatusByCategory, getStatusCode, isClientError, isServerError, isSuccess, isValidIp, isValidIpv4, isValidIpv6, network_exports, parseDnsResponse, parseGeoResponse, parseHar, searchHeaders, searchStatusCodes, statusCodeToText, typeNumberToLabel, validateDomain, validateHeaderName, validateHeaderValue, validateRobotsTxt, validateSitemap };
|
|
@@ -60,6 +60,7 @@ __export(units_exports, {
|
|
|
60
60
|
sortVersions: () => sortVersions,
|
|
61
61
|
splitSubnet: () => splitSubnet,
|
|
62
62
|
symbolicToPermissions: () => symbolicToPermissions,
|
|
63
|
+
validateCardNumber: () => validateCardNumber,
|
|
63
64
|
viewportToPx: () => viewportToPx
|
|
64
65
|
});
|
|
65
66
|
function pxToAll(px, baseFontSize = 16, viewportWidth = 1440, viewportHeight = 900) {
|
|
@@ -892,5 +893,65 @@ function sortVersions(versions, order = "asc") {
|
|
|
892
893
|
return order === "asc" ? cmp : -cmp;
|
|
893
894
|
});
|
|
894
895
|
}
|
|
896
|
+
var CARD_NETWORK_RULES = [
|
|
897
|
+
{ name: "American Express", lengths: [15], test: (d) => /^3[47]/.test(d) },
|
|
898
|
+
{ name: "Diners Club", lengths: [14], test: (d) => /^3(?:0[0-5]|[68])/.test(d) },
|
|
899
|
+
{
|
|
900
|
+
name: "Discover",
|
|
901
|
+
lengths: [16, 19],
|
|
902
|
+
test: (d) => /^(?:6011|65|64[4-9])/.test(d) || /^622(?:12[6-9]|1[3-9]\d|[2-8]\d{2}|9[01]\d|92[0-5])/.test(d)
|
|
903
|
+
},
|
|
904
|
+
{ name: "JCB", lengths: [16], test: (d) => /^35(?:2[89]|[3-8]\d)/.test(d) },
|
|
905
|
+
{
|
|
906
|
+
name: "Mastercard",
|
|
907
|
+
lengths: [16],
|
|
908
|
+
test: (d) => {
|
|
909
|
+
const two = parseInt(d.slice(0, 2), 10);
|
|
910
|
+
const four = parseInt(d.slice(0, 4), 10);
|
|
911
|
+
return two >= 51 && two <= 55 || four >= 2221 && four <= 2720;
|
|
912
|
+
}
|
|
913
|
+
},
|
|
914
|
+
{ name: "Maestro", lengths: [12, 13, 14, 15, 16, 17, 18, 19], test: (d) => /^(?:50|5[6-8]|6304|6390|67)/.test(d) },
|
|
915
|
+
{ name: "UnionPay", lengths: [16, 17, 18, 19], test: (d) => /^62/.test(d) },
|
|
916
|
+
{ name: "Visa", lengths: [13, 16, 19], test: (d) => /^4/.test(d) }
|
|
917
|
+
];
|
|
918
|
+
function luhnCheck(digits) {
|
|
919
|
+
let sum = 0;
|
|
920
|
+
let shouldDouble = false;
|
|
921
|
+
for (let i = digits.length - 1; i >= 0; i--) {
|
|
922
|
+
let d = parseInt(digits[i], 10);
|
|
923
|
+
if (shouldDouble) {
|
|
924
|
+
d *= 2;
|
|
925
|
+
if (d > 9) d -= 9;
|
|
926
|
+
}
|
|
927
|
+
sum += d;
|
|
928
|
+
shouldDouble = !shouldDouble;
|
|
929
|
+
}
|
|
930
|
+
return sum % 10 === 0;
|
|
931
|
+
}
|
|
932
|
+
function detectCardNetwork(digits) {
|
|
933
|
+
for (const rule of CARD_NETWORK_RULES) {
|
|
934
|
+
if (rule.lengths.includes(digits.length) && rule.test(digits)) return rule.name;
|
|
935
|
+
}
|
|
936
|
+
return null;
|
|
937
|
+
}
|
|
938
|
+
function formatCardNumber(digits, network) {
|
|
939
|
+
if (network === "American Express") {
|
|
940
|
+
return `${digits.slice(0, 4)} ${digits.slice(4, 10)} ${digits.slice(10)}`.trim();
|
|
941
|
+
}
|
|
942
|
+
return digits.match(/.{1,4}/g)?.join(" ") ?? digits;
|
|
943
|
+
}
|
|
944
|
+
function validateCardNumber(input) {
|
|
945
|
+
if (!input || !input.trim()) return { error: "Input is empty" };
|
|
946
|
+
const digits = input.replace(/[\s-]/g, "");
|
|
947
|
+
if (!/^\d+$/.test(digits)) return { error: "Card number must contain only digits, spaces, or hyphens" };
|
|
948
|
+
if (digits.length < 12 || digits.length > 19) {
|
|
949
|
+
return { error: `Card number length (${digits.length}) is outside the valid range of 12-19 digits` };
|
|
950
|
+
}
|
|
951
|
+
const valid = luhnCheck(digits);
|
|
952
|
+
const network = detectCardNetwork(digits);
|
|
953
|
+
const formatted = formatCardNumber(digits, network);
|
|
954
|
+
return { valid, network, length: digits.length, formatted };
|
|
955
|
+
}
|
|
895
956
|
|
|
896
|
-
export { BASE_LABELS, BASE_PREFIXES, BYTE_UNITS, COMMON_CURRENCIES, COMMON_LOCALES, COMMON_PERMISSIONS, COMMON_RATIOS, COMMON_SIZES, COMMON_VIEWPORTS, autoFormat, bumpVersion, calcAspectRatio, calcSubnet, compareSemver, convert, convertBytes, convertIp, coverBox, decimalToIp, decimalToIpCidr, describePermissions, fitIntoBox, formatNumber, formatValue, formatVwValue, formatWithSeparator, gcd, ipFromBinary, ipFromDecimal, ipFromHex, ipToBinary, ipToDecimal, ipToDecimalCidr, ipToHex, ipToOctal, isValid, isValidCidr, isValidIp, isValidIpv4, octalToPermissions, parseFileSize, parseInput, parseNumberString, parseSemver, permissionsToChmod, permissionsToOctal, permissionsToSymbolic, ptToPx, pxToAll, pxToViewport, remToPx, satisfiesRange, scaleByHeight, scaleByWidth, sortVersions, splitSubnet, symbolicToPermissions, units_exports, viewportToPx };
|
|
957
|
+
export { BASE_LABELS, BASE_PREFIXES, BYTE_UNITS, COMMON_CURRENCIES, COMMON_LOCALES, COMMON_PERMISSIONS, COMMON_RATIOS, COMMON_SIZES, COMMON_VIEWPORTS, autoFormat, bumpVersion, calcAspectRatio, calcSubnet, compareSemver, convert, convertBytes, convertIp, coverBox, decimalToIp, decimalToIpCidr, describePermissions, fitIntoBox, formatNumber, formatValue, formatVwValue, formatWithSeparator, gcd, ipFromBinary, ipFromDecimal, ipFromHex, ipToBinary, ipToDecimal, ipToDecimalCidr, ipToHex, ipToOctal, isValid, isValidCidr, isValidIp, isValidIpv4, octalToPermissions, parseFileSize, parseInput, parseNumberString, parseSemver, permissionsToChmod, permissionsToOctal, permissionsToSymbolic, ptToPx, pxToAll, pxToViewport, remToPx, satisfiesRange, scaleByHeight, scaleByWidth, sortVersions, splitSubnet, symbolicToPermissions, units_exports, validateCardNumber, viewportToPx };
|
package/dist/index.cjs
CHANGED
|
@@ -6665,6 +6665,7 @@ __export(units_exports, {
|
|
|
6665
6665
|
sortVersions: () => sortVersions,
|
|
6666
6666
|
splitSubnet: () => splitSubnet,
|
|
6667
6667
|
symbolicToPermissions: () => symbolicToPermissions,
|
|
6668
|
+
validateCardNumber: () => validateCardNumber,
|
|
6668
6669
|
viewportToPx: () => viewportToPx
|
|
6669
6670
|
});
|
|
6670
6671
|
function pxToAll(px, baseFontSize = 16, viewportWidth = 1440, viewportHeight = 900) {
|
|
@@ -7497,6 +7498,66 @@ function sortVersions(versions, order = "asc") {
|
|
|
7497
7498
|
return order === "asc" ? cmp : -cmp;
|
|
7498
7499
|
});
|
|
7499
7500
|
}
|
|
7501
|
+
var CARD_NETWORK_RULES = [
|
|
7502
|
+
{ name: "American Express", lengths: [15], test: (d) => /^3[47]/.test(d) },
|
|
7503
|
+
{ name: "Diners Club", lengths: [14], test: (d) => /^3(?:0[0-5]|[68])/.test(d) },
|
|
7504
|
+
{
|
|
7505
|
+
name: "Discover",
|
|
7506
|
+
lengths: [16, 19],
|
|
7507
|
+
test: (d) => /^(?:6011|65|64[4-9])/.test(d) || /^622(?:12[6-9]|1[3-9]\d|[2-8]\d{2}|9[01]\d|92[0-5])/.test(d)
|
|
7508
|
+
},
|
|
7509
|
+
{ name: "JCB", lengths: [16], test: (d) => /^35(?:2[89]|[3-8]\d)/.test(d) },
|
|
7510
|
+
{
|
|
7511
|
+
name: "Mastercard",
|
|
7512
|
+
lengths: [16],
|
|
7513
|
+
test: (d) => {
|
|
7514
|
+
const two = parseInt(d.slice(0, 2), 10);
|
|
7515
|
+
const four = parseInt(d.slice(0, 4), 10);
|
|
7516
|
+
return two >= 51 && two <= 55 || four >= 2221 && four <= 2720;
|
|
7517
|
+
}
|
|
7518
|
+
},
|
|
7519
|
+
{ name: "Maestro", lengths: [12, 13, 14, 15, 16, 17, 18, 19], test: (d) => /^(?:50|5[6-8]|6304|6390|67)/.test(d) },
|
|
7520
|
+
{ name: "UnionPay", lengths: [16, 17, 18, 19], test: (d) => /^62/.test(d) },
|
|
7521
|
+
{ name: "Visa", lengths: [13, 16, 19], test: (d) => /^4/.test(d) }
|
|
7522
|
+
];
|
|
7523
|
+
function luhnCheck(digits) {
|
|
7524
|
+
let sum = 0;
|
|
7525
|
+
let shouldDouble = false;
|
|
7526
|
+
for (let i = digits.length - 1; i >= 0; i--) {
|
|
7527
|
+
let d = parseInt(digits[i], 10);
|
|
7528
|
+
if (shouldDouble) {
|
|
7529
|
+
d *= 2;
|
|
7530
|
+
if (d > 9) d -= 9;
|
|
7531
|
+
}
|
|
7532
|
+
sum += d;
|
|
7533
|
+
shouldDouble = !shouldDouble;
|
|
7534
|
+
}
|
|
7535
|
+
return sum % 10 === 0;
|
|
7536
|
+
}
|
|
7537
|
+
function detectCardNetwork(digits) {
|
|
7538
|
+
for (const rule of CARD_NETWORK_RULES) {
|
|
7539
|
+
if (rule.lengths.includes(digits.length) && rule.test(digits)) return rule.name;
|
|
7540
|
+
}
|
|
7541
|
+
return null;
|
|
7542
|
+
}
|
|
7543
|
+
function formatCardNumber(digits, network) {
|
|
7544
|
+
if (network === "American Express") {
|
|
7545
|
+
return `${digits.slice(0, 4)} ${digits.slice(4, 10)} ${digits.slice(10)}`.trim();
|
|
7546
|
+
}
|
|
7547
|
+
return digits.match(/.{1,4}/g)?.join(" ") ?? digits;
|
|
7548
|
+
}
|
|
7549
|
+
function validateCardNumber(input) {
|
|
7550
|
+
if (!input || !input.trim()) return { error: "Input is empty" };
|
|
7551
|
+
const digits = input.replace(/[\s-]/g, "");
|
|
7552
|
+
if (!/^\d+$/.test(digits)) return { error: "Card number must contain only digits, spaces, or hyphens" };
|
|
7553
|
+
if (digits.length < 12 || digits.length > 19) {
|
|
7554
|
+
return { error: `Card number length (${digits.length}) is outside the valid range of 12-19 digits` };
|
|
7555
|
+
}
|
|
7556
|
+
const valid = luhnCheck(digits);
|
|
7557
|
+
const network = detectCardNetwork(digits);
|
|
7558
|
+
const formatted = formatCardNumber(digits, network);
|
|
7559
|
+
return { valid, network, length: digits.length, formatted };
|
|
7560
|
+
}
|
|
7500
7561
|
|
|
7501
7562
|
// src/tools/network.ts
|
|
7502
7563
|
var network_exports = {};
|
|
@@ -7530,7 +7591,9 @@ __export(network_exports, {
|
|
|
7530
7591
|
typeNumberToLabel: () => typeNumberToLabel,
|
|
7531
7592
|
validateDomain: () => validateDomain,
|
|
7532
7593
|
validateHeaderName: () => validateHeaderName,
|
|
7533
|
-
validateHeaderValue: () => validateHeaderValue
|
|
7594
|
+
validateHeaderValue: () => validateHeaderValue,
|
|
7595
|
+
validateRobotsTxt: () => validateRobotsTxt,
|
|
7596
|
+
validateSitemap: () => validateSitemap
|
|
7534
7597
|
});
|
|
7535
7598
|
var DNS_RECORD_TYPES = ["A", "AAAA", "CNAME", "MX", "TXT", "NS", "SOA", "PTR", "SRV", "CAA"];
|
|
7536
7599
|
function buildDnsQueryUrl(domain, type) {
|
|
@@ -8938,6 +9001,179 @@ function parseHar(input) {
|
|
|
8938
9001
|
summary: { totalRequests, totalSize, totalTime, avgTime, failedRequests, methods, statusCodes }
|
|
8939
9002
|
};
|
|
8940
9003
|
}
|
|
9004
|
+
var VALID_CHANGEFREQ = /* @__PURE__ */ new Set(["always", "hourly", "daily", "weekly", "monthly", "yearly", "never"]);
|
|
9005
|
+
function sitemapLineNumber(xml, index) {
|
|
9006
|
+
let line = 1;
|
|
9007
|
+
for (let i = 0; i < index; i++) {
|
|
9008
|
+
if (xml[i] === "\n") line++;
|
|
9009
|
+
}
|
|
9010
|
+
return line;
|
|
9011
|
+
}
|
|
9012
|
+
function extractSitemapTag(block, tag) {
|
|
9013
|
+
const m = block.match(new RegExp(`<${tag}[^>]*>([\\s\\S]*?)</${tag}>`, "i"));
|
|
9014
|
+
return m ? m[1].trim() : void 0;
|
|
9015
|
+
}
|
|
9016
|
+
function isValidW3CDatetime(s) {
|
|
9017
|
+
return /^\d{4}(-\d{2}(-\d{2}(T\d{2}:\d{2}(:\d{2}(\.\d+)?)?(Z|[+-]\d{2}:\d{2}))?)?)?$/.test(s);
|
|
9018
|
+
}
|
|
9019
|
+
function isAbsoluteHttpUrl(s) {
|
|
9020
|
+
return /^https?:\/\//i.test(s);
|
|
9021
|
+
}
|
|
9022
|
+
function validateSitemap(xml) {
|
|
9023
|
+
if (!xml || !xml.trim()) return { error: "Input is empty" };
|
|
9024
|
+
const trimmed = xml.trim();
|
|
9025
|
+
const issues = [];
|
|
9026
|
+
if (!/^\s*<\?xml/i.test(trimmed)) {
|
|
9027
|
+
issues.push({ severity: "warning", line: 1, message: 'Missing XML declaration (<?xml version="1.0" encoding="UTF-8"?>)' });
|
|
9028
|
+
}
|
|
9029
|
+
const isUrlset = /<urlset[\s>]/i.test(trimmed);
|
|
9030
|
+
const isSitemapIndex = /<sitemapindex[\s>]/i.test(trimmed);
|
|
9031
|
+
if (!isUrlset && !isSitemapIndex) {
|
|
9032
|
+
return { error: "Not a valid sitemap: root element must be <urlset> or <sitemapindex>" };
|
|
9033
|
+
}
|
|
9034
|
+
if (isUrlset && isSitemapIndex) {
|
|
9035
|
+
return { error: "Ambiguous file: contains both <urlset> and <sitemapindex> root elements" };
|
|
9036
|
+
}
|
|
9037
|
+
const type = isUrlset ? "urlset" : "sitemapindex";
|
|
9038
|
+
if (isUrlset && !/xmlns\s*=\s*["']http:\/\/www\.sitemaps\.org\/schemas\/sitemap\/0\.9["']/i.test(trimmed)) {
|
|
9039
|
+
issues.push({ severity: "warning", line: 1, message: "Missing or non-standard xmlns namespace (expected http://www.sitemaps.org/schemas/sitemap/0.9)" });
|
|
9040
|
+
}
|
|
9041
|
+
const blockTag = isUrlset ? "url" : "sitemap";
|
|
9042
|
+
const blockRe = new RegExp(`<${blockTag}>([\\s\\S]*?)</${blockTag}>`, "gi");
|
|
9043
|
+
const seenLocs = /* @__PURE__ */ new Set();
|
|
9044
|
+
const entries = [];
|
|
9045
|
+
let match;
|
|
9046
|
+
while ((match = blockRe.exec(trimmed)) !== null) {
|
|
9047
|
+
const block = match[1];
|
|
9048
|
+
const line = sitemapLineNumber(trimmed, match.index);
|
|
9049
|
+
const loc = extractSitemapTag(block, "loc");
|
|
9050
|
+
if (!loc) {
|
|
9051
|
+
issues.push({ severity: "error", line, message: `<${blockTag}> entry is missing required <loc>` });
|
|
9052
|
+
continue;
|
|
9053
|
+
}
|
|
9054
|
+
if (!isAbsoluteHttpUrl(loc)) {
|
|
9055
|
+
issues.push({ severity: "error", line, message: `<loc>${loc}</loc> must be an absolute URL starting with http:// or https://` });
|
|
9056
|
+
}
|
|
9057
|
+
if (/&(?!amp;|lt;|gt;|apos;|quot;|#\d+;)/.test(loc)) {
|
|
9058
|
+
issues.push({ severity: "error", line, message: `<loc>${loc}</loc> contains an unescaped '&' (use & instead)` });
|
|
9059
|
+
}
|
|
9060
|
+
if (seenLocs.has(loc)) {
|
|
9061
|
+
issues.push({ severity: "warning", line, message: `Duplicate <loc>${loc}</loc>` });
|
|
9062
|
+
}
|
|
9063
|
+
seenLocs.add(loc);
|
|
9064
|
+
const lastmod = extractSitemapTag(block, "lastmod");
|
|
9065
|
+
if (lastmod !== void 0 && !isValidW3CDatetime(lastmod)) {
|
|
9066
|
+
issues.push({ severity: "warning", line, message: `<lastmod>${lastmod}</lastmod> is not a valid W3C datetime` });
|
|
9067
|
+
}
|
|
9068
|
+
if (type === "urlset") {
|
|
9069
|
+
const changefreq = extractSitemapTag(block, "changefreq");
|
|
9070
|
+
if (changefreq !== void 0 && !VALID_CHANGEFREQ.has(changefreq.toLowerCase())) {
|
|
9071
|
+
issues.push({ severity: "error", line, message: `<changefreq>${changefreq}</changefreq> must be one of: ${[...VALID_CHANGEFREQ].join(", ")}` });
|
|
9072
|
+
}
|
|
9073
|
+
const priority = extractSitemapTag(block, "priority");
|
|
9074
|
+
if (priority !== void 0) {
|
|
9075
|
+
const p = Number(priority);
|
|
9076
|
+
if (Number.isNaN(p) || p < 0 || p > 1) {
|
|
9077
|
+
issues.push({ severity: "error", line, message: `<priority>${priority}</priority> must be a number between 0.0 and 1.0` });
|
|
9078
|
+
}
|
|
9079
|
+
}
|
|
9080
|
+
entries.push({ loc, lastmod, changefreq, priority, line });
|
|
9081
|
+
} else {
|
|
9082
|
+
entries.push({ loc, lastmod, line });
|
|
9083
|
+
}
|
|
9084
|
+
}
|
|
9085
|
+
if (entries.length === 0) {
|
|
9086
|
+
issues.push({ severity: "error", line: 1, message: `No <${blockTag}> entries found` });
|
|
9087
|
+
}
|
|
9088
|
+
if (type === "urlset" && entries.length > 5e4) {
|
|
9089
|
+
issues.push({ severity: "error", line: 1, message: `Sitemap contains ${entries.length} URLs, exceeding the 50,000 URL limit per the sitemaps.org spec` });
|
|
9090
|
+
}
|
|
9091
|
+
const valid = !issues.some((i) => i.severity === "error");
|
|
9092
|
+
return { type, urlCount: entries.length, entries, issues, valid };
|
|
9093
|
+
}
|
|
9094
|
+
var KNOWN_ROBOTS_DIRECTIVES = /* @__PURE__ */ new Set(["user-agent", "disallow", "allow", "sitemap", "crawl-delay", "host"]);
|
|
9095
|
+
function validateRobotsTxt(text) {
|
|
9096
|
+
if (!text || !text.trim()) return { error: "Input is empty" };
|
|
9097
|
+
const lines = text.split("\n");
|
|
9098
|
+
const issues = [];
|
|
9099
|
+
const groups = [];
|
|
9100
|
+
const sitemaps = [];
|
|
9101
|
+
let currentGroup = null;
|
|
9102
|
+
for (let i = 0; i < lines.length; i++) {
|
|
9103
|
+
const rawLine = lines[i];
|
|
9104
|
+
const lineNum = i + 1;
|
|
9105
|
+
const commentIdx = rawLine.indexOf("#");
|
|
9106
|
+
const line = (commentIdx >= 0 ? rawLine.slice(0, commentIdx) : rawLine).trim();
|
|
9107
|
+
if (!line) continue;
|
|
9108
|
+
const colonIdx = line.indexOf(":");
|
|
9109
|
+
if (colonIdx === -1) {
|
|
9110
|
+
issues.push({ severity: "error", line: lineNum, message: `Malformed line (missing ':'): "${line}"` });
|
|
9111
|
+
continue;
|
|
9112
|
+
}
|
|
9113
|
+
const directive = line.slice(0, colonIdx).trim().toLowerCase();
|
|
9114
|
+
const value = line.slice(colonIdx + 1).trim();
|
|
9115
|
+
if (!KNOWN_ROBOTS_DIRECTIVES.has(directive)) {
|
|
9116
|
+
issues.push({ severity: "warning", line: lineNum, message: `Unknown directive "${directive}"` });
|
|
9117
|
+
continue;
|
|
9118
|
+
}
|
|
9119
|
+
if (directive === "sitemap") {
|
|
9120
|
+
if (!/^https?:\/\//i.test(value)) {
|
|
9121
|
+
issues.push({ severity: "error", line: lineNum, message: `Sitemap URL "${value}" must be absolute (start with http:// or https://)` });
|
|
9122
|
+
}
|
|
9123
|
+
sitemaps.push(value);
|
|
9124
|
+
continue;
|
|
9125
|
+
}
|
|
9126
|
+
if (directive === "user-agent") {
|
|
9127
|
+
if (!value) {
|
|
9128
|
+
issues.push({ severity: "error", line: lineNum, message: "User-agent directive is missing a value" });
|
|
9129
|
+
}
|
|
9130
|
+
if (currentGroup && currentGroup.rules.length === 0 && currentGroup.crawlDelay === void 0) {
|
|
9131
|
+
currentGroup.userAgents.push(value);
|
|
9132
|
+
} else {
|
|
9133
|
+
currentGroup = { userAgents: [value], rules: [], line: lineNum };
|
|
9134
|
+
groups.push(currentGroup);
|
|
9135
|
+
}
|
|
9136
|
+
continue;
|
|
9137
|
+
}
|
|
9138
|
+
if (!currentGroup) {
|
|
9139
|
+
issues.push({ severity: "error", line: lineNum, message: `"${directive}" directive found before any User-agent line` });
|
|
9140
|
+
continue;
|
|
9141
|
+
}
|
|
9142
|
+
if (directive === "disallow" || directive === "allow") {
|
|
9143
|
+
if (value !== "" && !value.startsWith("/") && !value.startsWith("*")) {
|
|
9144
|
+
issues.push({ severity: "warning", line: lineNum, message: `${directive === "disallow" ? "Disallow" : "Allow"} value "${value}" should start with "/" (or be empty)` });
|
|
9145
|
+
}
|
|
9146
|
+
if (currentGroup.rules.some((r) => r.type === directive && r.value === value)) {
|
|
9147
|
+
issues.push({ severity: "warning", line: lineNum, message: `Duplicate ${directive} rule for "${value}" in this group` });
|
|
9148
|
+
}
|
|
9149
|
+
currentGroup.rules.push({ type: directive, value, line: lineNum });
|
|
9150
|
+
} else if (directive === "crawl-delay") {
|
|
9151
|
+
const n = Number(value);
|
|
9152
|
+
if (Number.isNaN(n) || n < 0) {
|
|
9153
|
+
issues.push({ severity: "error", line: lineNum, message: `Crawl-delay "${value}" must be a non-negative number` });
|
|
9154
|
+
} else {
|
|
9155
|
+
currentGroup.crawlDelay = n;
|
|
9156
|
+
}
|
|
9157
|
+
}
|
|
9158
|
+
}
|
|
9159
|
+
if (groups.length === 0) {
|
|
9160
|
+
issues.push({ severity: "error", line: 1, message: "No User-agent groups found" });
|
|
9161
|
+
}
|
|
9162
|
+
const seenUA = /* @__PURE__ */ new Map();
|
|
9163
|
+
for (const g of groups) {
|
|
9164
|
+
for (const ua of g.userAgents) {
|
|
9165
|
+
const key = ua.toLowerCase();
|
|
9166
|
+
const firstLine = seenUA.get(key);
|
|
9167
|
+
if (firstLine !== void 0) {
|
|
9168
|
+
issues.push({ severity: "warning", line: g.line, message: `Duplicate User-agent "${ua}" (first seen on line ${firstLine})` });
|
|
9169
|
+
} else {
|
|
9170
|
+
seenUA.set(key, g.line);
|
|
9171
|
+
}
|
|
9172
|
+
}
|
|
9173
|
+
}
|
|
9174
|
+
const valid = !issues.some((i) => i.severity === "error");
|
|
9175
|
+
return { groups, sitemaps, issues, valid };
|
|
9176
|
+
}
|
|
8941
9177
|
|
|
8942
9178
|
// src/tools/api.ts
|
|
8943
9179
|
var api_exports = {};
|
package/dist/index.d.cts
CHANGED
|
@@ -5,8 +5,8 @@ export { t as text } from './text-Bbx-tZ43.cjs';
|
|
|
5
5
|
export { d as data } from './data-D8XTI7Du.cjs';
|
|
6
6
|
export { g as generators } from './generators-BGtRGpJZ.cjs';
|
|
7
7
|
export { t as time } from './time-DbT8fjaF.cjs';
|
|
8
|
-
export { u as units } from './units-
|
|
9
|
-
export { n as network } from './network-
|
|
8
|
+
export { u as units } from './units-DRT6W-vu.cjs';
|
|
9
|
+
export { n as network } from './network-DaNoZ5ER.cjs';
|
|
10
10
|
export { a as api } from './api-Xl7OzIgq.cjs';
|
|
11
11
|
export { c as code } from './code-BUqyaofO.cjs';
|
|
12
12
|
export { c as color } from './color-tPwZCr9H.cjs';
|
package/dist/index.d.ts
CHANGED
|
@@ -5,8 +5,8 @@ export { t as text } from './text-Bbx-tZ43.js';
|
|
|
5
5
|
export { d as data } from './data-D8XTI7Du.js';
|
|
6
6
|
export { g as generators } from './generators-BGtRGpJZ.js';
|
|
7
7
|
export { t as time } from './time-DbT8fjaF.js';
|
|
8
|
-
export { u as units } from './units-
|
|
9
|
-
export { n as network } from './network-
|
|
8
|
+
export { u as units } from './units-DRT6W-vu.js';
|
|
9
|
+
export { n as network } from './network-DaNoZ5ER.js';
|
|
10
10
|
export { a as api } from './api-Xl7OzIgq.js';
|
|
11
11
|
export { c as code } from './code-BUqyaofO.js';
|
|
12
12
|
export { c as color } from './color-tPwZCr9H.js';
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { media_exports as media } from './chunk-GUUYEIU6.js';
|
|
2
|
-
export { units_exports as units } from './chunk-
|
|
3
|
-
export { network_exports as network } from './chunk-
|
|
2
|
+
export { units_exports as units } from './chunk-YVFM5WYI.js';
|
|
3
|
+
export { network_exports as network } from './chunk-OB56VNKJ.js';
|
|
4
4
|
export { api_exports as api } from './chunk-Q3B3YWOA.js';
|
|
5
5
|
export { code_exports as code } from './chunk-V5S6OJ4A.js';
|
|
6
6
|
export { color_exports as color } from './chunk-BPVAB4P2.js';
|