Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -22,7 +22,7 @@
"test:e2e:accessibility": "node scripts/run-playwright.mjs tests/ui-accessibility.spec.ts --project=chromium",
"test:e2e:chromium": "node scripts/run-playwright.mjs --project=chromium",
"test:e2e:visual": "node scripts/run-playwright.mjs --config=playwright.visual.config.ts",
"verify:cheap": "npm run check:runtime && npm run lint && npm run typecheck && npm run test",
"verify:cheap": "npm run check:runtime && npm run lint && npm run typecheck && npm run test && npm run check:type-scale",
"verify:ui": "npm run check:runtime && npm run test:e2e:chromium",
"verify:release": "npm run check:runtime && npm run lint && npm run typecheck && npm run test && npm run build && npm run test:e2e && npm run check:production-readiness && npm run governance:release && npm run eval:quality:release",
"ci:env-check": "node scripts/check-ci-env.mjs",
Expand DownExpand Up@@ -53,6 +53,7 @@
"backfill:text-normalization": "tsx scripts/backfill-text-normalization.ts",
"check:supabase-project": "tsx scripts/check-supabase-project.ts",
"check:indexing": "tsx scripts/check-indexing.ts",
"check:type-scale": "node scripts/check-type-scale.mjs",
"recover:ingestion": "tsx scripts/recover-ingestion-queue.ts",
"registry:seed": "tsx scripts/seed-registry-records.ts",
"reindex": "tsx scripts/reindex.ts",
Expand Down
62 changes: 62 additions & 0 deletions scripts/check-type-scale.mjs
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
#!/usr/bin/env node
// Guardrail/diagnostic: flags arbitrary Tailwind font-size utilities
// (e.g. text-[12px], text-[1.45rem]) that bypass the design type scale.
//
// The scale lives in the @theme block of src/app/globals.css: named steps
// text-4xs … text-2xl-minus, on top of Tailwind's default xs/sm/base/lg/xl/2xl.
// Arbitrary text-[<n><unit>] values re-introduce off-scale sizes; this check
// tracks that drift. Colour utilities (text-[color:var(--…)]) are the sanctioned
// token-access form and are intentionally NOT flagged.
//
// Usage:
// node scripts/check-type-scale.mjs report only, exit 0 (default)
// node scripts/check-type-scale.mjs --strict exit 1 if any found (promote to a
// CI gate once the backlog is cleared)

import { readFileSync } from "node:fs";
import { execSync } from "node:child_process";

const strict = process.argv.includes("--strict");
const ARBITRARY = /\btext-\[(\d*\.?\d+)(px|rem|em)\]/g;

// Tracked source files under src (fast; respects .gitignore).
const files = execSync("git ls-files src", { encoding: "utf8" })
.split("\n")
.filter((f) => /\.(tsx?|jsx?|css)$/.test(f));

const hits = [];
for (const file of files) {
let text;
try {
text = readFileSync(file, "utf8");
} catch {
continue;
}
text.split("\n").forEach((line, i) => {
for (const m of line.matchAll(ARBITRARY)) {
hits.push({ file, line: i + 1, match: m[0] });
}
});
}

if (hits.length === 0) {
console.log("✓ type-scale: no arbitrary text-[<n>px|rem|em] font sizes in src.");
process.exit(0);
}

const bySize = new Map();
for (const h of hits) bySize.set(h.match, (bySize.get(h.match) ?? 0) + 1);
const fileCount = new Set(hits.map((h) => h.file)).size;

console.log(`type-scale: ${hits.length} arbitrary font-size utilities bypass the scale (across ${fileCount} files):\n`);
for (const [size, n] of [...bySize.entries()].sort((a, b) => b[1] - a[1])) {
console.log(` ${String(n).padStart(4)} ${size}`);
}
console.log("\nPrefer a named @theme step from src/app/globals.css (text-3xs, text-sm-minus, text-2xl-minus, …).");
console.log("Colour utilities like text-[color:var(--…)] are fine and not counted.");

if (strict) {
console.error("\n✗ --strict: arbitrary font sizes present.");
process.exit(1);
}
process.exit(0);
7 changes: 6 additions & 1 deletion src/app/globals.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -38,12 +38,17 @@
2xs 11px small chips / secondary labels (most common small size)
(xs 12 · sm 14 · base 16 come from Tailwind's default scale)
sm-minus 13px one notch under sm — dense body/labels bigger than xs
base-minus 15px one notch under base — comfortable body just under 16 */
base-minus 15px one notch under base — comfortable body just under 16
(lg 18 · xl 20 · 2xl 24 come from Tailwind's default scale)
lg-minus 17px one notch under lg — display titles a shade under 18
2xl-minus 22px one notch under 2xl — wide-screen nowrap headings */
--text-4xs: 0.5rem;
--text-3xs: 0.625rem;
--text-2xs: 0.6875rem;
--text-sm-minus: 0.8125rem;
--text-base-minus: 0.9375rem;
--text-lg-minus: 1.0625rem;
--text-2xl-minus: 1.375rem;

/* Font families: bind Tailwind's font-sans / font-mono to the loaded Geist
faces (variables set on <html> by next/font). font-mono is used for
Expand Down