diff --git a/package.json b/package.json index d2c228f..9d58fe2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@aet/tailwind", - "version": "0.0.1-beta.10", + "version": "0.0.1-beta.11", "main": "dist/index.js", "license": "MIT", "scripts": { diff --git a/src/babel-tailwind.ts b/src/babel-tailwind.ts index 8068ddb..64d6c31 100644 --- a/src/babel-tailwind.ts +++ b/src/babel-tailwind.ts @@ -35,6 +35,8 @@ interface BabelPluginState { export type ClassNameCollector = (path: string, entries: StyleMapEntry[]) => void; +const trim = (value: string) => value.replace(/\s+/g, " ").trim(); + export function babelTailwind( { styleMap, @@ -137,7 +139,7 @@ export function babelTailwind( const value = quasis[0].value.cooked; if (value) { - const trimmed = value.replace(/\s+/g, " ").trim(); + const trimmed = trim(value); const className = getClass(trimmed); recordIfAbsent({ key: className, @@ -156,30 +158,32 @@ export function babelTailwind( const { callee, arguments: args } = node; if (!t.isIdentifier(callee, { name: macroFunction })) return; - if (args.length !== 1) { - throw new Error(`${macroFunction} should be called with exactly one argument`); - } - - const [arg] = args; - if (!t.isObjectExpression(arg)) { - throw new Error(`${macroFunction} should be called with an object literal`); - } - - const ev = path.get("arguments")[0].evaluate(); - if (!ev.confident || typeof ev.value !== "object" || ev.value == null) { - throw new Error(`${macroFunction} should be called with a static object literal`); - } - - const trimmed = Object.entries(ev.value) - .flatMap(([modifier, classes]) => { - if (typeof classes !== "string") { - throw new Error(`Value for "${modifier}" should be a string`); + const trimmed = args + .flatMap((arg, i) => { + if (t.isStringLiteral(arg)) { + return trim(arg.value); } - return classes - .replace(/\s+/g, " ") - .trim() - .split(" ") - .map(cls => modifier + ":" + cls); + if (!t.isObjectExpression(arg)) { + throw new Error(`${macroFunction} should be called with an object literal`); + } + + const ev = path.get("arguments")[i].evaluate(); + if (!ev.confident || typeof ev.value !== "object" || ev.value == null) { + throw new Error( + `${macroFunction} should be called with a static object literal` + ); + } + + return Object.entries(ev.value).flatMap(([modifier, classes]) => { + if (typeof classes !== "string") { + throw new Error(`Value for "${modifier}" should be a string`); + } + return classes + .replace(/\s+/g, " ") + .trim() + .split(" ") + .map(cls => modifier + ":" + cls); + }); }) .join(" "); diff --git a/src/index.test.ts b/src/index.test.ts index bd89444..4fb9913 100644 --- a/src/index.test.ts +++ b/src/index.test.ts @@ -159,22 +159,33 @@ describe("babel-tailwind", () => { expect(files.css.text).toMatch(`.${clsName} {\n text-align: center;\n}`); }); - it("supports grouped tw", async () => { + it.only("supports grouped tw", async () => { const { files } = await compileESBuild({ clsx: "emotion", expectFiles: 2, javascript: /* tsx */ ` - export default tw({ + export default tw("text-sm", { "group-hover": "text-center", "[&>div]": "font-semibold", }) `, }); - const clsName = getClassName("group-hover:text-center [&>div]:font-semibold"); + const clsName = getClassName("text-sm group-hover:text-center [&>div]:font-semibold"); expect(files.js.text).toContain(`= "${clsName}"`); expect(files.css.text).toMatch( - `.group:hover .${clsName} {\n text-align: center;\n}\n.${clsName} > div {\n font-weight: 600;\n}` + [ + `.${clsName} {`, + " font-size: 0.875rem;", + " line-height: 1.25rem;", + "}", + `.group:hover .${clsName} {`, + " text-align: center;", + "}", + `.${clsName} > div {`, + " font-weight: 600;", + "}", + ].join("\n") ); });