#!/usr/bin/env node /** * @file One-off codemod: shifts every raw `blue-*`/`amber-*` Tailwind utility * one shade darker (100→200 ... 700→800), mirroring the 1-step darkening * already applied to the accent token (`#2563eb` blue-600 → `#1d4ed8` * blue-700). `blue` here is the "current stage" / info color (e.g. * PipelineMap's `current` state, unrelated to the `accent` CSS-variable * token); `amber` is the warning/pending/auto-detected color used across * badges, banners, and the pipeline's dashed "auto: " chip. `950` is * left alone — already the darkest step available. * @author Nguyễn Ngọc Trí Vĩ */ import { readdirSync, readFileSync, writeFileSync, statSync } from "node:fs"; import { join } from "node:path"; import { fileURLToPath } from "node:url"; const SHIFT = { 50: 100, 100: 200, 200: 300, 300: 400, 400: 500, 500: 600, 600: 700, 700: 800, 800: 900, }; const COLORS = ["blue", "amber"]; const PROPS = ["text", "bg", "border", "ring", "from", "to", "via", "fill"]; // Descending by `from` — JS enumerates integer-like object keys ascending // regardless of source order, and shifting low-to-high would let an already // -shifted "200" (from 100) get caught and shifted AGAIN by the 200 rule. // Highest-first guarantees each original shade is only ever matched once. const SHIFTS_DESC = Object.entries(SHIFT) .map(([from, to]) => [Number(from), to]) .sort((a, b) => b[0] - a[0]); function rewrite(text) { let out = text; for (const prop of PROPS) { for (const color of COLORS) { for (const [from, to] of SHIFTS_DESC) { const re = new RegExp(`\\b${prop}-${color}-${from}(\\/[0-9]+)?\\b`, "g"); out = out.replace(re, (_m, opacity) => `${prop}-${color}-${to}${opacity || ""}`); } } } return out; } function walk(dir, files = []) { for (const entry of readdirSync(dir)) { const full = join(dir, entry); const st = statSync(full); if (st.isDirectory()) { if (entry === "node_modules") continue; walk(full, files); } else if (entry.endsWith(".tsx")) { files.push(full); } } return files; } const scriptDir = fileURLToPath(new URL(".", import.meta.url)); const root = join(scriptDir, "..", "client", "src"); const files = walk(root); let changed = 0; for (const file of files) { const before = readFileSync(file, "utf8"); const after = rewrite(before); if (after !== before) { writeFileSync(file, after); changed++; } } console.log(`rewrote ${changed} file(s)`);