diff --git a/src/assets.ts b/src/assets.ts new file mode 100644 index 0000000..1fe717d --- /dev/null +++ b/src/assets.ts @@ -0,0 +1,16 @@ +/** + * @see https://github.com/tailwindlabs/tailwindcss/blob/v4.1.13/packages/%40tailwindcss-browser/src/assets.ts + */ +import index from "tailwindcss-v4/index.css"; +import preflight from "tailwindcss-v4/preflight.css"; +import theme from "tailwindcss-v4/theme.css"; +import utilities from "tailwindcss-v4/utilities.css"; + +const css = { + index, + preflight, + theme, + utilities, +}; + +export default { css }; diff --git a/src/compile-css.test.ts b/src/compile-css.test.ts new file mode 100644 index 0000000..c059ee5 --- /dev/null +++ b/src/compile-css.test.ts @@ -0,0 +1,15 @@ +import { expect, it } from "vitest"; +import compileCss from "./compile-css.js"; + +it("compiled css should contain standard tailwindcss layers", async () => { + const compiledCss = await compileCss([], "", { addPreflight: true }); + const standardLayers = ["theme", "base", "utilities"]; + standardLayers.forEach((layer) => { + expect(compiledCss).toContain(`@layer ${layer}`); + }); +}); + +it("compiled css should contain standard tailwindcss layers order declaration", async () => { + const compiledCss = await compileCss([], "", { addPreflight: true }); + expect(compiledCss).toContain("@layer theme, base, components, utilities;"); +}); diff --git a/src/compile-css.ts b/src/compile-css.ts index 5e194e4..c0ef0c2 100644 --- a/src/compile-css.ts +++ b/src/compile-css.ts @@ -1,8 +1,59 @@ import { compile as tailwindV4Compile } from "tailwindcss-v4"; -import tailwindV4PreflightCss from "tailwindcss-v4/preflight.css"; -import tailwindV4DefaultThemeCss from "tailwindcss-v4/theme.css"; +import assets from "./assets.js"; import extractImports from "./extract-imports.js"; +/** + * Same as loadStylesheet function from `@tailwindcss/browser`, + * but with instrumentation removed. + * + * @see https://github.com/tailwindlabs/tailwindcss/blob/v4.1.13/packages/%40tailwindcss-browser/src/index.ts#L109 + */ +// eslint-disable-next-line @typescript-eslint/require-await +async function loadStylesheet(id: string, base: string) { + if (id === "tailwindcss") { + return { + path: "virtual:tailwindcss-v4/index.css", + base, + content: assets.css.index, + }; + } + if ( + id === "tailwindcss/preflight" || + id === "tailwindcss/preflight.css" || + id === "./preflight.css" + ) { + return { + path: "virtual:tailwindcss-v4/preflight.css", + base, + content: assets.css.preflight, + }; + } + if ( + id === "tailwindcss/theme" || + id === "tailwindcss/theme.css" || + id === "./theme.css" + ) { + return { + path: "virtual:tailwindcss-v4/theme.css", + base, + content: assets.css.theme, + }; + } + if ( + id === "tailwindcss/utilities" || + id === "tailwindcss/utilities.css" || + id === "./utilities.css" + ) { + return { + path: "virtual:tailwindcss-v4/utilities.css", + base, + content: assets.css.utilities, + }; + } + + throw new Error(`The browser build does not support @import for "${id}"`); +} + /** * Options for compiling CSS. * @see {compileCss} @@ -52,13 +103,17 @@ export default async function compileCss( const { cssWithoutImports: configurationCssWithoutImports, importRules } = extractImports(configurationCss); const compiler = await tailwindV4Compile( + // Since preflight can be disabled, we need to import each layer explicitly, + // instead of just `@import "tailwindcss"`. ` ${importRules} - ${addPreflight ? tailwindV4PreflightCss : ""} - ${tailwindV4DefaultThemeCss} + @layer theme, base, components, utilities; + @import "tailwindcss/theme.css" layer(theme); + ${addPreflight ? '@import "tailwindcss/preflight.css" layer(base);' : ""} + @import "tailwindcss/utilities.css" layer(utilities); ${configurationCssWithoutImports} - @tailwind utilities; `, + { loadStylesheet }, ); return compiler.build(classNameCandidates); } diff --git a/src/types/tailwindcss-v4.d.ts b/src/types/tailwindcss-v4.d.ts index dc3b843..e754f2e 100644 --- a/src/types/tailwindcss-v4.d.ts +++ b/src/types/tailwindcss-v4.d.ts @@ -1,4 +1,4 @@ -declare module "tailwindcss-v4/theme.css" { +declare module "tailwindcss-v4/index.css" { const content: string; export default content; } @@ -7,3 +7,13 @@ declare module "tailwindcss-v4/preflight.css" { const content: string; export default content; } + +declare module "tailwindcss-v4/theme.css" { + const content: string; + export default content; +} + +declare module "tailwindcss-v4/utilities.css" { + const content: string; + export default content; +}