raven-mcp 1.10.0 → 1.12.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 +7 -5
- package/dist/audit-consistency.d.ts +52 -0
- package/dist/audit-consistency.js +290 -0
- package/dist/audit-consistency.js.map +1 -0
- package/dist/compact.d.ts +3 -0
- package/dist/compact.js +103 -0
- package/dist/compact.js.map +1 -0
- package/dist/contrast.d.ts +32 -0
- package/dist/contrast.js +217 -15
- package/dist/contrast.js.map +1 -1
- package/dist/device-frame.d.ts +73 -0
- package/dist/device-frame.js +483 -0
- package/dist/device-frame.js.map +1 -0
- package/dist/index.js +137 -11
- package/dist/index.js.map +1 -1
- package/dist/layout-orphans.d.ts +36 -0
- package/dist/layout-orphans.js +119 -0
- package/dist/layout-orphans.js.map +1 -0
- package/dist/score-page.d.ts +36 -0
- package/dist/score-page.js +95 -0
- package/dist/score-page.js.map +1 -0
- package/dist/video-playback.d.ts +61 -0
- package/dist/video-playback.js +201 -0
- package/dist/video-playback.js.map +1 -0
- package/package.json +1 -1
- package/src/data/principles/color-systems.json +32 -0
- package/src/data/principles/spacing-systems.json +55 -0
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@ A design knowledge MCP server that Claude can query when generating UI. Eight la
|
|
|
10
10
|
|
|
11
11
|
Raven gives Claude access to a comprehensive design knowledge base:
|
|
12
12
|
|
|
13
|
-
- **Principles** — Nielsen's 10 Heuristics, all 21 Laws of UX, Gestalt principles, WCAG accessibility, typography rules, color theory, mobile UX, D4D framework, UX writing, service design, and
|
|
13
|
+
- **Principles** — Nielsen's 10 Heuristics, all 21 Laws of UX, Gestalt principles, WCAG accessibility, typography rules, color theory, mobile UX, D4D framework, UX writing, service design, brand, color-systems (palette-size discipline), and spacing-systems (base-unit grid + scale limits)
|
|
14
14
|
- **Patterns** — Proven UI patterns for signup flows, pricing pages, navigation, forms, landing pages, dashboards, modals, empty/error/loading states, CTAs, social proof, mobile conversion — plus content patterns (error messages, empty-state copy, notifications, form validation) and service patterns (service blueprinting, human handoff, signup-as-service, omnichannel continuity, moments of truth)
|
|
15
15
|
- **Content systems** — Voice & tone guides from publicly documented brand systems: Mailchimp, GOV.UK, Shopify Polaris, and Atlassian
|
|
16
16
|
- **Research** — Qualitative, quantitative, and usability methods with do/don't protocols and checklists. Metrics frameworks: HEART, AARRR/Pirate, North Star Metric, conversion funnel, RICE, OKRs.
|
|
@@ -55,7 +55,7 @@ cd raven-mcp && npm install && npm run build
|
|
|
55
55
|
| `get_principles` | Get design principles relevant to a UI context |
|
|
56
56
|
| `get_pattern` | Get proven patterns for a specific UI type |
|
|
57
57
|
| `get_business_strategy` | Get business/monetization strategies |
|
|
58
|
-
| `evaluate_design` | Evaluate a design description against principles. Pass base64 PNG screenshots (`before_screenshot`/`after_screenshot`) for a structured before/after pixel diff with `fix_confirmed`, `changed_ratio`, and changed region. |
|
|
58
|
+
| `evaluate_design` | Evaluate a design description against principles. Pass base64 PNG screenshots (`before_screenshot`/`after_screenshot`) for a structured before/after pixel diff with `fix_confirmed`, `changed_ratio`, and changed region. Pass `compact: true` to return only scores and violations (drops full principle/pattern bodies) when the full payload is too large. |
|
|
59
59
|
| `search_knowledge` | Search across all principles, patterns, and strategies |
|
|
60
60
|
| `get_checklist` | Get a pre-publish checklist for a UI type |
|
|
61
61
|
| `get_d4d_framework` | Get Design for Delight framework templates |
|
|
@@ -63,14 +63,16 @@ cd raven-mcp && npm install && npm run build
|
|
|
63
63
|
| `get_design_system` | Get tokens for a specific design system |
|
|
64
64
|
| `compose_system` | Mix tokens from different systems |
|
|
65
65
|
| `get_brand_system` | Get a full system styled like a well-known brand |
|
|
66
|
-
| `audit_page` | Audit HTML/CSS against Raven's quality standards — pass `html` for static audit, or `url` to render headless with optional `scroll_settle` (scroll to bottom + settle reveals) and `viewport` parameters; `containerMaxWidth` makes container checks token-aware |
|
|
66
|
+
| `audit_page` | Audit HTML/CSS against Raven's quality standards — pass `html` for static audit, or `url` to render headless with optional `scroll_settle` (scroll to bottom + settle reveals) and `viewport` parameters; `containerMaxWidth` makes container checks token-aware. Pass `compact: true` to return only scores, violations, and fix_priority (drops embedded base64 screenshots) when the full payload is too large. |
|
|
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
|
-
| `
|
|
70
|
+
| `suggest_contrast_fix` | Given failing WCAG color pairs, return the minimal fg/bg change that clears the AA/AAA target — concrete passing values to fix `audit_contrast` failures |
|
|
71
|
+
| `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. Pass `compact: true` to return only findings and summary (drops per-capture base64 screenshots) when the full payload is too large. |
|
|
71
72
|
| `audit_content` | Per-item content verdicts (pass/warn/fail) for headings, prose, CTAs, labels, captions, metrics & outcomes against UX-writing principles + deterministic heuristics (metric needs number+unit; CTA action-led ≤4 words; prose flags passive/jargon/hedging; caption-vs-heading duplication) — with a before→after rewrite suggestion per item. Pure offline |
|
|
72
73
|
| `audit_typography` | Typographic-**scale** report over rendered DOM text nodes (or a supplied snapshot) — detects the dominant modular-scale ratio and flags off-scale sizes, checks line-height consistency vs the body rhythm, and flags weight ladders >4 weights or non-standard values. Goes beyond `audit_page`'s pass/fail typography checks |
|
|
73
74
|
| `audit_tap_targets` | WCAG 2.5.5 / Apple 44pt **web** tap-target audit — enumerates every interactive element (rendered URL or snapshot) and emits a per-element fix table: selector, role, text, measured w/h, per-axis pixel deficit, and a concrete CSS fix, sorted worst-first |
|
|
75
|
+
| `audit_device_frame` | Flag cropped content in device-mockup frames — `frames` (container box + intrinsic media + object-fit, or a DevTools snippet) detects object-fit:cover crop loss when frame AR ≠ media AR; `clips` (first/last frame PNGs) detects baked-in pan/zoom (Ken Burns); `edge_frames` (PNGs) flags content truncated at a frame edge |
|
|
74
76
|
| `audit_swiftui` | Audit SwiftUI source against Apple HIG — Dynamic Type, semantic colors, 44pt targets, 4/8pt spacing, AccentColor |
|
|
75
77
|
| `audit_ios_screen` | Score a rendered iOS screen from an accessibility/view-hierarchy snapshot — 44pt targets + contrast + rhythm, in points |
|
|
76
78
|
| `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 |
|
|
@@ -148,7 +150,7 @@ Returns flagged elements with selector, hiding class, visibility at each breakpo
|
|
|
148
150
|
|
|
149
151
|
## Contrast audits
|
|
150
152
|
|
|
151
|
-
`audit_contrast` computes WCAG contrast ratios for every text element on a rendered page, reporting AA (4.5:1 normal text, 3:1 large) and AAA (7:1 normal, 4.5:1 large) pass-fail. Useful for catching small-text / low-contrast pairs that a screenshot eyedropper would catch manually — Raven replaces the math.
|
|
153
|
+
`audit_contrast` computes WCAG contrast ratios for every text element on a rendered page, reporting AA (4.5:1 normal text, 3:1 large) and AAA (7:1 normal, 4.5:1 large) pass-fail. Useful for catching small-text / low-contrast pairs that a screenshot eyedropper would catch manually — Raven replaces the math. The background color is composited from the full ancestor stack (nearest opaque layer onward) for accurate contrast on layered UIs.
|
|
152
154
|
|
|
153
155
|
**Usage:**
|
|
154
156
|
- `audit_contrast(url)` — render a live page and audit all text.
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
export type ConsistencyDimension = {
|
|
2
|
+
reference: string | null;
|
|
3
|
+
source: "token" | "modal" | "none";
|
|
4
|
+
outliers: string[];
|
|
5
|
+
};
|
|
6
|
+
export type ConsistencyIssue = {
|
|
7
|
+
severity: "warning";
|
|
8
|
+
rule: string;
|
|
9
|
+
message: string;
|
|
10
|
+
fix: string;
|
|
11
|
+
};
|
|
12
|
+
export type ConsistencyPageResult = {
|
|
13
|
+
name: string;
|
|
14
|
+
container: {
|
|
15
|
+
px: number | null;
|
|
16
|
+
classes: string[];
|
|
17
|
+
signature: string;
|
|
18
|
+
};
|
|
19
|
+
hero: {
|
|
20
|
+
size_px: number | null;
|
|
21
|
+
classes: string;
|
|
22
|
+
signature: string;
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
export type ConsistencyResult = {
|
|
26
|
+
page_count: number;
|
|
27
|
+
pages: ConsistencyPageResult[];
|
|
28
|
+
consistency: {
|
|
29
|
+
container: ConsistencyDimension;
|
|
30
|
+
hero: ConsistencyDimension;
|
|
31
|
+
};
|
|
32
|
+
issues: ConsistencyIssue[];
|
|
33
|
+
score: number;
|
|
34
|
+
grade: "A" | "B" | "C" | "D";
|
|
35
|
+
summary: string;
|
|
36
|
+
};
|
|
37
|
+
export type AuditConsistencyOptions = {
|
|
38
|
+
container_token?: number;
|
|
39
|
+
hero_token?: string;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Audit multiple pages for cross-page consistency of:
|
|
43
|
+
* - Content-container width (container_px / container_classes)
|
|
44
|
+
* - Hero heading tier (hero_size_px / hero_classes)
|
|
45
|
+
*
|
|
46
|
+
* Infers the canonical (modal) value from the corpus when no token is supplied.
|
|
47
|
+
* Pure — no I/O, no browser. Assumes pages.length >= 2.
|
|
48
|
+
*/
|
|
49
|
+
export declare function auditConsistency(pages: Array<{
|
|
50
|
+
name: string;
|
|
51
|
+
html: string;
|
|
52
|
+
}>, opts?: AuditConsistencyOptions): ConsistencyResult;
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
// ── Cross-page consistency audit ─────────────────────────────────────
|
|
2
|
+
//
|
|
3
|
+
// Accepts multiple pages (name + HTML string) and flags cross-page
|
|
4
|
+
// divergence in (a) content-container width and (b) hero heading tier.
|
|
5
|
+
// The canonical (reference) value for each dimension is inferred from the
|
|
6
|
+
// corpus modal when no token is supplied, so callers need not know the
|
|
7
|
+
// project's token in advance.
|
|
8
|
+
//
|
|
9
|
+
// Pure HTML-string analysis: no I/O, no browser.
|
|
10
|
+
// Reuses `containerScaleWidths` from audit-container.ts; does NOT modify it.
|
|
11
|
+
//
|
|
12
|
+
// Addresses GitHub issue #9 ("single-blob audit blind spot") — fix #1
|
|
13
|
+
// (multi-page / corpus audit mode).
|
|
14
|
+
import { containerScaleWidths } from "./audit-container.js";
|
|
15
|
+
// ── Per-page extraction helpers ──────────────────────────────────────
|
|
16
|
+
var CONTAINER_CLASS_RE = /\b(max-w-[a-z0-9.]+|container[a-z0-9-]*|w-screen|w-full)\b/gi;
|
|
17
|
+
/**
|
|
18
|
+
* Extract container-class tokens from the page HTML.
|
|
19
|
+
* Returns a sorted, unique array of class tokens matching the pattern.
|
|
20
|
+
*/
|
|
21
|
+
function extractContainerClasses(html) {
|
|
22
|
+
var found = [];
|
|
23
|
+
var m;
|
|
24
|
+
var re = new RegExp(CONTAINER_CLASS_RE.source, "gi");
|
|
25
|
+
while ((m = re.exec(html)) !== null) {
|
|
26
|
+
found.push(m[0].toLowerCase());
|
|
27
|
+
}
|
|
28
|
+
// Sort + deduplicate
|
|
29
|
+
var unique = Array.from(new Set(found)).sort();
|
|
30
|
+
return unique;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Largest declared heading font-size in px among h1/h2 CSS rules, or null.
|
|
34
|
+
* Mirrors the approach in page-checks.ts lines ~135-138: regex for h1/h2 CSS
|
|
35
|
+
* rules then pulls the font-size value.
|
|
36
|
+
*/
|
|
37
|
+
function extractHeroSizePx(html) {
|
|
38
|
+
var best = null;
|
|
39
|
+
var tags = ["h1", "h2"];
|
|
40
|
+
for (var i = 0; i < tags.length; i++) {
|
|
41
|
+
var ht = tags[i];
|
|
42
|
+
var hre = new RegExp("(?:^|[\\s,}])" + ht + "\\b[^{]*\\{[^}]*font-size\\s*:\\s*(\\d+(?:\\.\\d+)?)\\s*px", "i");
|
|
43
|
+
var hm = html.match(hre);
|
|
44
|
+
if (hm) {
|
|
45
|
+
var n = parseFloat(hm[1]);
|
|
46
|
+
if (!isNaN(n) && (best === null || n > best))
|
|
47
|
+
best = n;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return best;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Extract the class attribute of the FIRST <h1 ...> tag in the page.
|
|
54
|
+
* Returns "" if none found or no class attr present.
|
|
55
|
+
*/
|
|
56
|
+
function extractFirstH1Classes(html) {
|
|
57
|
+
var m = html.match(/<h1\b([^>]*)>/i);
|
|
58
|
+
if (!m)
|
|
59
|
+
return "";
|
|
60
|
+
var attrs = m[1];
|
|
61
|
+
var classMatch = attrs.match(/\bclass\s*=\s*(?:"([^"]*?)"|'([^']*?)'|([^\s>]*))/i);
|
|
62
|
+
if (!classMatch)
|
|
63
|
+
return "";
|
|
64
|
+
return (classMatch[1] || classMatch[2] || classMatch[3] || "").trim();
|
|
65
|
+
}
|
|
66
|
+
var HERO_TYPE_SCALE_RE = /\btext-(display-[a-z0-9]+|[0-9]?xl|xs|sm|base|lg|xl)\b/i;
|
|
67
|
+
/**
|
|
68
|
+
* Derive the hero signature for a page.
|
|
69
|
+
* If hero_size_px is known, use that as the signature (e.g. "64").
|
|
70
|
+
* Else find the first type-scale class in hero_classes.
|
|
71
|
+
* Else "".
|
|
72
|
+
*/
|
|
73
|
+
function heroSignature(heroPx, heroClasses) {
|
|
74
|
+
if (heroPx !== null)
|
|
75
|
+
return String(heroPx);
|
|
76
|
+
var m = heroClasses.match(HERO_TYPE_SCALE_RE);
|
|
77
|
+
if (m)
|
|
78
|
+
return m[0];
|
|
79
|
+
return "";
|
|
80
|
+
}
|
|
81
|
+
// ── Per-page extraction ───────────────────────────────────────────────
|
|
82
|
+
function extractPage(name, html) {
|
|
83
|
+
// Container
|
|
84
|
+
var widths = containerScaleWidths(html);
|
|
85
|
+
var containerPx = widths.length > 0 ? Math.max.apply(null, widths) : null;
|
|
86
|
+
var containerClasses = extractContainerClasses(html);
|
|
87
|
+
var containerSignature;
|
|
88
|
+
if (containerPx !== null) {
|
|
89
|
+
containerSignature = String(containerPx);
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
containerSignature = containerClasses.join(" ");
|
|
93
|
+
}
|
|
94
|
+
// Hero
|
|
95
|
+
var heroPx = extractHeroSizePx(html);
|
|
96
|
+
var heroClasses = extractFirstH1Classes(html);
|
|
97
|
+
var herSig = heroSignature(heroPx, heroClasses);
|
|
98
|
+
return {
|
|
99
|
+
name: name,
|
|
100
|
+
container: {
|
|
101
|
+
px: containerPx,
|
|
102
|
+
classes: containerClasses,
|
|
103
|
+
signature: containerSignature
|
|
104
|
+
},
|
|
105
|
+
hero: {
|
|
106
|
+
size_px: heroPx,
|
|
107
|
+
classes: heroClasses,
|
|
108
|
+
signature: herSig
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
// ── Modal inference ───────────────────────────────────────────────────
|
|
113
|
+
/**
|
|
114
|
+
* Find the modal (most frequent) value among non-empty strings.
|
|
115
|
+
* Returns null if all are empty, or if there's a tie among ≥2 distinct values.
|
|
116
|
+
*/
|
|
117
|
+
function findModal(values) {
|
|
118
|
+
var nonEmpty = values.filter(function (v) { return v !== ""; });
|
|
119
|
+
if (nonEmpty.length === 0)
|
|
120
|
+
return null;
|
|
121
|
+
var counts = {};
|
|
122
|
+
for (var i = 0; i < nonEmpty.length; i++) {
|
|
123
|
+
var v = nonEmpty[i];
|
|
124
|
+
counts[v] = (counts[v] || 0) + 1;
|
|
125
|
+
}
|
|
126
|
+
var maxCount = 0;
|
|
127
|
+
var keys = Object.keys(counts);
|
|
128
|
+
for (var k = 0; k < keys.length; k++) {
|
|
129
|
+
if (counts[keys[k]] > maxCount)
|
|
130
|
+
maxCount = counts[keys[k]];
|
|
131
|
+
}
|
|
132
|
+
// All values with the max count
|
|
133
|
+
var leaders = keys.filter(function (k) { return counts[k] === maxCount; });
|
|
134
|
+
// Tie among ≥2 distinct values → no modal
|
|
135
|
+
if (leaders.length >= 2)
|
|
136
|
+
return null;
|
|
137
|
+
return leaders[0];
|
|
138
|
+
}
|
|
139
|
+
function checkDimension(pageNames, signatures, token) {
|
|
140
|
+
// All non-empty signatures
|
|
141
|
+
var nonEmpty = signatures.filter(function (s) { return s !== ""; });
|
|
142
|
+
// 1. Token override
|
|
143
|
+
if (token !== undefined && token !== null) {
|
|
144
|
+
var ref = String(token);
|
|
145
|
+
var outliers = [];
|
|
146
|
+
for (var i = 0; i < signatures.length; i++) {
|
|
147
|
+
var sig = signatures[i];
|
|
148
|
+
if (sig !== "" && sig !== ref) {
|
|
149
|
+
outliers.push(pageNames[i]);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return { reference: ref, source: "token", outliers: outliers };
|
|
153
|
+
}
|
|
154
|
+
// 2. All empty → source "none"
|
|
155
|
+
if (nonEmpty.length === 0) {
|
|
156
|
+
return { reference: null, source: "none", outliers: [] };
|
|
157
|
+
}
|
|
158
|
+
// 3. Modal inference
|
|
159
|
+
var modal = findModal(signatures);
|
|
160
|
+
if (modal !== null) {
|
|
161
|
+
// Clear modal: outliers are non-empty pages that differ
|
|
162
|
+
var outliers2 = [];
|
|
163
|
+
for (var j = 0; j < signatures.length; j++) {
|
|
164
|
+
if (signatures[j] !== "" && signatures[j] !== modal) {
|
|
165
|
+
outliers2.push(pageNames[j]);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
return { reference: modal, source: "modal", outliers: outliers2 };
|
|
169
|
+
}
|
|
170
|
+
// 4. Tie (no modal): emit all non-empty differing pages as outliers.
|
|
171
|
+
// reference is null (can't declare canonical without a token), so source is
|
|
172
|
+
// "none" — "modal" always carries a non-null reference, keeping the two fields
|
|
173
|
+
// internally consistent for consumers.
|
|
174
|
+
var allOutliers = [];
|
|
175
|
+
for (var m = 0; m < signatures.length; m++) {
|
|
176
|
+
if (signatures[m] !== "") {
|
|
177
|
+
allOutliers.push(pageNames[m]);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
return { reference: null, source: "none", outliers: allOutliers };
|
|
181
|
+
}
|
|
182
|
+
// ── Issue generation ──────────────────────────────────────────────────
|
|
183
|
+
function makeContainerIssue(outliers, reference) {
|
|
184
|
+
// Reference may be a numeric px width ("1152") or a class signature ("container-wide");
|
|
185
|
+
// only suffix "px" for the numeric form.
|
|
186
|
+
var refIsNumeric = reference !== null && /^\d+(?:\.\d+)?$/.test(reference);
|
|
187
|
+
var refStr = reference === null ? "(no modal — all values diverge)" : (refIsNumeric ? reference + "px" : reference);
|
|
188
|
+
var pageList = outliers.join(", ");
|
|
189
|
+
return {
|
|
190
|
+
severity: "warning",
|
|
191
|
+
rule: "consistency/container-width",
|
|
192
|
+
message: "Container-width inconsistency across pages. Reference: " +
|
|
193
|
+
refStr +
|
|
194
|
+
". Divergent page(s): " +
|
|
195
|
+
pageList +
|
|
196
|
+
".",
|
|
197
|
+
fix: "Align all pages to the same container token (" +
|
|
198
|
+
(reference === null ? "the project canonical width" : refStr) +
|
|
199
|
+
"). Use a shared layout wrapper so the container is defined once, not per-page."
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
function makeHeroIssue(outliers, reference) {
|
|
203
|
+
var refStr = reference !== null ? reference : "(no modal — all values diverge)";
|
|
204
|
+
var pageList = outliers.join(", ");
|
|
205
|
+
return {
|
|
206
|
+
severity: "warning",
|
|
207
|
+
rule: "consistency/hero-tier",
|
|
208
|
+
message: "Hero heading tier inconsistency across pages. Reference: " +
|
|
209
|
+
refStr +
|
|
210
|
+
". Divergent page(s): " +
|
|
211
|
+
pageList +
|
|
212
|
+
".",
|
|
213
|
+
fix: "Use the same hero heading class/size (" +
|
|
214
|
+
(reference !== null ? reference : "define a canonical tier") +
|
|
215
|
+
") for the top-level heading on every page. If a page intentionally uses a smaller heading, document the exception in the design system."
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Audit multiple pages for cross-page consistency of:
|
|
220
|
+
* - Content-container width (container_px / container_classes)
|
|
221
|
+
* - Hero heading tier (hero_size_px / hero_classes)
|
|
222
|
+
*
|
|
223
|
+
* Infers the canonical (modal) value from the corpus when no token is supplied.
|
|
224
|
+
* Pure — no I/O, no browser. Assumes pages.length >= 2.
|
|
225
|
+
*/
|
|
226
|
+
export function auditConsistency(pages, opts) {
|
|
227
|
+
var options = opts || {};
|
|
228
|
+
// Extract per-page data
|
|
229
|
+
var pageResults = pages.map(function (p) {
|
|
230
|
+
return extractPage(p.name, p.html);
|
|
231
|
+
});
|
|
232
|
+
var pageNames = pageResults.map(function (p) { return p.name; });
|
|
233
|
+
var containerSigs = pageResults.map(function (p) { return p.container.signature; });
|
|
234
|
+
var heroSigs = pageResults.map(function (p) { return p.hero.signature; });
|
|
235
|
+
// Consistency checks
|
|
236
|
+
var containerDim = checkDimension(pageNames, containerSigs, options.container_token);
|
|
237
|
+
var heroDim = checkDimension(pageNames, heroSigs, options.hero_token);
|
|
238
|
+
// Issues
|
|
239
|
+
var issues = [];
|
|
240
|
+
if (containerDim.outliers.length > 0) {
|
|
241
|
+
issues.push(makeContainerIssue(containerDim.outliers, containerDim.reference));
|
|
242
|
+
}
|
|
243
|
+
if (heroDim.outliers.length > 0) {
|
|
244
|
+
issues.push(makeHeroIssue(heroDim.outliers, heroDim.reference));
|
|
245
|
+
}
|
|
246
|
+
// Scoring
|
|
247
|
+
var failCount = (containerDim.outliers.length > 0 ? 1 : 0) +
|
|
248
|
+
(heroDim.outliers.length > 0 ? 1 : 0);
|
|
249
|
+
var score = Math.round(((2 - failCount) / 2) * 100);
|
|
250
|
+
var grade = failCount === 0 ? "A" : failCount === 1 ? "C" : "D";
|
|
251
|
+
// Summary
|
|
252
|
+
var summary;
|
|
253
|
+
if (failCount === 0) {
|
|
254
|
+
summary =
|
|
255
|
+
"All " +
|
|
256
|
+
pages.length +
|
|
257
|
+
" pages are consistent on container width and hero heading tier. Score: " +
|
|
258
|
+
score +
|
|
259
|
+
"/100 (A).";
|
|
260
|
+
}
|
|
261
|
+
else {
|
|
262
|
+
var dims = [];
|
|
263
|
+
if (containerDim.outliers.length > 0)
|
|
264
|
+
dims.push("container width");
|
|
265
|
+
if (heroDim.outliers.length > 0)
|
|
266
|
+
dims.push("hero heading tier");
|
|
267
|
+
summary =
|
|
268
|
+
pages.length +
|
|
269
|
+
" pages audited. Inconsistency detected in: " +
|
|
270
|
+
dims.join(", ") +
|
|
271
|
+
". Score: " +
|
|
272
|
+
score +
|
|
273
|
+
"/100 (" +
|
|
274
|
+
grade +
|
|
275
|
+
").";
|
|
276
|
+
}
|
|
277
|
+
return {
|
|
278
|
+
page_count: pages.length,
|
|
279
|
+
pages: pageResults,
|
|
280
|
+
consistency: {
|
|
281
|
+
container: containerDim,
|
|
282
|
+
hero: heroDim
|
|
283
|
+
},
|
|
284
|
+
issues: issues,
|
|
285
|
+
score: score,
|
|
286
|
+
grade: grade,
|
|
287
|
+
summary: summary
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
//# sourceMappingURL=audit-consistency.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit-consistency.js","sourceRoot":"","sources":["../src/audit-consistency.ts"],"names":[],"mappings":"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"}
|
package/dist/compact.js
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
// src/compact.ts
|
|
2
|
+
// Compact response shaping for the heavy audit/eval tools. Pure, no side effects.
|
|
3
|
+
// Strips embedded reference bulk (base64 screenshots, principle/pattern bodies, raw DOM)
|
|
4
|
+
// while preserving the decision-grade signal: scores, violations, fix_priority.
|
|
5
|
+
export function compactAuditPage(result) {
|
|
6
|
+
const out = {};
|
|
7
|
+
if ("score" in result)
|
|
8
|
+
out.score = result.score;
|
|
9
|
+
if ("grade" in result)
|
|
10
|
+
out.grade = result.grade;
|
|
11
|
+
if ("summary" in result)
|
|
12
|
+
out.summary = result.summary;
|
|
13
|
+
if ("passes" in result && Array.isArray(result.passes)) {
|
|
14
|
+
out.passes_count = result.passes.length;
|
|
15
|
+
}
|
|
16
|
+
else if ("passes_count" in result) {
|
|
17
|
+
out.passes_count = result.passes_count;
|
|
18
|
+
}
|
|
19
|
+
if ("errors" in result)
|
|
20
|
+
out.errors = result.errors;
|
|
21
|
+
if ("warnings" in result)
|
|
22
|
+
out.warnings = result.warnings;
|
|
23
|
+
if ("fix_priority" in result)
|
|
24
|
+
out.fix_priority = result.fix_priority;
|
|
25
|
+
if ("notes" in result)
|
|
26
|
+
out.notes = result.notes;
|
|
27
|
+
if ("unloaded_video_artifacts" in result)
|
|
28
|
+
out.unloaded_video_artifacts = result.unloaded_video_artifacts;
|
|
29
|
+
if ("adversarial_verification" in result)
|
|
30
|
+
out.adversarial_verification = result.adversarial_verification;
|
|
31
|
+
if (result.capture && typeof result.capture === "object") {
|
|
32
|
+
const cap = {};
|
|
33
|
+
if ("url" in result.capture)
|
|
34
|
+
cap.url = result.capture.url;
|
|
35
|
+
if ("viewport" in result.capture)
|
|
36
|
+
cap.viewport = result.capture.viewport;
|
|
37
|
+
if ("scrolledToBottom" in result.capture)
|
|
38
|
+
cap.scrolledToBottom = result.capture.scrolledToBottom;
|
|
39
|
+
out.capture = cap; // screenshot_bytes (the base64) intentionally dropped
|
|
40
|
+
}
|
|
41
|
+
return out;
|
|
42
|
+
}
|
|
43
|
+
export function compactEvaluation(evaluation) {
|
|
44
|
+
const out = {};
|
|
45
|
+
if ("design_description" in evaluation)
|
|
46
|
+
out.design_description = evaluation.design_description;
|
|
47
|
+
if ("context" in evaluation)
|
|
48
|
+
out.context = evaluation.context;
|
|
49
|
+
if ("goals" in evaluation)
|
|
50
|
+
out.goals = evaluation.goals;
|
|
51
|
+
if ("evaluation_guidance" in evaluation)
|
|
52
|
+
out.evaluation_guidance = evaluation.evaluation_guidance;
|
|
53
|
+
if (Array.isArray(evaluation.principles_to_check)) {
|
|
54
|
+
out.principles_to_check = evaluation.principles_to_check.map((p) => ({ id: p.id, name: p.name }));
|
|
55
|
+
}
|
|
56
|
+
if (Array.isArray(evaluation.applicable_patterns)) {
|
|
57
|
+
out.applicable_patterns = evaluation.applicable_patterns.map((p) => ({ id: p.id, name: p.name }));
|
|
58
|
+
}
|
|
59
|
+
if ("total_principles" in evaluation)
|
|
60
|
+
out.total_principles = evaluation.total_principles;
|
|
61
|
+
if ("total_patterns" in evaluation)
|
|
62
|
+
out.total_patterns = evaluation.total_patterns;
|
|
63
|
+
if ("before_after_diff" in evaluation)
|
|
64
|
+
out.before_after_diff = evaluation.before_after_diff;
|
|
65
|
+
if ("fix_confirmed" in evaluation)
|
|
66
|
+
out.fix_confirmed = evaluation.fix_confirmed;
|
|
67
|
+
return out;
|
|
68
|
+
}
|
|
69
|
+
export function compactAuditUrl(result) {
|
|
70
|
+
const out = {};
|
|
71
|
+
if ("tool" in result)
|
|
72
|
+
out.tool = result.tool;
|
|
73
|
+
if ("url" in result)
|
|
74
|
+
out.url = result.url;
|
|
75
|
+
if ("viewports" in result)
|
|
76
|
+
out.viewports = result.viewports;
|
|
77
|
+
if ("themes" in result)
|
|
78
|
+
out.themes = result.themes;
|
|
79
|
+
if ("findings" in result)
|
|
80
|
+
out.findings = result.findings;
|
|
81
|
+
if ("counts" in result)
|
|
82
|
+
out.counts = result.counts;
|
|
83
|
+
if ("summary" in result)
|
|
84
|
+
out.summary = result.summary;
|
|
85
|
+
if ("warnings" in result)
|
|
86
|
+
out.warnings = result.warnings;
|
|
87
|
+
if (Array.isArray(result.captures)) {
|
|
88
|
+
out.captures = result.captures.map((c) => {
|
|
89
|
+
const cc = {};
|
|
90
|
+
if ("viewport" in c)
|
|
91
|
+
cc.viewport = c.viewport;
|
|
92
|
+
if ("theme" in c)
|
|
93
|
+
cc.theme = c.theme;
|
|
94
|
+
if ("scrolledToBottom" in c)
|
|
95
|
+
cc.scrolledToBottom = c.scrolledToBottom;
|
|
96
|
+
if ("screenshot_bytes" in c)
|
|
97
|
+
cc.screenshot_bytes = c.screenshot_bytes;
|
|
98
|
+
return cc; // base64 `screenshot` intentionally dropped
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
return out;
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=compact.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compact.js","sourceRoot":"","sources":["../src/compact.ts"],"names":[],"mappings":"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"}
|
package/dist/contrast.d.ts
CHANGED
|
@@ -42,6 +42,15 @@ export declare function relativeLuminance(rgb: [number, number, number]): number
|
|
|
42
42
|
* contrastRatio([0,0,0], [255,255,255]) === 21 (±0.01).
|
|
43
43
|
*/
|
|
44
44
|
export declare function contrastRatio(fg: [number, number, number], bg: [number, number, number]): number;
|
|
45
|
+
/**
|
|
46
|
+
* Composite an ordered stack of CSS color strings onto an opaque white base.
|
|
47
|
+
*
|
|
48
|
+
* @param layers - CSS color strings ordered **nearest ancestor first → furthest last**.
|
|
49
|
+
* Each is parsed with parseColor. Fully-transparent layers (a === 0) are skipped.
|
|
50
|
+
* The stack is composited alpha-over from furthest→nearest onto white [255,255,255].
|
|
51
|
+
* @returns An opaque [r, g, b] triple. Empty or all-transparent input → [255,255,255].
|
|
52
|
+
*/
|
|
53
|
+
export declare function compositeBackground(layers: string[]): [number, number, number];
|
|
45
54
|
/**
|
|
46
55
|
* Score a pre-collected snapshot of elements. No browser required.
|
|
47
56
|
*/
|
|
@@ -49,6 +58,7 @@ export declare function auditContrastSnapshot(elements: Array<{
|
|
|
49
58
|
selector: string;
|
|
50
59
|
color: string;
|
|
51
60
|
bgColor: string;
|
|
61
|
+
bgColors?: string[];
|
|
52
62
|
fontPx?: number;
|
|
53
63
|
bold?: boolean;
|
|
54
64
|
text?: string;
|
|
@@ -65,3 +75,25 @@ export declare function auditContrastUrl(url: string, opts?: {
|
|
|
65
75
|
timeoutMs?: number;
|
|
66
76
|
theme?: "light" | "dark";
|
|
67
77
|
}): Promise<ContrastResult>;
|
|
78
|
+
export type ContrastFixDetail = {
|
|
79
|
+
color: string;
|
|
80
|
+
ratio: number;
|
|
81
|
+
direction: "lighter" | "darker";
|
|
82
|
+
};
|
|
83
|
+
export type SuggestContrastFix = {
|
|
84
|
+
fg: string;
|
|
85
|
+
bg: string;
|
|
86
|
+
currentRatio: number;
|
|
87
|
+
targetRatio: number;
|
|
88
|
+
passes: boolean;
|
|
89
|
+
fgFix: ContrastFixDetail | null;
|
|
90
|
+
bgFix: ContrastFixDetail | null;
|
|
91
|
+
reachable: boolean;
|
|
92
|
+
recommendation: string;
|
|
93
|
+
};
|
|
94
|
+
export declare function suggestContrastFix(fg: string, bg: string, opts?: {
|
|
95
|
+
targetRatio?: number;
|
|
96
|
+
level?: "AA" | "AAA";
|
|
97
|
+
fontPx?: number;
|
|
98
|
+
bold?: boolean;
|
|
99
|
+
}): SuggestContrastFix;
|