Support vite cache invalidation
This commit is contained in:
parent
2a3e7390cf
commit
2a6df0dd4a
32
package.json
32
package.json
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@aet/tailwind",
|
||||
"version": "0.0.1-beta.6",
|
||||
"version": "0.0.1-beta.8",
|
||||
"main": "dist/index.js",
|
||||
"license": "MIT",
|
||||
"private": true,
|
||||
@ -12,38 +12,40 @@
|
||||
"dist"
|
||||
],
|
||||
"devDependencies": {
|
||||
"@aet/eslint-rules": "^0.0.25",
|
||||
"@aet/eslint-rules": "^0.0.33",
|
||||
"@types/babel__core": "^7.20.5",
|
||||
"@types/bun": "^1.1.0",
|
||||
"@types/bun": "^1.1.6",
|
||||
"@types/dedent": "^0.7.2",
|
||||
"@types/lodash": "^4.17.0",
|
||||
"@types/node": "^20.12.7",
|
||||
"@types/lodash": "^4.17.6",
|
||||
"@types/node": "^20.14.9",
|
||||
"@types/postcss-safe-parser": "^5.0.4",
|
||||
"@types/react": "^18.3.3",
|
||||
"cli-highlight": "^2.1.11",
|
||||
"clsx": "^2.1.1",
|
||||
"colord": "^2.9.3",
|
||||
"css-what": "^6.1.0",
|
||||
"dedent": "^1.5.3",
|
||||
"esbuild": "^0.20.2",
|
||||
"esbuild": "^0.21.5",
|
||||
"esbuild-register": "^3.5.0",
|
||||
"eslint": "^8.57.0",
|
||||
"postcss-nested": "^6.0.1",
|
||||
"postcss-safe-parser": "^7.0.0",
|
||||
"prettier": "^3.2.5",
|
||||
"tailwindcss": "^3.4.3",
|
||||
"tsup": "^8.0.2",
|
||||
"typescript": "^5.4.5",
|
||||
"vite": "^5.2.10",
|
||||
"vitest": "^1.5.2"
|
||||
"prettier": "^3.3.2",
|
||||
"tailwindcss": "^3.4.4",
|
||||
"tsup": "^8.1.0",
|
||||
"typescript": "^5.5.2",
|
||||
"vite": "^5.3.2",
|
||||
"vitest": "^1.6.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"tailwindcss": "^3.4.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.24.4",
|
||||
"@babel/core": "^7.24.7",
|
||||
"@emotion/hash": "^0.9.1",
|
||||
"lodash": "^4.17.21",
|
||||
"postcss": "^8.4.38",
|
||||
"type-fest": "^4.17.0"
|
||||
"type-fest": "^4.20.1"
|
||||
},
|
||||
"prettier": {
|
||||
"arrowParens": "avoid",
|
||||
@ -53,4 +55,4 @@
|
||||
"singleQuote": false,
|
||||
"trailingComma": "es5"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
5215
pnpm-lock.yaml
generated
5215
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -1,25 +1,51 @@
|
||||
#!/usr/bin/env bun
|
||||
import { promises as fs } from "node:fs";
|
||||
import { type Options, build } from "tsup";
|
||||
import { build, defineConfig } from "tsup";
|
||||
import { pick } from "lodash";
|
||||
import tsupConfig from "../tsup.config";
|
||||
import pkg from "../package.json" with { type: "json" };
|
||||
|
||||
await build(tsupConfig as Options);
|
||||
await Bun.write(
|
||||
"dist/package.json",
|
||||
JSON.stringify(
|
||||
pick(pkg, ["name", "version", "license", "dependencies", "author"]),
|
||||
null,
|
||||
2
|
||||
)
|
||||
);
|
||||
const tsupConfig = defineConfig({
|
||||
outDir: "dist",
|
||||
splitting: false,
|
||||
sourcemap: false,
|
||||
dts: true,
|
||||
treeshake: true,
|
||||
platform: "node",
|
||||
define: {
|
||||
"process.env.BABEL_TAILWIND_BUILD": "true",
|
||||
},
|
||||
banner: {
|
||||
js: "/* eslint-disable */",
|
||||
},
|
||||
});
|
||||
|
||||
await Bun.write(
|
||||
`dist/base.d.ts`,
|
||||
`/**\n * \`@tailwind base\` component.\n */\nexport {};`
|
||||
);
|
||||
await fs.copyFile("README.md", "dist/README.md");
|
||||
await fs.copyFile("LICENSE.md", "dist/LICENSE.md");
|
||||
await Promise.all([
|
||||
build({
|
||||
...tsupConfig,
|
||||
entry: ["src/classed.tsx"],
|
||||
outDir: "dist",
|
||||
external: ["react", "react/jsx-runtime", "clsx"],
|
||||
format: "esm",
|
||||
clean: true,
|
||||
}),
|
||||
build({
|
||||
...tsupConfig,
|
||||
entry: ["src/index.ts"],
|
||||
}),
|
||||
Bun.write(
|
||||
"dist/package.json",
|
||||
JSON.stringify(
|
||||
pick(pkg, ["name", "version", "license", "dependencies", "author"]),
|
||||
null,
|
||||
2
|
||||
)
|
||||
),
|
||||
Bun.write(`dist/base.d.ts`, `/**\n * \`@tailwind base\` component.\n */\nexport {};`),
|
||||
]);
|
||||
|
||||
await Promise.all([
|
||||
fs.copyFile("README.md", "dist/README.md"),
|
||||
fs.copyFile("LICENSE.md", "dist/LICENSE.md"),
|
||||
]);
|
||||
|
||||
process.exit(0);
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { basename, dirname, extname, join } from "node:path";
|
||||
import type babel from "@babel/core";
|
||||
import hash from "@emotion/hash";
|
||||
import { type NodePath, type types as t } from "@babel/core";
|
||||
import type { SourceLocation, StyleMapEntry } from "./shared";
|
||||
import { type ResolveTailwindOptions, getClassName } from "./index";
|
||||
@ -18,7 +19,7 @@ const extractJSXContainer = (attr: NonNullable<t.JSXAttribute["value"]>): t.Expr
|
||||
|
||||
function matchPath(
|
||||
nodePath: NodePath<t.Node | null | undefined>,
|
||||
fns: (dig: (nodePath: NodePath) => void) => babel.Visitor
|
||||
fns: (dig: (nodePath: NodePath<t.Node | null | undefined>) => void) => babel.Visitor
|
||||
) {
|
||||
if (!nodePath.node) return;
|
||||
const fn = fns(path => matchPath(path, fns))[nodePath.node.type] as any;
|
||||
@ -42,6 +43,7 @@ export function babelTailwind(
|
||||
taggedTemplateName,
|
||||
jsxAttributeAction = "delete",
|
||||
jsxAttributeName = "css",
|
||||
vite,
|
||||
}: ResolveTailwindOptions,
|
||||
onCollect: ClassNameCollector | undefined
|
||||
) {
|
||||
@ -102,12 +104,18 @@ export function babelTailwind(
|
||||
}
|
||||
|
||||
const cssName = basename(filename, extname(filename)) + ".css";
|
||||
node.body.unshift(
|
||||
t.importDeclaration([], t.stringLiteral(`tailwind:./${cssName}`))
|
||||
);
|
||||
|
||||
const path = join(dirname(filename), cssName);
|
||||
const value = Array.from(tailwindMap.values());
|
||||
|
||||
let importee = `tailwind:./${cssName}`;
|
||||
if (vite) {
|
||||
const cacheKey = hash(value.map(x => x.className).join(","));
|
||||
importee += `?${cacheKey}`;
|
||||
}
|
||||
|
||||
node.body.unshift(t.importDeclaration([], t.stringLiteral(importee)));
|
||||
|
||||
styleMap.set(path, value);
|
||||
onCollect?.(path, value);
|
||||
},
|
||||
@ -172,6 +180,11 @@ export function babelTailwind(
|
||||
path.replaceWith(t.stringLiteral(className));
|
||||
}
|
||||
},
|
||||
ArrayExpression(path) {
|
||||
for (const element of path.get("elements")) {
|
||||
go(element);
|
||||
}
|
||||
},
|
||||
JSXExpressionContainer(path) {
|
||||
go(path.get("expression"));
|
||||
},
|
||||
|
32
src/classed.tsx
Normal file
32
src/classed.tsx
Normal file
@ -0,0 +1,32 @@
|
||||
import cx from "clsx";
|
||||
import { type FunctionComponent, forwardRef } from "react";
|
||||
|
||||
interface WithClassName<P = object> extends FunctionComponent<P> {
|
||||
className: string;
|
||||
}
|
||||
|
||||
export const classed: {
|
||||
(
|
||||
type: "input",
|
||||
className: string | string[]
|
||||
): WithClassName<
|
||||
React.DetailedHTMLProps<React.InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>
|
||||
>;
|
||||
<K extends keyof JSX.IntrinsicElements>(
|
||||
type: K,
|
||||
className: string | string[]
|
||||
): WithClassName<JSX.IntrinsicElements[K]>;
|
||||
(
|
||||
type: string,
|
||||
className: string | string[]
|
||||
): WithClassName<React.ClassAttributes<any> & React.DOMAttributes<any>>;
|
||||
<P>(type: FunctionComponent<P>, className: string | string[]): WithClassName<P>;
|
||||
<P>(type: React.ComponentClass<P>, className: string | string[]): WithClassName<P>;
|
||||
} = (Component: any, classNameInput: string | (string | false)[]) => {
|
||||
const className = cx(classNameInput);
|
||||
const component: any = forwardRef<any, any>(({ className: cls, ...props }, ref) => (
|
||||
<Component {...props} ref={ref} className={cx(className, cls)} />
|
||||
));
|
||||
component.className = className;
|
||||
return component;
|
||||
};
|
@ -83,6 +83,11 @@ export interface TailwindPluginOptions {
|
||||
* async css => (await postcss.process(css, { plugins: [tailwindcss()] })).css
|
||||
*/
|
||||
compile?(css: string): Promise<string>;
|
||||
|
||||
/**
|
||||
* Using the vite plugin?
|
||||
*/
|
||||
vite?: boolean;
|
||||
}
|
||||
|
||||
export type ResolveTailwindOptions = SetRequired<
|
||||
@ -139,6 +144,7 @@ export function getTailwindPlugins(options: TailwindPluginOptions) {
|
||||
compile,
|
||||
babel: (onCollect?: ClassNameCollector) => babelTailwind(resolvedOptions, onCollect),
|
||||
esbuild: () => esbuildPlugin(styleMap, compile),
|
||||
/** Requires `options.vite` to be `true`. */
|
||||
vite: () => vitePlugin(styleMap, compile),
|
||||
styleMap,
|
||||
options,
|
||||
|
@ -15,15 +15,17 @@ export const vitePlugin = (styleMap: StyleMap, compile: Compile): vite.Plugin =>
|
||||
}
|
||||
|
||||
if (id.startsWith("tailwind:")) {
|
||||
const resolved = join(dirname(importer!), id.slice("tailwind:".length));
|
||||
const [name, cacheKey] = id.slice("tailwind:".length).split("?");
|
||||
const resolved = join(dirname(importer!), name);
|
||||
if (styleMap.has(resolved)) {
|
||||
return {
|
||||
id: ROLLUP_PREFIX + resolved,
|
||||
id: ROLLUP_PREFIX + resolved + "?" + cacheKey,
|
||||
moduleSideEffects: true,
|
||||
};
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
async load(id: string) {
|
||||
if (id.startsWith(ROLLUP_PREFIX)) {
|
||||
const resolved = id.slice(ROLLUP_PREFIX.length);
|
||||
@ -31,8 +33,9 @@ export const vitePlugin = (styleMap: StyleMap, compile: Compile): vite.Plugin =>
|
||||
return await compile("@tailwind base");
|
||||
}
|
||||
|
||||
if (styleMap.has(resolved)) {
|
||||
return await compile(toCSSText(styleMap.get(resolved)!));
|
||||
const name = resolved.split("?")[0];
|
||||
if (styleMap.has(name)) {
|
||||
return await compile(toCSSText(styleMap.get(name)!));
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -1,18 +0,0 @@
|
||||
import { defineConfig } from "tsup";
|
||||
|
||||
export default defineConfig({
|
||||
entry: ["src/index.ts"],
|
||||
outDir: "dist",
|
||||
splitting: false,
|
||||
sourcemap: false,
|
||||
clean: true,
|
||||
dts: true,
|
||||
treeshake: true,
|
||||
platform: "node",
|
||||
define: {
|
||||
"process.env.BABEL_TAILWIND_BUILD": "true",
|
||||
},
|
||||
banner: {
|
||||
js: "/* eslint-disable */",
|
||||
},
|
||||
});
|
Loading…
x
Reference in New Issue
Block a user