diff --git a/__tests__/utils.test.ts b/__tests__/utils.test.ts index efc64df..37ea9f4 100644 --- a/__tests__/utils.test.ts +++ b/__tests__/utils.test.ts @@ -3,7 +3,7 @@ import postcss from "postcss"; import Loaders from "../src/loaders"; import postcssNoop from "../src/loaders/postcss/noop"; import loadSass from "../src/loaders/sass/load"; -import { ensurePCSSOption } from "../src/utils/options"; +import { ensurePCSSOption, ensurePCSSPlugins } from "../src/utils/options"; import { mm, getMap, stripMap } from "../src/utils/sourcemap"; import { humanlizePath } from "../src/utils/path"; @@ -21,16 +21,16 @@ test("noop", async () => { }); describe("load-module", () => { - test("wrong path", () => { - expect(loadModule("totallyWRONGPATH/here")).toBeUndefined(); + test("wrong path", async () => { + expect(await loadModule("totallyWRONGPATH/here")).toBeUndefined(); }); - test("correct cwd path", () => { - expect(loadModule(humanlizePath(fixture("utils/fixture")))).toBe("this is fixture"); + test("correct cwd path", async () => { + expect(await loadModule(humanlizePath(fixture("utils/fixture")))).toBe("this is fixture"); }); - test("correct absolute path", () => { - expect(loadModule(fixture("utils/fixture"))).toBe("this is fixture"); + test("correct absolute path", async () => { + expect(await loadModule(fixture("utils/fixture"))).toBe("this is fixture"); }); }); @@ -68,8 +68,14 @@ describe("load-sass", () => { }); describe("option-utils", () => { - test("wrong postcss option", () => { - expect(() => ensurePCSSOption("pumpinizer", "plugin")).toThrowErrorMatchingSnapshot(); + test("wrong postcss option", async () => { + await expect(ensurePCSSOption("pumpinizer", "plugin")).rejects.toThrowErrorMatchingSnapshot(); + }); + + test("plugin as array without options", async () => { + const plugins = await ensurePCSSPlugins([["autoprefixer"]]); + expect(plugins).toHaveLength(1); + expect(typeof plugins[0]).toBe("function"); }); }); diff --git a/package-lock.json b/package-lock.json index 8901d18..cc411e1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,12 +10,12 @@ "license": "MIT", "dependencies": { "@rollup/pluginutils": "^5.0.0", - "cosmiconfig": "^8.0.0", + "cosmiconfig": "^9.0.0", "cssnano": "^7.0.0", "fs-extra": "^11.0.0", "icss-utils": "^5.1.0", - "mime-types": "^2.1.35", - "p-queue": "^8.0.0", + "mime-types": "^3.0.0", + "p-queue": "^9.0.0", "postcss": "^8.4.31", "postcss-modules-extract-imports": "^3.0.0", "postcss-modules-local-by-default": "^4.0.3", @@ -46,7 +46,7 @@ "@types/fs-extra": "^11.0.0", "@types/jest": "^29.0.0", "@types/less": "^3.0.6", - "@types/mime-types": "^2.1.4", + "@types/mime-types": "^3.0.0", "@types/node": "^22.0.0", "@types/resolve": "^1.20.5", "@types/stylus": "^0.48.42", @@ -68,7 +68,7 @@ "less": "^4.2.0", "lint-staged": "^15.0.0", "minireset.css": "^0.0.7", - "postcss-custom-properties": "^14.0.0", + "postcss-custom-properties": "^15.0.0", "prettier": "^3.0.0", "rollup": "^4.4.1", "rollup-plugin-dts": "^6.1.0", @@ -78,14 +78,14 @@ "semantic-release": "^25.0.1", "shx": "^0.3.4", "stylus": "^0.61.0", - "sugarss": "^4.0.1", + "sugarss": "^5.0.0", "ts-jest": "^29.0.0", "typedoc": "^0.27.0", "typedoc-plugin-missing-exports": "^3.0.0", "typescript": "^5.0.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=20.19.0" }, "peerDependencies": { "rollup": "^2.63.0 || ^3.0.0 || ^4.0.0" @@ -2103,40 +2103,6 @@ "node": ">=v18" } }, - "node_modules/@commitlint/load/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, - "license": "Python-2.0" - }, - "node_modules/@commitlint/load/node_modules/cosmiconfig": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.2.tgz", - "integrity": "sha512-gtTZxTDau1wL7Y7zifc2dd8jHSK/k6BTx/2Xp/BpdlAdnlYWFVt7qhJqgwi7637yRwRQ3qL4ZidbB4I8tA5VOg==", - "dev": true, - "license": "MIT", - "dependencies": { - "env-paths": "^2.2.1", - "import-fresh": "^3.3.0", - "js-yaml": "^4.1.0", - "parse-json": "^5.2.0" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/d-fischer" - }, - "peerDependencies": { - "typescript": ">=4.9.5" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, "node_modules/@commitlint/load/node_modules/cosmiconfig-typescript-loader": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-6.3.0.tgz", @@ -2155,29 +2121,6 @@ "typescript": ">=5" } }, - "node_modules/@commitlint/load/node_modules/js-yaml": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.0.tgz", - "integrity": "sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/puzrin" - }, - { - "type": "github", - "url": "https://github.com/sponsors/nodeca" - } - ], - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, "node_modules/@commitlint/message": { "version": "20.4.3", "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-20.4.3.tgz", @@ -2316,40 +2259,6 @@ "node": ">=v18" } }, - "node_modules/@commitlint/prompt/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, - "license": "Python-2.0" - }, - "node_modules/@commitlint/prompt/node_modules/cosmiconfig": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.2.tgz", - "integrity": "sha512-gtTZxTDau1wL7Y7zifc2dd8jHSK/k6BTx/2Xp/BpdlAdnlYWFVt7qhJqgwi7637yRwRQ3qL4ZidbB4I8tA5VOg==", - "dev": true, - "license": "MIT", - "dependencies": { - "env-paths": "^2.2.1", - "import-fresh": "^3.3.0", - "js-yaml": "^4.1.0", - "parse-json": "^5.2.0" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/d-fischer" - }, - "peerDependencies": { - "typescript": ">=4.9.5" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, "node_modules/@commitlint/prompt/node_modules/cosmiconfig-typescript-loader": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-6.3.0.tgz", @@ -2394,29 +2303,6 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/@commitlint/prompt/node_modules/js-yaml": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.0.tgz", - "integrity": "sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/puzrin" - }, - { - "type": "github", - "url": "https://github.com/sponsors/nodeca" - } - ], - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, "node_modules/@commitlint/read": { "version": "20.5.0", "resolved": "https://registry.npmjs.org/@commitlint/read/-/read-20.5.0.tgz", @@ -2560,9 +2446,9 @@ } }, "node_modules/@csstools/cascade-layer-name-parser": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@csstools/cascade-layer-name-parser/-/cascade-layer-name-parser-2.0.5.tgz", - "integrity": "sha512-p1ko5eHgV+MgXFVa4STPKpvPxr6ReS8oS2jzTukjR74i5zJNyWO1ZM1m8YKBXnzDKWfBN1ztLYlHxbVemDD88A==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@csstools/cascade-layer-name-parser/-/cascade-layer-name-parser-3.0.0.tgz", + "integrity": "sha512-/3iksyevwRfSJx5yH0RkcrcYXwuhMQx3Juqf40t97PeEy2/Mz2TItZ/z/216qpe4GgOyFBP8MKIwVvytzHmfIQ==", "dev": true, "funding": [ { @@ -2576,17 +2462,17 @@ ], "license": "MIT", "engines": { - "node": ">=18" + "node": ">=20.19.0" }, "peerDependencies": { - "@csstools/css-parser-algorithms": "^3.0.5", - "@csstools/css-tokenizer": "^3.0.4" + "@csstools/css-parser-algorithms": "^4.0.0", + "@csstools/css-tokenizer": "^4.0.0" } }, "node_modules/@csstools/css-parser-algorithms": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.5.tgz", - "integrity": "sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-4.0.0.tgz", + "integrity": "sha512-+B87qS7fIG3L5h3qwJ/IFbjoVoOe/bpOdh9hAjXbvx0o8ImEmUsGXN0inFOnk2ChCFgqkkGFQ+TpM5rbhkKe4w==", "dev": true, "funding": [ { @@ -2600,16 +2486,16 @@ ], "license": "MIT", "engines": { - "node": ">=18" + "node": ">=20.19.0" }, "peerDependencies": { - "@csstools/css-tokenizer": "^3.0.4" + "@csstools/css-tokenizer": "^4.0.0" } }, "node_modules/@csstools/css-tokenizer": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.4.tgz", - "integrity": "sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-4.0.0.tgz", + "integrity": "sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA==", "dev": true, "funding": [ { @@ -2623,13 +2509,13 @@ ], "license": "MIT", "engines": { - "node": ">=18" + "node": ">=20.19.0" } }, "node_modules/@csstools/utilities": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@csstools/utilities/-/utilities-2.0.0.tgz", - "integrity": "sha512-5VdOr0Z71u+Yp3ozOx8T11N703wIFGVRgOWbOZMKgglPJsWA54MRIoMNVMa7shUToIhx5J8vX4sOZgD2XiihiQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@csstools/utilities/-/utilities-3.0.0.tgz", + "integrity": "sha512-etDqA/4jYvOGBM6yfKCOsEXfH96BKztZdgGmGqKi2xHnDe0ILIBraRspwgYatJH9JsCZ5HCGoCst8w18EKOAdg==", "dev": true, "funding": [ { @@ -2643,7 +2529,7 @@ ], "license": "MIT-0", "engines": { - "node": ">=18" + "node": ">=20.19.0" }, "peerDependencies": { "postcss": "^8.4" @@ -5577,9 +5463,9 @@ "license": "MIT" }, "node_modules/@types/mime-types": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@types/mime-types/-/mime-types-2.1.4.tgz", - "integrity": "sha512-lfU4b34HOri+kAY5UheuFMWPDOI+OPceBSHZKp69gEyTL/mmJ4cnU6Y/rlme3UL3GyOn6Y42hyIEw0/q8sWx5w==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/mime-types/-/mime-types-3.0.1.tgz", + "integrity": "sha512-xRMsfuQbnRq1Ef+C+RKaENOxXX87Ygl38W1vDfPHRku02TgQr+Qd8iivLtAMcR0KF5/29xlnFihkTlbqFrGOVQ==", "dev": true, "license": "MIT" }, @@ -7356,15 +7242,15 @@ "license": "MIT" }, "node_modules/cosmiconfig": { - "version": "8.3.6", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", - "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.2.tgz", + "integrity": "sha512-gtTZxTDau1wL7Y7zifc2dd8jHSK/k6BTx/2Xp/BpdlAdnlYWFVt7qhJqgwi7637yRwRQ3qL4ZidbB4I8tA5VOg==", "license": "MIT", "dependencies": { + "env-paths": "^2.2.1", "import-fresh": "^3.3.0", "js-yaml": "^4.1.0", - "parse-json": "^5.2.0", - "path-type": "^4.0.0" + "parse-json": "^5.2.0" }, "engines": { "node": ">=14" @@ -8258,7 +8144,6 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -13392,24 +13277,28 @@ } }, "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", + "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", "license": "MIT", "dependencies": { - "mime-db": "1.52.0" + "mime-db": "^1.54.0" }, "engines": { - "node": ">= 0.6" + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/mimic-fn": { @@ -15989,16 +15878,28 @@ } }, "node_modules/p-queue": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-8.1.1.tgz", - "integrity": "sha512-aNZ+VfjobsWryoiPnEApGGmf5WmNsCo9xu8dfaYamG5qaLP7ClhLN6NgsFe6SwJ2UbLEBK5dv9x8Mn5+RVhMWQ==", + "version": "9.3.3", + "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-9.3.3.tgz", + "integrity": "sha512-NXAOdnEe5FsZJfT4oK84lE1Y5cFFdWlRuOo5tww8DyNMxyRXwn39fIkUtNLKppcPC+UYU/bXujNCUGDv01y7CA==", "license": "MIT", "dependencies": { - "eventemitter3": "^5.0.1", - "p-timeout": "^6.1.2" + "eventemitter3": "^5.0.4", + "p-timeout": "^7.0.0" }, "engines": { - "node": ">=18" + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-queue/node_modules/p-timeout": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-7.0.1.tgz", + "integrity": "sha512-AxTM2wDGORHGEkPCt8yqxOTMgpfbEHqF51f/5fJCmwFC3C/zNcGT63SymH2ttOAaiIws2zVg4+izQCjrakcwHg==", + "license": "MIT", + "engines": { + "node": ">=20" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -16018,6 +15919,7 @@ "version": "6.1.4", "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-6.1.4.tgz", "integrity": "sha512-MyIV3ZA/PmyBN/ud8vV9XzwTrNtR4jFrObymZYnZqMmW0zA8Z17vnT0rBgFE/TlohB+YCHqXMgZzb3Csp49vqg==", + "dev": true, "license": "MIT", "engines": { "node": ">=14.16" @@ -16153,6 +16055,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -16408,9 +16311,9 @@ } }, "node_modules/postcss-custom-properties": { - "version": "14.0.6", - "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-14.0.6.tgz", - "integrity": "sha512-fTYSp3xuk4BUeVhxCSJdIPhDLpJfNakZKoiTDx7yRGCdlZrSJR7mWKVOBS4sBF+5poPQFMj2YdXx1VHItBGihQ==", + "version": "15.0.1", + "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-15.0.1.tgz", + "integrity": "sha512-cuyq8sd8dLY0GLbelz1KB8IMIoDECo6RVXMeHeXY2Uw3Q05k/d1GVITdaKLsheqrHbnxlwxzSRZQQ5u+rNtbMg==", "dev": true, "funding": [ { @@ -16424,14 +16327,14 @@ ], "license": "MIT", "dependencies": { - "@csstools/cascade-layer-name-parser": "^2.0.5", - "@csstools/css-parser-algorithms": "^3.0.5", - "@csstools/css-tokenizer": "^3.0.4", - "@csstools/utilities": "^2.0.0", + "@csstools/cascade-layer-name-parser": "^3.0.0", + "@csstools/css-parser-algorithms": "^4.0.0", + "@csstools/css-tokenizer": "^4.0.0", + "@csstools/utilities": "^3.0.0", "postcss-value-parser": "^4.2.0" }, "engines": { - "node": ">=18" + "node": ">=20.19.0" }, "peerDependencies": { "postcss": "^8.4" @@ -18071,13 +17974,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/semantic-release/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, - "license": "Python-2.0" - }, "node_modules/semantic-release/node_modules/clean-stack": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-5.3.0.tgz", @@ -18127,33 +18023,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/semantic-release/node_modules/cosmiconfig": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.2.tgz", - "integrity": "sha512-gtTZxTDau1wL7Y7zifc2dd8jHSK/k6BTx/2Xp/BpdlAdnlYWFVt7qhJqgwi7637yRwRQ3qL4ZidbB4I8tA5VOg==", - "dev": true, - "license": "MIT", - "dependencies": { - "env-paths": "^2.2.1", - "import-fresh": "^3.3.0", - "js-yaml": "^4.1.0", - "parse-json": "^5.2.0" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/d-fischer" - }, - "peerDependencies": { - "typescript": ">=4.9.5" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, "node_modules/semantic-release/node_modules/emoji-regex": { "version": "10.6.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", @@ -18267,29 +18136,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/semantic-release/node_modules/js-yaml": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.0.tgz", - "integrity": "sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/puzrin" - }, - { - "type": "github", - "url": "https://github.com/sponsors/nodeca" - } - ], - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, "node_modules/semantic-release/node_modules/lru-cache": { "version": "11.5.2", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.2.tgz", @@ -19366,17 +19212,23 @@ } }, "node_modules/sugarss": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/sugarss/-/sugarss-4.0.1.tgz", - "integrity": "sha512-WCjS5NfuVJjkQzK10s8WOBY+hhDxxNt/N6ZaGwxFZ+wN3/lKKFSaaKUNecULcTTvE4urLcKaZFQD8vO0mOZujw==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/sugarss/-/sugarss-5.0.1.tgz", + "integrity": "sha512-ctS5RYCBVvPoZAnzIaX5QSShK8ZiZxD5HUqSxlusvEMC+QZQIPCPOIJg6aceFX+K2rf4+SH89eu++h1Zmsr2nw==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "license": "MIT", "engines": { - "node": ">=12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" + "node": ">=18.0" }, "peerDependencies": { "postcss": "^8.3.3" diff --git a/package.json b/package.json index 39be80b..f4e5c09 100644 --- a/package.json +++ b/package.json @@ -54,12 +54,12 @@ }, "dependencies": { "@rollup/pluginutils": "^5.0.0", - "cosmiconfig": "^8.0.0", + "cosmiconfig": "^9.0.0", "cssnano": "^7.0.0", "fs-extra": "^11.0.0", "icss-utils": "^5.1.0", - "mime-types": "^2.1.35", - "p-queue": "^8.0.0", + "mime-types": "^3.0.0", + "p-queue": "^9.0.0", "postcss": "^8.4.31", "postcss-modules-extract-imports": "^3.0.0", "postcss-modules-local-by-default": "^4.0.3", @@ -90,7 +90,7 @@ "@types/fs-extra": "^11.0.0", "@types/jest": "^29.0.0", "@types/less": "^3.0.6", - "@types/mime-types": "^2.1.4", + "@types/mime-types": "^3.0.0", "@types/node": "^22.0.0", "@types/resolve": "^1.20.5", "@types/stylus": "^0.48.42", @@ -112,7 +112,7 @@ "less": "^4.2.0", "lint-staged": "^15.0.0", "minireset.css": "^0.0.7", - "postcss-custom-properties": "^14.0.0", + "postcss-custom-properties": "^15.0.0", "prettier": "^3.0.0", "rollup": "^4.4.1", "rollup-plugin-dts": "^6.1.0", @@ -122,7 +122,7 @@ "semantic-release": "^25.0.1", "shx": "^0.3.4", "stylus": "^0.61.0", - "sugarss": "^4.0.1", + "sugarss": "^5.0.0", "ts-jest": "^29.0.0", "typedoc": "^0.27.0", "typedoc-plugin-missing-exports": "^3.0.0", @@ -132,6 +132,6 @@ "rollup": "^2.63.0 || ^3.0.0 || ^4.0.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=20.19.0" } } diff --git a/src/index.ts b/src/index.ts index f7b1587..c1106c7 100644 --- a/src/index.ts +++ b/src/index.ts @@ -15,8 +15,6 @@ import { inferSourceMapOption, inferHandlerOption, ensureUseOption, - ensurePCSSOption, - ensurePCSSPlugins, } from "./utils/options"; export default (options: Options = {}): Plugin => { @@ -47,14 +45,13 @@ export default (options: Options = {}): Plugin => { ) throw new Error("`inject.treeshakeable` option is incompatible with `namedExports` option"); - if (options.parser) loaderOpts.postcss.parser = ensurePCSSOption(options.parser, "parser"); + if (options.parser) loaderOpts.postcss.parser = options.parser; - if (options.syntax) loaderOpts.postcss.syntax = ensurePCSSOption(options.syntax, "syntax"); + if (options.syntax) loaderOpts.postcss.syntax = options.syntax; - if (options.stringifier) - loaderOpts.postcss.stringifier = ensurePCSSOption(options.stringifier, "stringifier"); + if (options.stringifier) loaderOpts.postcss.stringifier = options.stringifier; - if (options.plugins) loaderOpts.postcss.plugins = ensurePCSSPlugins(options.plugins); + if (options.plugins) loaderOpts.postcss.plugins = options.plugins; const loaders = new Loaders({ use: [["postcss", loaderOpts], ...ensureUseOption(options), ["sourcemap", {}]], diff --git a/src/loaders/postcss/config.ts b/src/loaders/postcss/config.ts index a1aa48f..e62904c 100644 --- a/src/loaders/postcss/config.ts +++ b/src/loaders/postcss/config.ts @@ -29,7 +29,9 @@ export default async function ( type Found = { config: Config | ((ctx: Record) => Config); isEmpty?: boolean }; const searchPath = config.path ? path.resolve(config.path) : dir; - const found: Found | null = await cosmiconfig("postcss").search(searchPath); + const found: Found | null = await cosmiconfig("postcss", { searchStrategy: "global" }).search( + searchPath, + ); if (!found || found.isEmpty) return { plugins: [], options: {} }; @@ -43,10 +45,10 @@ export default async function ( }) : found.config; - const result: Result = { plugins: ensurePCSSPlugins(plugins), options: {} }; - if (parser) result.options.parser = ensurePCSSOption(parser, "parser"); - if (syntax) result.options.syntax = ensurePCSSOption(syntax, "syntax"); - if (stringifier) result.options.stringifier = ensurePCSSOption(stringifier, "stringifier"); + const result: Result = { plugins: await ensurePCSSPlugins(plugins), options: {} }; + if (parser) result.options.parser = await ensurePCSSOption(parser, "parser"); + if (syntax) result.options.syntax = await ensurePCSSOption(syntax, "syntax"); + if (stringifier) result.options.stringifier = await ensurePCSSOption(stringifier, "stringifier"); return result; } diff --git a/src/loaders/postcss/index.ts b/src/loaders/postcss/index.ts index 0ec6122..3dce86a 100644 --- a/src/loaders/postcss/index.ts +++ b/src/loaders/postcss/index.ts @@ -8,6 +8,7 @@ import { PostCSSLoaderOptions, InjectOptions } from "../../types"; import { humanlizePath, normalizePath } from "../../utils/path"; import { mm } from "../../utils/sourcemap"; import { resolveAsync } from "../../utils/resolve"; +import { ensurePCSSOption, ensurePCSSPlugins } from "../../utils/options"; import safeId from "../../utils/safe-id"; import { Loader } from "../types"; import loadConfig from "./config"; @@ -67,12 +68,21 @@ const loader: Loader = { delete postcssOpts.plugins; + // Resolve string-based parser/syntax/stringifier/plugins lazily (async) + if (typeof postcssOpts.parser === "string") + postcssOpts.parser = await ensurePCSSOption(postcssOpts.parser, "parser"); + if (typeof postcssOpts.syntax === "string") + postcssOpts.syntax = await ensurePCSSOption(postcssOpts.syntax, "syntax"); + if (typeof postcssOpts.stringifier === "string") + postcssOpts.stringifier = await ensurePCSSOption(postcssOpts.stringifier, "stringifier"); + if (options.import) plugins.push(postcssImport({ extensions: options.extensions, ...options.import })); if (options.url) plugins.push(postcssUrl({ inline: Boolean(options.inject), ...options.url })); - if (options.postcss.plugins) plugins.push(...options.postcss.plugins); + if (options.postcss.plugins) + plugins.push(...(await ensurePCSSPlugins(options.postcss.plugins))); if (config.plugins) plugins.push(...config.plugins); @@ -96,7 +106,7 @@ const loader: Loader = { // Avoid PostCSS warning if (plugins.length === 0) plugins.push(postcssNoop); - const res = await postcss(plugins).process(code, postcssOpts); + const res = await postcss(plugins).process(code, postcssOpts as ProcessOptions); for (const msg of res.messages) switch (msg.type) { diff --git a/src/types.ts b/src/types.ts index e623731..68992f0 100644 --- a/src/types.ts +++ b/src/types.ts @@ -53,13 +53,13 @@ export interface PostCSSLoaderOptions extends Record { /** Options for PostCSS processor */ postcss: { /** @see {@link Options.parser} */ - parser?: postcss.Parser; + parser?: string | postcss.Parser; /** @see {@link Options.syntax} */ - syntax?: postcss.Syntax; + syntax?: string | postcss.Syntax; /** @see {@link Options.stringifier} */ - stringifier?: postcss.Stringifier; + stringifier?: string | postcss.Stringifier; /** @see {@link Options.plugins} */ - plugins?: postcss.AcceptedPlugin[]; + plugins?: Options["plugins"]; }; } diff --git a/src/utils/load-module.ts b/src/utils/load-module.ts index f576015..6bd6a53 100644 --- a/src/utils/load-module.ts +++ b/src/utils/load-module.ts @@ -1,4 +1,4 @@ -import { resolveSync, ResolveOpts } from "./resolve"; +import { resolveSync, ResolveOpts, packageFilterBuilder } from "./resolve"; import { createRequire } from "node:module"; const require = createRequire(import.meta.url); @@ -9,15 +9,23 @@ const options: ResolveOpts = { basedirs: [process.cwd()], extensions: [".js", ".mjs", ".cjs", ".json"], preserveSymlinks: false, - packageFilter: pkg => pkg, + packageFilter: packageFilterBuilder(), }; -export default function (moduleId: string): unknown { +export default async function (moduleId: string): Promise { if (loaded[moduleId]) return loaded[moduleId]; if (loaded[moduleId] === null) return; try { - loaded[moduleId] = require(resolveSync([moduleId, `./${moduleId}`], options)); + const resolved = resolveSync([moduleId, `./${moduleId}`], options); + try { + loaded[moduleId] = require(resolved); + } catch { + // ESM module that cannot be require()d (e.g. .mjs in jest VM context) + + const mod = (await import(resolved)) as { default: unknown }; + loaded[moduleId] = mod.default; + } } catch { loaded[moduleId] = null; return; diff --git a/src/utils/options.ts b/src/utils/options.ts index ba30eda..e12b14f 100644 --- a/src/utils/options.ts +++ b/src/utils/options.ts @@ -68,14 +68,14 @@ export function ensureUseOption(opts: Options): [string, Record } type PCSSOption = "parser" | "syntax" | "stringifier" | "plugin"; -export function ensurePCSSOption(option: T | string, type: PCSSOption): T { +export async function ensurePCSSOption(option: T | string, type: PCSSOption): Promise { if (typeof option !== "string") return option; - const module = loadModule(option); + const module = await loadModule(option); if (!module) throw new Error(`Unable to load PostCSS ${type} \`${option}\``); return module as T; } -export function ensurePCSSPlugins(plugins: Options["plugins"]): AcceptedPlugin[] { +export async function ensurePCSSPlugins(plugins: Options["plugins"]): Promise { if (plugins === undefined) return []; else if (typeof plugins !== "object") throw new TypeError("`plugins` option must be an array or an object!"); @@ -85,15 +85,18 @@ export function ensurePCSSPlugins(plugins: Options["plugins"]): AcceptedPlugin[] if (!p) continue; if (!Array.isArray(p)) { - ps.push(ensurePCSSOption(p, "plugin")); + // eslint-disable-next-line no-await-in-loop + ps.push(await ensurePCSSOption(p, "plugin")); continue; } const [plug, opts] = p; if (opts) { - ps.push(ensurePCSSOption(plug, "plugin")(opts)); + // eslint-disable-next-line no-await-in-loop + ps.push((await ensurePCSSOption(plug, "plugin"))(opts)); } else { - ps.push(ensurePCSSOption(plug, "plugin")); + // eslint-disable-next-line no-await-in-loop + ps.push(await ensurePCSSOption(plug, "plugin")); } } diff --git a/src/utils/resolve.ts b/src/utils/resolve.ts index c5cc7a6..acf9ee1 100644 --- a/src/utils/resolve.ts +++ b/src/utils/resolve.ts @@ -48,6 +48,10 @@ export const packageFilterBuilder: PackageFilterBuilderFn = (opts = {}) => { pkg.main = resolvedExport; return pkg; } + if (Array.isArray(resolvedExport) && resolvedExport.length > 0) { + pkg.main = resolvedExport[0]; + return pkg; + } } catch { /* noop */ }