@detiq/crawler 1.1.9 → 1.1.11
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/dist/accessibility-auditor.js +54 -74
- package/dist/ai-login.js +227 -249
- package/dist/auth-token-rotator.js +57 -67
- package/dist/auth.js +299 -336
- package/dist/browser-extension.js +104 -142
- package/dist/captcha-solver.js +98 -125
- package/dist/color-contrast.js +77 -89
- package/dist/content-chunker.js +126 -126
- package/dist/content-dedup.js +54 -71
- package/dist/cookie-consent.js +68 -83
- package/dist/cookie-jar.js +53 -60
- package/dist/crawler.js +4494 -5353
- package/dist/custom-js-injector.js +45 -61
- package/dist/dark-mode-capture.js +67 -81
- package/dist/dead-link-detector.js +47 -55
- package/dist/element-hash.js +8 -12
- package/dist/email-otp.js +154 -195
- package/dist/engine-router.js +87 -98
- package/dist/export/bulk-export.js +70 -55
- package/dist/export/vector-export.js +77 -105
- package/dist/extractors/advanced.js +249 -266
- package/dist/extractors/artifact-envelope.js +59 -58
- package/dist/failure-analysis-agent.js +37 -33
- package/dist/feature-flag-detector.js +51 -66
- package/dist/form-detector.js +55 -75
- package/dist/frontier.js +76 -101
- package/dist/gap-pass.js +68 -89
- package/dist/graphql-detector.js +62 -72
- package/dist/http-engine.js +282 -330
- package/dist/incremental-diff.js +54 -87
- package/dist/index.js +67 -28
- package/dist/input-fuzzer.js +93 -97
- package/dist/interactive-probe.js +715 -827
- package/dist/job-queue.js +2151 -2169
- package/dist/js-coverage.js +52 -56
- package/dist/js-router-detector.js +86 -117
- package/dist/language-detector.js +51 -63
- package/dist/link-classifier.js +32 -50
- package/dist/live-view.js +91 -108
- package/dist/locator-extractor.js +151 -187
- package/dist/logger.js +9 -7
- package/dist/markdown-extract.js +48 -61
- package/dist/native-crawler.js +780 -946
- package/dist/network-observer.js +135 -156
- package/dist/network-throttle.js +29 -40
- package/dist/openapi-generator.js +77 -92
- package/dist/pdf-extractor.js +72 -90
- package/dist/performance-metrics.js +80 -102
- package/dist/phash.js +125 -144
- package/dist/pii-scrubber.js +65 -68
- package/dist/playwright-recorder.js +70 -58
- package/dist/policies/crawl-safety.js +31 -34
- package/dist/profiles/domain-profile.js +130 -125
- package/dist/proxy.js +146 -172
- package/dist/rate-limiter.js +58 -65
- package/dist/redirect-tracker.js +60 -64
- package/dist/redis-frontier.js +116 -136
- package/dist/redis-queue.js +157 -144
- package/dist/response-cache.js +127 -140
- package/dist/responsive-detector.js +42 -46
- package/dist/retry-policy.js +46 -50
- package/dist/robots-txt.js +69 -83
- package/dist/screen-reader.js +45 -70
- package/dist/screenshot-masker.js +59 -77
- package/dist/seo-checker.js +88 -107
- package/dist/session-capture.js +192 -212
- package/dist/session-export.js +107 -133
- package/dist/sitemap-writer.js +38 -41
- package/dist/sitemap.js +141 -202
- package/dist/skyvern.js +123 -148
- package/dist/sqs-queue.js +42 -42
- package/dist/sso-token.js +74 -90
- package/dist/stealth/human-behavior.js +156 -173
- package/dist/telemetry.js +68 -82
- package/dist/test-executor.js +309 -335
- package/dist/tls-fingerprint.js +77 -88
- package/dist/url-pattern-completer.js +71 -90
- package/dist/visual-diff-verdict.js +23 -38
- package/dist/webhook-notifier.js +71 -69
- package/dist/websocket-detector.js +56 -68
- package/dist/worker.js +29 -38
- package/package.json +1 -1
- package/src/job-queue.ts +136 -0
|
@@ -1,77 +1,57 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Accessibility auditor — lightweight a11y checks using Playwright's aria snapshot
|
|
3
|
-
* and manual DOM queries. No axe-core dependency needed.
|
|
4
|
-
*
|
|
5
|
-
* Checks:
|
|
6
|
-
* 1. Images without alt text
|
|
7
|
-
* 2. Form inputs without associated labels
|
|
8
|
-
* 3. Buttons/links with no accessible name
|
|
9
|
-
* 4. Missing lang attribute on html element
|
|
10
|
-
* 5. Missing page title
|
|
11
|
-
* 6. Empty headings
|
|
12
|
-
* 7. Color contrast (limited — detects text with inline style color only)
|
|
13
|
-
* 8. Keyboard-unfocusable interactive elements (tabIndex=-1 on buttons)
|
|
14
|
-
*/
|
|
15
1
|
async function queryAll(page, selector) {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}
|
|
2
|
+
try {
|
|
3
|
+
return await page.$$eval(selector, (els) => els.map((el) => ({
|
|
4
|
+
outerHTML: el.outerHTML?.slice(0, 200) ?? "",
|
|
5
|
+
textContent: (el.textContent ?? "").trim().slice(0, 100),
|
|
6
|
+
tabIndex: el.tabIndex,
|
|
7
|
+
getAttribute: (a) => el.getAttribute(a)
|
|
8
|
+
})));
|
|
9
|
+
} catch {
|
|
10
|
+
return [];
|
|
11
|
+
}
|
|
27
12
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
// 7. Links with no accessible name
|
|
69
|
-
const emptyLinks = await page.$$eval('a[href]:not([aria-label]):not([aria-labelledby])', els => els.filter((e) => !(e.textContent ?? '').trim() && !e.querySelector('img[alt]')).map((e) => e.outerHTML?.slice(0, 120) ?? ''));
|
|
70
|
-
if (emptyLinks.length > 0)
|
|
71
|
-
violations.push({ rule: 'link-name', severity: 'serious', count: emptyLinks.length, examples: emptyLinks.slice(0, 3) });
|
|
72
|
-
else
|
|
73
|
-
passCount++;
|
|
74
|
-
const totalChecks = passCount + violations.length;
|
|
75
|
-
const score = totalChecks > 0 ? Math.round((passCount / totalChecks) * 100) : 100;
|
|
76
|
-
return { url, violations, passCount, score, auditedAt };
|
|
13
|
+
async function auditAccessibility(page, url) {
|
|
14
|
+
const violations = [];
|
|
15
|
+
let passCount = 0;
|
|
16
|
+
const auditedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
17
|
+
const imgs = await page.$$eval("img:not([alt])", (els) => els.map((e) => e.outerHTML?.slice(0, 120) ?? ""));
|
|
18
|
+
if (imgs.length > 0) violations.push({ rule: "image-alt", severity: "critical", count: imgs.length, examples: imgs.slice(0, 3) });
|
|
19
|
+
else passCount++;
|
|
20
|
+
const unlabeledInputs = await page.$$eval(
|
|
21
|
+
'input:not([type="hidden"]):not([type="submit"]):not([type="button"]):not([aria-label]):not([aria-labelledby]):not([id])',
|
|
22
|
+
(els) => els.map((e) => e.outerHTML?.slice(0, 120) ?? "")
|
|
23
|
+
);
|
|
24
|
+
if (unlabeledInputs.length > 0) violations.push({ rule: "label", severity: "serious", count: unlabeledInputs.length, examples: unlabeledInputs.slice(0, 3) });
|
|
25
|
+
else passCount++;
|
|
26
|
+
const emptyButtons = await page.$$eval(
|
|
27
|
+
"button:not([aria-label]):not([aria-labelledby])",
|
|
28
|
+
(els) => els.filter((e) => !(e.textContent ?? "").trim()).map((e) => e.outerHTML?.slice(0, 120) ?? "")
|
|
29
|
+
);
|
|
30
|
+
if (emptyButtons.length > 0) violations.push({ rule: "button-name", severity: "critical", count: emptyButtons.length, examples: emptyButtons.slice(0, 3) });
|
|
31
|
+
else passCount++;
|
|
32
|
+
const htmlLang = await page.$eval("html", (el) => el.getAttribute("lang") ?? "").catch(() => "");
|
|
33
|
+
if (!htmlLang) violations.push({ rule: "html-has-lang", severity: "serious", count: 1, examples: ["<html> missing lang attribute"] });
|
|
34
|
+
else passCount++;
|
|
35
|
+
const title = await page.title().catch(() => "");
|
|
36
|
+
if (!title) violations.push({ rule: "document-title", severity: "serious", count: 1, examples: ["Page has no <title>"] });
|
|
37
|
+
else passCount++;
|
|
38
|
+
const emptyHeadings = await page.$$eval(
|
|
39
|
+
"h1,h2,h3,h4,h5,h6",
|
|
40
|
+
(els) => els.filter((e) => !(e.textContent ?? "").trim()).map((e) => e.tagName.toLowerCase())
|
|
41
|
+
);
|
|
42
|
+
if (emptyHeadings.length > 0) violations.push({ rule: "empty-heading", severity: "moderate", count: emptyHeadings.length, examples: emptyHeadings.slice(0, 3) });
|
|
43
|
+
else passCount++;
|
|
44
|
+
const emptyLinks = await page.$$eval(
|
|
45
|
+
"a[href]:not([aria-label]):not([aria-labelledby])",
|
|
46
|
+
(els) => els.filter((e) => !(e.textContent ?? "").trim() && !e.querySelector("img[alt]")).map((e) => e.outerHTML?.slice(0, 120) ?? "")
|
|
47
|
+
);
|
|
48
|
+
if (emptyLinks.length > 0) violations.push({ rule: "link-name", severity: "serious", count: emptyLinks.length, examples: emptyLinks.slice(0, 3) });
|
|
49
|
+
else passCount++;
|
|
50
|
+
const totalChecks = passCount + violations.length;
|
|
51
|
+
const score = totalChecks > 0 ? Math.round(passCount / totalChecks * 100) : 100;
|
|
52
|
+
return { url, violations, passCount, score, auditedAt };
|
|
77
53
|
}
|
|
54
|
+
export {
|
|
55
|
+
auditAccessibility
|
|
56
|
+
};
|
|
57
|
+
//# sourceMappingURL=accessibility-auditor.js.map
|