You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
81 lines
4.5 KiB
81 lines
4.5 KiB
/**
|
|
* Muta-prueba del clasificador `--names` (gramática D-TH.6, firmada 2026-08-20).
|
|
*
|
|
* Un guard que no se ve rojo sobre casos conocidos es un guard que pasa sobre
|
|
* el vacío. Éste asserta contra el catálogo VIVO, así que se actualiza cuando
|
|
* el catálogo se mueve — y esa es su gracia: si alguien reintroduce el idioma
|
|
* viejo, el caso correspondiente cae.
|
|
*/
|
|
import { execSync } from 'node:child_process';
|
|
|
|
const out = execSync('node --import tsx/esm scripts/theming-census.ts --names --json', {
|
|
encoding: 'utf8',
|
|
maxBuffer: 1 << 28
|
|
});
|
|
type F = { component: string; key: string; klass: string; to?: string };
|
|
const all: F[] = JSON.parse(out);
|
|
const find = (c: string, k: string) => all.find((f) => f.component === c && f.key === k);
|
|
|
|
const CASES: Array<[string, string, string, string | undefined, string]> = [
|
|
// [componente, clave, clase esperada, destino, por qué existe el caso]
|
|
|
|
// ── La gramática, ya aplicada ────────────────────────────────────────────
|
|
['accordion', 'trigger-fg', 'ok', undefined, 'tinta = fg: el caso central de la firma'],
|
|
['tabs', 'active-trigger-fg', 'ok', undefined, 'tinta + modificador delante'],
|
|
['tag-group', 'hover-primary-solid-bg', 'ok', undefined, 'modificador delante a nivel receta'],
|
|
['toggle', 'solid-hover-bg', 'ok', undefined, 'ya lo hablaba antes del codemod'],
|
|
['gradient-builder', 'checker-fg', 'ok', undefined, 'la corrección de los 7 ya revisados'],
|
|
|
|
// ── Lo que NO se toca: rol/paleta lleva el modificador DETRÁS por canon ──
|
|
['button', 'primary-solid-hover', 'role-slot', undefined, 'COLOR_ROLE_SLOTS, no deriva'],
|
|
['button', 'palette-solid-hover', 'role-slot', undefined, '24 consumos: romperla habría roto button'],
|
|
['toggle', 'palette-hover', 'role-slot', undefined, 'palette-{slot}'],
|
|
|
|
// ── Exentas firmadas ────────────────────────────────────────────────────
|
|
['accordion', 'trigger-focus-ring-color', 'exempt', undefined, 'espeja la familia del SISTEMA'],
|
|
['aura', 'orb-color-idle', 'exempt', undefined, 'color como sustantivo'],
|
|
['gradient-builder', 'stop-color-title-fg', 'exempt', undefined, 'stop-color ES la parte'],
|
|
|
|
// ── Contextual DETRÁS — la otra mitad de la firma ────────────────────────
|
|
// Sin estos casos el clasificador promovía cualquier valor del morfo y
|
|
// reescribía --sidebar-width-icon (el raíl colapsado) como
|
|
// --sidebar-icon-width (la anchura de un icono).
|
|
['sidebar', 'width-icon', 'ok', undefined, 'modo colapsado: contextual'],
|
|
['radio-group', 'gap-vertical', 'ok', undefined, 'orientación: contextual'],
|
|
['meter', 'indicator-bg-below', 'ok', undefined, 'zona semántica: contextual'],
|
|
['progress', 'indicator-bg-loaded', 'ok', undefined, 'contextual, no interactivo'],
|
|
['drawer', 'footer-margin-top', 'ok', undefined, 'eje dimensional'],
|
|
|
|
// ── Capa de estado: lo decide el VALOR **y** la PROPIEDAD ────────────────
|
|
// El velo de §38 es background-image. Un hover de borde o de tinta no es la
|
|
// capa de estado por muy neutro que sea su valor: es deuda de nombre.
|
|
['splitter', 'handle-bg-hover', 'state-layer', undefined, 'neutro Y pinta fondo'],
|
|
['scroll-area', 'thumb-bg-hover', 'state-layer', undefined, 'neutro Y pinta fondo'],
|
|
['switch', 'track-bg-off-hover', 'state-layer', undefined, 'fondo vía privado, un salto'],
|
|
['field', 'control-border-hover', 'modifier', 'hover-control-border', 'BORDE: no es la capa de estado'],
|
|
['tabs', 'trigger-color-hover', 'both', 'hover-trigger-fg', 'TINTA: no es la capa de estado'],
|
|
['dropdown-menu', 'hover-item-bg', 'ok', undefined, 'acento (--color-primary-element): palette swap legítimo'],
|
|
['pagination', 'hover-selected-bg', 'ok', undefined, 'acento: se renombró, no migra']
|
|
];
|
|
|
|
let bad = 0;
|
|
for (const [c, k, klass, to, why] of CASES) {
|
|
const f = find(c, k);
|
|
if (!f) {
|
|
console.log(` ? ${c}.${k} — NO EXISTE en el catálogo (${why})`);
|
|
bad++;
|
|
continue;
|
|
}
|
|
const okKlass = f.klass === klass;
|
|
const okTo = to === undefined ? !f.to : f.to === to;
|
|
if (okKlass && okTo) console.log(` ok ${c}.${k} → ${f.klass}${f.to ? ' / ' + f.to : ''}`);
|
|
else {
|
|
console.log(
|
|
` XX ${c}.${k} → ${f.klass}${f.to ? ' / ' + f.to : ''} ESPERADO ${klass}${to ? ' / ' + to : ''} (${why})`
|
|
);
|
|
bad++;
|
|
}
|
|
}
|
|
console.log(bad === 0 ? '\nMUTA-PRUEBA VERDE' : `\nMUTA-PRUEBA ROJA: ${bad} caso(s)`);
|
|
process.exit(bad === 0 ? 0 : 1);
|