@hale-bopp/valentino-engine 2.1.0 → 2.3.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 +63 -2
- package/dist/bin/commands/cockpit.d.ts +16 -0
- package/dist/bin/commands/cockpit.d.ts.map +1 -0
- package/dist/bin/commands/cockpit.js +205 -0
- package/dist/bin/commands/cockpit.js.map +1 -0
- package/dist/bin/commands/theme-audit.d.ts +7 -0
- package/dist/bin/commands/theme-audit.d.ts.map +1 -0
- package/dist/bin/commands/theme-audit.js +70 -0
- package/dist/bin/commands/theme-audit.js.map +1 -0
- package/dist/bin/commands/validate.d.ts.map +1 -1
- package/dist/bin/commands/validate.js +94 -1
- package/dist/bin/commands/validate.js.map +1 -1
- package/dist/bin/valentino.js +15 -1
- package/dist/bin/valentino.js.map +1 -1
- package/dist/cockpit-server.d.ts +17 -0
- package/dist/cockpit-server.d.ts.map +1 -0
- package/dist/cockpit-server.js +505 -0
- package/dist/cockpit-server.js.map +1 -0
- package/dist/cockpit-web/index.html +979 -0
- package/dist/core/cockpit-api.d.ts +99 -0
- package/dist/core/cockpit-api.d.ts.map +1 -0
- package/dist/core/cockpit-api.js +269 -0
- package/dist/core/cockpit-api.js.map +1 -0
- package/dist/core/cockpit-repl.d.ts +51 -0
- package/dist/core/cockpit-repl.d.ts.map +1 -0
- package/dist/core/cockpit-repl.js +217 -0
- package/dist/core/cockpit-repl.js.map +1 -0
- package/dist/core/contrast-usage-probe.d.ts +84 -0
- package/dist/core/contrast-usage-probe.d.ts.map +1 -0
- package/dist/core/contrast-usage-probe.js +244 -0
- package/dist/core/contrast-usage-probe.js.map +1 -0
- package/dist/core/contrast-usage-probe.test.d.ts +2 -0
- package/dist/core/contrast-usage-probe.test.d.ts.map +1 -0
- package/dist/core/contrast-usage-probe.test.js +186 -0
- package/dist/core/contrast-usage-probe.test.js.map +1 -0
- package/dist/core/editor.d.ts +80 -0
- package/dist/core/editor.d.ts.map +1 -0
- package/dist/core/editor.js +421 -0
- package/dist/core/editor.js.map +1 -0
- package/dist/core/gallery.d.ts +53 -0
- package/dist/core/gallery.d.ts.map +1 -0
- package/dist/core/gallery.js +123 -0
- package/dist/core/gallery.js.map +1 -0
- package/dist/core/gallery.test.d.ts +2 -0
- package/dist/core/gallery.test.d.ts.map +1 -0
- package/dist/core/gallery.test.js +127 -0
- package/dist/core/gallery.test.js.map +1 -0
- package/dist/core/intent-parser.d.ts +67 -0
- package/dist/core/intent-parser.d.ts.map +1 -0
- package/dist/core/intent-parser.js +485 -0
- package/dist/core/intent-parser.js.map +1 -0
- package/dist/core/openrouter-client.d.ts +38 -0
- package/dist/core/openrouter-client.d.ts.map +1 -0
- package/dist/core/openrouter-client.js +123 -0
- package/dist/core/openrouter-client.js.map +1 -0
- package/dist/core/page-generator.d.ts +85 -0
- package/dist/core/page-generator.d.ts.map +1 -0
- package/dist/core/page-generator.js +353 -0
- package/dist/core/page-generator.js.map +1 -0
- package/dist/core/page-generator.test.d.ts +2 -0
- package/dist/core/page-generator.test.d.ts.map +1 -0
- package/dist/core/page-generator.test.js +138 -0
- package/dist/core/page-generator.test.js.map +1 -0
- package/dist/core/page-status.d.ts +15 -1
- package/dist/core/page-status.d.ts.map +1 -1
- package/dist/core/page-status.js +21 -0
- package/dist/core/page-status.js.map +1 -1
- package/dist/core/project-adapter.d.ts +73 -0
- package/dist/core/project-adapter.d.ts.map +1 -0
- package/dist/core/project-adapter.js +364 -0
- package/dist/core/project-adapter.js.map +1 -0
- package/dist/core/schema-export.d.ts +32 -0
- package/dist/core/schema-export.d.ts.map +1 -0
- package/dist/core/schema-export.js +493 -0
- package/dist/core/schema-export.js.map +1 -0
- package/dist/core/theme-audit.d.ts +104 -0
- package/dist/core/theme-audit.d.ts.map +1 -0
- package/dist/core/theme-audit.js +127 -0
- package/dist/core/theme-audit.js.map +1 -0
- package/dist/core/theme-audit.test.d.ts +2 -0
- package/dist/core/theme-audit.test.d.ts.map +1 -0
- package/dist/core/theme-audit.test.js +198 -0
- package/dist/core/theme-audit.test.js.map +1 -0
- package/dist/core/url-import.d.ts +41 -0
- package/dist/core/url-import.d.ts.map +1 -0
- package/dist/core/url-import.js +207 -0
- package/dist/core/url-import.js.map +1 -0
- package/dist/core/video-import.d.ts +46 -0
- package/dist/core/video-import.d.ts.map +1 -0
- package/dist/core/video-import.js +192 -0
- package/dist/core/video-import.js.map +1 -0
- package/dist/core/visual-import.d.ts +42 -0
- package/dist/core/visual-import.d.ts.map +1 -0
- package/dist/core/visual-import.js +227 -0
- package/dist/core/visual-import.js.map +1 -0
- package/dist/index.d.ts +31 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +31 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp/index.js +32 -0
- package/dist/mcp/index.js.map +1 -1
- package/package.json +10 -4
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Theme Audit — static contrast analysis for theme-packs against surfaces.
|
|
3
|
+
*
|
|
4
|
+
* Crosses every text token in a theme-pack with every Valentino surface
|
|
5
|
+
* background and reports WCAG contrast violations.
|
|
6
|
+
* Pure function, zero DOM, zero fetch.
|
|
7
|
+
*/
|
|
8
|
+
import { type ContrastLevel } from './contrast.js';
|
|
9
|
+
export type SurfaceKind = 'light' | 'dark';
|
|
10
|
+
export type SurfaceDefinition = {
|
|
11
|
+
/** Surface name matching data-surface attribute (e.g. 'default', 'muted') */
|
|
12
|
+
name: string;
|
|
13
|
+
/** Flat background color for contrast calculation (hex). For gradients, use the lightest stop. */
|
|
14
|
+
background: string;
|
|
15
|
+
/** Whether this surface is light or dark — determines which tokens are at risk */
|
|
16
|
+
kind: SurfaceKind;
|
|
17
|
+
};
|
|
18
|
+
export type ThemePackTokens = {
|
|
19
|
+
/** Theme-pack id (e.g. 'accoglienza') */
|
|
20
|
+
id: string;
|
|
21
|
+
/** CSS variable overrides: key = var name, value = color string */
|
|
22
|
+
cssVars: Record<string, string>;
|
|
23
|
+
};
|
|
24
|
+
export type TokenRole = 'text' | 'background' | 'border' | 'accent' | 'unknown';
|
|
25
|
+
export type ThemeAuditViolation = {
|
|
26
|
+
/** CSS variable name (e.g. '--text-secondary') */
|
|
27
|
+
token: string;
|
|
28
|
+
/** Role inferred from token name */
|
|
29
|
+
role: TokenRole;
|
|
30
|
+
/** The color value from the theme-pack */
|
|
31
|
+
value: string;
|
|
32
|
+
/** Surface where the violation occurs */
|
|
33
|
+
surface: string;
|
|
34
|
+
/** Background color of that surface */
|
|
35
|
+
surfaceBackground: string;
|
|
36
|
+
/** Computed contrast ratio */
|
|
37
|
+
ratio: number;
|
|
38
|
+
/** Required minimum ratio */
|
|
39
|
+
required: number;
|
|
40
|
+
/** WCAG level tested */
|
|
41
|
+
level: ContrastLevel;
|
|
42
|
+
};
|
|
43
|
+
export type ThemeAuditResult = {
|
|
44
|
+
themePackId: string;
|
|
45
|
+
level: ContrastLevel;
|
|
46
|
+
violations: ThemeAuditViolation[];
|
|
47
|
+
checked: number;
|
|
48
|
+
passed: boolean;
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Default Valentino surface backgrounds.
|
|
52
|
+
* For gradients, we use the lightest color (worst-case for dark text)
|
|
53
|
+
* or darkest color (worst-case for light text).
|
|
54
|
+
*/
|
|
55
|
+
export declare const VALENTINO_SURFACES: SurfaceDefinition[];
|
|
56
|
+
export declare function inferTokenRole(varName: string): TokenRole;
|
|
57
|
+
/**
|
|
58
|
+
* Audit a theme-pack's text tokens against all surfaces.
|
|
59
|
+
*
|
|
60
|
+
* For each text token (--text-*, --font-* excluded since fonts aren't colors):
|
|
61
|
+
* - Check contrast on every light surface (text on light bg)
|
|
62
|
+
* - Check contrast on every dark surface (text on dark bg)
|
|
63
|
+
*
|
|
64
|
+
* Accent tokens are also checked since they may be used as interactive text.
|
|
65
|
+
*
|
|
66
|
+
* If `foundationTokens` is provided, tokens NOT overridden by the theme-pack
|
|
67
|
+
* are checked using the foundation (CSS :root) value. This catches the case
|
|
68
|
+
* where the base theme defines a color that fails on a surface, and no
|
|
69
|
+
* theme-pack overrides it.
|
|
70
|
+
*/
|
|
71
|
+
export declare function auditThemePack(themePack: ThemePackTokens, options?: {
|
|
72
|
+
surfaces?: SurfaceDefinition[];
|
|
73
|
+
level?: ContrastLevel;
|
|
74
|
+
/** Foundation :root tokens (base theme). Tokens not in the theme-pack are checked from here. */
|
|
75
|
+
foundationTokens?: Record<string, string>;
|
|
76
|
+
}): ThemeAuditResult;
|
|
77
|
+
export type RegistryViolation = {
|
|
78
|
+
token: string;
|
|
79
|
+
themePackId: string;
|
|
80
|
+
reason: string;
|
|
81
|
+
};
|
|
82
|
+
/**
|
|
83
|
+
* Validate that a theme-pack only overrides tokens allowed by the registry
|
|
84
|
+
* and that overridden values are parseable colors.
|
|
85
|
+
*/
|
|
86
|
+
export declare function validateThemePackAgainstRegistry(themePack: ThemePackTokens, registry: {
|
|
87
|
+
mutableTokens: string[];
|
|
88
|
+
}): RegistryViolation[];
|
|
89
|
+
export type BatchAuditResult = {
|
|
90
|
+
results: ThemeAuditResult[];
|
|
91
|
+
registryViolations: RegistryViolation[];
|
|
92
|
+
allPassed: boolean;
|
|
93
|
+
};
|
|
94
|
+
/**
|
|
95
|
+
* Audit multiple theme-packs at once, optionally validating against the registry.
|
|
96
|
+
*/
|
|
97
|
+
export declare function auditThemePacks(themePacks: ThemePackTokens[], options?: {
|
|
98
|
+
surfaces?: SurfaceDefinition[];
|
|
99
|
+
level?: ContrastLevel;
|
|
100
|
+
registry?: {
|
|
101
|
+
mutableTokens: string[];
|
|
102
|
+
};
|
|
103
|
+
}): BatchAuditResult;
|
|
104
|
+
//# sourceMappingURL=theme-audit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"theme-audit.d.ts","sourceRoot":"","sources":["../../src/core/theme-audit.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAiC,KAAK,aAAa,EAAE,MAAM,eAAe,CAAC;AAIlF,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,MAAM,CAAC;AAE3C,MAAM,MAAM,iBAAiB,GAAG;IAC5B,6EAA6E;IAC7E,IAAI,EAAE,MAAM,CAAC;IACb,kGAAkG;IAClG,UAAU,EAAE,MAAM,CAAC;IACnB,kFAAkF;IAClF,IAAI,EAAE,WAAW,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC1B,yCAAyC;IACzC,EAAE,EAAE,MAAM,CAAC;IACX,mEAAmE;IACnE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACnC,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,YAAY,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEhF,MAAM,MAAM,mBAAmB,GAAG;IAC9B,kDAAkD;IAClD,KAAK,EAAE,MAAM,CAAC;IACd,oCAAoC;IACpC,IAAI,EAAE,SAAS,CAAC;IAChB,0CAA0C;IAC1C,KAAK,EAAE,MAAM,CAAC;IACd,yCAAyC;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,uCAAuC;IACvC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,8BAA8B;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,6BAA6B;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,wBAAwB;IACxB,KAAK,EAAE,aAAa,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,aAAa,CAAC;IACrB,UAAU,EAAE,mBAAmB,EAAE,CAAC;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;CACnB,CAAC;AAIF;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,EAAE,iBAAiB,EAQjD,CAAC;AAIF,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAWzD;AAID;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAC1B,SAAS,EAAE,eAAe,EAC1B,OAAO,CAAC,EAAE;IACN,QAAQ,CAAC,EAAE,iBAAiB,EAAE,CAAC;IAC/B,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,gGAAgG;IAChG,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC7C,GACF,gBAAgB,CA+ClB;AAID,MAAM,MAAM,iBAAiB,GAAG;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF;;;GAGG;AACH,wBAAgB,gCAAgC,CAC5C,SAAS,EAAE,eAAe,EAC1B,QAAQ,EAAE;IAAE,aAAa,EAAE,MAAM,EAAE,CAAA;CAAE,GACtC,iBAAiB,EAAE,CAerB;AAID,MAAM,MAAM,gBAAgB,GAAG;IAC3B,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAC5B,kBAAkB,EAAE,iBAAiB,EAAE,CAAC;IACxC,SAAS,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF;;GAEG;AACH,wBAAgB,eAAe,CAC3B,UAAU,EAAE,eAAe,EAAE,EAC7B,OAAO,CAAC,EAAE;IACN,QAAQ,CAAC,EAAE,iBAAiB,EAAE,CAAC;IAC/B,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,QAAQ,CAAC,EAAE;QAAE,aAAa,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;CAC1C,GACF,gBAAgB,CAWlB"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Theme Audit — static contrast analysis for theme-packs against surfaces.
|
|
3
|
+
*
|
|
4
|
+
* Crosses every text token in a theme-pack with every Valentino surface
|
|
5
|
+
* background and reports WCAG contrast violations.
|
|
6
|
+
* Pure function, zero DOM, zero fetch.
|
|
7
|
+
*/
|
|
8
|
+
import { checkWcagContrast, parseColor } from './contrast.js';
|
|
9
|
+
// ── Default surface map ──────────────────────────────────────────────────────
|
|
10
|
+
/**
|
|
11
|
+
* Default Valentino surface backgrounds.
|
|
12
|
+
* For gradients, we use the lightest color (worst-case for dark text)
|
|
13
|
+
* or darkest color (worst-case for light text).
|
|
14
|
+
*/
|
|
15
|
+
export const VALENTINO_SURFACES = [
|
|
16
|
+
{ name: 'default', background: '#ffffff', kind: 'light' },
|
|
17
|
+
{ name: 'muted', background: '#f8fafc', kind: 'light' },
|
|
18
|
+
{ name: 'accent', background: '#fff7fb', kind: 'light' },
|
|
19
|
+
{ name: 'reading-light', background: '#ffffff', kind: 'light' },
|
|
20
|
+
{ name: 'ops-light', background: '#f8fafc', kind: 'light' },
|
|
21
|
+
{ name: 'dark', background: '#020617', kind: 'dark' },
|
|
22
|
+
{ name: 'shell-dark', background: '#020617', kind: 'dark' },
|
|
23
|
+
];
|
|
24
|
+
// ── Token role inference ─────────────────────────────────────────────────────
|
|
25
|
+
export function inferTokenRole(varName) {
|
|
26
|
+
const lower = varName.toLowerCase();
|
|
27
|
+
if (lower.includes('text') || lower.includes('font') || lower.includes('color'))
|
|
28
|
+
return 'text';
|
|
29
|
+
if (lower.includes('bg') || lower.includes('background') || lower.includes('surface'))
|
|
30
|
+
return 'background';
|
|
31
|
+
if (lower.includes('border') || lower.includes('glass-border'))
|
|
32
|
+
return 'border';
|
|
33
|
+
if (lower.includes('accent') || lower.includes('gold') || lower.includes('cyan') || lower.includes('violet'))
|
|
34
|
+
return 'accent';
|
|
35
|
+
return 'unknown';
|
|
36
|
+
}
|
|
37
|
+
// ── Core audit function ──────────────────────────────────────────────────────
|
|
38
|
+
/**
|
|
39
|
+
* Audit a theme-pack's text tokens against all surfaces.
|
|
40
|
+
*
|
|
41
|
+
* For each text token (--text-*, --font-* excluded since fonts aren't colors):
|
|
42
|
+
* - Check contrast on every light surface (text on light bg)
|
|
43
|
+
* - Check contrast on every dark surface (text on dark bg)
|
|
44
|
+
*
|
|
45
|
+
* Accent tokens are also checked since they may be used as interactive text.
|
|
46
|
+
*
|
|
47
|
+
* If `foundationTokens` is provided, tokens NOT overridden by the theme-pack
|
|
48
|
+
* are checked using the foundation (CSS :root) value. This catches the case
|
|
49
|
+
* where the base theme defines a color that fails on a surface, and no
|
|
50
|
+
* theme-pack overrides it.
|
|
51
|
+
*/
|
|
52
|
+
export function auditThemePack(themePack, options) {
|
|
53
|
+
const surfaces = options?.surfaces ?? VALENTINO_SURFACES;
|
|
54
|
+
const level = options?.level ?? 'AA';
|
|
55
|
+
const violations = [];
|
|
56
|
+
let checked = 0;
|
|
57
|
+
// Merge: theme-pack overrides foundation
|
|
58
|
+
const effectiveTokens = {
|
|
59
|
+
...(options?.foundationTokens ?? {}),
|
|
60
|
+
...themePack.cssVars,
|
|
61
|
+
};
|
|
62
|
+
for (const [varName, value] of Object.entries(effectiveTokens)) {
|
|
63
|
+
const role = inferTokenRole(varName);
|
|
64
|
+
// Only check tokens that are used as foreground text/accent
|
|
65
|
+
if (role !== 'text' && role !== 'accent')
|
|
66
|
+
continue;
|
|
67
|
+
// Skip non-color values (e.g. font-family)
|
|
68
|
+
if (!parseColor(value))
|
|
69
|
+
continue;
|
|
70
|
+
for (const surface of surfaces) {
|
|
71
|
+
checked++;
|
|
72
|
+
const result = checkWcagContrast(value, surface.background, level);
|
|
73
|
+
if (!result.passes) {
|
|
74
|
+
violations.push({
|
|
75
|
+
token: varName,
|
|
76
|
+
role,
|
|
77
|
+
value,
|
|
78
|
+
surface: surface.name,
|
|
79
|
+
surfaceBackground: surface.background,
|
|
80
|
+
ratio: result.ratio,
|
|
81
|
+
required: level === 'AAA' ? 7.0 : 4.5,
|
|
82
|
+
level,
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return {
|
|
88
|
+
themePackId: themePack.id,
|
|
89
|
+
level,
|
|
90
|
+
violations,
|
|
91
|
+
checked,
|
|
92
|
+
passed: violations.length === 0,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Validate that a theme-pack only overrides tokens allowed by the registry
|
|
97
|
+
* and that overridden values are parseable colors.
|
|
98
|
+
*/
|
|
99
|
+
export function validateThemePackAgainstRegistry(themePack, registry) {
|
|
100
|
+
const violations = [];
|
|
101
|
+
const allowed = new Set(registry.mutableTokens);
|
|
102
|
+
for (const varName of Object.keys(themePack.cssVars)) {
|
|
103
|
+
if (!allowed.has(varName)) {
|
|
104
|
+
violations.push({
|
|
105
|
+
token: varName,
|
|
106
|
+
themePackId: themePack.id,
|
|
107
|
+
reason: `Token "${varName}" is not in the registry's mutableTokens list`,
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return violations;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Audit multiple theme-packs at once, optionally validating against the registry.
|
|
115
|
+
*/
|
|
116
|
+
export function auditThemePacks(themePacks, options) {
|
|
117
|
+
const results = themePacks.map(tp => auditThemePack(tp, options));
|
|
118
|
+
const registryViolations = options?.registry
|
|
119
|
+
? themePacks.flatMap(tp => validateThemePackAgainstRegistry(tp, options.registry))
|
|
120
|
+
: [];
|
|
121
|
+
return {
|
|
122
|
+
results,
|
|
123
|
+
registryViolations,
|
|
124
|
+
allPassed: results.every(r => r.passed) && registryViolations.length === 0,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=theme-audit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"theme-audit.js","sourceRoot":"","sources":["../../src/core/theme-audit.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"theme-audit.test.d.ts","sourceRoot":"","sources":["../../src/core/theme-audit.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { auditThemePack, auditThemePacks, validateThemePackAgainstRegistry, inferTokenRole, VALENTINO_SURFACES, } from './theme-audit.js';
|
|
3
|
+
// ── inferTokenRole ───────────────────────────────────────────────────────────
|
|
4
|
+
describe('inferTokenRole', () => {
|
|
5
|
+
it('classifies --text-secondary as text', () => {
|
|
6
|
+
expect(inferTokenRole('--text-secondary')).toBe('text');
|
|
7
|
+
});
|
|
8
|
+
it('classifies --text-primary as text', () => {
|
|
9
|
+
expect(inferTokenRole('--text-primary')).toBe('text');
|
|
10
|
+
});
|
|
11
|
+
it('classifies --text-sovereign-gold as text', () => {
|
|
12
|
+
expect(inferTokenRole('--text-sovereign-gold')).toBe('text');
|
|
13
|
+
});
|
|
14
|
+
it('classifies --accent-neural-cyan as accent', () => {
|
|
15
|
+
expect(inferTokenRole('--accent-neural-cyan')).toBe('accent');
|
|
16
|
+
});
|
|
17
|
+
it('classifies --bg-deep-void as background', () => {
|
|
18
|
+
expect(inferTokenRole('--bg-deep-void')).toBe('background');
|
|
19
|
+
});
|
|
20
|
+
it('classifies --glass-border as border', () => {
|
|
21
|
+
expect(inferTokenRole('--glass-border')).toBe('border');
|
|
22
|
+
});
|
|
23
|
+
it('classifies --font-family as text', () => {
|
|
24
|
+
expect(inferTokenRole('--font-family')).toBe('text');
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
// ── auditThemePack ──────────────────────────────────────────────────────────
|
|
28
|
+
describe('auditThemePack', () => {
|
|
29
|
+
const accoglienza = {
|
|
30
|
+
id: 'accoglienza',
|
|
31
|
+
cssVars: {
|
|
32
|
+
'--bg-deep-void': '#0b1221',
|
|
33
|
+
'--text-sovereign-gold': '#fbbf24',
|
|
34
|
+
'--accent-neural-cyan': '#60a5fa',
|
|
35
|
+
'--glass-border': 'rgba(96, 165, 250, 0.22)',
|
|
36
|
+
'--glass-bg': 'rgba(11, 18, 33, 0.72)',
|
|
37
|
+
'--text-primary': '#f8fafc',
|
|
38
|
+
'--text-secondary': '#d1d5db',
|
|
39
|
+
'--font-family': 'system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif',
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
it('detects --text-secondary failing on light surfaces', () => {
|
|
43
|
+
const result = auditThemePack(accoglienza);
|
|
44
|
+
const textSecondaryFails = result.violations.filter(v => v.token === '--text-secondary');
|
|
45
|
+
expect(textSecondaryFails.length).toBeGreaterThan(0);
|
|
46
|
+
// Should fail on all 5 light surfaces
|
|
47
|
+
const lightSurfaces = textSecondaryFails.map(v => v.surface);
|
|
48
|
+
expect(lightSurfaces).toContain('default');
|
|
49
|
+
expect(lightSurfaces).toContain('muted');
|
|
50
|
+
});
|
|
51
|
+
it('detects --text-primary failing on light surfaces (light text on white)', () => {
|
|
52
|
+
const result = auditThemePack(accoglienza);
|
|
53
|
+
const textPrimaryFails = result.violations.filter(v => v.token === '--text-primary');
|
|
54
|
+
// #f8fafc on #ffffff → ~1.01:1, should fail
|
|
55
|
+
expect(textPrimaryFails.length).toBeGreaterThan(0);
|
|
56
|
+
});
|
|
57
|
+
it('passes a well-configured dark-only theme-pack on dark surfaces only', () => {
|
|
58
|
+
const result = auditThemePack(accoglienza, {
|
|
59
|
+
surfaces: VALENTINO_SURFACES.filter(s => s.kind === 'dark'),
|
|
60
|
+
});
|
|
61
|
+
// --text-primary (#f8fafc) and --text-secondary (#d1d5db) should pass on dark (#020617)
|
|
62
|
+
const textFails = result.violations.filter(v => v.token.startsWith('--text'));
|
|
63
|
+
expect(textFails).toEqual([]);
|
|
64
|
+
});
|
|
65
|
+
it('skips non-color values like font-family', () => {
|
|
66
|
+
const result = auditThemePack(accoglienza);
|
|
67
|
+
const fontFails = result.violations.filter(v => v.token === '--font-family');
|
|
68
|
+
expect(fontFails).toEqual([]);
|
|
69
|
+
});
|
|
70
|
+
it('skips background/border tokens', () => {
|
|
71
|
+
const result = auditThemePack(accoglienza);
|
|
72
|
+
const bgFails = result.violations.filter(v => v.token === '--bg-deep-void');
|
|
73
|
+
const borderFails = result.violations.filter(v => v.token === '--glass-border');
|
|
74
|
+
expect(bgFails).toEqual([]);
|
|
75
|
+
expect(borderFails).toEqual([]);
|
|
76
|
+
});
|
|
77
|
+
it('supports AAA level', () => {
|
|
78
|
+
const result = auditThemePack(accoglienza, { level: 'AAA' });
|
|
79
|
+
// AAA requires 7.0:1, should have more violations than AA
|
|
80
|
+
const aaResult = auditThemePack(accoglienza, { level: 'AA' });
|
|
81
|
+
expect(result.violations.length).toBeGreaterThanOrEqual(aaResult.violations.length);
|
|
82
|
+
});
|
|
83
|
+
it('reports correct ratio and required values', () => {
|
|
84
|
+
const result = auditThemePack(accoglienza);
|
|
85
|
+
for (const v of result.violations) {
|
|
86
|
+
expect(v.ratio).toBeGreaterThan(0);
|
|
87
|
+
expect(v.required).toBe(4.5);
|
|
88
|
+
expect(v.level).toBe('AA');
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
it('passes a theme-pack with high-contrast text tokens', () => {
|
|
92
|
+
const highContrast = {
|
|
93
|
+
id: 'high-contrast',
|
|
94
|
+
cssVars: {
|
|
95
|
+
'--text-primary': '#000000',
|
|
96
|
+
'--text-secondary': '#333333',
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
const result = auditThemePack(highContrast);
|
|
100
|
+
// #000000 and #333333 on any bg should pass (or at worst #333333 on dark)
|
|
101
|
+
const lightFails = result.violations.filter(v => VALENTINO_SURFACES.find(s => s.name === v.surface)?.kind === 'light');
|
|
102
|
+
expect(lightFails).toEqual([]);
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
// ── validateThemePackAgainstRegistry ─────────────────────────────────────────
|
|
106
|
+
describe('validateThemePackAgainstRegistry', () => {
|
|
107
|
+
const registry = {
|
|
108
|
+
mutableTokens: [
|
|
109
|
+
'--bg-deep-void', '--text-sovereign-gold', '--accent-neural-cyan',
|
|
110
|
+
'--glass-border', '--glass-bg', '--text-primary', '--text-secondary',
|
|
111
|
+
'--font-family',
|
|
112
|
+
],
|
|
113
|
+
};
|
|
114
|
+
it('passes when all tokens are in the allowed list', () => {
|
|
115
|
+
const tp = {
|
|
116
|
+
id: 'test',
|
|
117
|
+
cssVars: { '--text-primary': '#000', '--text-secondary': '#333' },
|
|
118
|
+
};
|
|
119
|
+
expect(validateThemePackAgainstRegistry(tp, registry)).toEqual([]);
|
|
120
|
+
});
|
|
121
|
+
it('reports unauthorized tokens', () => {
|
|
122
|
+
const tp = {
|
|
123
|
+
id: 'rogue',
|
|
124
|
+
cssVars: { '--text-primary': '#000', '--custom-sneaky': '#f00' },
|
|
125
|
+
};
|
|
126
|
+
const violations = validateThemePackAgainstRegistry(tp, registry);
|
|
127
|
+
expect(violations).toHaveLength(1);
|
|
128
|
+
expect(violations[0].token).toBe('--custom-sneaky');
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
// ── foundationTokens (base theme fallback) ──────────────────────────────────
|
|
132
|
+
describe('auditThemePack with foundationTokens', () => {
|
|
133
|
+
const foundation = {
|
|
134
|
+
'--text-primary': '#f8fafc',
|
|
135
|
+
'--text-secondary': '#cbd5e1',
|
|
136
|
+
'--accent-neural-cyan': '#0cd6c7',
|
|
137
|
+
};
|
|
138
|
+
it('checks foundation tokens when no theme-pack overrides them', () => {
|
|
139
|
+
const emptyPack = { id: 'empty', cssVars: {} };
|
|
140
|
+
const result = auditThemePack(emptyPack, { foundationTokens: foundation });
|
|
141
|
+
// --text-primary (#f8fafc) and --text-secondary (#cbd5e1) fail on light
|
|
142
|
+
const lightFails = result.violations.filter(v => VALENTINO_SURFACES.find(s => s.name === v.surface)?.kind === 'light');
|
|
143
|
+
expect(lightFails.length).toBeGreaterThan(0);
|
|
144
|
+
});
|
|
145
|
+
it('theme-pack override takes precedence over foundation', () => {
|
|
146
|
+
const overridePack = {
|
|
147
|
+
id: 'override',
|
|
148
|
+
cssVars: { '--text-secondary': '#333333' },
|
|
149
|
+
};
|
|
150
|
+
const result = auditThemePack(overridePack, { foundationTokens: foundation });
|
|
151
|
+
// --text-secondary is now #333333 (from pack), not #cbd5e1 (from foundation)
|
|
152
|
+
const textSecLight = result.violations.filter(v => v.token === '--text-secondary' && VALENTINO_SURFACES.find(s => s.name === v.surface)?.kind === 'light');
|
|
153
|
+
expect(textSecLight).toEqual([]);
|
|
154
|
+
});
|
|
155
|
+
it('foundation tokens not in theme-pack are still checked', () => {
|
|
156
|
+
const partialPack = {
|
|
157
|
+
id: 'partial',
|
|
158
|
+
cssVars: { '--text-secondary': '#333333' },
|
|
159
|
+
};
|
|
160
|
+
const result = auditThemePack(partialPack, { foundationTokens: foundation });
|
|
161
|
+
// --text-primary (#f8fafc from foundation) still fails on light
|
|
162
|
+
const textPrimaryFails = result.violations.filter(v => v.token === '--text-primary');
|
|
163
|
+
expect(textPrimaryFails.length).toBeGreaterThan(0);
|
|
164
|
+
});
|
|
165
|
+
it('checked count includes both foundation and theme-pack tokens', () => {
|
|
166
|
+
const emptyPack = { id: 'empty', cssVars: {} };
|
|
167
|
+
const result = auditThemePack(emptyPack, { foundationTokens: foundation });
|
|
168
|
+
// 3 tokens × 7 surfaces = 21 checks
|
|
169
|
+
expect(result.checked).toBe(21);
|
|
170
|
+
});
|
|
171
|
+
});
|
|
172
|
+
// ── auditThemePacks (batch) ─────────────────────────────────────────────────
|
|
173
|
+
describe('auditThemePacks', () => {
|
|
174
|
+
it('audits multiple theme-packs and aggregates results', () => {
|
|
175
|
+
const packs = [
|
|
176
|
+
{ id: 'a', cssVars: { '--text-secondary': '#cbd5e1' } },
|
|
177
|
+
{ id: 'b', cssVars: { '--text-secondary': '#333333' } },
|
|
178
|
+
];
|
|
179
|
+
const result = auditThemePacks(packs);
|
|
180
|
+
expect(result.results).toHaveLength(2);
|
|
181
|
+
// Pack 'a' should fail on light, pack 'b' should pass on light
|
|
182
|
+
expect(result.results[0].passed).toBe(false);
|
|
183
|
+
// Pack 'b' #333333 on dark (#020617) might also fail, so just check light violations
|
|
184
|
+
const bLightViolations = result.results[1].violations.filter(v => VALENTINO_SURFACES.find(s => s.name === v.surface)?.kind === 'light');
|
|
185
|
+
expect(bLightViolations).toEqual([]);
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
// ── VALENTINO_SURFACES ──────────────────────────────────────────────────────
|
|
189
|
+
describe('VALENTINO_SURFACES', () => {
|
|
190
|
+
it('has 7 surfaces', () => {
|
|
191
|
+
expect(VALENTINO_SURFACES).toHaveLength(7);
|
|
192
|
+
});
|
|
193
|
+
it('has 5 light and 2 dark surfaces', () => {
|
|
194
|
+
expect(VALENTINO_SURFACES.filter(s => s.kind === 'light')).toHaveLength(5);
|
|
195
|
+
expect(VALENTINO_SURFACES.filter(s => s.kind === 'dark')).toHaveLength(2);
|
|
196
|
+
});
|
|
197
|
+
});
|
|
198
|
+
//# sourceMappingURL=theme-audit.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"theme-audit.test.js","sourceRoot":"","sources":["../../src/core/theme-audit.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* URL Import — Fetch web page → screenshot → PageSpecV1.
|
|
3
|
+
* Feature #784 (Il Sarto Copia), PBI #786.
|
|
4
|
+
*
|
|
5
|
+
* Two modes:
|
|
6
|
+
* - Playwright mode: headless browser screenshot → vision LLM (best quality)
|
|
7
|
+
* - HTML mode: fetch HTML → LLM text analysis (fallback, no Playwright needed)
|
|
8
|
+
*
|
|
9
|
+
* Zero hard dependencies on Playwright — dynamic import, graceful fallback.
|
|
10
|
+
*/
|
|
11
|
+
import type { VisionLlmCallback, VisualImportResult, VisualImportOptions } from './visual-import.js';
|
|
12
|
+
export type UrlImportResult = VisualImportResult & {
|
|
13
|
+
mode: 'playwright' | 'html-fallback';
|
|
14
|
+
url: string;
|
|
15
|
+
/** Page title extracted from HTML */
|
|
16
|
+
pageTitle?: string;
|
|
17
|
+
};
|
|
18
|
+
export type UrlImportOptions = VisualImportOptions & {
|
|
19
|
+
/** Viewport width for screenshot (default: 1440) */
|
|
20
|
+
viewportWidth?: number;
|
|
21
|
+
/** Viewport height for screenshot (default: 900) */
|
|
22
|
+
viewportHeight?: number;
|
|
23
|
+
/** Wait time in ms after page load (default: 2000) */
|
|
24
|
+
waitAfterLoad?: number;
|
|
25
|
+
/** Force HTML fallback even if Playwright is available */
|
|
26
|
+
forceHtmlFallback?: boolean;
|
|
27
|
+
};
|
|
28
|
+
export type HtmlLlmCallback = (systemPrompt: string, userPrompt: string) => Promise<string>;
|
|
29
|
+
/**
|
|
30
|
+
* Import a web page by URL → PageSpecV1.
|
|
31
|
+
*
|
|
32
|
+
* Tries Playwright screenshot first (best quality).
|
|
33
|
+
* Falls back to HTML fetch + LLM text analysis.
|
|
34
|
+
*
|
|
35
|
+
* @param url - The web page URL to import
|
|
36
|
+
* @param visionLlm - Vision LLM callback (for screenshot mode)
|
|
37
|
+
* @param htmlLlm - Text LLM callback (for HTML fallback mode)
|
|
38
|
+
* @param options - Import options
|
|
39
|
+
*/
|
|
40
|
+
export declare function importFromUrl(url: string, visionLlm: VisionLlmCallback, htmlLlm: HtmlLlmCallback, options: UrlImportOptions): Promise<UrlImportResult>;
|
|
41
|
+
//# sourceMappingURL=url-import.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"url-import.d.ts","sourceRoot":"","sources":["../../src/core/url-import.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,KAAK,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAQrG,MAAM,MAAM,eAAe,GAAG,kBAAkB,GAAG;IAC/C,IAAI,EAAE,YAAY,GAAG,eAAe,CAAC;IACrC,GAAG,EAAE,MAAM,CAAC;IACZ,qCAAqC;IACrC,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG,mBAAmB,GAAG;IACjD,oDAAoD;IACpD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,oDAAoD;IACpD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,sDAAsD;IACtD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,0DAA0D;IAC1D,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC/B,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG,CAC1B,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,KACjB,OAAO,CAAC,MAAM,CAAC,CAAC;AA+LrB;;;;;;;;;;GAUG;AACH,wBAAsB,aAAa,CAC/B,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,iBAAiB,EAC5B,OAAO,EAAE,eAAe,EACxB,OAAO,EAAE,gBAAgB,GAC1B,OAAO,CAAC,eAAe,CAAC,CAwB1B"}
|