diff --git a/apps/console/package.json b/apps/console/package.json index c9f61d3ab..7b1ed8a74 100644 --- a/apps/console/package.json +++ b/apps/console/package.json @@ -42,7 +42,7 @@ "@babel/core": "^7.26.7", "@babel/preset-env": "^7.26.7", "@babel/preset-typescript": "^7.26.0", - "@deanc/esbuild-plugin-postcss": "^1.0.2", + "@probo/esbuild-plugin-postcss": "^0.0.1", "@eslint/js": "^9.21.0", "@probo/tsconfig": "^0.0.1", "@tailwindcss/postcss": "^4.0.9", diff --git a/apps/console/scripts/esbuild.mjs b/apps/console/scripts/esbuild.mjs index aed0cc20b..6994b03e5 100644 --- a/apps/console/scripts/esbuild.mjs +++ b/apps/console/scripts/esbuild.mjs @@ -1,5 +1,5 @@ import babel from "@babel/core"; -import postCssPlugin from "@deanc/esbuild-plugin-postcss"; +import postCssPlugin from "@probo/esbuild-plugin-postcss"; import autoprefixer from "autoprefixer"; import { execSync, spawn } from "child_process"; import * as esbuild from "esbuild"; @@ -9,7 +9,6 @@ import path from "node:path"; import process from "node:process"; import tailwindcssPlugin from "@tailwindcss/postcss"; - async function copyRecursive(src, dest) { await fs.mkdir(dest, { recursive: true }); const files = await fs.readdir(src); diff --git a/apps/console/src/App.css b/apps/console/src/App.css index 697db477c..4f3930d1d 100644 --- a/apps/console/src/App.css +++ b/apps/console/src/App.css @@ -1,4 +1,4 @@ -@import 'tailwindcss'; +@import "tailwindcss"; @plugin 'tailwindcss-animate'; diff --git a/apps/console/src/App.tsx b/apps/console/src/App.tsx index 276e39bdb..6e76d8cf6 100644 --- a/apps/console/src/App.tsx +++ b/apps/console/src/App.tsx @@ -5,7 +5,7 @@ import { createRoot } from "react-dom/client"; import { HelmetProvider } from "react-helmet-async"; import { RelayEnvironmentProvider } from "react-relay"; import { BrowserRouter, Route, Routes, useLocation } from "react-router"; -import "App.css"; +import "./App.css"; import ErrorBoundary from "./components/ErrorBoundary"; import ConsoleLayout from "./layouts/ConsoleLayout"; import AuthLayout from "./layouts/AuthLayout"; diff --git a/package-lock.json b/package-lock.json index 3640a045e..809086965 100644 --- a/package-lock.json +++ b/package-lock.json @@ -49,8 +49,8 @@ "@babel/core": "^7.26.7", "@babel/preset-env": "^7.26.7", "@babel/preset-typescript": "^7.26.0", - "@deanc/esbuild-plugin-postcss": "^1.0.2", "@eslint/js": "^9.21.0", + "@probo/esbuild-plugin-postcss": "^0.0.1", "@probo/tsconfig": "^0.0.1", "@tailwindcss/postcss": "^4.0.9", "@types/babel-core": "^6.25.10", @@ -1679,23 +1679,6 @@ "node": ">=6.9.0" } }, - "node_modules/@deanc/esbuild-plugin-postcss": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@deanc/esbuild-plugin-postcss/-/esbuild-plugin-postcss-1.0.2.tgz", - "integrity": "sha512-+WAlrGxipNmcnr9lWlrmzC0mevQ7QqL31bMJu38AyOV44APSoqtzXh103sAkbolKxMcVhuw78m4xjdTKNjvpYA==", - "dev": true, - "license": "ISC", - "dependencies": { - "autoprefixer": "^10.2.4", - "css-tree": "^1.1.2", - "fs-extra": "^9.0.1", - "postcss": "^8.2.4", - "tmp": "^0.2.1" - }, - "peerDependencies": { - "esbuild": "^0.8.32" - } - }, "node_modules/@esbuild/aix-ppc64": { "version": "0.25.0", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.0.tgz", @@ -2556,6 +2539,10 @@ "resolved": "apps/console", "link": true }, + "node_modules/@probo/esbuild-plugin-postcss": { + "resolved": "packages/esbuild-plugin-postcss", + "link": true + }, "node_modules/@probo/tsconfig": { "resolved": "packages/tsconfig", "link": true @@ -4242,16 +4229,6 @@ "node": ">= 0.4" } }, - "node_modules/at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">= 4.0.0" - } - }, "node_modules/autoprefixer": { "version": "10.4.20", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz", @@ -4767,20 +4744,6 @@ "node": ">= 8" } }, - "node_modules/css-tree": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", - "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "mdn-data": "2.0.14", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, "node_modules/csstype": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", @@ -5668,22 +5631,6 @@ "url": "https://github.com/sponsors/rawify" } }, - "node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -6557,19 +6504,6 @@ "node": ">=6" } }, - "node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, "node_modules/jsx-ast-utils": { "version": "3.3.5", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", @@ -6927,13 +6861,6 @@ "node": ">= 0.4" } }, - "node_modules/mdn-data": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", - "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==", - "dev": true, - "license": "CC0-1.0" - }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -6985,7 +6912,6 @@ "version": "3.3.8", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", - "dev": true, "funding": [ { "type": "github", @@ -7302,7 +7228,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, "license": "ISC" }, "node_modules/picomatch": { @@ -7332,7 +7257,6 @@ "version": "8.5.1", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.1.tgz", "integrity": "sha512-6oz2beyjc5VMn/KV1pPw8fliQkhBXrVn1Z3TVyqZxU8kZpzEKhBdmCFqI6ZbmGtamQvQGuU1sgPTk8ZrXDD7jQ==", - "dev": true, "funding": [ { "type": "opencollective", @@ -8067,21 +7991,10 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -8266,16 +8179,6 @@ "node": ">=6" } }, - "node_modules/tmp": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", - "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.14" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -8544,16 +8447,6 @@ "node": ">=4" } }, - "node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10.0.0" - } - }, "node_modules/update-browserslist-db": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.2.tgz", @@ -8804,6 +8697,20 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "packages/esbuild-plugin-postcss": { + "name": "@probo/esbuild-plugin-postcss", + "version": "0.0.1", + "dependencies": { + "postcss": "^8.5" + }, + "devDependencies": { + "autoprefixer": "^10.4.20", + "esbuild": "^0.25.0" + }, + "peerDependencies": { + "esbuild": "^0.25.0" + } + }, "packages/tsconfig": { "name": "@probo/tsconfig", "version": "0.0.1", diff --git a/packages/esbuild-plugin-postcss/package.json b/packages/esbuild-plugin-postcss/package.json new file mode 100644 index 000000000..5eb4938d9 --- /dev/null +++ b/packages/esbuild-plugin-postcss/package.json @@ -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" + } +} diff --git a/packages/esbuild-plugin-postcss/src/index.mjs b/packages/esbuild-plugin-postcss/src/index.mjs new file mode 100644 index 000000000..d5a806170 --- /dev/null +++ b/packages/esbuild-plugin-postcss/src/index.mjs @@ -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], + }; + }, + ); + }, +}); diff --git a/packages/esbuild-plugin-postcss/tests/esbuild.test.mjs b/packages/esbuild-plugin-postcss/tests/esbuild.test.mjs new file mode 100644 index 000000000..6adf45ea7 --- /dev/null +++ b/packages/esbuild-plugin-postcss/tests/esbuild.test.mjs @@ -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); + } +}