diff --git a/.prettierrc.json b/.prettierrc.json index 0967ef42..84cc551f 100644 --- a/.prettierrc.json +++ b/.prettierrc.json @@ -1 +1,4 @@ -{} +{ + "$schema": "https://json.schemastore.org/prettierrc", + "singleQuote": true +} diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c451d9b..a6222958 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -61,6 +61,29 @@ + + + + +## v2.1.2 (2025-03-16) + +#### :bug: Bug Fix +* [#658](https://github.com/bmish/eslint-doc-generator/pull/658) Fix regression in ESM plugin loading ([@marcalexiei](https://github.com/marcalexiei)) + +#### :house: Internal +* [#654](https://github.com/bmish/eslint-doc-generator/pull/654) Use `.prettierrc.json` instead of `eslint` `prettier` rule to configure format options ([@marcalexiei](https://github.com/marcalexiei)) + +#### Committers: 1 +- Marco Pasqualetti ([@marcalexiei](https://github.com/marcalexiei)) + + +## v2.1.1 (2025-03-10) + +#### :bug: Bug Fix +* [#648](https://github.com/bmish/eslint-doc-generator/pull/648) Fix ESM support in Node 22+ when the package includes the `main` property ([@marcalexiei](https://github.com/marcalexiei)) + +#### Committers: 1 +- Marco Pasqualetti ([@marcalexiei](https://github.com/marcalexiei)) ## v2.1.0 (2025-03-04) diff --git a/eslint.config.js b/eslint.config.js index aae7129b..6f4f11ed 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -25,12 +25,7 @@ export default tseslint.config( rules: { 'n/no-missing-import': 'off', // bug with recognizing node: prefix https://github.com/mysticatea/eslint-plugin-node/issues/275 - 'prettier/prettier': [ - 'error', - { - singleQuote: true, - }, - ], + 'prettier/prettier': 'error', // see `.prettierrc.json` for format config // unicorn rules: 'unicorn/expiring-todo-comments': 'off', diff --git a/lib/package-json.ts b/lib/package-json.ts index 00b71bf6..f355eae4 100644 --- a/lib/package-json.ts +++ b/lib/package-json.ts @@ -35,8 +35,34 @@ async function loadPackageJson(path: string): Promise { export async function loadPlugin(path: string): Promise { const pluginRoot = getPluginRoot(path); try { - // Try require first which should work for CJS plugins. - return require(pluginRoot) as Plugin; // eslint-disable-line import/no-dynamic-require + /** + * Try require first which should work for CJS plugins. + * From Node 22 requiring on ESM module returns the module object + * @see https://github.com/bmish/eslint-doc-generator/issues/615 + */ + type cjsOrEsmPlugin = + | Plugin + | { + __esModule: boolean; + default: Plugin; + /* some plugins might have additional exports besides `default` */ + [key: string]: unknown; + }; + // eslint-disable-next-line import/no-dynamic-require + const _plugin = require(pluginRoot) as cjsOrEsmPlugin; + + /* istanbul ignore next */ + if ( + '__esModule' in _plugin && + _plugin.__esModule && + // Ensure that we return only the default key when only a default export is present + // @see https://github.com/bmish/eslint-doc-generator/issues/656#issuecomment-2726745618 + Object.keys(_plugin).length === 2 && + ['__esModule', 'default'].every((it) => Boolean(_plugin[it])) + ) { + return _plugin.default; + } + return _plugin as Plugin; } catch (error) { // Otherwise, for ESM plugins, we'll have to try to resolve the exact plugin entry point and import it. const pluginPackageJson = await loadPackageJson(path); diff --git a/package-lock.json b/package-lock.json index f73774bf..a39329ef 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "eslint-doc-generator", - "version": "2.1.0", + "version": "2.1.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "eslint-doc-generator", - "version": "2.1.0", + "version": "2.1.2", "license": "ISC", "dependencies": { "@typescript-eslint/utils": "^8.0.0", @@ -678,6 +678,15 @@ "node": "*" } }, + "node_modules/@eslint/config-helpers": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.1.0.tgz", + "integrity": "sha512-kLrdPDJE1ckPo94kmPPf9Hfd0DU0Jw6oKYrhe+pwSC0iTUInmTa+w6fw8sGgcfkFJGNdWOUeOaDM4quW4a7OkA==", + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@eslint/core": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.12.0.tgz", @@ -758,9 +767,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.21.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.21.0.tgz", - "integrity": "sha512-BqStZ3HX8Yz6LvsF5ByXYrtigrV5AXADWLAGc7PH/1SxOb7/FIYYMszZZWiUou/GB9P2lXWk2SV4d+Z8h0nknw==", + "version": "9.22.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.22.0.tgz", + "integrity": "sha512-vLFajx9o8d1/oL2ZkpMYbkLv8nDB6yaIwFNt7nI4+I80U/z03SxmfOMsLbvWr3p7C+Wnoh//aOu2pQW8cS0HCQ==", "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2067,9 +2076,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.13.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.4.tgz", - "integrity": "sha512-ywP2X0DYtX3y08eFVx5fNIw7/uIv8hYUKgXoK8oayJlLnKcRfEYCxWMVE1XagUdVtCJlZT1AU4LXEABW+L1Peg==", + "version": "22.13.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.10.tgz", + "integrity": "sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw==", "dev": true, "license": "MIT", "dependencies": { @@ -4699,17 +4708,18 @@ } }, "node_modules/eslint": { - "version": "9.21.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.21.0.tgz", - "integrity": "sha512-KjeihdFqTPhOMXTt7StsDxriV4n66ueuF/jfPNC3j/lduHwr/ijDwJMsF+wyMJethgiKi5wniIE243vi07d3pg==", + "version": "9.22.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.22.0.tgz", + "integrity": "sha512-9V/QURhsRN40xuHXWjV64yvrzMjcz7ZyNoF2jJFmy9j/SLk0u1OLSZgXi28MrXjymnjEGSR80WCdab3RGMDveQ==", "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.19.2", + "@eslint/config-helpers": "^0.1.0", "@eslint/core": "^0.12.0", "@eslint/eslintrc": "^3.3.0", - "@eslint/js": "9.21.0", + "@eslint/js": "9.22.0", "@eslint/plugin-kit": "^0.2.7", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", @@ -4721,7 +4731,7 @@ "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.2.0", + "eslint-scope": "^8.3.0", "eslint-visitor-keys": "^4.2.0", "espree": "^10.3.0", "esquery": "^1.5.0", @@ -5082,9 +5092,9 @@ } }, "node_modules/eslint-scope": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", - "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.3.0.tgz", + "integrity": "sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==", "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", @@ -11850,9 +11860,9 @@ } }, "node_modules/prettier": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.2.tgz", - "integrity": "sha512-lc6npv5PH7hVqozBR7lkBNOGXV9vMwROAPlumdBkX0wTbbzPu/U1hk5yL8p2pt4Xoc+2mkT8t/sow2YrV/M5qg==", + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz", + "integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==", "dev": true, "license": "MIT", "bin": { diff --git a/package.json b/package.json index 852af729..7612b2ed 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "eslint-doc-generator", - "version": "2.1.0", + "version": "2.1.2", "description": "Automatic documentation generator for ESLint plugins and rules.", "keywords": [ "doc", diff --git a/test/lib/generate/cjs-test.ts b/test/lib/generate/cjs-test.ts index 3c824056..a19b806f 100644 --- a/test/lib/generate/cjs-test.ts +++ b/test/lib/generate/cjs-test.ts @@ -62,11 +62,7 @@ describe('generate (cjs)', function () { describe('package.json `main` field points to non-existent file', function () { it('throws an error', async function () { - const FIXTURE_PATH = join( - 'test', - 'fixtures', - 'cjs-main-file-does-not-exist', - ); + const FIXTURE_PATH = join(FIXTURE_ROOT, 'cjs-main-file-does-not-exist'); await expect(generate(FIXTURE_PATH)).rejects.toThrow( /Cannot find module/u, );