@detiq/crawler 1.1.9 → 1.1.10

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