Rewrite esbuild postcss plugin

Signed-off-by: gearnode <bryan@frimin.fr>
This commit is contained in:
gearnode
2025-03-02 10:48:30 +01:00
parent 69d947b6ab
commit eef87f3907
8 changed files with 163 additions and 117 deletions

View File

@@ -0,0 +1,21 @@
{
"name": "@probo/esbuild-plugin-postcss",
"version": "0.0.1",
"exports": {
".": "./src/index.mjs"
},
"scripts": {
"test": "node tests/esbuild.test.mjs"
},
"type": "module",
"dependencies": {
"postcss": "^8.5"
},
"peerDependencies": {
"esbuild": "^0.25.0"
},
"devDependencies": {
"autoprefixer": "^10.4.20",
"esbuild": "^0.25.0"
}
}

View File

@@ -0,0 +1,52 @@
import postcss from "postcss";
import path from "node:path";
import fs from "node:fs/promises";
import os from "node:os";
import process from "node:process";
export default (options = { plugins: [] }) => ({
name: "postcss",
setup: async function (build) {
const { rootDir = options.rootDir || process.cwd() } = options;
const tmpDirPath = await fs.mkdtemp(
path.join(os.tmpdir(), "esbuild-plugin-postcss-"),
);
build.onResolve(
{ filter: /.\.(css)$/, namespace: "file" },
async (args) => {
const resolution = await build.resolve(args.path, {
resolveDir: args.resolveDir,
kind: args.kind,
});
if (resolution.errors.length > 0) {
return { errors: resolution.errors };
}
const sourceFullPath = resolution.path;
const sourceExt = path.extname(sourceFullPath);
const sourceBaseName = path.basename(sourceFullPath, sourceExt);
const sourceDir = path.dirname(sourceFullPath);
const sourceRelDir = path.relative(path.dirname(rootDir), sourceDir);
const tmpDir = path.resolve(tmpDirPath, sourceRelDir);
const tmpFilePath = path.resolve(tmpDir, `${sourceBaseName}.css`);
await fs.mkdir(tmpDir, { recursive: true });
const css = await fs.readFile(sourceFullPath);
const result = await postcss(options.plugins).process(css, {
from: sourceFullPath,
to: tmpFilePath,
});
await fs.writeFile(tmpFilePath, result.css);
return {
path: tmpFilePath,
watchFiles: [sourceFullPath],
};
},
);
},
});

View File

@@ -0,0 +1,67 @@
import { strict as assert } from "node:assert";
import path from "node:path";
import fs from "node:fs/promises";
import os from "node:os";
import * as esbuild from "esbuild";
import postcssPlugin from "../src/index.mjs";
import postcss from "postcss";
import autoprefixer from "autoprefixer";
// Create a temporary directory for our test
const tmpDir = await fs.mkdtemp(
path.join(os.tmpdir(), "esbuild-postcss-test-"),
);
const inputFile = path.join(tmpDir, "input.css");
const outputFile = path.join(tmpDir, "output.js");
// Create a simple CSS file for testing
const cssContent = `
.example {
display: flex;
user-select: none;
}
`;
// Write the test CSS file
await fs.writeFile(inputFile, cssContent);
// Test the plugin with autoprefixer
try {
console.log("Testing PostCSS plugin with autoprefixer...");
const result = await esbuild.build({
entryPoints: [inputFile],
bundle: true,
outfile: outputFile,
plugins: [
postcssPlugin({
plugins: [autoprefixer],
}),
],
});
console.log("Build completed successfully");
const outputContent = await fs.readFile(outputFile, "utf8");
assert(
outputContent.includes("-webkit-user-select"),
"Expected -webkit-user-select to be added by autoprefixer",
);
assert(
outputContent.includes("-moz-user-select"),
"Expected -moz-user-select to be added by autoprefixer",
);
console.log("Test passed: Autoprefixer correctly processed CSS");
} catch (error) {
console.error("Test failed:", error);
process.exit(1);
} finally {
try {
await fs.rm(tmpDir, { recursive: true, force: true });
console.log("Cleaned up temporary test files");
} catch (cleanupError) {
console.warn("Warning: Failed to clean up temporary files:", cleanupError);
}
}