fix: put plugin-only tailwind classes in core's utilities layer, SDK 1.0.4

This commit is contained in:
LukeGus committed 2026-10-08 13:38:52 -05:00
1 parent d6c4ec01b5
commit 878f1ebaa3
6 files changed
+169 -13

No files matched your search

+62
View File
@@ -7,6 +7,10 @@ import {
build,
lowerPluginLayers,
} from "../packages/plugin-sdk/cli/commands/build.mjs";
import {
classNamesInCss,
splitByCoreClasses,
} from "../packages/plugin-sdk/cli/lib/css-classes.mjs";
const cleanups: Array<() => void> = [];
@@ -102,6 +106,64 @@ describe("plugin CSS layers", () => {
);
});
it("can leave a plugin's own classes in core's utilities layer", () => {
expect(
lowerPluginLayers(
"@layer properties{a{b:c}}@layer utilities{.w-px{width:1px}}",
{ utilities: false },
),
).toBe(
"@layer termix-plugin-properties{a{b:c}}@layer utilities{.w-px{width:1px}}",
);
});
it("reads class names from selectors, not declarations", () => {
const names = classNamesInCss(
String.raw`.w-28{width:calc(var(--spacing) * 28)}@media (width>=48rem){.md\:w-44{width:0.5rem}}.group-hover\:opacity-100:is(:where(.group):hover *){opacity:1}.top-1\/2{top:50%}.\32 xl\:flex{display:flex}`,
);
expect([...names].sort()).toEqual(
[
"2xl:flex",
"group",
"group-hover:opacity-100",
"md:w-44",
"top-1/2",
"w-28",
].sort(),
);
});
it("splits a plugin's classes by whether core ships them", () => {
expect(
splitByCoreClasses(
["w-28", "md:w-44", "hidden"],
new Set(["w-28", "hidden"]),
),
).toEqual({ shared: ["w-28", "hidden"], own: ["md:w-44"] });
});
it("keeps classes core ships below core and the plugin's own beside core's", async () => {
vi.spyOn(console, "log").mockImplementation(() => {});
// Core's class list comes from scanning this repo, this file included,
// so the plugin-only class is put together here instead of written out.
const width = ["w-", "[321px]"].join("");
const dir = fixturePlugin();
fs.mkdirSync(path.join(dir, "src", "frontend"), { recursive: true });
fs.writeFileSync(
path.join(dir, "src", "frontend", "index.tsx"),
`export const a = <div className="hidden md:${width}" />;\n`,
);
await build({ cwd: dir });
const css = fs.readFileSync(path.join(dir, "dist", "frontend.css"), "utf8");
const lowered = css.slice(css.indexOf("@layer termix-plugin-utilities"));
const own = css.slice(css.lastIndexOf("@layer utilities{"));
expect(lowered).toMatch(/^@layer termix-plugin-utilities\{[^@]*\.hidden\{/);
expect(own).toContain(String.raw`.md\:w-\[321px\]`);
expect(own).not.toContain(".hidden{");
});
it("is ordered in core's CSS between base and core's utilities", () => {
const css = fs.readFileSync(
path.join(__dirname, "..", "src", "ui", "index.css"),