91 lines
2.5 KiB
TypeScript
91 lines
2.5 KiB
TypeScript
import { dirname, join } from "node:path";
|
|
import type * as esbuild from "esbuild";
|
|
import { CssSyntaxError } from "postcss";
|
|
import { type Compile, type StyleMap, pkgName, toCSSText } from "./shared";
|
|
|
|
const PLUGIN_NAME = "tailwind";
|
|
const ESBUILD_NAMESPACE = "babel-tailwind";
|
|
|
|
export const esbuildPlugin = (styleMap: StyleMap, compile: Compile): esbuild.Plugin => ({
|
|
name: PLUGIN_NAME,
|
|
|
|
setup(build) {
|
|
build.onResolve({ filter: /^tailwind:.+\.css$/ }, ({ path, importer }) => {
|
|
const resolved = join(dirname(importer), path.replace(/^tailwind:/, ""));
|
|
if (styleMap.has(resolved)) {
|
|
return {
|
|
path: resolved,
|
|
namespace: ESBUILD_NAMESPACE,
|
|
};
|
|
}
|
|
});
|
|
|
|
build.onResolve({ filter: RegExp(`^${pkgName}/base$`) }, () => ({
|
|
path: "directive:base",
|
|
namespace: ESBUILD_NAMESPACE,
|
|
}));
|
|
|
|
build.onLoad({ filter: /.*/, namespace: ESBUILD_NAMESPACE }, async ({ path }) => {
|
|
if (path === "directive:base") {
|
|
return {
|
|
contents: (await compile("@tailwind base")).css,
|
|
loader: "css",
|
|
};
|
|
}
|
|
|
|
if (!styleMap.has(path)) return;
|
|
|
|
const styles = styleMap.get(path)!;
|
|
|
|
try {
|
|
const result = await compile(toCSSText(styles));
|
|
return {
|
|
contents: result.css,
|
|
loader: "css",
|
|
};
|
|
} catch (e) {
|
|
if (e instanceof CssSyntaxError) {
|
|
const lines = e.source!.split("\n");
|
|
const cls = lines
|
|
.at(e.line! - 2)!
|
|
.slice(1, -1)
|
|
.trim();
|
|
|
|
const entry = styles.find(s => s.key === cls)!;
|
|
if (!entry) {
|
|
throw new Error("Could not find entry for CSS");
|
|
}
|
|
|
|
const { location: loc } = entry;
|
|
const errLoc: Partial<esbuild.Location> = {
|
|
file: loc.filename,
|
|
line: loc.start.line,
|
|
column: loc.start.column,
|
|
length: loc.end.column - loc.start.column,
|
|
lineText: loc.text,
|
|
};
|
|
|
|
const doesNotExist = e.reason.match(/The `(.+)` class does not exist/)?.[1];
|
|
if (doesNotExist) {
|
|
const index = loc.text.indexOf(doesNotExist, loc.start.column);
|
|
if (index !== -1) {
|
|
errLoc.column = index;
|
|
errLoc.length = doesNotExist.length;
|
|
}
|
|
}
|
|
|
|
return {
|
|
errors: [
|
|
{
|
|
text: e.reason,
|
|
location: errLoc,
|
|
},
|
|
],
|
|
};
|
|
}
|
|
throw e;
|
|
}
|
|
});
|
|
},
|
|
});
|