@ecopages/postcss-processor
Advanced tools
| import type postcss from 'postcss'; | ||
| /** | ||
| * Finds the nearest directory containing a package.json by walking up from a file path. | ||
| * Falls back to `process.cwd()` when no package.json is found. | ||
| */ | ||
| export declare function resolveAppRootFromPath(filePath: string): string; | ||
| /** | ||
| * Creates a postcss-import instance that resolves bare package imports from the app root. | ||
| */ | ||
| export declare function createAppAwarePostcssImport(appRoot: string): postcss.AcceptedPlugin; |
| import { existsSync, readFileSync } from "node:fs"; | ||
| import { createRequire } from "node:module"; | ||
| import path from "node:path"; | ||
| import postcssImportDefault from "postcss-import"; | ||
| const requireFromProcessor = createRequire(import.meta.url); | ||
| function resolveAppRootFromPath(filePath) { | ||
| let dir = path.dirname(path.resolve(filePath)); | ||
| const filesystemRoot = path.parse(dir).root; | ||
| while (dir !== filesystemRoot) { | ||
| if (existsSync(path.join(dir, "package.json"))) { | ||
| return dir; | ||
| } | ||
| const parent = path.dirname(dir); | ||
| if (parent === dir) { | ||
| break; | ||
| } | ||
| dir = parent; | ||
| } | ||
| return process.cwd(); | ||
| } | ||
| function loadPostcssImport(requireFromApp) { | ||
| try { | ||
| return requireFromApp("postcss-import"); | ||
| } catch { | ||
| return postcssImportDefault; | ||
| } | ||
| } | ||
| function loadResolveImportId(requireFromApp) { | ||
| try { | ||
| return requireFromApp("postcss-import/lib/resolve-id"); | ||
| } catch { | ||
| return requireFromProcessor("postcss-import/lib/resolve-id"); | ||
| } | ||
| } | ||
| function splitPackageSpecifier(id) { | ||
| if (id.startsWith("@")) { | ||
| const [scope, name, ...rest2] = id.split("/"); | ||
| return { | ||
| packageName: `${scope}/${name}`, | ||
| subpath: rest2.join("/") | ||
| }; | ||
| } | ||
| const [packageName, ...rest] = id.split("/"); | ||
| return { packageName, subpath: rest.join("/") }; | ||
| } | ||
| function resolveExportTarget(pkg, packageDir, subpath) { | ||
| const exports = pkg.exports; | ||
| if (!exports) { | ||
| return null; | ||
| } | ||
| const keys = [`./${subpath}`, `./${subpath.replace(/\.css$/, "")}`]; | ||
| for (const key of keys) { | ||
| const entry = exports[key]; | ||
| if (!entry) { | ||
| continue; | ||
| } | ||
| const target = typeof entry === "string" ? entry : entry.style ?? entry.import ?? entry.require ?? entry.default; | ||
| if (!target) { | ||
| continue; | ||
| } | ||
| const resolved = path.join(packageDir, target); | ||
| if (existsSync(resolved)) { | ||
| return resolved; | ||
| } | ||
| } | ||
| return null; | ||
| } | ||
| function resolveBarePackageImport(id, requireFromApp) { | ||
| const { packageName, subpath } = splitPackageSpecifier(id); | ||
| const packageJsonPath = requireFromApp.resolve(`${packageName}/package.json`); | ||
| const packageDir = path.dirname(packageJsonPath); | ||
| const pkg = JSON.parse(readFileSync(packageJsonPath, "utf-8")); | ||
| if (subpath) { | ||
| const directPath = path.join(packageDir, subpath); | ||
| if (existsSync(directPath)) { | ||
| return directPath; | ||
| } | ||
| const exportPath = resolveExportTarget(pkg, packageDir, subpath); | ||
| if (exportPath) { | ||
| return exportPath; | ||
| } | ||
| throw new Error(`Unable to resolve "${id}"`); | ||
| } | ||
| if (pkg.style) { | ||
| const stylePath = path.join(packageDir, pkg.style); | ||
| if (existsSync(stylePath)) { | ||
| return stylePath; | ||
| } | ||
| } | ||
| const indexCssPath = path.join(packageDir, "index.css"); | ||
| if (existsSync(indexCssPath)) { | ||
| return indexCssPath; | ||
| } | ||
| if (pkg.main && /\.css$/.test(pkg.main)) { | ||
| const mainPath = path.join(packageDir, pkg.main); | ||
| if (existsSync(mainPath)) { | ||
| return mainPath; | ||
| } | ||
| } | ||
| throw new Error(`Unable to resolve CSS entry for package "${id}"`); | ||
| } | ||
| function createAppAwarePostcssImport(appRoot) { | ||
| const requireFromApp = createRequire(path.join(appRoot, "package.json")); | ||
| const postcssImport = loadPostcssImport(requireFromApp); | ||
| const resolveImportId = loadResolveImportId(requireFromApp); | ||
| const resolve = (id, base, options, node) => { | ||
| return resolveImportId(id, base, options, node).catch((error) => { | ||
| if (id.startsWith(".") || path.isAbsolute(id)) { | ||
| throw error; | ||
| } | ||
| try { | ||
| return resolveBarePackageImport(id, requireFromApp); | ||
| } catch { | ||
| throw error; | ||
| } | ||
| }); | ||
| }; | ||
| return postcssImport({ | ||
| root: appRoot, | ||
| resolve | ||
| }); | ||
| } | ||
| export { | ||
| createAppAwarePostcssImport, | ||
| resolveAppRootFromPath | ||
| }; |
+3
-3
| { | ||
| "name": "@ecopages/postcss-processor", | ||
| "version": "0.2.0-beta.4", | ||
| "version": "0.2.0-beta.5", | ||
| "description": "Postcss processor, transform string or postcss file to css", | ||
@@ -20,3 +20,3 @@ "keywords": [ | ||
| "dependencies": { | ||
| "@ecopages/file-system": "0.2.0-beta.4", | ||
| "@ecopages/file-system": "0.2.0-beta.5", | ||
| "@ecopages/logger": "^0.2.3", | ||
@@ -31,3 +31,3 @@ "autoprefixer": "^10.5.0", | ||
| "peerDependencies": { | ||
| "@ecopages/core": "0.2.0-beta.4", | ||
| "@ecopages/core": "0.2.0-beta.5", | ||
| "@tailwindcss/postcss": ">=4", | ||
@@ -34,0 +34,0 @@ "tailwindcss": ">=3" |
| import autoprefixer from "autoprefixer"; | ||
| import browserslist from "browserslist"; | ||
| import cssnano from "cssnano"; | ||
| import postcssImport from "postcss-import"; | ||
| import { createAppAwarePostcssImport } from "../postcss-import-app-aware.js"; | ||
| import tailwindcss from "tailwindcss"; | ||
| import tailwindcssNesting from "tailwindcss/nesting/index.js"; | ||
| function tailwindV3Preset() { | ||
| const appRoot = process.cwd(); | ||
| const browserslistConfig = browserslist.loadConfig({ path: process.cwd() }); | ||
@@ -13,3 +14,3 @@ const autoprefixerOptions = browserslistConfig ? {} : { | ||
| const pluginFactories = { | ||
| "postcss-import": () => postcssImport(), | ||
| "postcss-import": () => createAppAwarePostcssImport(appRoot), | ||
| "tailwindcss/nesting": () => tailwindcssNesting(), | ||
@@ -16,0 +17,0 @@ tailwindcss: () => tailwindcss(), |
@@ -6,6 +6,7 @@ import tailwindcss from "@tailwindcss/postcss"; | ||
| import path from "node:path"; | ||
| import postcssImport from "postcss-import"; | ||
| import postcssNested from "postcss-nested"; | ||
| import { createAppAwarePostcssImport, resolveAppRootFromPath } from "../postcss-import-app-aware.js"; | ||
| function tailwindV4Preset(options) { | ||
| const { referencePath } = options; | ||
| const appRoot = resolveAppRootFromPath(referencePath); | ||
| const browserslistConfig = browserslist.loadConfig({ path: process.cwd() }); | ||
@@ -19,3 +20,3 @@ const autoprefixerOptions = browserslistConfig ? {} : { | ||
| const pluginFactories = { | ||
| "postcss-import": () => postcssImport(), | ||
| "postcss-import": () => createAppAwarePostcssImport(appRoot), | ||
| "postcss-nested": () => postcssNested(), | ||
@@ -22,0 +23,0 @@ "@tailwindcss/postcss": createTailwindPlugin, |
47171
10.3%23
9.52%1143
13.73%+ Added
+ Added
- Removed
- Removed