import { readFileSync } from "node:fs"; import { describe, expect, it } from "vitest"; import { type ButtonSize, type ButtonVariant, buttonClass, type IconButtonSize, type IconButtonVariant, iconButtonClass, } from "./buttonStyles"; import { type ChipSize, type ChipVariant, chipClass } from "./chipStyles"; // Tailwind generates CSS only for the class names it FINDS in the source, token by token. A class // assembled at runtime (`${ACT}hover:text-fg`) is never found whole, so it ships with no rule at all: // every hover colour of Button, IconButton and Chip was dead that way, found in an audit by // reading the stylesheet (0 rules for `not-aria-disabled`). So: every class a primitive can emit has // to stand in its source file whole, between the delimiters the scanner splits on. const tokens = (file: string) => new Set(readFileSync(new URL(file, import.meta.url), "utf8").split(/[\s"'`{}$]+/)); // Records, so a new variant or size that is not listed here fails to compile. const keys = (r: Record) => Object.keys(r) as K[]; const BV = keys({ primary: true, danger: true, warn: true, outline: true, "outline-accent": true, "outline-danger": true, "outline-warn": true, ghost: true, glass: true, overlay: true, media: true, "danger-soft": true, link: true, "link-muted": true, }); // prettier-ignore const BS = keys({ xs: true, sm: true, md: true, lg: true, none: true }); const IV = keys({ ghost: true, "ghost-accent": true, primary: true, outline: true, "outline-accent": true, "outline-danger": true, "outline-warn": true, danger: true, "danger-soft": true, glass: true, media: true, overlay: true, }); // prettier-ignore const IS = keys({ sm: true, md: true, lg: true, player: true }); const CV = keys({ filter: true, token: true, tag: true, suggest: true, ghost: true }); const CS = keys({ md: true, sm: true, xs: true }); const missing = (emitted: string[], file: string) => { const found = tokens(file); return [...new Set(emitted.flatMap((c) => c.split(/\s+/)).filter(Boolean))].filter( (c) => !found.has(c), ); }; describe("every class a primitive emits is visible to the Tailwind scanner", () => { it("Button and IconButton", () => { const emitted: string[] = []; for (const pressed of [undefined, true]) { for (const variant of BV) for (const size of BS) emitted.push(buttonClass({ variant, size, pressed, round: true })); for (const variant of IV) for (const size of IS) emitted.push(iconButtonClass({ variant, size, pressed })); } expect(missing(emitted, "./buttonStyles.ts")).toEqual([]); }); it("Chip", () => { const emitted = CV.flatMap((v) => CS.map((s) => chipClass(v, s))); expect(missing(emitted, "./chipStyles.ts")).toEqual([]); }); });