raven-mcp 1.8.0 → 1.9.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 +1 -0
- package/dist/asset-integrity.d.ts +30 -0
- package/dist/asset-integrity.js +66 -0
- package/dist/asset-integrity.js.map +1 -1
- package/dist/audit-url.d.ts +74 -0
- package/dist/audit-url.js +327 -0
- package/dist/audit-url.js.map +1 -0
- package/dist/capture.d.ts +7 -0
- package/dist/capture.js +136 -0
- package/dist/capture.js.map +1 -1
- package/dist/contrast.d.ts +1 -0
- package/dist/contrast.js +21 -0
- package/dist/contrast.js.map +1 -1
- package/dist/index.js +46 -193
- package/dist/index.js.map +1 -1
- package/dist/page-checks.d.ts +26 -0
- package/dist/page-checks.js +212 -0
- package/dist/page-checks.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -67,6 +67,7 @@ cd raven-mcp && npm install && npm run build
|
|
|
67
67
|
| `audit_layout` | Evaluate visual rhythm, alignment, and optical balance |
|
|
68
68
|
| `audit_responsive_visibility` | Render a URL at multiple breakpoints and flag content elements that are visible on desktop but hidden on mobile (display:none/opacity:0/zero-size) — categorises each as likely-oversight (content vanishing on mobile) vs intentional (decorative) |
|
|
69
69
|
| `audit_contrast` | Compute WCAG contrast ratios for every text element on a rendered page and report AA (4.5:1 / 3:1 large) and AAA pass-fail per element, with delta-to-pass for failures |
|
|
70
|
+
| `audit_url` | Render a live URL at each viewport×theme, scroll-settle, fire interactions, capture real pixels + DOM, then run the page/contrast/responsive/blank-media checks **plus** sliced-image edge-symmetry and hover-state white-wash detection over the captures — every finding tagged confirmed/likely-artifact/inconclusive, ranked by severity |
|
|
70
71
|
| `audit_swiftui` | Audit SwiftUI source against Apple HIG — Dynamic Type, semantic colors, 44pt targets, 4/8pt spacing, AccentColor |
|
|
71
72
|
| `audit_ios_screen` | Score a rendered iOS screen from an accessibility/view-hierarchy snapshot — 44pt targets + contrast + rhythm, in points |
|
|
72
73
|
| `audit_ios_privacy` | Audit Info.plist (or Expo app.json) /PRIVACY.md/entitlements/source — usage-string honesty, ATS, Android permissions, bundled secrets, undisclosed default data-egress |
|
|
@@ -11,3 +11,33 @@ export type AssetIntegrityOptions = {
|
|
|
11
11
|
varianceThreshold?: number;
|
|
12
12
|
};
|
|
13
13
|
export declare function auditAssetIntegrity(imagePaths: string[], opts?: AssetIntegrityOptions): Promise<AssetIntegrityResult[]>;
|
|
14
|
+
export type ImageEdgeSample = {
|
|
15
|
+
selector: string;
|
|
16
|
+
width: number;
|
|
17
|
+
height: number;
|
|
18
|
+
edges: {
|
|
19
|
+
top: number;
|
|
20
|
+
bottom: number;
|
|
21
|
+
left: number;
|
|
22
|
+
right: number;
|
|
23
|
+
};
|
|
24
|
+
tainted: boolean;
|
|
25
|
+
};
|
|
26
|
+
export type ImageEdgeVerdict = {
|
|
27
|
+
selector: string;
|
|
28
|
+
verdict: "clean" | "likely-sliced" | "inconclusive";
|
|
29
|
+
cut_edge: "top" | "bottom" | "left" | "right" | null;
|
|
30
|
+
confidence: number;
|
|
31
|
+
edges: {
|
|
32
|
+
top: number;
|
|
33
|
+
bottom: number;
|
|
34
|
+
left: number;
|
|
35
|
+
right: number;
|
|
36
|
+
};
|
|
37
|
+
reason: string;
|
|
38
|
+
};
|
|
39
|
+
export type ImageEdgeOptions = {
|
|
40
|
+
highVarianceThreshold?: number;
|
|
41
|
+
uniformRatio?: number;
|
|
42
|
+
};
|
|
43
|
+
export declare function auditImageEdges(samples: ImageEdgeSample[], opts?: ImageEdgeOptions): ImageEdgeVerdict[];
|
package/dist/asset-integrity.js
CHANGED
|
@@ -101,4 +101,70 @@ function errorMessage(error) {
|
|
|
101
101
|
}
|
|
102
102
|
return String(error);
|
|
103
103
|
}
|
|
104
|
+
export function auditImageEdges(samples, opts = {}) {
|
|
105
|
+
const highVar = opts.highVarianceThreshold ?? 200;
|
|
106
|
+
const uniformRatio = opts.uniformRatio ?? 0.25;
|
|
107
|
+
return (samples || []).map(function (sample) {
|
|
108
|
+
const e = sample.edges;
|
|
109
|
+
if (sample.tainted) {
|
|
110
|
+
return {
|
|
111
|
+
selector: sample.selector,
|
|
112
|
+
verdict: "inconclusive",
|
|
113
|
+
cut_edge: null,
|
|
114
|
+
confidence: 0,
|
|
115
|
+
edges: e,
|
|
116
|
+
reason: "image pixels unreadable (cross-origin canvas taint) — could not sample edges"
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
// Opposite-edge pairs: an edge "looks cut" when it carries high-variance
|
|
120
|
+
// content while the edge facing it is near-uniform.
|
|
121
|
+
const pairs = [
|
|
122
|
+
{ edge: "bottom", v: e.bottom, opposite: e.top },
|
|
123
|
+
{ edge: "top", v: e.top, opposite: e.bottom },
|
|
124
|
+
{ edge: "right", v: e.right, opposite: e.left },
|
|
125
|
+
{ edge: "left", v: e.left, opposite: e.right }
|
|
126
|
+
];
|
|
127
|
+
let worst = null;
|
|
128
|
+
for (const p of pairs) {
|
|
129
|
+
const asymmetric = p.v > highVar && p.opposite < highVar * uniformRatio;
|
|
130
|
+
if (asymmetric && (worst === null || p.v > worst.v)) {
|
|
131
|
+
worst = p;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
if (worst === null) {
|
|
135
|
+
return {
|
|
136
|
+
selector: sample.selector,
|
|
137
|
+
verdict: "clean",
|
|
138
|
+
cut_edge: null,
|
|
139
|
+
confidence: clamp(1 - maxEdge(e) / highVar, 0, 1),
|
|
140
|
+
edges: e,
|
|
141
|
+
reason: "all edges uniform — no content running into a frame edge"
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
// Confidence grows with how far the cut edge exceeds the threshold and how
|
|
145
|
+
// uniform the opposite edge is.
|
|
146
|
+
const overshoot = clamp(worst.v / (highVar * 4), 0, 1);
|
|
147
|
+
const oppositeUniformity = clamp(1 - worst.opposite / (highVar * uniformRatio), 0, 1);
|
|
148
|
+
const confidence = Math.max(0.5, (overshoot + oppositeUniformity) / 2);
|
|
149
|
+
return {
|
|
150
|
+
selector: sample.selector,
|
|
151
|
+
verdict: "likely-sliced",
|
|
152
|
+
cut_edge: worst.edge,
|
|
153
|
+
confidence: Math.round(confidence * 100) / 100,
|
|
154
|
+
edges: e,
|
|
155
|
+
reason: "high-variance content at the " +
|
|
156
|
+
worst.edge +
|
|
157
|
+
" edge (variance " +
|
|
158
|
+
Math.round(worst.v) +
|
|
159
|
+
") with a uniform opposite edge (variance " +
|
|
160
|
+
Math.round(worst.opposite) +
|
|
161
|
+
") — content appears cut off at the " +
|
|
162
|
+
worst.edge +
|
|
163
|
+
" frame edge"
|
|
164
|
+
};
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
function maxEdge(e) {
|
|
168
|
+
return Math.max(e.top, e.bottom, e.left, e.right);
|
|
169
|
+
}
|
|
104
170
|
//# sourceMappingURL=asset-integrity.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"asset-integrity.js","sourceRoot":"","sources":["../src/asset-integrity.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"asset-integrity.js","sourceRoot":"","sources":["../src/asset-integrity.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* audit-url.ts — Layer 0 render-and-capture transport.
|
|
3
|
+
*
|
|
4
|
+
* Renders a live URL at each viewport×theme, scroll-settles, fires interactions,
|
|
5
|
+
* captures real pixels + DOM, then runs the EXISTING checks (audit_page rule
|
|
6
|
+
* engine, contrast, responsive-visibility, video-blank, screenshot diff) plus
|
|
7
|
+
* pixel checks (image edge symmetry) over the captured output. Every finding is
|
|
8
|
+
* tagged confirmed | likely-artifact | inconclusive with its evidence, and
|
|
9
|
+
* ranked by severity.
|
|
10
|
+
*
|
|
11
|
+
* This tool does NOT reimplement the checks — it reuses:
|
|
12
|
+
* · runPageChecks (the audit_page rule engine, shared verbatim)
|
|
13
|
+
* · verifyFindings (the adversarial confirmed/likely-artifact tagger)
|
|
14
|
+
* · captureResponsiveVisibility (desktop-visible / mobile-hidden divergence)
|
|
15
|
+
* · auditContrastUrl (per-element WCAG AA/AAA)
|
|
16
|
+
* · capturePage video-blank detection
|
|
17
|
+
* · auditImageEdges (sliced/cropped image edge symmetry)
|
|
18
|
+
* · diffScreenshots (baseline vs post-interaction state diff)
|
|
19
|
+
*/
|
|
20
|
+
import type { Interaction, Theme } from "./capture.js";
|
|
21
|
+
export type ViewportSpec = {
|
|
22
|
+
w: number;
|
|
23
|
+
h: number;
|
|
24
|
+
label?: string;
|
|
25
|
+
};
|
|
26
|
+
export type Verdict = "confirmed" | "likely-artifact" | "inconclusive";
|
|
27
|
+
export type FindingSource = "page" | "contrast" | "responsive-visibility" | "video" | "asset-integrity" | "hover-state";
|
|
28
|
+
export type AuditUrlFinding = {
|
|
29
|
+
source: FindingSource;
|
|
30
|
+
rule: string;
|
|
31
|
+
severity: "error" | "warning" | "info";
|
|
32
|
+
message: string;
|
|
33
|
+
fix: string;
|
|
34
|
+
selector?: string;
|
|
35
|
+
viewport: string;
|
|
36
|
+
theme: Theme;
|
|
37
|
+
verdict: Verdict;
|
|
38
|
+
evidence: string;
|
|
39
|
+
};
|
|
40
|
+
export type AuditUrlCapture = {
|
|
41
|
+
viewport: string;
|
|
42
|
+
theme: Theme;
|
|
43
|
+
scrolledToBottom: boolean;
|
|
44
|
+
screenshot_bytes: number;
|
|
45
|
+
screenshot?: string;
|
|
46
|
+
};
|
|
47
|
+
export type AuditUrlResult = {
|
|
48
|
+
tool: "audit_url";
|
|
49
|
+
url: string;
|
|
50
|
+
viewports: ViewportSpec[];
|
|
51
|
+
themes: Theme[];
|
|
52
|
+
findings: AuditUrlFinding[];
|
|
53
|
+
counts: {
|
|
54
|
+
total: number;
|
|
55
|
+
confirmed: number;
|
|
56
|
+
likely_artifact: number;
|
|
57
|
+
inconclusive: number;
|
|
58
|
+
errors: number;
|
|
59
|
+
warnings: number;
|
|
60
|
+
};
|
|
61
|
+
summary: string;
|
|
62
|
+
captures: AuditUrlCapture[];
|
|
63
|
+
warnings: string[];
|
|
64
|
+
};
|
|
65
|
+
export type AuditUrlOptions = {
|
|
66
|
+
viewports?: ViewportSpec[];
|
|
67
|
+
themes?: Theme[];
|
|
68
|
+
scroll_settle?: boolean;
|
|
69
|
+
interactions?: Interaction[];
|
|
70
|
+
containerMaxWidth?: number;
|
|
71
|
+
timeoutMs?: number;
|
|
72
|
+
includeScreenshots?: boolean;
|
|
73
|
+
};
|
|
74
|
+
export declare function auditUrl(url: string, opts?: AuditUrlOptions): Promise<AuditUrlResult>;
|
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* audit-url.ts — Layer 0 render-and-capture transport.
|
|
3
|
+
*
|
|
4
|
+
* Renders a live URL at each viewport×theme, scroll-settles, fires interactions,
|
|
5
|
+
* captures real pixels + DOM, then runs the EXISTING checks (audit_page rule
|
|
6
|
+
* engine, contrast, responsive-visibility, video-blank, screenshot diff) plus
|
|
7
|
+
* pixel checks (image edge symmetry) over the captured output. Every finding is
|
|
8
|
+
* tagged confirmed | likely-artifact | inconclusive with its evidence, and
|
|
9
|
+
* ranked by severity.
|
|
10
|
+
*
|
|
11
|
+
* This tool does NOT reimplement the checks — it reuses:
|
|
12
|
+
* · runPageChecks (the audit_page rule engine, shared verbatim)
|
|
13
|
+
* · verifyFindings (the adversarial confirmed/likely-artifact tagger)
|
|
14
|
+
* · captureResponsiveVisibility (desktop-visible / mobile-hidden divergence)
|
|
15
|
+
* · auditContrastUrl (per-element WCAG AA/AAA)
|
|
16
|
+
* · capturePage video-blank detection
|
|
17
|
+
* · auditImageEdges (sliced/cropped image edge symmetry)
|
|
18
|
+
* · diffScreenshots (baseline vs post-interaction state diff)
|
|
19
|
+
*/
|
|
20
|
+
import { capturePage, verifyFindings, CaptureUnavailableError } from "./capture.js";
|
|
21
|
+
import { runPageChecks } from "./page-checks.js";
|
|
22
|
+
import { captureResponsiveVisibility } from "./responsive.js";
|
|
23
|
+
import { auditContrastUrl } from "./contrast.js";
|
|
24
|
+
import { auditImageEdges } from "./asset-integrity.js";
|
|
25
|
+
import { diffScreenshots } from "./image-diff.js";
|
|
26
|
+
const DEFAULT_VIEWPORTS = [
|
|
27
|
+
{ w: 393, h: 852, label: "iphone" },
|
|
28
|
+
{ w: 1440, h: 900, label: "desktop" },
|
|
29
|
+
{ w: 2160, h: 1200, label: "wide" }
|
|
30
|
+
];
|
|
31
|
+
const DEFAULT_THEMES = ["light", "dark"];
|
|
32
|
+
const SEVERITY_RANK = { error: 0, warning: 1, info: 2 };
|
|
33
|
+
function viewportLabel(v) {
|
|
34
|
+
return (v.label ? v.label : "vp") + " " + v.w + "×" + v.h;
|
|
35
|
+
}
|
|
36
|
+
export async function auditUrl(url, opts = {}) {
|
|
37
|
+
const viewports = opts.viewports && opts.viewports.length > 0 ? opts.viewports : DEFAULT_VIEWPORTS;
|
|
38
|
+
const themes = opts.themes && opts.themes.length > 0 ? opts.themes : DEFAULT_THEMES;
|
|
39
|
+
const scrollSettle = opts.scroll_settle !== false; // default true
|
|
40
|
+
const interactions = Array.isArray(opts.interactions) ? opts.interactions : [];
|
|
41
|
+
const timeoutMs = typeof opts.timeoutMs === "number" ? opts.timeoutMs : 30000;
|
|
42
|
+
const includeScreenshots = opts.includeScreenshots === true;
|
|
43
|
+
const findings = [];
|
|
44
|
+
const captures = [];
|
|
45
|
+
const warnings = [];
|
|
46
|
+
// ── Responsive visibility (run ONCE across all viewport widths) ─────────────
|
|
47
|
+
try {
|
|
48
|
+
const widths = viewports.map((v) => v.w);
|
|
49
|
+
const rv = await captureResponsiveVisibility(url, widths, { timeoutMs });
|
|
50
|
+
const rvLabel = "responsive " + Math.min(...rv.breakpoints) + "→" + Math.max(...rv.breakpoints);
|
|
51
|
+
for (const row of rv.flagged) {
|
|
52
|
+
const oversight = row.category === "likely-oversight";
|
|
53
|
+
findings.push({
|
|
54
|
+
source: "responsive-visibility",
|
|
55
|
+
rule: "responsive/hidden-on-mobile",
|
|
56
|
+
severity: oversight ? "error" : "info",
|
|
57
|
+
message: (oversight ? "Content element" : "Decorative element") +
|
|
58
|
+
" is visible on desktop but hidden on mobile" +
|
|
59
|
+
(row.hidingClass ? " (" + row.hidingClass + ")" : ""),
|
|
60
|
+
fix: oversight
|
|
61
|
+
? "This is real content invisible on mobile — remove the responsive-hide or provide a mobile equivalent."
|
|
62
|
+
: "Decorative element intentionally hidden on mobile — no action needed.",
|
|
63
|
+
selector: row.selector,
|
|
64
|
+
viewport: rvLabel,
|
|
65
|
+
theme: themes[0],
|
|
66
|
+
verdict: oversight ? "confirmed" : "likely-artifact",
|
|
67
|
+
evidence: "computed visibility across breakpoints: " +
|
|
68
|
+
row.visibleAt.map((b) => b.breakpoint + "px=" + (b.visible ? "shown" : "hidden")).join(", ")
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
if (error instanceof CaptureUnavailableError) {
|
|
74
|
+
return unavailableResult(url, viewports, themes);
|
|
75
|
+
}
|
|
76
|
+
warnings.push("responsive-visibility failed: " + errorMessage(error));
|
|
77
|
+
}
|
|
78
|
+
// ── Per viewport × theme ────────────────────────────────────────────────────
|
|
79
|
+
let firstPass = true;
|
|
80
|
+
for (const vp of viewports) {
|
|
81
|
+
for (const theme of themes) {
|
|
82
|
+
const vpLabel = viewportLabel(vp);
|
|
83
|
+
let cap;
|
|
84
|
+
try {
|
|
85
|
+
cap = await capturePage(url, {
|
|
86
|
+
viewport: { w: vp.w, h: vp.h },
|
|
87
|
+
theme,
|
|
88
|
+
scroll_settle: scrollSettle,
|
|
89
|
+
interactions,
|
|
90
|
+
collectImageEdges: firstPass, // image slicing is source-level — sample once
|
|
91
|
+
timeoutMs
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
catch (error) {
|
|
95
|
+
if (error instanceof CaptureUnavailableError) {
|
|
96
|
+
return unavailableResult(url, viewports, themes);
|
|
97
|
+
}
|
|
98
|
+
warnings.push("capture failed (" + vpLabel + "/" + theme + "): " + errorMessage(error));
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
captures.push({
|
|
102
|
+
viewport: vpLabel,
|
|
103
|
+
theme,
|
|
104
|
+
scrolledToBottom: cap.scrolledToBottom,
|
|
105
|
+
screenshot_bytes: cap.screenshotBase64 ? cap.screenshotBase64.length : 0,
|
|
106
|
+
screenshot: includeScreenshots ? cap.screenshotBase64 : undefined
|
|
107
|
+
});
|
|
108
|
+
for (const w of cap.warnings)
|
|
109
|
+
warnings.push(vpLabel + "/" + theme + ": " + w);
|
|
110
|
+
// ── Page checks over the rendered DOM, then adversarially verify ─────────
|
|
111
|
+
const pageResult = runPageChecks(cap.renderedHtml, { containerMaxWidth: opts.containerMaxWidth });
|
|
112
|
+
const verifiable = pageResult.issues.map((iss, i) => ({
|
|
113
|
+
key: iss.rule + ":" + i,
|
|
114
|
+
kind: "issue",
|
|
115
|
+
rule: iss.rule,
|
|
116
|
+
message: iss.message
|
|
117
|
+
}));
|
|
118
|
+
let verdicts = [];
|
|
119
|
+
try {
|
|
120
|
+
verdicts = await verifyFindings({ html: cap.renderedHtml }, verifiable, { viewport: { w: vp.w, h: vp.h }, timeoutMs });
|
|
121
|
+
}
|
|
122
|
+
catch (error) {
|
|
123
|
+
warnings.push("page-check verification failed (" + vpLabel + "/" + theme + "): " + errorMessage(error));
|
|
124
|
+
}
|
|
125
|
+
pageResult.issues.forEach((iss, i) => {
|
|
126
|
+
const v = verdicts[i];
|
|
127
|
+
findings.push({
|
|
128
|
+
source: "page",
|
|
129
|
+
rule: iss.rule,
|
|
130
|
+
severity: iss.severity,
|
|
131
|
+
message: iss.message,
|
|
132
|
+
fix: iss.fix,
|
|
133
|
+
viewport: vpLabel,
|
|
134
|
+
theme,
|
|
135
|
+
verdict: normalizeVerdict(v ? v.verdict : undefined),
|
|
136
|
+
evidence: v && v.evidence ? v.evidence : "rendered-DOM check (no independent re-check available)"
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
// ── Blank / empty media containers ───────────────────────────────────────
|
|
140
|
+
for (const va of cap.videoArtifacts) {
|
|
141
|
+
findings.push({
|
|
142
|
+
source: "video",
|
|
143
|
+
rule: "media/blank-container",
|
|
144
|
+
severity: "warning",
|
|
145
|
+
message: "Media element rendered blank after scroll + play attempt",
|
|
146
|
+
fix: "If this is a real video, ensure a valid source loads (and preload allows it); if it is a lazy preload=none clip, this is expected.",
|
|
147
|
+
selector: va.selector,
|
|
148
|
+
viewport: vpLabel,
|
|
149
|
+
theme,
|
|
150
|
+
// preload=none that we actively played and still got nothing back is a
|
|
151
|
+
// genuinely empty/broken container, not merely lazy — surface it.
|
|
152
|
+
verdict: "confirmed",
|
|
153
|
+
evidence: "video readyState stayed < 2 (HAVE_CURRENT_DATA) after scrollIntoView + play(); preload=\"" +
|
|
154
|
+
va.preload +
|
|
155
|
+
"\""
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
// ── Image edge symmetry (sliced/cropped) — first pass only ───────────────
|
|
159
|
+
if (firstPass && cap.imageEdges && cap.imageEdges.length > 0) {
|
|
160
|
+
const edgeVerdicts = auditImageEdges(cap.imageEdges);
|
|
161
|
+
for (const ev of edgeVerdicts) {
|
|
162
|
+
if (ev.verdict === "clean")
|
|
163
|
+
continue;
|
|
164
|
+
findings.push({
|
|
165
|
+
source: "asset-integrity",
|
|
166
|
+
rule: "asset/sliced-edge",
|
|
167
|
+
severity: ev.verdict === "likely-sliced" ? "warning" : "info",
|
|
168
|
+
message: ev.verdict === "likely-sliced"
|
|
169
|
+
? "Image content appears cut off at the " + ev.cut_edge + " edge"
|
|
170
|
+
: "Image edges could not be analysed",
|
|
171
|
+
fix: ev.verdict === "likely-sliced"
|
|
172
|
+
? "Re-export the image so content does not run into the " + ev.cut_edge + " frame edge."
|
|
173
|
+
: "Serve the image same-origin (or with CORS) so its pixels can be sampled.",
|
|
174
|
+
selector: ev.selector,
|
|
175
|
+
viewport: vpLabel,
|
|
176
|
+
theme,
|
|
177
|
+
verdict: ev.verdict === "likely-sliced" ? "confirmed" : "inconclusive",
|
|
178
|
+
evidence: ev.reason
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
// ── Hover/interaction state diff (white-wash etc.) ───────────────────────
|
|
183
|
+
if (interactions.length > 0) {
|
|
184
|
+
try {
|
|
185
|
+
const baseline = await capturePage(url, {
|
|
186
|
+
viewport: { w: vp.w, h: vp.h },
|
|
187
|
+
theme,
|
|
188
|
+
scroll_settle: scrollSettle,
|
|
189
|
+
timeoutMs
|
|
190
|
+
});
|
|
191
|
+
const diff = await diffScreenshots(baseline.screenshotBase64, cap.screenshotBase64);
|
|
192
|
+
const brightness = diff.dimensions.find((d) => d.dimension === "brightness");
|
|
193
|
+
const before = brightness ? brightness.before : 0;
|
|
194
|
+
const after = brightness ? brightness.after : 0;
|
|
195
|
+
const wash = diff.changed_ratio > 0.3 && after - before > 0.2 && after > 0.7;
|
|
196
|
+
if (wash) {
|
|
197
|
+
findings.push({
|
|
198
|
+
source: "hover-state",
|
|
199
|
+
rule: "interaction/state-wash",
|
|
200
|
+
severity: "warning",
|
|
201
|
+
message: "Firing the interaction(s) washed a large region toward white — content may be obscured in this state",
|
|
202
|
+
fix: "Check the interaction's resulting state (e.g. an overlay/filter at full opacity) — it should not white-out underlying content.",
|
|
203
|
+
viewport: vpLabel,
|
|
204
|
+
theme,
|
|
205
|
+
verdict: "confirmed",
|
|
206
|
+
evidence: Math.round(diff.changed_ratio * 100) +
|
|
207
|
+
"% of pixels changed and mean brightness rose " +
|
|
208
|
+
before.toFixed(2) +
|
|
209
|
+
" → " +
|
|
210
|
+
after.toFixed(2) +
|
|
211
|
+
" after the interaction (near-white)"
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
catch (error) {
|
|
216
|
+
warnings.push("hover-state diff failed (" + vpLabel + "/" + theme + "): " + errorMessage(error));
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
// ── Per-element WCAG contrast ────────────────────────────────────────────
|
|
220
|
+
try {
|
|
221
|
+
const contrast = await auditContrastUrl(url, { viewport: { w: vp.w, h: vp.h }, theme, timeoutMs });
|
|
222
|
+
for (const row of contrast.aa_failures) {
|
|
223
|
+
findings.push({
|
|
224
|
+
source: "contrast",
|
|
225
|
+
rule: "contrast/aa",
|
|
226
|
+
severity: "error",
|
|
227
|
+
message: "Text fails WCAG AA contrast (" +
|
|
228
|
+
row.ratio +
|
|
229
|
+
":1, needs " +
|
|
230
|
+
row.required_aa +
|
|
231
|
+
":1)" +
|
|
232
|
+
(row.text ? ': "' + row.text + '"' : ""),
|
|
233
|
+
fix: "Increase contrast by " +
|
|
234
|
+
row.delta_to_aa +
|
|
235
|
+
" — darken the text or lighten the background until the ratio reaches " +
|
|
236
|
+
row.required_aa +
|
|
237
|
+
":1.",
|
|
238
|
+
selector: row.selector,
|
|
239
|
+
viewport: vpLabel,
|
|
240
|
+
theme,
|
|
241
|
+
verdict: "confirmed",
|
|
242
|
+
evidence: "computed ratio " +
|
|
243
|
+
row.ratio +
|
|
244
|
+
":1 between " +
|
|
245
|
+
row.foreground +
|
|
246
|
+
" on " +
|
|
247
|
+
row.background +
|
|
248
|
+
" at " +
|
|
249
|
+
row.fontPx +
|
|
250
|
+
"px (required AA " +
|
|
251
|
+
row.required_aa +
|
|
252
|
+
":1)"
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
catch (error) {
|
|
257
|
+
if (error instanceof CaptureUnavailableError) {
|
|
258
|
+
return unavailableResult(url, viewports, themes);
|
|
259
|
+
}
|
|
260
|
+
warnings.push("contrast audit failed (" + vpLabel + "/" + theme + "): " + errorMessage(error));
|
|
261
|
+
}
|
|
262
|
+
firstPass = false;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
// ── Rank by severity, then group by source ──────────────────────────────────
|
|
266
|
+
findings.sort((a, b) => {
|
|
267
|
+
const sr = (SEVERITY_RANK[a.severity] ?? 9) - (SEVERITY_RANK[b.severity] ?? 9);
|
|
268
|
+
if (sr !== 0)
|
|
269
|
+
return sr;
|
|
270
|
+
return a.source.localeCompare(b.source);
|
|
271
|
+
});
|
|
272
|
+
const counts = {
|
|
273
|
+
total: findings.length,
|
|
274
|
+
confirmed: findings.filter((f) => f.verdict === "confirmed").length,
|
|
275
|
+
likely_artifact: findings.filter((f) => f.verdict === "likely-artifact").length,
|
|
276
|
+
inconclusive: findings.filter((f) => f.verdict === "inconclusive").length,
|
|
277
|
+
errors: findings.filter((f) => f.severity === "error").length,
|
|
278
|
+
warnings: findings.filter((f) => f.severity === "warning").length
|
|
279
|
+
};
|
|
280
|
+
const summary = findings.length +
|
|
281
|
+
" findings across " +
|
|
282
|
+
viewports.length +
|
|
283
|
+
" viewport(s) × " +
|
|
284
|
+
themes.length +
|
|
285
|
+
" theme(s) — " +
|
|
286
|
+
counts.confirmed +
|
|
287
|
+
" confirmed, " +
|
|
288
|
+
counts.likely_artifact +
|
|
289
|
+
" likely-artifact, " +
|
|
290
|
+
counts.inconclusive +
|
|
291
|
+
" inconclusive";
|
|
292
|
+
return {
|
|
293
|
+
tool: "audit_url",
|
|
294
|
+
url,
|
|
295
|
+
viewports,
|
|
296
|
+
themes,
|
|
297
|
+
findings,
|
|
298
|
+
counts,
|
|
299
|
+
summary,
|
|
300
|
+
captures,
|
|
301
|
+
warnings
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
function normalizeVerdict(v) {
|
|
305
|
+
if (v === "confirmed" || v === "likely-artifact" || v === "inconclusive")
|
|
306
|
+
return v;
|
|
307
|
+
return "inconclusive";
|
|
308
|
+
}
|
|
309
|
+
function unavailableResult(url, viewports, themes) {
|
|
310
|
+
return {
|
|
311
|
+
tool: "audit_url",
|
|
312
|
+
url,
|
|
313
|
+
viewports,
|
|
314
|
+
themes,
|
|
315
|
+
findings: [],
|
|
316
|
+
counts: { total: 0, confirmed: 0, likely_artifact: 0, inconclusive: 0, errors: 0, warnings: 0 },
|
|
317
|
+
summary: "audit_url needs headless chromium. Run: npx playwright install chromium",
|
|
318
|
+
captures: [],
|
|
319
|
+
warnings: ["Playwright chromium not available. Run: npx playwright install chromium"]
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
function errorMessage(error) {
|
|
323
|
+
if (error instanceof Error)
|
|
324
|
+
return error.message;
|
|
325
|
+
return String(error);
|
|
326
|
+
}
|
|
327
|
+
//# sourceMappingURL=audit-url.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit-url.js","sourceRoot":"","sources":["../src/audit-url.ts"],"names":[],"mappings":"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"}
|
package/dist/capture.d.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import type { ImageEdgeSample } from "./asset-integrity.js";
|
|
2
|
+
export type { ImageEdgeSample } from "./asset-integrity.js";
|
|
3
|
+
export type Theme = "light" | "dark";
|
|
1
4
|
export declare class CaptureUnavailableError extends Error {
|
|
2
5
|
constructor(message?: string);
|
|
3
6
|
}
|
|
@@ -15,8 +18,10 @@ export type CaptureResult = {
|
|
|
15
18
|
w: number;
|
|
16
19
|
h: number;
|
|
17
20
|
};
|
|
21
|
+
theme?: Theme;
|
|
18
22
|
scrolledToBottom: boolean;
|
|
19
23
|
videoArtifacts: VideoArtifact[];
|
|
24
|
+
imageEdges?: ImageEdgeSample[];
|
|
20
25
|
warnings: string[];
|
|
21
26
|
};
|
|
22
27
|
export type Interaction = {
|
|
@@ -31,6 +36,8 @@ export type CaptureOptions = {
|
|
|
31
36
|
w: number;
|
|
32
37
|
h: number;
|
|
33
38
|
};
|
|
39
|
+
theme?: Theme;
|
|
40
|
+
collectImageEdges?: boolean;
|
|
34
41
|
timeoutMs?: number;
|
|
35
42
|
};
|
|
36
43
|
export declare function capturePage(url: string, opts?: CaptureOptions): Promise<CaptureResult>;
|