Add extra processing options

This commit is contained in:
Alex
2024-04-06 21:04:33 -04:00
parent 8c789367af
commit ee14d81e8e
4 changed files with 140 additions and 72 deletions

View File

@ -1,14 +1,14 @@
import { readFileSync } from "node:fs";
import { basename, dirname, extname, join } from "node:path";
import { once } from "lodash";
import hash from "@emotion/hash";
import type babel from "@babel/core";
import type * as vite from "vite";
import type * as esbuild from "esbuild";
import { type NodePath, type types as t, transformSync } from "@babel/core";
import { type NodePath, type types as t } from "@babel/core";
import tailwind, { type Config } from "tailwindcss";
import postcss from "postcss";
export { babelPlugin } from "./esbuild-babel";
const PLUGIN_NAME = "tailwind";
const ESBUILD_NAMESPACE = "babel-tailwind";
const ROLLUP_PREFIX = "\0tailwind:";
@ -50,7 +50,7 @@ export interface TailwindPluginOptions {
/**
* Tailwind CSS configuration
*/
tailwindConfig: Omit<Config, "content">;
tailwindConfig?: Omit<Config, "content">;
/**
* Directives to prefix to all Tailwind stylesheets
@ -68,6 +68,12 @@ export interface TailwindPluginOptions {
*/
jsxAttributeName?: string;
/**
* What to do with the original attribute after processing
* @default "delete"
*/
jsxAttributeAction?: "delete" | "preserve" | ["rename", string];
/**
* Tagged template macro function to use for Tailwind classes
* @default "tw"
@ -108,6 +114,7 @@ function babelTailwind(
clsx,
getClassName: getClass = getClassName,
taggedTemplateName,
jsxAttributeAction = "delete",
jsxAttributeName = "css",
}: TailwindPluginOptions
) {
@ -190,8 +197,13 @@ function babelTailwind(
JSXAttribute(path, { tailwindMap, getCx }) {
const { name } = path.node;
if (name.name !== jsxAttributeName) return;
const valuePath = path.get("value");
if (name.name !== jsxAttributeName || !valuePath.node) return;
if (!valuePath.node) return;
const copy =
jsxAttributeAction === "delete" ? undefined : t.cloneNode(valuePath.node, true);
const parent = path.parent as t.JSXOpeningElement;
const classNameAttribute = parent.attributes.find(
@ -246,56 +258,19 @@ function babelTailwind(
t.jsxAttribute(t.jsxIdentifier("className"), valuePath.node)
);
}
path.remove();
if (jsxAttributeAction === "delete") {
path.remove();
} else {
path.node.value = copy!;
if (Array.isArray(jsxAttributeAction) && jsxAttributeAction[0] === "rename") {
path.node.name.name = jsxAttributeAction[1];
}
}
},
}));
}
/**
* An esbuild plugin that processes files with Babel if `getPlugins` returns any plugins.
*/
export const babelPlugin = ({
filter = /\.[jt]sx?$/,
plugins: getPlugins,
}: {
filter?: RegExp;
plugins:
| babel.PluginItem[]
| ((file: { path: string; contents: string }) => babel.PluginItem[]);
}): esbuild.Plugin => ({
name: "babel-plugin",
setup(build) {
build.onLoad({ filter }, ({ path }) => {
const load = once(() => readFileSync(path, "utf-8"));
const plugins = Array.isArray(getPlugins)
? getPlugins
: getPlugins({
path,
get contents() {
return load();
},
});
if (!plugins.length) {
return;
}
const { code } = transformSync(load(), {
parserOpts: {
plugins: ["jsx", "decorators", "typescript", "importAttributes"],
},
filename: path,
plugins,
})!;
return {
contents: code!,
loader: extname(path).slice(1) as "js" | "ts",
};
});
},
});
type Compile = ReturnType<typeof createPostCSS>;
/** @internal */