longevity: il controllo sui colori guarda tutto il foglio, non solo lg-score

Filtrava le regole sul selettore ("solo quelle con lg-score nel nome"): un elenco
di quali regole guardare invecchia appena nasce una classe nuova, ed e' successo
subito con .lg-radar__voce-nome, .lg-radar__intro, .lg-macro__nota (Task 3), mai
controllate perche' non contengono quella stringa. Tolto il filtro sul selettore:
ora si scandisce ogni regola del foglio (che e' interamente prefissato lg- per
costruzione), con un elenco di eccezioni dichiarate (selettore + valore + motivo)
per gli usi legittimi di un colore fuori lista (il #fff del testo sul bottone
pieno d'accento). Verificato rosso con un colore-giudizio iniettato sia su una
classe del radar sia su una del macro-score, verde ripristinato in entrambi i casi.
This commit is contained in:
2026-08-22 14:43:57 +02:00
parent 6630be7a02
commit a56398ea02
+23 -5
View File
@@ -33,12 +33,21 @@ describe('il guscio della piattaforma', () => {
expect(css).not.toMatch(/--lg-ok|--lg-buono|--lg-verde/);
});
it("nelle regole di un punteggio compaiono solo i colori ammessi: l'accento, il tratteggio, il fuori range", () => {
it('in tutto il foglio compaiono solo i colori ammessi, salvo le eccezioni dichiarate', () => {
// Il test sopra cerca nomi vietati: chi scrivesse un verde in esadecimale, o lo
// chiamasse con un nome innocuo (var(--lg-buona-salute)), passerebbe indisturbato.
// Qui si fa il contrario: si elenca ciò che PUò comparire in una regola che riguarda
// un punteggio (selettore con "lg-score"), e qualunque altro colore — letterale
// (esadecimale, rgb(), nome CSS) o var() con un altro nome — è una regressione.
// Qui si fa il contrario: si elenca ciò che PUÒ comparire, e qualunque altro colore —
// letterale (esadecimale, rgb(), nome CSS) o var() con un altro nome — è una
// regressione.
//
// PRIMA questo test filtrava le regole sul selettore ("solo quelle con 'lg-score' nel
// nome"): un elenco di QUALI regole guardare invecchia appena nasce una classe nuova —
// è successo con .lg-radar__voce-nome, .lg-radar__intro, .lg-macro__nota (Task 3): non
// contengono la stringa "lg-score", quindi non venivano MAI controllate, in silenzio.
// Il foglio è interamente prefissato `lg-` per costruzione (verificato dal test sopra):
// non serve scegliere quali regole guardare, si guardano TUTTE, e le eccezioni
// legittime si dichiarano una per una — selettore, valore esatto, motivo — così un
// colore fuori lista entra solo con una decisione visibile, mai con un buco nel filtro.
const css = leggi('src/styles/longevity.css');
const AMMESSI = new Set([
'--c-accent', '--c-accent-dark', // l'accento del sito: l'unica leva per l'intensità
@@ -48,13 +57,21 @@ describe('il guscio della piattaforma', () => {
'--lg-tratteggio', // il perimetro di ciò che non sappiamo
'--lg-fuori-range', // SOLO una misura sospetta, mai un punteggio
]);
// Eccezioni dichiarate: selettore esatto + valore esatto + perché non è un giudizio sul
// punteggio. Ogni riga qui è una decisione presa a vista, non un buco silenzioso.
const ECCEZIONI: { selettore: string; valore: string; motivo: string }[] = [
{
selettore: '.lg-form__nav button:last-child:not(:only-child)',
valore: '#fff',
motivo: "testo bianco per contrasto sul bottone pieno d'accento — non un colore di punteggio",
},
];
const NON_COLORE = /^(transparent|inherit|initial|unset|currentcolor|none)$/i;
const PROP_COLORE = /^(color|background|background-color|border(-\w+)?-color|outline-color|fill|stroke)$/i;
const violazioni: string[] = [];
for (const regola of css.matchAll(/([^{}]+)\{([^{}]*)\}/g)) {
const selettore = regola[1].trim();
if (!/lg-score/i.test(selettore)) continue; // solo le regole che riguardano un punteggio
for (const dich of regola[2].split(';')) {
const due = dich.indexOf(':');
if (due < 0) continue;
@@ -63,6 +80,7 @@ describe('il guscio della piattaforma', () => {
if (!PROP_COLORE.test(prop) || val === '' || NON_COLORE.test(val)) continue;
const varMatch = val.match(/^var\(\s*(--[a-z0-9-]+)\s*(?:,.*)?\)$/i);
if (varMatch && AMMESSI.has(varMatch[1])) continue;
if (ECCEZIONI.some((e) => e.selettore === selettore && e.valore === val)) continue;
violazioni.push(`${selettore} { ${prop}: ${val} }`);
}
}