467 Stellen. Nicht durch einen anderen Strich ersetzt, sondern durch das
Satzzeichen, das an der jeweiligen Stelle richtig ist: Doppelpunkt, wo eine
Erlaeuterung folgt; Komma, wo der Satz weiterlaeuft; Punkt, wo zwei
Hauptsaetze aneinanderstiessen. Ein Halbgeviertstrich waere nur derselbe
Griff mit kuerzerem Strich gewesen.
Regelbasiert ersetzt und danach nachgeprueft, weil eine Regel allein nicht
reicht. Gefunden und einzeln korrigiert:
- Eingeschobene Saetze mit Strichpaar. Nur der oeffnende Strich passte ins
Muster, der schliessende blieb als "—," stehen. Drei Stellen, jetzt mit
Klammern oder als eigener Satz.
- Doppelte Doppelpunkte, wo beide Striche eines Paars zu Doppelpunkten wurden
("Globale Regeln: Schrift, Groessen, Abstaende: kommen aus HiveGrid").
Sieben Stellen in Doku und Oberflaeche, jetzt in Klammern.
- Pfade, denen ein Komma statt eines Doppelpunkts folgte.
- Ausgerichtete Kommentartabellen, in denen der Strich eine Spalte war.
Nicht angefasst: drei Geviertstriche, die keine Prosa sind, sondern
Tabellenplatzhalter fuer "kein Wert" (Trichter, Auftraege, Kunden). Dort ist
der Strich die Angabe selbst; ihn zu entfernen liesse leere Zellen zurueck.
tsc, lint, build, verify:carbon und verify:layout laufen sauber.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QPeZNwSeU7qG3RRCwaxEZX
138 lines
5.0 KiB
JavaScript
138 lines
5.0 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* Prüft chartTheme.ts gegen docs/carbon-referenz.json.
|
|
*
|
|
* Warum das existiert: „Wir halten uns an IBM Carbon" ist eine Behauptung,
|
|
* solange sie niemand nachrechnet. Farbwerte driften beim Kopieren, und die
|
|
* Carbon-Dokumentation widerspricht stellenweise dem ausgelieferten Code.
|
|
* Dieser Prüfer macht aus der Behauptung eine Zusage.
|
|
*
|
|
* Aufruf: npm run verify:carbon
|
|
*/
|
|
|
|
import { readFileSync } from "node:fs";
|
|
import { fileURLToPath } from "node:url";
|
|
import { dirname, join } from "node:path";
|
|
|
|
const wurzel = join(dirname(fileURLToPath(import.meta.url)), "..");
|
|
const referenz = JSON.parse(readFileSync(join(wurzel, "docs/carbon-referenz.json"), "utf8"));
|
|
const theme = readFileSync(join(wurzel, "features/dashboard/utils/chartTheme.ts"), "utf8");
|
|
|
|
const fehler = [];
|
|
const hinweise = [];
|
|
|
|
/** Liest ein exportiertes Array von Hex-Werten aus dem Theme. */
|
|
function hexArray(name) {
|
|
const block = theme.match(new RegExp(`export const ${name}[^=]*=\\s*\\[([\\s\\S]*?)\\]`));
|
|
if (!block) return null;
|
|
return [...block[1].matchAll(/#[0-9a-fA-F]{6}/g)].map((m) => m[0].toLowerCase());
|
|
}
|
|
|
|
/** Liest einen einzelnen Hex-Wert aus einem Objektfeld im Theme. */
|
|
function hexFeld(objekt, feld) {
|
|
const block = theme.match(new RegExp(`export const ${objekt}[^=]*=\\s*\\{([\\s\\S]*?)\\}`));
|
|
if (!block) return null;
|
|
const treffer = block[1].match(new RegExp(`${feld}\\s*:\\s*"(#[0-9a-fA-F]{6})"`));
|
|
return treffer ? treffer[1].toLowerCase() : null;
|
|
}
|
|
|
|
/* -------------------------------------------------- Kategoriale Palette */
|
|
|
|
const palette = hexArray("KATEGORIE_FARBEN");
|
|
const soll = referenz.kategorialePalette.werte.map((w) => w.toLowerCase());
|
|
|
|
if (!palette) {
|
|
fehler.push("KATEGORIE_FARBEN nicht gefunden");
|
|
} else if (palette.length !== soll.length) {
|
|
fehler.push(`Palette hat ${palette.length} Farben, Carbon hat ${soll.length}`);
|
|
} else {
|
|
palette.forEach((farbe, i) => {
|
|
if (farbe !== soll[i]) {
|
|
fehler.push(`Palette Position ${i + 1}: ${farbe}: Carbon: ${soll[i]}`);
|
|
}
|
|
});
|
|
}
|
|
|
|
/* ------------------------------------------------------- Neutrale Werte */
|
|
|
|
const neutraleZuordnung = {
|
|
grid: "gitterlinie",
|
|
achse: "achsenlinie",
|
|
textSekundaer: "achsenbeschriftung",
|
|
text: "textPrimaer",
|
|
};
|
|
|
|
for (const [feld, refName] of Object.entries(neutraleZuordnung)) {
|
|
const ist = hexFeld("CHART", feld);
|
|
const sollWert = referenz.neutraleWerte[refName].wert.toLowerCase();
|
|
if (ist === null) fehler.push(`CHART.${feld} nicht gefunden`);
|
|
else if (ist !== sollWert) {
|
|
fehler.push(
|
|
`CHART.${feld} = ${ist}: Carbon ${referenz.neutraleWerte[refName].token}: ${sollWert}`
|
|
);
|
|
}
|
|
}
|
|
|
|
/* ---------------------------------------------------------------- Tooltip */
|
|
|
|
const tooltipBg = hexFeld("CHART", "tooltipBg");
|
|
const tooltipFg = hexFeld("CHART", "tooltipFg");
|
|
if (tooltipBg !== referenz.tooltip.hintergrund.wert.toLowerCase()) {
|
|
fehler.push(
|
|
`CHART.tooltipBg = ${tooltipBg}: Carbon ${referenz.tooltip.hintergrund.token}: ${referenz.tooltip.hintergrund.wert}`
|
|
);
|
|
}
|
|
if (tooltipFg !== referenz.tooltip.text.wert.toLowerCase()) {
|
|
fehler.push(`CHART.tooltipFg = ${tooltipFg}: Carbon: ${referenz.tooltip.text.wert}`);
|
|
}
|
|
|
|
/* ------------------------------------------------- Achsen-Tickanzahl */
|
|
|
|
const raster = theme.match(/nettesRaster\(\s*\n?\s*max: number,\s*\n?\s*maxIntervalle = (\d+)/);
|
|
if (raster && Number(raster[1]) !== referenz.achsen.ticksYAchse) {
|
|
fehler.push(
|
|
`nettesRaster maxIntervalle = ${raster[1]}: Carbon numberOfTicks (y): ${referenz.achsen.ticksYAchse}`
|
|
);
|
|
}
|
|
|
|
/* -------------------------------------------- Bewusste Abweichungen melden */
|
|
|
|
const balken = theme.match(/maxBreite:\s*(\d+)/);
|
|
const abwBalken = referenz.bewusstAbweichend.balkenMaxBreitePx;
|
|
if (balken) {
|
|
if (Number(balken[1]) !== abwBalken.hier) {
|
|
fehler.push(
|
|
`BALKEN.maxBreite = ${balken[1]}, dokumentiert ist ${abwBalken.hier}. ` +
|
|
`Entweder den Wert zurücksetzen oder docs/carbon-referenz.json nachziehen.`
|
|
);
|
|
} else {
|
|
hinweises(`Balkenbreite ${abwBalken.hier} px statt Carbon ${abwBalken.carbon} px`, abwBalken.grund);
|
|
}
|
|
}
|
|
function hinweises(titel, grund) {
|
|
hinweise.push({ titel, grund });
|
|
}
|
|
hinweises(
|
|
"Feste Farbe je Kategorie statt n-Serien-Palette",
|
|
referenz.bewusstAbweichend.festeKategorieFarben.grund
|
|
);
|
|
|
|
/* ------------------------------------------------------------- Ausgabe */
|
|
|
|
console.log(`Carbon-Abgleich gegen ${referenz.quelle.version} (${referenz.quelle.geprueftAm})\n`);
|
|
|
|
if (hinweise.length) {
|
|
console.log("Bewusste Abweichungen (dokumentiert, kein Fehler):");
|
|
for (const h of hinweise) console.log(` · ${h.titel}\n ${h.grund}\n`);
|
|
}
|
|
|
|
if (fehler.length) {
|
|
console.error(`${fehler.length} Abweichung(en) von Carbon:`);
|
|
for (const f of fehler) console.error(` ✗ ${f}`);
|
|
console.error("\nEntweder chartTheme.ts korrigieren oder die Abweichung in");
|
|
console.error("docs/carbon-referenz.json unter 'bewusstAbweichend' begründen.");
|
|
process.exit(1);
|
|
}
|
|
|
|
console.log("✓ Palette, neutrale Werte, Tooltip und Achsenraster stimmen mit Carbon überein.");
|