diff --git a/.eslint-doc-generatorrc.js b/.eslint-doc-generatorrc.js index 126bdd6a..5c4ef3b6 100644 --- a/.eslint-doc-generatorrc.js +++ b/.eslint-doc-generatorrc.js @@ -1,6 +1,16 @@ +'use strict'; + /** @type {import('eslint-doc-generator').GenerateOptions} */ module.exports = { - ignoreConfig: ['all', 'rules', 'rules-recommended', 'tests', 'tests-recommended'], + ignoreConfig: [ + 'all', + 'rules', + 'rules-recommended', + 'tests', + 'tests-recommended', + ], ruleDocSectionInclude: ['Rule Details'], - urlConfigs: 'https://github.com/eslint-community/eslint-plugin-eslint-plugin#presets', + ruleListSplit: 'meta.docs.category', + urlConfigs: + 'https://github.com/eslint-community/eslint-plugin-eslint-plugin#presets', }; diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index 4ff2ad29..00000000 --- a/.eslintrc.js +++ /dev/null @@ -1,79 +0,0 @@ -'use strict'; - -module.exports = { - root: true, - parserOptions: { - ecmaVersion: 2021, - sourceType: 'script', - }, - extends: [ - 'not-an-aardvark/node', - 'plugin:eslint-comments/recommended', - 'plugin:node/recommended', - 'plugin:prettier/recommended', - 'plugin:unicorn/recommended', - ], - rules: { - 'comma-dangle': [ - 'error', - { - arrays: 'always-multiline', - objects: 'always-multiline', - functions: 'never', // disallow trailing commas in function(es2017) - }, - ], - 'require-jsdoc': 'error', - - 'eslint-comments/no-unused-disable': 'error', - 'eslint-comments/require-description': 'error', - - 'unicorn/consistent-function-scoping': 'off', - 'unicorn/no-array-callback-reference': 'off', - 'unicorn/no-array-for-each': 'off', - 'unicorn/no-array-reduce': 'off', - 'unicorn/no-null': 'off', - 'unicorn/prefer-module': 'off', - 'unicorn/prefer-node-protocol': 'off', // TODO: enable once we drop support for Node 14.17. - 'unicorn/prevent-abbreviations': 'off', - }, - overrides: [ - { - // Apply eslint-plugin rules to our own rules/tests (but not docs). - files: ['lib/**/*.js', 'tests/**/*.js'], - extends: ['plugin:eslint-plugin/all'], - rules: { - 'eslint-plugin/report-message-format': ['error', '^[^a-z].*.$'], - 'eslint-plugin/require-meta-docs-url': [ - 'error', - { - pattern: - 'https://github.com/eslint-community/eslint-plugin-eslint-plugin/tree/HEAD/docs/rules/{{name}}.md', - }, - ], - }, - }, - { - files: ['tests/**/*.js'], - env: { mocha: true }, - }, - { - files: ['**/*.md'], - processor: 'markdown/markdown', - }, - { - // Markdown JS code samples in documentation: - files: ['**/*.md/*.js'], - plugins: ['markdown'], - noInlineConfig: true, - rules: { - 'no-undef': 'off', - 'no-unused-vars': 'off', - strict: 'off', - - 'eslint-comments/require-description': 'off', - - 'unicorn/filename-case': 'off', - }, - }, - ], -}; diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 8e479e68..8df690e3 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -12,9 +12,10 @@ jobs: fail-fast: false matrix: node-version: - - '18' - - '16' - - '14' + - 20 + - 18 + - 16 + - 14 os: - ubuntu-latest steps: diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b05340f..73fe8c91 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ +## [5.1.0](https://github.com/eslint-community/eslint-plugin-eslint-plugin/compare/v5.0.8...v5.1.0) (2023-05-18) + + +### Features + +* support `eslint.config.js` ([#347](https://github.com/eslint-community/eslint-plugin-eslint-plugin/issues/347)) ([6f6b1f4](https://github.com/eslint-community/eslint-plugin-eslint-plugin/commit/6f6b1f420d6d18ac13d023f71ce0512caed7cb0e)) + ## [5.0.8](https://github.com/eslint-community/eslint-plugin-eslint-plugin/compare/v5.0.7...v5.0.8) (2023-01-20) diff --git a/README.md b/README.md index 5e421374..9e240627 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,8 @@ Here's an example ESLint configuration that: * Enables the `recommended` configuration * Enables an optional/non-recommended rule +### **[.eslintrc.json](https://eslint.org/docs/latest/use/configure/configuration-files)** + ```json { "parserOptions": { @@ -52,6 +54,21 @@ Here's an example ESLint configuration that: } ``` +### [`eslint.config.js`](https://eslint.org/docs/latest/use/configure/configuration-files-new) (requires eslint>=v8.23.0) + +```js +const eslintPluginRecommended = require("eslint-plugin-eslint-plugin/configs/recommended"); +module.exports = [ + eslintPluginRecommended, + { + languageOptions: {sourceType: "commonjs"}, + rules: { + "eslint-plugin/require-meta-docs-description": "error", + }, + }, +]; +``` + ## Rules @@ -61,23 +78,21 @@ Here's an example ESLint configuration that: 🔧 Automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/user-guide/command-line-interface#--fix).\ 💡 Manually fixable by [editor suggestions](https://eslint.org/docs/developer-guide/working-with-rules#providing-suggestions). +### Rules + | Name                          | Description | 💼 | 🔧 | 💡 | | :--------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------- | :- | :- | :- | -| [consistent-output](docs/rules/consistent-output.md) | enforce consistent use of `output` assertions in rule tests | ✅ | | | | [fixer-return](docs/rules/fixer-return.md) | require fixer functions to return a fix | ✅ | | | | [meta-property-ordering](docs/rules/meta-property-ordering.md) | enforce the order of meta properties | | 🔧 | | | [no-deprecated-context-methods](docs/rules/no-deprecated-context-methods.md) | disallow usage of deprecated methods on rule context objects | ✅ | 🔧 | | | [no-deprecated-report-api](docs/rules/no-deprecated-report-api.md) | disallow the version of `context.report()` with multiple arguments | ✅ | 🔧 | | -| [no-identical-tests](docs/rules/no-identical-tests.md) | disallow identical tests | ✅ | 🔧 | | | [no-missing-message-ids](docs/rules/no-missing-message-ids.md) | disallow `messageId`s that are missing from `meta.messages` | ✅ | | | | [no-missing-placeholders](docs/rules/no-missing-placeholders.md) | disallow missing placeholders in rule report messages | ✅ | | | -| [no-only-tests](docs/rules/no-only-tests.md) | disallow the test case property `only` | ✅ | | 💡 | | [no-unused-message-ids](docs/rules/no-unused-message-ids.md) | disallow unused `messageId`s in `meta.messages` | ✅ | | | | [no-unused-placeholders](docs/rules/no-unused-placeholders.md) | disallow unused placeholders in rule report messages | ✅ | | | | [no-useless-token-range](docs/rules/no-useless-token-range.md) | disallow unnecessary calls to `sourceCode.getFirstToken()` and `sourceCode.getLastToken()` | ✅ | 🔧 | | | [prefer-message-ids](docs/rules/prefer-message-ids.md) | require using `messageId` instead of `message` to report rule violations | ✅ | | | | [prefer-object-rule](docs/rules/prefer-object-rule.md) | disallow function-style rules | ✅ | 🔧 | | -| [prefer-output-null](docs/rules/prefer-output-null.md) | disallow invalid RuleTester test cases where the `output` matches the `code` | ✅ | 🔧 | | | [prefer-placeholders](docs/rules/prefer-placeholders.md) | require using placeholders for dynamic report messages | | | | | [prefer-replace-text](docs/rules/prefer-replace-text.md) | require using `replaceText()` instead of `replaceTextRange()` | | | | | [report-message-format](docs/rules/report-message-format.md) | enforce a consistent format for rule report messages | | | | @@ -87,8 +102,17 @@ Here's an example ESLint configuration that: | [require-meta-has-suggestions](docs/rules/require-meta-has-suggestions.md) | require suggestable rules to implement a `meta.hasSuggestions` property | ✅ | 🔧 | | | [require-meta-schema](docs/rules/require-meta-schema.md) | require rules to implement a `meta.schema` property | ✅ | | 💡 | | [require-meta-type](docs/rules/require-meta-type.md) | require rules to implement a `meta.type` property | ✅ | | | -| [test-case-property-ordering](docs/rules/test-case-property-ordering.md) | require the properties of a test case to be placed in a consistent order | | 🔧 | | -| [test-case-shorthand-strings](docs/rules/test-case-shorthand-strings.md) | enforce consistent usage of shorthand strings for test cases with no options | | 🔧 | | + +### Tests + +| Name                        | Description | 💼 | 🔧 | 💡 | +| :----------------------------------------------------------------------- | :--------------------------------------------------------------------------- | :- | :- | :- | +| [consistent-output](docs/rules/consistent-output.md) | enforce consistent use of `output` assertions in rule tests | ✅ | | | +| [no-identical-tests](docs/rules/no-identical-tests.md) | disallow identical tests | ✅ | 🔧 | | +| [no-only-tests](docs/rules/no-only-tests.md) | disallow the test case property `only` | ✅ | | 💡 | +| [prefer-output-null](docs/rules/prefer-output-null.md) | disallow invalid RuleTester test cases where the `output` matches the `code` | ✅ | 🔧 | | +| [test-case-property-ordering](docs/rules/test-case-property-ordering.md) | require the properties of a test case to be placed in a consistent order | | 🔧 | | +| [test-case-shorthand-strings](docs/rules/test-case-shorthand-strings.md) | enforce consistent usage of shorthand strings for test cases with no options | | 🔧 | | diff --git a/configs/all.js b/configs/all.js new file mode 100644 index 00000000..131aeea1 --- /dev/null +++ b/configs/all.js @@ -0,0 +1,13 @@ +/** + * @fileoverview the `all` config for `eslint.config.js` + * @author 唯然 + */ + +'use strict'; + +const mod = require('../lib/index.js'); + +module.exports = { + plugins: { 'eslint-plugin': mod }, + rules: mod.configs.all.rules, +}; diff --git a/configs/recommended.js b/configs/recommended.js new file mode 100644 index 00000000..977b4e24 --- /dev/null +++ b/configs/recommended.js @@ -0,0 +1,13 @@ +/** + * @fileoverview the `recommended` config for `eslint.config.js` + * @author 唯然 + */ + +'use strict'; + +const mod = require('../lib/index.js'); + +module.exports = { + plugins: { 'eslint-plugin': mod }, + rules: mod.configs.recommended.rules, +}; diff --git a/configs/rules-recommended.js b/configs/rules-recommended.js new file mode 100644 index 00000000..dd784e45 --- /dev/null +++ b/configs/rules-recommended.js @@ -0,0 +1,13 @@ +/** + * @fileoverview the `rules-recommended` config for `eslint.config.js` + * @author 唯然 + */ + +'use strict'; + +const mod = require('../lib/index.js'); + +module.exports = { + plugins: { 'eslint-plugin': mod }, + rules: mod.configs['rules-recommended'].rules, +}; diff --git a/configs/rules.js b/configs/rules.js new file mode 100644 index 00000000..1a4f8a90 --- /dev/null +++ b/configs/rules.js @@ -0,0 +1,13 @@ +/** + * @fileoverview the `rules` config for `eslint.config.js` + * @author 唯然 + */ + +'use strict'; + +const mod = require('../lib/index.js'); + +module.exports = { + plugins: { 'eslint-plugin': mod }, + rules: mod.configs.rules.rules, +}; diff --git a/configs/tests-recommended.js b/configs/tests-recommended.js new file mode 100644 index 00000000..41c50540 --- /dev/null +++ b/configs/tests-recommended.js @@ -0,0 +1,13 @@ +/** + * @fileoverview the `tests-recommended` config for `eslint.config.js` + * @author 唯然 + */ + +'use strict'; + +const mod = require('../lib/index.js'); + +module.exports = { + plugins: { 'eslint-plugin': mod }, + rules: mod.configs['tests-recommended'].rules, +}; diff --git a/configs/tests.js b/configs/tests.js new file mode 100644 index 00000000..53ea6c87 --- /dev/null +++ b/configs/tests.js @@ -0,0 +1,13 @@ +/** + * @fileoverview the `tests` config for `eslint.config.js` + * @author 唯然 + */ + +'use strict'; + +const mod = require('../lib/index.js'); + +module.exports = { + plugins: { 'eslint-plugin': mod }, + rules: mod.configs.tests.rules, +}; diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 00000000..94bebc30 --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,88 @@ +'use strict'; + +const js = require('@eslint/js'); +const { FlatCompat } = require('@eslint/eslintrc'); +const globals = require('globals'); +const markdown = require('eslint-plugin-markdown'); +const eslintPluginConfig = require('eslint-plugin-eslint-plugin/configs/all'); + +const compat = new FlatCompat({ + baseDirectory: __dirname, + recommendedConfig: js.configs.recommended, +}); + +module.exports = [ + ...compat.extends( + 'not-an-aardvark/node', + 'plugin:eslint-comments/recommended', + 'plugin:node/recommended', + 'plugin:prettier/recommended', + 'plugin:unicorn/recommended' + ), + { + languageOptions: { sourceType: 'commonjs' }, + rules: { + 'comma-dangle': [ + 'error', + { + arrays: 'always-multiline', + objects: 'always-multiline', + functions: 'never', // disallow trailing commas in function(es2017) + }, + ], + 'require-jsdoc': 'error', + + 'eslint-comments/no-unused-disable': 'error', + 'eslint-comments/require-description': 'error', + + 'unicorn/consistent-function-scoping': 'off', + 'unicorn/no-array-callback-reference': 'off', + 'unicorn/no-array-for-each': 'off', + 'unicorn/no-array-reduce': 'off', + 'unicorn/no-null': 'off', + 'unicorn/prefer-module': 'off', + 'unicorn/prefer-node-protocol': 'off', // TODO: enable once we drop support for Node 14.17. + 'unicorn/prevent-abbreviations': 'off', + }, + }, + { + // Apply eslint-plugin rules to our own rules/tests (but not docs). + files: ['lib/**/*.js', 'tests/**/*.js'], + plugins: eslintPluginConfig.plugins, + rules: { + ...eslintPluginConfig.rules, + 'eslint-plugin/report-message-format': ['error', '^[^a-z].*.$'], + 'eslint-plugin/require-meta-docs-url': [ + 'error', + { + pattern: + 'https://github.com/eslint-community/eslint-plugin-eslint-plugin/tree/HEAD/docs/rules/{{name}}.md', + }, + ], + }, + }, + { + files: ['tests/**/*.js'], + languageOptions: { globals: globals.mocha }, + }, + { + files: ['**/*.md'], + plugins: { markdown }, + processor: 'markdown/markdown', + }, + { + // Markdown JS code samples in documentation: + files: ['**/*.md/*.js'], + plugins: { markdown }, + linterOptions: { noInlineConfig: true }, + rules: { + 'no-undef': 'off', + 'no-unused-vars': 'off', + strict: 'off', + + 'eslint-comments/require-description': 'off', + + 'unicorn/filename-case': 'off', + }, + }, +]; diff --git a/lib/index.js b/lib/index.js index baab06b4..4ff4ef76 100644 --- a/lib/index.js +++ b/lib/index.js @@ -41,6 +41,11 @@ const allRules = Object.fromEntries( ]) ); +module.exports.meta = { + name: packageMetadata.name, + version: packageMetadata.version, +}; + module.exports.rules = allRules; module.exports.configs = Object.keys(configFilters).reduce( diff --git a/package.json b/package.json index 7ea8eecf..a7ba93b1 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,12 @@ { "name": "eslint-plugin-eslint-plugin", - "version": "5.0.8", + "version": "5.1.0", "description": "An ESLint plugin for linting ESLint plugins", "author": "Teddy Katz", "main": "./lib/index.js", "exports": { ".": "./lib/index.js", + "./configs/*": "./configs/*.js", "./package.json": "./package.json" }, "license": "MIT", @@ -22,7 +23,8 @@ "update:eslint-docs": "eslint-doc-generator" }, "files": [ - "lib/" + "lib/", + "configs/" ], "keywords": [ "eslint", @@ -50,6 +52,8 @@ "devDependencies": { "@commitlint/cli": "^17.1.2", "@commitlint/config-conventional": "^17.1.0", + "@eslint/eslintrc": "^2.0.2", + "@eslint/js": "^8.37.0", "@release-it/conventional-changelog": "^4.3.0", "@typescript-eslint/parser": "^5.36.2", "chai": "^4.3.6", @@ -57,19 +61,20 @@ "eslint": "^8.23.0", "eslint-config-not-an-aardvark": "^2.1.0", "eslint-config-prettier": "^8.5.0", - "eslint-doc-generator": "^1.0.0", + "eslint-doc-generator": "^1.4.3", "eslint-plugin-eslint-comments": "^3.2.0", "eslint-plugin-eslint-plugin": "file:./", "eslint-plugin-markdown": "^3.0.0", "eslint-plugin-node": "^11.1.0", "eslint-plugin-prettier": "^4.2.1", - "eslint-plugin-unicorn": "^45.0.2", + "eslint-plugin-unicorn": "^46.0.0", "eslint-remote-tester": "^3.0.0", "eslint-scope": "^7.1.1", "espree": "^9.4.0", + "globals": "^13.20.0", "husky": "^8.0.1", "lodash": "^4.17.21", - "markdownlint-cli": "^0.33.0", + "markdownlint-cli": "^0.34.0", "mocha": "^10.0.0", "npm-package-json-lint": "^6.3.0", "npm-run-all": "^4.1.5",