uxinspect 0.2.0 → 0.11.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/README.md +332 -22
- package/dist/a11y-filter.d.ts +15 -0
- package/dist/a11y-filter.d.ts.map +1 -0
- package/dist/a11y-filter.js +107 -0
- package/dist/a11y-filter.js.map +1 -0
- package/dist/ab-compare.d.ts +23 -0
- package/dist/ab-compare.d.ts.map +1 -0
- package/dist/ab-compare.js +340 -0
- package/dist/ab-compare.js.map +1 -0
- package/dist/ai-codegen.d.ts +30 -0
- package/dist/ai-codegen.d.ts.map +1 -0
- package/dist/ai-codegen.js +296 -0
- package/dist/ai-codegen.js.map +1 -0
- package/dist/ai-triage.d.ts +26 -0
- package/dist/ai-triage.d.ts.map +1 -0
- package/dist/ai-triage.js +207 -0
- package/dist/ai-triage.js.map +1 -0
- package/dist/amp.d.ts +32 -0
- package/dist/amp.d.ts.map +1 -0
- package/dist/amp.js +179 -0
- package/dist/amp.js.map +1 -0
- package/dist/animation-audit.d.ts +25 -0
- package/dist/animation-audit.d.ts.map +1 -0
- package/dist/animation-audit.js +296 -0
- package/dist/animation-audit.js.map +1 -0
- package/dist/api.d.ts +3 -0
- package/dist/api.d.ts.map +1 -0
- package/dist/api.js +85 -0
- package/dist/api.js.map +1 -0
- package/dist/aria-audit.d.ts +20 -0
- package/dist/aria-audit.d.ts.map +1 -0
- package/dist/aria-audit.js +445 -0
- package/dist/aria-audit.js.map +1 -0
- package/dist/assertions.d.ts +30 -0
- package/dist/assertions.d.ts.map +1 -0
- package/dist/assertions.js +342 -0
- package/dist/assertions.js.map +1 -0
- package/dist/autofix.d.ts +40 -0
- package/dist/autofix.d.ts.map +1 -0
- package/dist/autofix.js +244 -0
- package/dist/autofix.js.map +1 -0
- package/dist/badge.d.ts +27 -0
- package/dist/badge.d.ts.map +1 -0
- package/dist/badge.js +183 -0
- package/dist/badge.js.map +1 -0
- package/dist/baseline-drift.d.ts +43 -0
- package/dist/baseline-drift.d.ts.map +1 -0
- package/dist/baseline-drift.js +208 -0
- package/dist/baseline-drift.js.map +1 -0
- package/dist/bdd.d.ts +31 -0
- package/dist/bdd.d.ts.map +1 -0
- package/dist/bdd.js +316 -0
- package/dist/bdd.js.map +1 -0
- package/dist/bisect.d.ts +32 -0
- package/dist/bisect.d.ts.map +1 -0
- package/dist/bisect.js +253 -0
- package/dist/bisect.js.map +1 -0
- package/dist/budget-diff.d.ts +37 -0
- package/dist/budget-diff.d.ts.map +1 -0
- package/dist/budget-diff.js +273 -0
- package/dist/budget-diff.js.map +1 -0
- package/dist/budget-file.d.ts +15 -0
- package/dist/budget-file.d.ts.map +1 -0
- package/dist/budget-file.js +185 -0
- package/dist/budget-file.js.map +1 -0
- package/dist/bundle-size.d.ts +36 -0
- package/dist/bundle-size.d.ts.map +1 -0
- package/dist/bundle-size.js +347 -0
- package/dist/bundle-size.js.map +1 -0
- package/dist/cache-headers.d.ts +33 -0
- package/dist/cache-headers.d.ts.map +1 -0
- package/dist/cache-headers.js +270 -0
- package/dist/cache-headers.js.map +1 -0
- package/dist/canonical-audit.d.ts +19 -0
- package/dist/canonical-audit.d.ts.map +1 -0
- package/dist/canonical-audit.js +196 -0
- package/dist/canonical-audit.js.map +1 -0
- package/dist/chaos.d.ts +38 -0
- package/dist/chaos.d.ts.map +1 -0
- package/dist/chaos.js +348 -0
- package/dist/chaos.js.map +1 -0
- package/dist/cli.js +201 -23
- package/dist/cli.js.map +1 -1
- package/dist/clickjacking-audit.d.ts +18 -0
- package/dist/clickjacking-audit.d.ts.map +1 -0
- package/dist/clickjacking-audit.js +231 -0
- package/dist/clickjacking-audit.js.map +1 -0
- package/dist/cls-culprit.d.ts +36 -0
- package/dist/cls-culprit.d.ts.map +1 -0
- package/dist/cls-culprit.js +203 -0
- package/dist/cls-culprit.js.map +1 -0
- package/dist/cls-timeline.d.ts +30 -0
- package/dist/cls-timeline.d.ts.map +1 -0
- package/dist/cls-timeline.js +61 -0
- package/dist/cls-timeline.js.map +1 -0
- package/dist/codegen-converter.d.ts +19 -0
- package/dist/codegen-converter.d.ts.map +1 -0
- package/dist/codegen-converter.js +464 -0
- package/dist/codegen-converter.js.map +1 -0
- package/dist/compression.d.ts +14 -0
- package/dist/compression.d.ts.map +1 -0
- package/dist/compression.js +150 -0
- package/dist/compression.js.map +1 -0
- package/dist/console-errors.d.ts +24 -0
- package/dist/console-errors.d.ts.map +1 -0
- package/dist/console-errors.js +96 -0
- package/dist/console-errors.js.map +1 -0
- package/dist/content-quality.d.ts +34 -0
- package/dist/content-quality.d.ts.map +1 -0
- package/dist/content-quality.js +124 -0
- package/dist/content-quality.js.map +1 -0
- package/dist/contract-openapi.d.ts +74 -0
- package/dist/contract-openapi.d.ts.map +1 -0
- package/dist/contract-openapi.js +305 -0
- package/dist/contract-openapi.js.map +1 -0
- package/dist/cookie-banner.d.ts +27 -0
- package/dist/cookie-banner.d.ts.map +1 -0
- package/dist/cookie-banner.js +285 -0
- package/dist/cookie-banner.js.map +1 -0
- package/dist/cookie-flags-audit.d.ts +35 -0
- package/dist/cookie-flags-audit.d.ts.map +1 -0
- package/dist/cookie-flags-audit.js +167 -0
- package/dist/cookie-flags-audit.js.map +1 -0
- package/dist/cpu-throttle.d.ts +34 -0
- package/dist/cpu-throttle.d.ts.map +1 -0
- package/dist/cpu-throttle.js +149 -0
- package/dist/cpu-throttle.js.map +1 -0
- package/dist/crawl.d.ts +29 -0
- package/dist/crawl.d.ts.map +1 -0
- package/dist/crawl.js +153 -0
- package/dist/crawl.js.map +1 -0
- package/dist/critical-css.d.ts +25 -0
- package/dist/critical-css.d.ts.map +1 -0
- package/dist/critical-css.js +353 -0
- package/dist/critical-css.js.map +1 -0
- package/dist/cross-browser.d.ts +44 -0
- package/dist/cross-browser.d.ts.map +1 -0
- package/dist/cross-browser.js +300 -0
- package/dist/cross-browser.js.map +1 -0
- package/dist/csrf-audit.d.ts +33 -0
- package/dist/csrf-audit.d.ts.map +1 -0
- package/dist/csrf-audit.js +276 -0
- package/dist/csrf-audit.js.map +1 -0
- package/dist/css-coverage.d.ts +20 -0
- package/dist/css-coverage.d.ts.map +1 -0
- package/dist/css-coverage.js +91 -0
- package/dist/css-coverage.js.map +1 -0
- package/dist/csv-exporter.d.ts +34 -0
- package/dist/csv-exporter.d.ts.map +1 -0
- package/dist/csv-exporter.js +241 -0
- package/dist/csv-exporter.js.map +1 -0
- package/dist/dark-mode-audit.d.ts +31 -0
- package/dist/dark-mode-audit.d.ts.map +1 -0
- package/dist/dark-mode-audit.js +236 -0
- package/dist/dark-mode-audit.js.map +1 -0
- package/dist/dead-images.d.ts +18 -0
- package/dist/dead-images.d.ts.map +1 -0
- package/dist/dead-images.js +236 -0
- package/dist/dead-images.js.map +1 -0
- package/dist/deadclicks.d.ts +19 -0
- package/dist/deadclicks.d.ts.map +1 -0
- package/dist/deadclicks.js +109 -0
- package/dist/deadclicks.js.map +1 -0
- package/dist/discord-formatter.d.ts +39 -0
- package/dist/discord-formatter.d.ts.map +1 -0
- package/dist/discord-formatter.js +191 -0
- package/dist/discord-formatter.js.map +1 -0
- package/dist/dom-audit.d.ts +23 -0
- package/dist/dom-audit.d.ts.map +1 -0
- package/dist/dom-audit.js +111 -0
- package/dist/dom-audit.js.map +1 -0
- package/dist/driver.d.ts.map +1 -1
- package/dist/driver.js +10 -0
- package/dist/driver.js.map +1 -1
- package/dist/error-page-audit.d.ts +26 -0
- package/dist/error-page-audit.d.ts.map +1 -0
- package/dist/error-page-audit.js +219 -0
- package/dist/error-page-audit.js.map +1 -0
- package/dist/event-listener-audit.d.ts +22 -0
- package/dist/event-listener-audit.d.ts.map +1 -0
- package/dist/event-listener-audit.js +156 -0
- package/dist/event-listener-audit.js.map +1 -0
- package/dist/exposed-paths.d.ts +21 -0
- package/dist/exposed-paths.d.ts.map +1 -0
- package/dist/exposed-paths.js +116 -0
- package/dist/exposed-paths.js.map +1 -0
- package/dist/favicon-audit.d.ts +28 -0
- package/dist/favicon-audit.d.ts.map +1 -0
- package/dist/favicon-audit.js +358 -0
- package/dist/favicon-audit.js.map +1 -0
- package/dist/flaky-detector.d.ts +32 -0
- package/dist/flaky-detector.d.ts.map +1 -0
- package/dist/flaky-detector.js +254 -0
- package/dist/flaky-detector.js.map +1 -0
- package/dist/flaky.d.ts +28 -0
- package/dist/flaky.d.ts.map +1 -0
- package/dist/flaky.js +106 -0
- package/dist/flaky.js.map +1 -0
- package/dist/focus-trap-audit.d.ts +29 -0
- package/dist/focus-trap-audit.d.ts.map +1 -0
- package/dist/focus-trap-audit.js +285 -0
- package/dist/focus-trap-audit.js.map +1 -0
- package/dist/font-loading.d.ts +29 -0
- package/dist/font-loading.d.ts.map +1 -0
- package/dist/font-loading.js +216 -0
- package/dist/font-loading.js.map +1 -0
- package/dist/forms-audit.d.ts +23 -0
- package/dist/forms-audit.d.ts.map +1 -0
- package/dist/forms-audit.js +147 -0
- package/dist/forms-audit.js.map +1 -0
- package/dist/github-annotations.d.ts +17 -0
- package/dist/github-annotations.d.ts.map +1 -0
- package/dist/github-annotations.js +264 -0
- package/dist/github-annotations.js.map +1 -0
- package/dist/graphql.d.ts +60 -0
- package/dist/graphql.d.ts.map +1 -0
- package/dist/graphql.js +188 -0
- package/dist/graphql.js.map +1 -0
- package/dist/har-waterfall.d.ts +37 -0
- package/dist/har-waterfall.d.ts.map +1 -0
- package/dist/har-waterfall.js +376 -0
- package/dist/har-waterfall.js.map +1 -0
- package/dist/heading-hierarchy.d.ts +20 -0
- package/dist/heading-hierarchy.d.ts.map +1 -0
- package/dist/heading-hierarchy.js +112 -0
- package/dist/heading-hierarchy.js.map +1 -0
- package/dist/headless-detect.d.ts +22 -0
- package/dist/headless-detect.d.ts.map +1 -0
- package/dist/headless-detect.js +167 -0
- package/dist/headless-detect.js.map +1 -0
- package/dist/history-timeline.d.ts +13 -0
- package/dist/history-timeline.d.ts.map +1 -0
- package/dist/history-timeline.js +327 -0
- package/dist/history-timeline.js.map +1 -0
- package/dist/hreflang-audit.d.ts +26 -0
- package/dist/hreflang-audit.d.ts.map +1 -0
- package/dist/hreflang-audit.js +273 -0
- package/dist/hreflang-audit.js.map +1 -0
- package/dist/hydration-audit.d.ts +21 -0
- package/dist/hydration-audit.d.ts.map +1 -0
- package/dist/hydration-audit.js +277 -0
- package/dist/hydration-audit.js.map +1 -0
- package/dist/image-audit.d.ts +41 -0
- package/dist/image-audit.d.ts.map +1 -0
- package/dist/image-audit.js +229 -0
- package/dist/image-audit.js.map +1 -0
- package/dist/index.d.ts +119 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +708 -2
- package/dist/index.js.map +1 -1
- package/dist/init-wizard.d.ts +33 -0
- package/dist/init-wizard.d.ts.map +1 -0
- package/dist/init-wizard.js +289 -0
- package/dist/init-wizard.js.map +1 -0
- package/dist/inp-audit.d.ts +26 -0
- package/dist/inp-audit.d.ts.map +1 -0
- package/dist/inp-audit.js +202 -0
- package/dist/inp-audit.js.map +1 -0
- package/dist/js-coverage.d.ts +20 -0
- package/dist/js-coverage.d.ts.map +1 -0
- package/dist/js-coverage.js +81 -0
- package/dist/js-coverage.js.map +1 -0
- package/dist/json-schema.d.ts +27 -0
- package/dist/json-schema.d.ts.map +1 -0
- package/dist/json-schema.js +284 -0
- package/dist/json-schema.js.map +1 -0
- package/dist/keyboard.d.ts +21 -0
- package/dist/keyboard.d.ts.map +1 -0
- package/dist/keyboard.js +119 -0
- package/dist/keyboard.js.map +1 -0
- package/dist/lang-audit.d.ts +24 -0
- package/dist/lang-audit.d.ts.map +1 -0
- package/dist/lang-audit.js +141 -0
- package/dist/lang-audit.js.map +1 -0
- package/dist/lcp-element.d.ts +22 -0
- package/dist/lcp-element.d.ts.map +1 -0
- package/dist/lcp-element.js +240 -0
- package/dist/lcp-element.js.map +1 -0
- package/dist/longtasks.d.ts +38 -0
- package/dist/longtasks.d.ts.map +1 -0
- package/dist/longtasks.js +97 -0
- package/dist/longtasks.js.map +1 -0
- package/dist/mailbox.d.ts +35 -0
- package/dist/mailbox.d.ts.map +1 -0
- package/dist/mailbox.js +207 -0
- package/dist/mailbox.js.map +1 -0
- package/dist/media-audit.d.ts +20 -0
- package/dist/media-audit.d.ts.map +1 -0
- package/dist/media-audit.js +182 -0
- package/dist/media-audit.js.map +1 -0
- package/dist/metrics-exporter.d.ts +23 -0
- package/dist/metrics-exporter.d.ts.map +1 -0
- package/dist/metrics-exporter.js +297 -0
- package/dist/metrics-exporter.js.map +1 -0
- package/dist/mixed-content.d.ts +19 -0
- package/dist/mixed-content.d.ts.map +1 -0
- package/dist/mixed-content.js +86 -0
- package/dist/mixed-content.js.map +1 -0
- package/dist/motion-prefs.d.ts +21 -0
- package/dist/motion-prefs.d.ts.map +1 -0
- package/dist/motion-prefs.js +170 -0
- package/dist/motion-prefs.js.map +1 -0
- package/dist/open-graph.d.ts +40 -0
- package/dist/open-graph.d.ts.map +1 -0
- package/dist/open-graph.js +200 -0
- package/dist/open-graph.js.map +1 -0
- package/dist/orphan-assets.d.ts +17 -0
- package/dist/orphan-assets.d.ts.map +1 -0
- package/dist/orphan-assets.js +174 -0
- package/dist/orphan-assets.js.map +1 -0
- package/dist/page-object.d.ts +18 -0
- package/dist/page-object.d.ts.map +1 -0
- package/dist/page-object.js +346 -0
- package/dist/page-object.js.map +1 -0
- package/dist/pagination-audit.d.ts +24 -0
- package/dist/pagination-audit.d.ts.map +1 -0
- package/dist/pagination-audit.js +285 -0
- package/dist/pagination-audit.js.map +1 -0
- package/dist/passive-security.d.ts +19 -0
- package/dist/passive-security.d.ts.map +1 -0
- package/dist/passive-security.js +149 -0
- package/dist/passive-security.js.map +1 -0
- package/dist/pr-comment.d.ts +13 -0
- package/dist/pr-comment.d.ts.map +1 -0
- package/dist/pr-comment.js +316 -0
- package/dist/pr-comment.js.map +1 -0
- package/dist/precommit.d.ts +24 -0
- package/dist/precommit.d.ts.map +1 -0
- package/dist/precommit.js +239 -0
- package/dist/precommit.js.map +1 -0
- package/dist/prerender-audit.d.ts +22 -0
- package/dist/prerender-audit.d.ts.map +1 -0
- package/dist/prerender-audit.js +158 -0
- package/dist/prerender-audit.js.map +1 -0
- package/dist/print-audit.d.ts +21 -0
- package/dist/print-audit.d.ts.map +1 -0
- package/dist/print-audit.js +281 -0
- package/dist/print-audit.js.map +1 -0
- package/dist/protocol-audit.d.ts +17 -0
- package/dist/protocol-audit.d.ts.map +1 -0
- package/dist/protocol-audit.js +128 -0
- package/dist/protocol-audit.js.map +1 -0
- package/dist/reading-level.d.ts +37 -0
- package/dist/reading-level.d.ts.map +1 -0
- package/dist/reading-level.js +220 -0
- package/dist/reading-level.js.map +1 -0
- package/dist/redirects.d.ts +24 -0
- package/dist/redirects.d.ts.map +1 -0
- package/dist/redirects.js +119 -0
- package/dist/redirects.js.map +1 -0
- package/dist/report.d.ts +1 -1
- package/dist/report.d.ts.map +1 -1
- package/dist/report.js +736 -1
- package/dist/report.js.map +1 -1
- package/dist/reporter-plugin.d.ts +32 -0
- package/dist/reporter-plugin.d.ts.map +1 -0
- package/dist/reporter-plugin.js +120 -0
- package/dist/reporter-plugin.js.map +1 -0
- package/dist/resource-hints.d.ts +23 -0
- package/dist/resource-hints.d.ts.map +1 -0
- package/dist/resource-hints.js +225 -0
- package/dist/resource-hints.js.map +1 -0
- package/dist/retire.d.ts +22 -0
- package/dist/retire.d.ts.map +1 -0
- package/dist/retire.js +140 -0
- package/dist/retire.js.map +1 -0
- package/dist/retry.d.ts +20 -0
- package/dist/retry.d.ts.map +1 -0
- package/dist/retry.js +120 -0
- package/dist/retry.js.map +1 -0
- package/dist/robots-audit.d.ts +24 -0
- package/dist/robots-audit.d.ts.map +1 -0
- package/dist/robots-audit.js +206 -0
- package/dist/robots-audit.js.map +1 -0
- package/dist/rum.d.ts +35 -0
- package/dist/rum.d.ts.map +1 -0
- package/dist/rum.js +219 -0
- package/dist/rum.js.map +1 -0
- package/dist/schedule.d.ts +30 -0
- package/dist/schedule.d.ts.map +1 -0
- package/dist/schedule.js +238 -0
- package/dist/schedule.js.map +1 -0
- package/dist/secret-scan.d.ts +24 -0
- package/dist/secret-scan.d.ts.map +1 -0
- package/dist/secret-scan.js +202 -0
- package/dist/secret-scan.js.map +1 -0
- package/dist/service-worker.d.ts +26 -0
- package/dist/service-worker.d.ts.map +1 -0
- package/dist/service-worker.js +179 -0
- package/dist/service-worker.js.map +1 -0
- package/dist/shard.d.ts +14 -0
- package/dist/shard.d.ts.map +1 -0
- package/dist/shard.js +72 -0
- package/dist/shard.js.map +1 -0
- package/dist/sitemap-flows.d.ts +13 -0
- package/dist/sitemap-flows.d.ts.map +1 -0
- package/dist/sitemap-flows.js +157 -0
- package/dist/sitemap-flows.js.map +1 -0
- package/dist/sitemap.d.ts +27 -0
- package/dist/sitemap.d.ts.map +1 -0
- package/dist/sitemap.js +137 -0
- package/dist/sitemap.js.map +1 -0
- package/dist/slack-formatter.d.ts +35 -0
- package/dist/slack-formatter.d.ts.map +1 -0
- package/dist/slack-formatter.js +193 -0
- package/dist/slack-formatter.js.map +1 -0
- package/dist/sourcemap-scan.d.ts +24 -0
- package/dist/sourcemap-scan.d.ts.map +1 -0
- package/dist/sourcemap-scan.js +232 -0
- package/dist/sourcemap-scan.js.map +1 -0
- package/dist/sri-audit.d.ts +23 -0
- package/dist/sri-audit.d.ts.map +1 -0
- package/dist/sri-audit.js +180 -0
- package/dist/sri-audit.js.map +1 -0
- package/dist/storage-audit.d.ts +28 -0
- package/dist/storage-audit.d.ts.map +1 -0
- package/dist/storage-audit.js +263 -0
- package/dist/storage-audit.js.map +1 -0
- package/dist/storybook.d.ts +48 -0
- package/dist/storybook.d.ts.map +1 -0
- package/dist/storybook.js +191 -0
- package/dist/storybook.js.map +1 -0
- package/dist/structured-data.d.ts +25 -0
- package/dist/structured-data.d.ts.map +1 -0
- package/dist/structured-data.js +164 -0
- package/dist/structured-data.js.map +1 -0
- package/dist/svg-audit.d.ts +20 -0
- package/dist/svg-audit.d.ts.map +1 -0
- package/dist/svg-audit.js +213 -0
- package/dist/svg-audit.js.map +1 -0
- package/dist/table-audit.d.ts +18 -0
- package/dist/table-audit.d.ts.map +1 -0
- package/dist/table-audit.js +188 -0
- package/dist/table-audit.js.map +1 -0
- package/dist/teams-formatter.d.ts +66 -0
- package/dist/teams-formatter.d.ts.map +1 -0
- package/dist/teams-formatter.js +194 -0
- package/dist/teams-formatter.js.map +1 -0
- package/dist/third-party.d.ts +35 -0
- package/dist/third-party.d.ts.map +1 -0
- package/dist/third-party.js +175 -0
- package/dist/third-party.js.map +1 -0
- package/dist/tls.d.ts +33 -0
- package/dist/tls.d.ts.map +1 -0
- package/dist/tls.js +122 -0
- package/dist/tls.js.map +1 -0
- package/dist/touchtargets.d.ts +22 -0
- package/dist/touchtargets.d.ts.map +1 -0
- package/dist/touchtargets.js +80 -0
- package/dist/touchtargets.js.map +1 -0
- package/dist/tracker-sniff.d.ts +25 -0
- package/dist/tracker-sniff.d.ts.map +1 -0
- package/dist/tracker-sniff.js +355 -0
- package/dist/tracker-sniff.js.map +1 -0
- package/dist/types.d.ts +265 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/visual-mask.d.ts +33 -0
- package/dist/visual-mask.d.ts.map +1 -0
- package/dist/visual-mask.js +102 -0
- package/dist/visual-mask.js.map +1 -0
- package/dist/visual-ssim.d.ts +26 -0
- package/dist/visual-ssim.d.ts.map +1 -0
- package/dist/visual-ssim.js +153 -0
- package/dist/visual-ssim.js.map +1 -0
- package/dist/watch-mode.d.ts +10 -0
- package/dist/watch-mode.d.ts.map +1 -0
- package/dist/watch-mode.js +156 -0
- package/dist/watch-mode.js.map +1 -0
- package/dist/web-worker-audit.d.ts +27 -0
- package/dist/web-worker-audit.d.ts.map +1 -0
- package/dist/web-worker-audit.js +324 -0
- package/dist/web-worker-audit.js.map +1 -0
- package/dist/webfonts.d.ts +26 -0
- package/dist/webfonts.d.ts.map +1 -0
- package/dist/webfonts.js +244 -0
- package/dist/webfonts.js.map +1 -0
- package/dist/webhook-reporter.d.ts +20 -0
- package/dist/webhook-reporter.d.ts.map +1 -0
- package/dist/webhook-reporter.js +124 -0
- package/dist/webhook-reporter.js.map +1 -0
- package/dist/websocket.d.ts +39 -0
- package/dist/websocket.d.ts.map +1 -0
- package/dist/websocket.js +233 -0
- package/dist/websocket.js.map +1 -0
- package/dist/worker-runtime.d.ts +129 -0
- package/dist/worker-runtime.d.ts.map +1 -0
- package/dist/worker-runtime.js +414 -0
- package/dist/worker-runtime.js.map +1 -0
- package/dist/zindex-audit.d.ts +28 -0
- package/dist/zindex-audit.d.ts.map +1 -0
- package/dist/zindex-audit.js +291 -0
- package/dist/zindex-audit.js.map +1 -0
- package/package.json +10 -2
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { InspectResult } from './types.js';
|
|
2
|
+
export interface MetricPoint {
|
|
3
|
+
name: string;
|
|
4
|
+
help: string;
|
|
5
|
+
unit?: string;
|
|
6
|
+
value: number;
|
|
7
|
+
labels: Record<string, string>;
|
|
8
|
+
kind: 'counter' | 'gauge' | 'histogram';
|
|
9
|
+
}
|
|
10
|
+
export interface OtlpPushOptions {
|
|
11
|
+
endpoint: string;
|
|
12
|
+
headers?: Record<string, string>;
|
|
13
|
+
timeoutMs?: number;
|
|
14
|
+
}
|
|
15
|
+
export declare function extractMetrics(result: InspectResult, resourceAttrs?: Record<string, string>): MetricPoint[];
|
|
16
|
+
export declare function toPrometheusText(metrics: MetricPoint[]): string;
|
|
17
|
+
export declare function toOtlpJson(metrics: MetricPoint[], resourceAttrs?: Record<string, string>): unknown;
|
|
18
|
+
export declare function pushOtlp(metrics: MetricPoint[], opts: OtlpPushOptions, resourceAttrs?: Record<string, string>): Promise<{
|
|
19
|
+
ok: boolean;
|
|
20
|
+
status: number;
|
|
21
|
+
error?: string;
|
|
22
|
+
}>;
|
|
23
|
+
//# sourceMappingURL=metrics-exporter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metrics-exporter.d.ts","sourceRoot":"","sources":["../src/metrics-exporter.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,IAAI,EAAE,SAAS,GAAG,OAAO,GAAG,WAAW,CAAC;CACzC;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAqJD,wBAAgB,cAAc,CAC5B,MAAM,EAAE,aAAa,EACrB,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACrC,WAAW,EAAE,CAiFf;AAiDD,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,MAAM,CAW/D;AAOD,wBAAgB,UAAU,CACxB,OAAO,EAAE,WAAW,EAAE,EACtB,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACrC,OAAO,CAqCT;AAED,wBAAsB,QAAQ,CAC5B,OAAO,EAAE,WAAW,EAAE,EACtB,IAAI,EAAE,eAAe,EACrB,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACrC,OAAO,CAAC;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAgC1D"}
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { fileURLToPath } from 'node:url';
|
|
3
|
+
import { dirname, resolve } from 'node:path';
|
|
4
|
+
const SCOPE_NAME = 'uxinspect';
|
|
5
|
+
const VALID_METRIC_CHAR = /[a-zA-Z0-9_:]/;
|
|
6
|
+
const VALID_METRIC_START = /[a-zA-Z_:]/;
|
|
7
|
+
const VALID_LABEL_START = /[a-zA-Z_]/;
|
|
8
|
+
const VALID_LABEL_CHAR = /[a-zA-Z0-9_]/;
|
|
9
|
+
function sanitizeMetricName(name) {
|
|
10
|
+
if (!name)
|
|
11
|
+
return '_';
|
|
12
|
+
const chars = [...name];
|
|
13
|
+
const first = chars[0];
|
|
14
|
+
let out = first && VALID_METRIC_START.test(first) ? first : '_';
|
|
15
|
+
for (let i = 1; i < chars.length; i++) {
|
|
16
|
+
const c = chars[i];
|
|
17
|
+
out += c && VALID_METRIC_CHAR.test(c) ? c : '_';
|
|
18
|
+
}
|
|
19
|
+
return out;
|
|
20
|
+
}
|
|
21
|
+
function sanitizeLabelKey(key) {
|
|
22
|
+
if (!key)
|
|
23
|
+
return '_';
|
|
24
|
+
const chars = [...key];
|
|
25
|
+
const first = chars[0];
|
|
26
|
+
let out = first && VALID_LABEL_START.test(first) ? first : '_';
|
|
27
|
+
for (let i = 1; i < chars.length; i++) {
|
|
28
|
+
const c = chars[i];
|
|
29
|
+
out += c && VALID_LABEL_CHAR.test(c) ? c : '_';
|
|
30
|
+
}
|
|
31
|
+
return out;
|
|
32
|
+
}
|
|
33
|
+
function escapeLabelValue(value) {
|
|
34
|
+
return value.replace(/\\/g, '\\\\').replace(/"/g, '\\"').replace(/\n/g, '\\n');
|
|
35
|
+
}
|
|
36
|
+
function readPackageVersion() {
|
|
37
|
+
try {
|
|
38
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
39
|
+
const candidates = [
|
|
40
|
+
resolve(here, '..', 'package.json'),
|
|
41
|
+
resolve(here, '..', '..', 'package.json'),
|
|
42
|
+
];
|
|
43
|
+
for (const p of candidates) {
|
|
44
|
+
try {
|
|
45
|
+
const raw = readFileSync(p, 'utf8');
|
|
46
|
+
const parsed = JSON.parse(raw);
|
|
47
|
+
if (parsed &&
|
|
48
|
+
typeof parsed === 'object' &&
|
|
49
|
+
'name' in parsed &&
|
|
50
|
+
'version' in parsed &&
|
|
51
|
+
parsed.name === 'uxinspect' &&
|
|
52
|
+
typeof parsed.version === 'string') {
|
|
53
|
+
return parsed.version;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
// ignore
|
|
63
|
+
}
|
|
64
|
+
return 'unknown';
|
|
65
|
+
}
|
|
66
|
+
function defaultResourceAttrs(extra) {
|
|
67
|
+
const out = {
|
|
68
|
+
'service.name': 'uxinspect',
|
|
69
|
+
'service.version': readPackageVersion(),
|
|
70
|
+
};
|
|
71
|
+
const env = process.env.NODE_ENV;
|
|
72
|
+
if (env)
|
|
73
|
+
out['deployment.environment'] = env;
|
|
74
|
+
if (extra) {
|
|
75
|
+
for (const [k, v] of Object.entries(extra)) {
|
|
76
|
+
out[k] = v;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return out;
|
|
80
|
+
}
|
|
81
|
+
function push(out, name, help, kind, value, labels, unit) {
|
|
82
|
+
out.push({ name: sanitizeMetricName(name), help, kind, value, labels, unit });
|
|
83
|
+
}
|
|
84
|
+
function mergeLabels(base, extra) {
|
|
85
|
+
const merged = {};
|
|
86
|
+
for (const [k, v] of Object.entries(base))
|
|
87
|
+
merged[sanitizeLabelKey(k)] = v;
|
|
88
|
+
for (const [k, v] of Object.entries(extra))
|
|
89
|
+
merged[sanitizeLabelKey(k)] = v;
|
|
90
|
+
return merged;
|
|
91
|
+
}
|
|
92
|
+
export function extractMetrics(result, resourceAttrs) {
|
|
93
|
+
const out = [];
|
|
94
|
+
const base = { url: result.url };
|
|
95
|
+
if (resourceAttrs) {
|
|
96
|
+
for (const [k, v] of Object.entries(resourceAttrs))
|
|
97
|
+
base[sanitizeLabelKey(k)] = v;
|
|
98
|
+
}
|
|
99
|
+
push(out, 'uxinspect_passed', 'Overall run passed (1) or failed (0)', 'gauge', result.passed ? 1 : 0, base);
|
|
100
|
+
push(out, 'uxinspect_duration_ms', 'Total run duration in milliseconds', 'gauge', result.durationMs, base, 'ms');
|
|
101
|
+
const flows = result.flows ?? [];
|
|
102
|
+
push(out, 'uxinspect_flows_total', 'Total number of flows executed', 'counter', flows.length, base);
|
|
103
|
+
push(out, 'uxinspect_flows_passed', 'Total number of flows that passed', 'counter', flows.filter((f) => f.passed).length, base);
|
|
104
|
+
const a11y = result.a11y ?? [];
|
|
105
|
+
let critical = 0;
|
|
106
|
+
let serious = 0;
|
|
107
|
+
for (const page of a11y) {
|
|
108
|
+
for (const v of page.violations) {
|
|
109
|
+
if (v.impact === 'critical')
|
|
110
|
+
critical++;
|
|
111
|
+
else if (v.impact === 'serious')
|
|
112
|
+
serious++;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
push(out, 'uxinspect_a11y_critical_total', 'Count of critical accessibility violations', 'counter', critical, base);
|
|
116
|
+
push(out, 'uxinspect_a11y_serious_total', 'Count of serious accessibility violations', 'counter', serious, base);
|
|
117
|
+
const visual = result.visual ?? [];
|
|
118
|
+
const visualDiffs = visual.filter((v) => !v.passed).length;
|
|
119
|
+
push(out, 'uxinspect_visual_diffs_total', 'Count of failing visual regression diffs', 'counter', visualDiffs, base);
|
|
120
|
+
const perf = result.perf ?? [];
|
|
121
|
+
for (const p of perf) {
|
|
122
|
+
const pl = mergeLabels(base, { page: p.page });
|
|
123
|
+
push(out, 'uxinspect_perf_lcp_ms', 'Largest Contentful Paint in milliseconds', 'gauge', p.metrics.lcp, pl, 'ms');
|
|
124
|
+
push(out, 'uxinspect_perf_cls', 'Cumulative Layout Shift (unitless)', 'gauge', p.metrics.cls, pl);
|
|
125
|
+
push(out, 'uxinspect_perf_fcp_ms', 'First Contentful Paint in milliseconds', 'gauge', p.metrics.fcp, pl, 'ms');
|
|
126
|
+
push(out, 'uxinspect_perf_tbt_ms', 'Total Blocking Time in milliseconds', 'gauge', p.metrics.tbt, pl, 'ms');
|
|
127
|
+
push(out, 'uxinspect_perf_si_ms', 'Speed Index in milliseconds', 'gauge', p.metrics.si, pl, 'ms');
|
|
128
|
+
}
|
|
129
|
+
const links = result.links ?? [];
|
|
130
|
+
let brokenLinks = 0;
|
|
131
|
+
for (const l of links)
|
|
132
|
+
brokenLinks += l.broken.length;
|
|
133
|
+
push(out, 'uxinspect_links_broken_total', 'Count of broken links found', 'counter', brokenLinks, base);
|
|
134
|
+
const consoleErrors = result.consoleErrors ?? [];
|
|
135
|
+
let errCount = 0;
|
|
136
|
+
for (const c of consoleErrors)
|
|
137
|
+
errCount += c.errorCount;
|
|
138
|
+
push(out, 'uxinspect_console_errors_total', 'Count of console errors captured', 'counter', errCount, base);
|
|
139
|
+
const budget = result.budget ?? [];
|
|
140
|
+
push(out, 'uxinspect_budget_violations_total', 'Count of budget violations', 'counter', budget.length, base);
|
|
141
|
+
const security = result.security;
|
|
142
|
+
let missingHeaders = 0;
|
|
143
|
+
if (security)
|
|
144
|
+
missingHeaders = security.issues.filter((i) => i.startsWith('missing ')).length;
|
|
145
|
+
push(out, 'uxinspect_security_headers_missing_total', 'Count of missing security headers', 'counter', missingHeaders, base);
|
|
146
|
+
const bundles = result.bundleSize ?? [];
|
|
147
|
+
for (const b of bundles) {
|
|
148
|
+
const bl = mergeLabels(base, { page: b.page });
|
|
149
|
+
push(out, 'uxinspect_bundle_size_bytes_total', 'Total bundle size in bytes (JS + CSS)', 'gauge', b.totalJsBytes + b.totalCssBytes, bl, 'By');
|
|
150
|
+
}
|
|
151
|
+
const forms = result.forms ?? [];
|
|
152
|
+
let formIssues = 0;
|
|
153
|
+
for (const f of forms)
|
|
154
|
+
formIssues += f.totalIssues;
|
|
155
|
+
push(out, 'uxinspect_forms_issues_total', 'Count of forms audit issues', 'counter', formIssues, base);
|
|
156
|
+
const deadImages = result.deadImages ?? [];
|
|
157
|
+
let deadImgCount = 0;
|
|
158
|
+
for (const d of deadImages)
|
|
159
|
+
deadImgCount += d.brokenCount;
|
|
160
|
+
push(out, 'uxinspect_dead_images_total', 'Count of broken or placeholder-only images', 'counter', deadImgCount, base);
|
|
161
|
+
const domSize = result.domSize ?? [];
|
|
162
|
+
for (const d of domSize) {
|
|
163
|
+
const dl = mergeLabels(base, { page: d.page });
|
|
164
|
+
push(out, 'uxinspect_dom_nodes', 'Total DOM node count for a page', 'gauge', d.totalNodes, dl);
|
|
165
|
+
}
|
|
166
|
+
return out;
|
|
167
|
+
}
|
|
168
|
+
function groupMetrics(metrics) {
|
|
169
|
+
const map = new Map();
|
|
170
|
+
for (const m of metrics) {
|
|
171
|
+
const existing = map.get(m.name);
|
|
172
|
+
if (existing) {
|
|
173
|
+
existing.points.push(m);
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
map.set(m.name, { name: m.name, help: m.help, kind: m.kind, unit: m.unit, points: [m] });
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
return [...map.values()];
|
|
180
|
+
}
|
|
181
|
+
function formatLabels(labels) {
|
|
182
|
+
const keys = Object.keys(labels).sort();
|
|
183
|
+
if (keys.length === 0)
|
|
184
|
+
return '';
|
|
185
|
+
const pairs = keys.map((k) => `${sanitizeLabelKey(k)}="${escapeLabelValue(labels[k] ?? '')}"`);
|
|
186
|
+
return `{${pairs.join(',')}}`;
|
|
187
|
+
}
|
|
188
|
+
function formatValue(v) {
|
|
189
|
+
if (!Number.isFinite(v)) {
|
|
190
|
+
if (Number.isNaN(v))
|
|
191
|
+
return 'NaN';
|
|
192
|
+
return v > 0 ? '+Inf' : '-Inf';
|
|
193
|
+
}
|
|
194
|
+
if (Number.isInteger(v))
|
|
195
|
+
return v.toString();
|
|
196
|
+
return v.toString();
|
|
197
|
+
}
|
|
198
|
+
function escapeHelp(help) {
|
|
199
|
+
return help.replace(/\\/g, '\\\\').replace(/\n/g, '\\n');
|
|
200
|
+
}
|
|
201
|
+
function promKind(kind) {
|
|
202
|
+
if (kind === 'counter')
|
|
203
|
+
return 'counter';
|
|
204
|
+
if (kind === 'histogram')
|
|
205
|
+
return 'histogram';
|
|
206
|
+
return 'gauge';
|
|
207
|
+
}
|
|
208
|
+
export function toPrometheusText(metrics) {
|
|
209
|
+
const groups = groupMetrics(metrics);
|
|
210
|
+
const lines = [];
|
|
211
|
+
for (const g of groups) {
|
|
212
|
+
lines.push(`# HELP ${g.name} ${escapeHelp(g.help)}`);
|
|
213
|
+
lines.push(`# TYPE ${g.name} ${promKind(g.kind)}`);
|
|
214
|
+
for (const p of g.points) {
|
|
215
|
+
lines.push(`${g.name}${formatLabels(p.labels)} ${formatValue(p.value)}`);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
return lines.join('\n') + '\n';
|
|
219
|
+
}
|
|
220
|
+
function toAttrs(labels) {
|
|
221
|
+
const keys = Object.keys(labels).sort();
|
|
222
|
+
return keys.map((k) => ({ key: sanitizeLabelKey(k), value: { stringValue: labels[k] ?? '' } }));
|
|
223
|
+
}
|
|
224
|
+
export function toOtlpJson(metrics, resourceAttrs) {
|
|
225
|
+
const attrs = defaultResourceAttrs(resourceAttrs);
|
|
226
|
+
const timeUnixNano = (Date.now() * 1_000_000).toString();
|
|
227
|
+
const groups = groupMetrics(metrics);
|
|
228
|
+
const otlpMetrics = groups.map((g) => {
|
|
229
|
+
const dataPoints = g.points.map((p) => ({
|
|
230
|
+
attributes: toAttrs(p.labels),
|
|
231
|
+
timeUnixNano,
|
|
232
|
+
asDouble: Number.isFinite(p.value) ? p.value : 0,
|
|
233
|
+
}));
|
|
234
|
+
const description = g.help;
|
|
235
|
+
const unit = g.unit ?? '';
|
|
236
|
+
if (g.kind === 'counter') {
|
|
237
|
+
return {
|
|
238
|
+
name: g.name,
|
|
239
|
+
description,
|
|
240
|
+
unit,
|
|
241
|
+
sum: { dataPoints, aggregationTemporality: 2, isMonotonic: true },
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
return { name: g.name, description, unit, gauge: { dataPoints } };
|
|
245
|
+
});
|
|
246
|
+
const payload = {
|
|
247
|
+
resourceMetrics: [
|
|
248
|
+
{
|
|
249
|
+
resource: { attributes: toAttrs(attrs) },
|
|
250
|
+
scopeMetrics: [
|
|
251
|
+
{
|
|
252
|
+
scope: { name: SCOPE_NAME, version: readPackageVersion() },
|
|
253
|
+
metrics: otlpMetrics,
|
|
254
|
+
},
|
|
255
|
+
],
|
|
256
|
+
},
|
|
257
|
+
],
|
|
258
|
+
};
|
|
259
|
+
return payload;
|
|
260
|
+
}
|
|
261
|
+
export async function pushOtlp(metrics, opts, resourceAttrs) {
|
|
262
|
+
const timeout = opts.timeoutMs ?? 10_000;
|
|
263
|
+
const body = JSON.stringify(toOtlpJson(metrics, resourceAttrs));
|
|
264
|
+
const controller = new AbortController();
|
|
265
|
+
const timer = setTimeout(() => controller.abort(), timeout);
|
|
266
|
+
try {
|
|
267
|
+
const headers = {
|
|
268
|
+
'content-type': 'application/json',
|
|
269
|
+
...(opts.headers ?? {}),
|
|
270
|
+
};
|
|
271
|
+
const res = await fetch(opts.endpoint, {
|
|
272
|
+
method: 'POST',
|
|
273
|
+
headers,
|
|
274
|
+
body,
|
|
275
|
+
signal: controller.signal,
|
|
276
|
+
});
|
|
277
|
+
if (!res.ok) {
|
|
278
|
+
let text = '';
|
|
279
|
+
try {
|
|
280
|
+
text = await res.text();
|
|
281
|
+
}
|
|
282
|
+
catch {
|
|
283
|
+
text = '';
|
|
284
|
+
}
|
|
285
|
+
return { ok: false, status: res.status, error: text.slice(0, 500) };
|
|
286
|
+
}
|
|
287
|
+
return { ok: true, status: res.status };
|
|
288
|
+
}
|
|
289
|
+
catch (err) {
|
|
290
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
291
|
+
return { ok: false, status: 0, error: msg };
|
|
292
|
+
}
|
|
293
|
+
finally {
|
|
294
|
+
clearTimeout(timer);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
//# sourceMappingURL=metrics-exporter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metrics-exporter.js","sourceRoot":"","sources":["../src/metrics-exporter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Page } from 'playwright';
|
|
2
|
+
export type InsecureResourceType = 'script' | 'style' | 'image' | 'iframe' | 'font' | 'xhr' | 'other';
|
|
3
|
+
export interface InsecureResource {
|
|
4
|
+
type: InsecureResourceType;
|
|
5
|
+
url: string;
|
|
6
|
+
initiator?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface MixedContentResult {
|
|
9
|
+
page: string;
|
|
10
|
+
httpsPage: boolean;
|
|
11
|
+
insecureResources: InsecureResource[];
|
|
12
|
+
cspPresent: boolean;
|
|
13
|
+
cspUpgradeInsecure: boolean;
|
|
14
|
+
cspBlockAllMixed: boolean;
|
|
15
|
+
referrerPolicy?: string;
|
|
16
|
+
passed: boolean;
|
|
17
|
+
}
|
|
18
|
+
export declare function checkMixedContent(page: Page): Promise<MixedContentResult>;
|
|
19
|
+
//# sourceMappingURL=mixed-content.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mixed-content.d.ts","sourceRoot":"","sources":["../src/mixed-content.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEvC,MAAM,MAAM,oBAAoB,GAAG,QAAQ,GAAG,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,CAAC;AAEtG,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,oBAAoB,CAAC;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,OAAO,CAAC;IACnB,iBAAiB,EAAE,gBAAgB,EAAE,CAAC;IACtC,UAAU,EAAE,OAAO,CAAC;IACpB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,gBAAgB,EAAE,OAAO,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,MAAM,EAAE,OAAO,CAAC;CACjB;AA0CD,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,kBAAkB,CAAC,CA0D/E"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
function classifyInitiator(initiatorType) {
|
|
2
|
+
switch (initiatorType) {
|
|
3
|
+
case 'script':
|
|
4
|
+
return 'script';
|
|
5
|
+
case 'css':
|
|
6
|
+
case 'link':
|
|
7
|
+
return 'style';
|
|
8
|
+
case 'img':
|
|
9
|
+
case 'image':
|
|
10
|
+
return 'image';
|
|
11
|
+
case 'iframe':
|
|
12
|
+
case 'subdocument':
|
|
13
|
+
return 'iframe';
|
|
14
|
+
case 'font':
|
|
15
|
+
return 'font';
|
|
16
|
+
case 'xmlhttprequest':
|
|
17
|
+
case 'fetch':
|
|
18
|
+
return 'xhr';
|
|
19
|
+
default:
|
|
20
|
+
return 'other';
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
function parseCspDirectives(csp) {
|
|
24
|
+
const directives = new Set();
|
|
25
|
+
for (const raw of csp.split(';')) {
|
|
26
|
+
const name = raw.trim().split(/\s+/)[0]?.toLowerCase();
|
|
27
|
+
if (name)
|
|
28
|
+
directives.add(name);
|
|
29
|
+
}
|
|
30
|
+
return directives;
|
|
31
|
+
}
|
|
32
|
+
export async function checkMixedContent(page) {
|
|
33
|
+
const pageUrl = page.url();
|
|
34
|
+
let pageProtocol = 'about:';
|
|
35
|
+
try {
|
|
36
|
+
pageProtocol = new URL(pageUrl).protocol;
|
|
37
|
+
}
|
|
38
|
+
catch { }
|
|
39
|
+
const httpsPage = pageProtocol === 'https:';
|
|
40
|
+
const snapshot = await page.evaluate(() => {
|
|
41
|
+
const entries = performance.getEntriesByType('resource').map((e) => ({
|
|
42
|
+
name: e.name,
|
|
43
|
+
initiatorType: e.initiatorType,
|
|
44
|
+
}));
|
|
45
|
+
const cspEl = document.querySelector('meta[http-equiv="Content-Security-Policy" i]');
|
|
46
|
+
const refEl = document.querySelector('meta[name="referrer" i]');
|
|
47
|
+
return {
|
|
48
|
+
pageProtocol: location.protocol,
|
|
49
|
+
entries,
|
|
50
|
+
cspMeta: cspEl?.content ?? null,
|
|
51
|
+
referrerMeta: refEl?.content ?? null,
|
|
52
|
+
referrerPolicy: document.referrerPolicy ?? '',
|
|
53
|
+
};
|
|
54
|
+
});
|
|
55
|
+
const insecureResources = [];
|
|
56
|
+
for (const entry of snapshot.entries) {
|
|
57
|
+
if (entry.name.toLowerCase().startsWith('http://')) {
|
|
58
|
+
insecureResources.push({
|
|
59
|
+
type: classifyInitiator(entry.initiatorType),
|
|
60
|
+
url: entry.name,
|
|
61
|
+
initiator: entry.initiatorType || undefined,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
const cspPresent = typeof snapshot.cspMeta === 'string' && snapshot.cspMeta.length > 0;
|
|
66
|
+
let cspUpgradeInsecure = false;
|
|
67
|
+
let cspBlockAllMixed = false;
|
|
68
|
+
if (cspPresent && snapshot.cspMeta) {
|
|
69
|
+
const directives = parseCspDirectives(snapshot.cspMeta);
|
|
70
|
+
cspUpgradeInsecure = directives.has('upgrade-insecure-requests');
|
|
71
|
+
cspBlockAllMixed = directives.has('block-all-mixed-content');
|
|
72
|
+
}
|
|
73
|
+
const referrerPolicy = snapshot.referrerMeta?.trim() || snapshot.referrerPolicy?.trim() || undefined;
|
|
74
|
+
const passed = !httpsPage || insecureResources.length === 0;
|
|
75
|
+
return {
|
|
76
|
+
page: pageUrl,
|
|
77
|
+
httpsPage,
|
|
78
|
+
insecureResources,
|
|
79
|
+
cspPresent,
|
|
80
|
+
cspUpgradeInsecure,
|
|
81
|
+
cspBlockAllMixed,
|
|
82
|
+
referrerPolicy,
|
|
83
|
+
passed,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=mixed-content.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mixed-content.js","sourceRoot":"","sources":["../src/mixed-content.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Page } from 'playwright';
|
|
2
|
+
export type MotionPrefsIssueType = 'no-reduced-motion' | 'no-dark-mode' | 'no-print-css' | 'autoplay-video' | 'infinite-animation-unstoppable' | 'flashing-content';
|
|
3
|
+
export interface MotionPrefsIssue {
|
|
4
|
+
type: MotionPrefsIssueType;
|
|
5
|
+
target?: string;
|
|
6
|
+
detail?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface MotionPrefsResult {
|
|
9
|
+
page: string;
|
|
10
|
+
respectsReducedMotion: boolean;
|
|
11
|
+
respectsDarkMode: boolean;
|
|
12
|
+
respectsPrint: boolean;
|
|
13
|
+
respectsForcedColors: boolean;
|
|
14
|
+
animationsCount: number;
|
|
15
|
+
autoplayVideos: number;
|
|
16
|
+
infiniteAnimations: number;
|
|
17
|
+
issues: MotionPrefsIssue[];
|
|
18
|
+
passed: boolean;
|
|
19
|
+
}
|
|
20
|
+
export declare function auditMotionPrefs(page: Page): Promise<MotionPrefsResult>;
|
|
21
|
+
//# sourceMappingURL=motion-prefs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"motion-prefs.d.ts","sourceRoot":"","sources":["../src/motion-prefs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEvC,MAAM,MAAM,oBAAoB,GAC5B,mBAAmB,GACnB,cAAc,GACd,cAAc,GACd,gBAAgB,GAChB,gCAAgC,GAChC,kBAAkB,CAAC;AAEvB,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,oBAAoB,CAAC;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,qBAAqB,EAAE,OAAO,CAAC;IAC/B,gBAAgB,EAAE,OAAO,CAAC;IAC1B,aAAa,EAAE,OAAO,CAAC;IACvB,oBAAoB,EAAE,OAAO,CAAC;IAC9B,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,MAAM,EAAE,gBAAgB,EAAE,CAAC;IAC3B,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAgM7E"}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
export async function auditMotionPrefs(page) {
|
|
2
|
+
const url = page.url();
|
|
3
|
+
const scan = await page.evaluate(() => {
|
|
4
|
+
function buildSelector(el) {
|
|
5
|
+
const id = el.id;
|
|
6
|
+
if (id)
|
|
7
|
+
return `#${CSS.escape(id)}`;
|
|
8
|
+
const testid = el.getAttribute('data-testid');
|
|
9
|
+
if (testid)
|
|
10
|
+
return `[data-testid="${testid}"]`;
|
|
11
|
+
const tag = el.tagName.toLowerCase();
|
|
12
|
+
const classes = Array.from(el.classList).slice(0, 3);
|
|
13
|
+
return classes.length ? `${tag}.${classes.map(c => CSS.escape(c)).join('.')}` : tag;
|
|
14
|
+
}
|
|
15
|
+
let respectsReducedMotion = false;
|
|
16
|
+
let respectsDarkMode = false;
|
|
17
|
+
let respectsPrint = false;
|
|
18
|
+
let respectsForcedColors = false;
|
|
19
|
+
let infiniteAnimations = 0;
|
|
20
|
+
const flashingSelectors = [];
|
|
21
|
+
function walkRules(rules, inReducedMotion) {
|
|
22
|
+
if (!rules)
|
|
23
|
+
return;
|
|
24
|
+
for (let i = 0; i < rules.length; i++) {
|
|
25
|
+
const rule = rules[i];
|
|
26
|
+
if (rule instanceof CSSMediaRule) {
|
|
27
|
+
const mediaText = rule.conditionText || rule.media.mediaText || '';
|
|
28
|
+
const lower = mediaText.toLowerCase();
|
|
29
|
+
let reducedMotionBranch = inReducedMotion;
|
|
30
|
+
if (lower.includes('(prefers-reduced-motion')) {
|
|
31
|
+
respectsReducedMotion = true;
|
|
32
|
+
reducedMotionBranch = true;
|
|
33
|
+
}
|
|
34
|
+
if (lower.includes('(prefers-color-scheme: dark')) {
|
|
35
|
+
respectsDarkMode = true;
|
|
36
|
+
}
|
|
37
|
+
if (lower.includes('(forced-colors')) {
|
|
38
|
+
respectsForcedColors = true;
|
|
39
|
+
}
|
|
40
|
+
if (/(^|[^a-z])print([^a-z]|$)/.test(lower)) {
|
|
41
|
+
respectsPrint = true;
|
|
42
|
+
}
|
|
43
|
+
walkRules(rule.cssRules, reducedMotionBranch);
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
if (rule instanceof CSSStyleRule) {
|
|
47
|
+
const style = rule.style;
|
|
48
|
+
const iter = style.getPropertyValue('animation-iteration-count').trim();
|
|
49
|
+
const shorthand = style.getPropertyValue('animation').trim();
|
|
50
|
+
const isInfinite = iter === 'infinite' || /\binfinite\b/.test(shorthand);
|
|
51
|
+
if (isInfinite) {
|
|
52
|
+
infiniteAnimations++;
|
|
53
|
+
const durRaw = style.getPropertyValue('animation-duration').trim() ||
|
|
54
|
+
(shorthand.match(/([\d.]+)(ms|s)\b/)?.[0] ?? '');
|
|
55
|
+
const durMs = parseDurationMs(durRaw);
|
|
56
|
+
if (durMs !== null && durMs > 0 && durMs < 500 && !inReducedMotion) {
|
|
57
|
+
flashingSelectors.push({
|
|
58
|
+
target: rule.selectorText,
|
|
59
|
+
detail: `animation-duration ${durRaw} with infinite iteration`,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
if (rule instanceof CSSSupportsRule ||
|
|
66
|
+
(typeof CSSContainerRule !== 'undefined' && rule instanceof CSSContainerRule) ||
|
|
67
|
+
(typeof CSSLayerBlockRule !== 'undefined' && rule instanceof CSSLayerBlockRule)) {
|
|
68
|
+
walkRules(rule.cssRules, inReducedMotion);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
function parseDurationMs(raw) {
|
|
73
|
+
if (!raw)
|
|
74
|
+
return null;
|
|
75
|
+
const m = raw.match(/([\d.]+)(ms|s)/);
|
|
76
|
+
if (!m)
|
|
77
|
+
return null;
|
|
78
|
+
const n = parseFloat(m[1]);
|
|
79
|
+
if (!isFinite(n))
|
|
80
|
+
return null;
|
|
81
|
+
return m[2] === 's' ? n * 1000 : n;
|
|
82
|
+
}
|
|
83
|
+
for (const sheet of Array.from(document.styleSheets)) {
|
|
84
|
+
try {
|
|
85
|
+
walkRules(sheet.cssRules, false);
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
// cross-origin stylesheet — skip
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
const animations = typeof document.getAnimations === 'function' ? document.getAnimations().length : 0;
|
|
92
|
+
const videos = Array.from(document.querySelectorAll('video'));
|
|
93
|
+
const autoplayBad = [];
|
|
94
|
+
let autoplayCount = 0;
|
|
95
|
+
for (const v of videos) {
|
|
96
|
+
const hasAutoplay = v.hasAttribute('autoplay') || v.autoplay;
|
|
97
|
+
if (!hasAutoplay)
|
|
98
|
+
continue;
|
|
99
|
+
autoplayCount++;
|
|
100
|
+
const muted = v.muted || v.hasAttribute('muted');
|
|
101
|
+
const hasAudio = (typeof v.mozHasAudio === 'boolean'
|
|
102
|
+
? v.mozHasAudio
|
|
103
|
+
: undefined) ??
|
|
104
|
+
(v
|
|
105
|
+
.webkitAudioDecodedByteCount ?? 0) > 0;
|
|
106
|
+
const assumedAudio = hasAudio || !muted;
|
|
107
|
+
if (!muted && assumedAudio) {
|
|
108
|
+
autoplayBad.push({
|
|
109
|
+
target: buildSelector(v),
|
|
110
|
+
detail: 'video[autoplay] is not muted (may play audio without consent)',
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
const issues = [];
|
|
115
|
+
if (!respectsReducedMotion) {
|
|
116
|
+
issues.push({
|
|
117
|
+
type: 'no-reduced-motion',
|
|
118
|
+
detail: 'No @media (prefers-reduced-motion) rules found',
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
if (!respectsDarkMode) {
|
|
122
|
+
issues.push({
|
|
123
|
+
type: 'no-dark-mode',
|
|
124
|
+
detail: 'No @media (prefers-color-scheme: dark) rules found',
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
if (!respectsPrint) {
|
|
128
|
+
issues.push({
|
|
129
|
+
type: 'no-print-css',
|
|
130
|
+
detail: 'No @media print rules found',
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
for (const a of autoplayBad) {
|
|
134
|
+
issues.push({ type: 'autoplay-video', target: a.target, detail: a.detail });
|
|
135
|
+
}
|
|
136
|
+
if (infiniteAnimations > 0 && !respectsReducedMotion) {
|
|
137
|
+
issues.push({
|
|
138
|
+
type: 'infinite-animation-unstoppable',
|
|
139
|
+
detail: `${infiniteAnimations} infinite animation(s) with no prefers-reduced-motion handling`,
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
for (const f of flashingSelectors) {
|
|
143
|
+
issues.push({ type: 'flashing-content', target: f.target, detail: f.detail });
|
|
144
|
+
}
|
|
145
|
+
return {
|
|
146
|
+
respectsReducedMotion,
|
|
147
|
+
respectsDarkMode,
|
|
148
|
+
respectsPrint,
|
|
149
|
+
respectsForcedColors,
|
|
150
|
+
animationsCount: animations,
|
|
151
|
+
autoplayVideos: autoplayCount,
|
|
152
|
+
infiniteAnimations,
|
|
153
|
+
issues,
|
|
154
|
+
};
|
|
155
|
+
});
|
|
156
|
+
const blocking = scan.issues.some(i => i.type === 'autoplay-video' || i.type === 'flashing-content');
|
|
157
|
+
return {
|
|
158
|
+
page: url,
|
|
159
|
+
respectsReducedMotion: scan.respectsReducedMotion,
|
|
160
|
+
respectsDarkMode: scan.respectsDarkMode,
|
|
161
|
+
respectsPrint: scan.respectsPrint,
|
|
162
|
+
respectsForcedColors: scan.respectsForcedColors,
|
|
163
|
+
animationsCount: scan.animationsCount,
|
|
164
|
+
autoplayVideos: scan.autoplayVideos,
|
|
165
|
+
infiniteAnimations: scan.infiniteAnimations,
|
|
166
|
+
issues: scan.issues,
|
|
167
|
+
passed: !blocking,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
//# sourceMappingURL=motion-prefs.js.map
|