scripts/lib/tailwind/

August 16, 2026 ยท View on GitHub

modulewhy it exists
tailwind-compile.tsCompiles the @theme preset with the manifests as content, and expands a manifest into the flat class list that compile needs. Here rather than inside build-tailwind.ts because several gates read it as well, one of them outside this domain, and a gate reaching into a build script would be the wrong direction. Derive the readers with grep -rln tailwind-compile scripts/check/ | grep -v '\.test\.', which is worth running rather than trusting: the set has already been written down wrong once, naming two gates that never imported it. compileEntry takes the inputs that decide its output and holds the sheet against them, through ../arena/artifact-cache.ts: the CLI spawn measures 360ms and a sweep asks for it three times, from check:tailwind, check:tailwind-generated and build:tailwind. layerInputs() is that set, the preset plus every manifest, and the entry text decides the entry's name, so two entries over one input set cannot collide. Called with no inputs it compiles, every time, which is what an entry assembled over a temporary directory needs and what makes the spawn-failure case reachable at all.
sheet-split.tsCuts the compiled sheet at its @layer base block, so a package can ship the preflight separately from what an adopter's own Tailwind would collide with. Read by both package assemblers.
manifest-surfaces.tsWhich contracted components each manifest draws (MANIFEST_COVERS) and which draw themselves (HAND_DRAWN). Here because check:appearance and check:states both read it and either owning it would make the two import each other.
theme-namespaces.tsWhich Tailwind theme namespace a property in Theme.css belongs to. The native set comes from tailwind-merge, which is the only correct source and the reason that package stays a devDependency; the module header says why deriving it from Tailwind's own theme file does not work.
component-css.tsThe one typed doorway to frameworks/tailwind/ManifestClasses.js, which is plain JS a browser loads and so can carry no annotation: the seven exports are re-declared here once, and check:manifest-classes imports them from here rather than reaching past it. Also: a manifest as the @apply rules that compile to the CSS one component renders, the Arena class names those rules define, and the strip that turns Tailwind's own namespace back into the Arena token behind it. Read by the build and by two gates.
component-sheets.tsCuts one compiled sheet into the per-component files a package ships plus the prelude they all import. Separate from component-css.ts because it knows about CSS block structure and nothing about manifests.
manifest-shapes.tsThe shape a *.manifest.json holds on disk, so its readers across four domains agree about it. Every one of them reached a manifest's classes through Object.entries() over a JSON.parse, which hands back unknown, so a reader spelling manifest.variants was making a claim about the file it never stated. Derived from ArenaClassManifest in frameworks/tailwind/ArenaStyles.ts rather than written a second time: that type describes the sheet classesManifest() emits and this one the authored source, and they differ in exactly one key -- an authored manifest may declare no slots. The fact worth knowing is stated there and holds here: a variant value is a string in variants and a boolean in defaultVariants and in a compound selector, which arenaTv() reconciles at runtime and tailwind-variants does not type, so frameworks/tailwind/Tv.ts carries the single cast that crosses that line. Three readers want only the class strings and take ManifestClassSource, a partial: their fixtures pass { slots } and { component, slots }, and tailwind-compile.test.ts names one of those cases after ignoring the metadata, so a type that rejected component would contradict the assertion.

Every X.test.ts beside a module covers that module. tailwind-vocabulary.test.ts covers the same module from the vocabulary side: which utility families the preset is expected to emit at all.