Validate Eidos color role slots

active-uix
dev 5 months ago
parent b48a6c48bf
commit 546ad40251

@ -38,10 +38,12 @@ Actualizacion Eidos ecosystem 2026-05-16:
- Grupos semanticos de color (`surface`, `content`, `border`, `focus`) quedan - Grupos semanticos de color (`surface`, `content`, `border`, `focus`) quedan
cerrados con key sets canonicos y valores no vacios antes de generar tokens cerrados con key sets canonicos y valores no vacios antes de generar tokens
de theme. de theme.
- Overrides de `semantics.color.roles.*.slots` quedan validados: solo slots
canonicos y pasos `1..12`.
- Validado: - Validado:
- `npx vitest run src/uix/eidos/active-eidos-config.test.ts` -> 32 tests OK. - `npx vitest run src/uix/eidos/active-eidos-config.test.ts` -> 33 tests OK.
- `npx vitest run src/uix/eidos/active-eidos.test.ts` -> 19 tests OK. - `npx vitest run src/uix/eidos/active-eidos.test.ts` -> 19 tests OK.
- `npx vitest run src/uix/eidos` -> 7 archivos, 72 tests OK. - `npx vitest run src/uix/eidos` -> 7 archivos, 73 tests OK.
- `npm run check` -> 0 errores, 0 warnings. - `npm run check` -> 0 errores, 0 warnings.
Actualizacion permutation runner 2026-05-16: Actualizacion permutation runner 2026-05-16:

@ -581,6 +581,28 @@ describe('ActiveEidos config', () => {
) )
}) })
it('validates semantic color role slot overrides', () => {
const cfg = structuredClone(THEME_BASE_OPTIONS)
;(cfg.semantics.color.roles as unknown as Record<string, unknown>).primary = {
scale: 'purple',
slots: {
solid: '13',
madeUp: '9'
}
}
const report = createEidos(cfg).validate()
expect(report.ok).toBe(false)
expect(
report.issues.some((issue) => issue.path === 'semantics.color.roles.primary.slots.solid')
).toBe(true)
expect(
report.issues.some((issue) => issue.path === 'semantics.color.roles.primary.slots.madeUp')
).toBe(true)
})
it('validates CSS-facing theme and color scale keys', () => { it('validates CSS-facing theme and color scale keys', () => {
const cfg = structuredClone(THEME_BASE_OPTIONS) const cfg = structuredClone(THEME_BASE_OPTIONS)

@ -4,6 +4,7 @@ import {
BORDER_STYLE_KEYS, BORDER_STYLE_KEYS,
BORDER_WIDTH_KEYS, BORDER_WIDTH_KEYS,
COLOR_ROLES, COLOR_ROLES,
COLOR_ROLE_SLOTS,
COLOR_SCALE_STEPS, COLOR_SCALE_STEPS,
CONTAINER_WIDTH_KEYS, CONTAINER_WIDTH_KEYS,
CONTENT_COLOR_KEYS, CONTENT_COLOR_KEYS,
@ -55,6 +56,8 @@ const BORDER_WIDTH_KEY_SET = new Set<string>(BORDER_WIDTH_KEYS)
const BORDER_STYLE_KEY_SET = new Set<string>(BORDER_STYLE_KEYS) const BORDER_STYLE_KEY_SET = new Set<string>(BORDER_STYLE_KEYS)
const BORDER_COLOR_KEY_SET = new Set<string>(BORDER_COLOR_KEYS) const BORDER_COLOR_KEY_SET = new Set<string>(BORDER_COLOR_KEYS)
const CONTENT_COLOR_KEY_SET = new Set<string>(CONTENT_COLOR_KEYS) const CONTENT_COLOR_KEY_SET = new Set<string>(CONTENT_COLOR_KEYS)
const COLOR_ROLE_SLOT_SET = new Set<string>(COLOR_ROLE_SLOTS)
const COLOR_SCALE_STEP_SET = new Set<string>(COLOR_SCALE_STEPS)
const CONTAINER_WIDTH_KEY_SET = new Set<string>(CONTAINER_WIDTH_KEYS) const CONTAINER_WIDTH_KEY_SET = new Set<string>(CONTAINER_WIDTH_KEYS)
const CONTENT_WIDTH_KEY_SET = new Set<string>(CONTENT_WIDTH_KEYS) const CONTENT_WIDTH_KEY_SET = new Set<string>(CONTENT_WIDTH_KEYS)
const DENSITY_KEY_SET = new Set<string>(DENSITY_KEYS) const DENSITY_KEY_SET = new Set<string>(DENSITY_KEYS)
@ -454,6 +457,14 @@ function validateColorRole(
return return
} }
if (roleDef !== undefined && typeof roleDef !== 'string' && !isPlainRecord(roleDef)) {
issues.push({
path,
message: 'color role definition must be a scale name or plain object'
})
return
}
const scaleName = resolveRoleScaleName(roleDef) const scaleName = resolveRoleScaleName(roleDef)
if (!scaleName) { if (!scaleName) {
issues.push({ issues.push({
@ -463,6 +474,10 @@ function validateColorRole(
return return
} }
if (typeof roleDef !== 'string' && roleDef?.slots !== undefined) {
validateColorRoleSlots(`${path}.slots`, roleDef.slots, issues)
}
const themeEntries = Object.entries(themes) const themeEntries = Object.entries(themes)
if (themeEntries.length === 0) { if (themeEntries.length === 0) {
if (!hasOwn(globalScales, scaleName)) { if (!hasOwn(globalScales, scaleName)) {
@ -484,6 +499,36 @@ function validateColorRole(
} }
} }
function validateColorRoleSlots(
path: string,
slots: unknown,
issues: EidosValidationIssue[]
): void {
if (!isPlainRecord(slots)) {
issues.push({
path,
message: 'color role slots must be a plain object'
})
return
}
for (const [slot, step] of Object.entries(slots)) {
if (!COLOR_ROLE_SLOT_SET.has(slot)) {
issues.push({
path: `${path}.${slot}`,
message: 'unknown color role slot'
})
continue
}
if (typeof step !== 'string' || !COLOR_SCALE_STEP_SET.has(step)) {
issues.push({
path: `${path}.${slot}`,
message: 'color role slot must point to a scale step from 1 to 12'
})
}
}
}
function validateTypography(options: EidosConfig, issues: EidosValidationIssue[]): void { function validateTypography(options: EidosConfig, issues: EidosValidationIssue[]): void {
const typography = options.primitives.typography const typography = options.primitives.typography
if (!typography) return if (!typography) return

Loading…
Cancel
Save

Powered by TurnKey Linux.