From c55bd3465fa1b5169ab289a473f09926c69eb8bf Mon Sep 17 00:00:00 2001 From: jjangga0214 Date: Sat, 10 Sep 2022 16:40:57 +0900 Subject: [PATCH 01/33] feat: support new config system Close #1885 --- {configs => configs-legacy}/all.js | 0 {configs => configs-legacy}/recommended.js | 0 configs/all.mjs | 8 ++ configs/recommended.mjs | 119 +++++++++++++++++++++ index.js | 4 +- index.mjs | 29 +++++ package.json | 14 ++- 7 files changed, 171 insertions(+), 3 deletions(-) rename {configs => configs-legacy}/all.js (100%) rename {configs => configs-legacy}/recommended.js (100%) create mode 100644 configs/all.mjs create mode 100644 configs/recommended.mjs create mode 100644 index.mjs diff --git a/configs/all.js b/configs-legacy/all.js similarity index 100% rename from configs/all.js rename to configs-legacy/all.js diff --git a/configs/recommended.js b/configs-legacy/recommended.js similarity index 100% rename from configs/recommended.js rename to configs-legacy/recommended.js diff --git a/configs/all.mjs b/configs/all.mjs new file mode 100644 index 0000000000..5a4fe59feb --- /dev/null +++ b/configs/all.mjs @@ -0,0 +1,8 @@ +import recommended from './recommended.mjs' + +export default { + ...recommended, + rules: Object.fromEntries(Object.entries(recommended.rules).map( + ([ruleId, severity]) => [ruleId, ruleId.startsWith('unicorn/') ? 'error' : severity], + )), +} diff --git a/configs/recommended.mjs b/configs/recommended.mjs new file mode 100644 index 0000000000..37615f3a9f --- /dev/null +++ b/configs/recommended.mjs @@ -0,0 +1,119 @@ +import unicorn from '../index.mjs' + +export default { + plugins: { + unicorn, + }, + rules: { + 'unicorn/better-regex': 'error', + 'unicorn/catch-error-name': 'error', + 'unicorn/consistent-destructuring': 'error', + 'unicorn/consistent-function-scoping': 'error', + 'unicorn/custom-error-definition': 'off', + 'unicorn/empty-brace-spaces': 'error', + 'unicorn/error-message': 'error', + 'unicorn/escape-case': 'error', + 'unicorn/expiring-todo-comments': 'error', + 'unicorn/explicit-length-check': 'error', + 'unicorn/filename-case': 'error', + 'unicorn/import-style': 'error', + 'unicorn/new-for-builtins': 'error', + 'unicorn/no-abusive-eslint-disable': 'error', + 'unicorn/no-array-callback-reference': 'error', + 'unicorn/no-array-for-each': 'error', + 'unicorn/no-array-method-this-argument': 'error', + 'unicorn/no-array-push-push': 'error', + 'unicorn/no-array-reduce': 'error', + 'unicorn/no-await-expression-member': 'error', + 'unicorn/no-console-spaces': 'error', + 'unicorn/no-document-cookie': 'error', + 'unicorn/no-empty-file': 'error', + 'unicorn/no-for-loop': 'error', + 'unicorn/no-hex-escape': 'error', + 'unicorn/no-instanceof-array': 'error', + 'unicorn/no-invalid-remove-event-listener': 'error', + 'unicorn/no-keyword-prefix': 'off', + 'unicorn/no-lonely-if': 'error', + 'no-nested-ternary': 'off', + 'unicorn/no-nested-ternary': 'error', + 'unicorn/no-new-array': 'error', + 'unicorn/no-new-buffer': 'error', + 'unicorn/no-null': 'error', + 'unicorn/no-object-as-default-parameter': 'error', + 'unicorn/no-process-exit': 'error', + 'unicorn/no-static-only-class': 'error', + 'unicorn/no-thenable': 'error', + 'unicorn/no-this-assignment': 'error', + 'unicorn/no-unreadable-array-destructuring': 'error', + 'unicorn/no-unreadable-iife': 'error', + 'unicorn/no-unsafe-regex': 'off', + 'unicorn/no-unused-properties': 'off', + 'unicorn/no-useless-fallback-in-spread': 'error', + 'unicorn/no-useless-length-check': 'error', + 'unicorn/no-useless-promise-resolve-reject': 'error', + 'unicorn/no-useless-spread': 'error', + 'unicorn/no-useless-switch-case': 'error', + 'unicorn/no-useless-undefined': 'error', + 'unicorn/no-zero-fractions': 'error', + 'unicorn/number-literal-case': 'error', + 'unicorn/numeric-separators-style': 'error', + 'unicorn/prefer-add-event-listener': 'error', + 'unicorn/prefer-array-find': 'error', + 'unicorn/prefer-array-flat': 'error', + 'unicorn/prefer-array-flat-map': 'error', + 'unicorn/prefer-array-index-of': 'error', + 'unicorn/prefer-array-some': 'error', + // TODO: Enable this by default when targeting a Node.js version that supports `Array#at`. + 'unicorn/prefer-at': 'off', + 'unicorn/prefer-code-point': 'error', + 'unicorn/prefer-date-now': 'error', + 'unicorn/prefer-default-parameters': 'error', + 'unicorn/prefer-dom-node-append': 'error', + 'unicorn/prefer-dom-node-dataset': 'error', + 'unicorn/prefer-dom-node-remove': 'error', + 'unicorn/prefer-dom-node-text-content': 'error', + // TODO: Enable this by default when targeting Node.js 16. + 'unicorn/prefer-event-target': 'off', + 'unicorn/prefer-export-from': 'error', + 'unicorn/prefer-includes': 'error', + 'unicorn/prefer-json-parse-buffer': 'off', + 'unicorn/prefer-keyboard-event-key': 'error', + 'unicorn/prefer-logical-operator-over-ternary': 'error', + 'unicorn/prefer-math-trunc': 'error', + 'unicorn/prefer-modern-dom-apis': 'error', + 'unicorn/prefer-modern-math-apis': 'error', + 'unicorn/prefer-module': 'error', + 'unicorn/prefer-native-coercion-functions': 'error', + 'unicorn/prefer-negative-index': 'error', + 'unicorn/prefer-node-protocol': 'error', + 'unicorn/prefer-number-properties': 'error', + 'unicorn/prefer-object-from-entries': 'error', + 'unicorn/prefer-optional-catch-binding': 'error', + 'unicorn/prefer-prototype-methods': 'error', + 'unicorn/prefer-query-selector': 'error', + 'unicorn/prefer-reflect-apply': 'error', + 'unicorn/prefer-regexp-test': 'error', + 'unicorn/prefer-set-has': 'error', + 'unicorn/prefer-spread': 'error', + // TODO: Enable this by default when targeting Node.js 16. + 'unicorn/prefer-string-replace-all': 'off', + 'unicorn/prefer-string-slice': 'error', + 'unicorn/prefer-string-starts-ends-with': 'error', + 'unicorn/prefer-string-trim-start-end': 'error', + 'unicorn/prefer-switch': 'error', + 'unicorn/prefer-ternary': 'error', + 'unicorn/prefer-top-level-await': 'error', + 'unicorn/prefer-type-error': 'error', + 'unicorn/prevent-abbreviations': 'error', + 'unicorn/relative-url-style': 'error', + 'unicorn/require-array-join-separator': 'error', + 'unicorn/require-number-to-fixed-digits-argument': 'error', + // Turned off because we can't distinguish `widow.postMessage` and `{Worker,MessagePort,Client,BroadcastChannel}#postMessage()` + // See #1396 + 'unicorn/require-post-message-target-origin': 'off', + 'unicorn/string-content': 'off', + 'unicorn/template-indent': 'error', + 'unicorn/text-encoding-identifier-case': 'error', + 'unicorn/throw-new-error': 'error', + }, +}; diff --git a/index.js b/index.js index 1ab1204490..2758d69a7d 100644 --- a/index.js +++ b/index.js @@ -1,8 +1,8 @@ 'use strict'; const createDeprecatedRules = require('./rules/utils/create-deprecated-rules.js'); const {loadRules} = require('./rules/utils/rule.js'); -const recommendedConfig = require('./configs/recommended.js'); -const allRulesEnabledConfig = require('./configs/all.js'); +const recommendedConfig = require('./configs-legacy/recommended.js'); +const allRulesEnabledConfig = require('./configs-legacy/all.js'); const deprecatedRules = createDeprecatedRules({ // {ruleId: ReplacementRuleId | ReplacementRuleId[]}, if no replacement, use `{ruleId: []}` diff --git a/index.mjs b/index.mjs new file mode 100644 index 0000000000..4d2f1a7ac0 --- /dev/null +++ b/index.mjs @@ -0,0 +1,29 @@ +import createDeprecatedRules from './rules/utils/create-deprecated-rules.js'; +import { loadRules } from './rules/utils/rule.js'; + +const deprecatedRules = createDeprecatedRules({ + // {ruleId: ReplacementRuleId | ReplacementRuleId[]}, if no replacement, use `{ruleId: []}` + 'import-index': [], + 'no-array-instanceof': 'unicorn/no-instanceof-array', + 'no-fn-reference-in-iterator': 'unicorn/no-array-callback-reference', + 'no-reduce': 'unicorn/no-array-reduce', + 'prefer-dataset': 'unicorn/prefer-dom-node-dataset', + 'prefer-event-key': 'unicorn/prefer-keyboard-event-key', + 'prefer-exponentiation-operator': 'prefer-exponentiation-operator', + 'prefer-flat-map': 'unicorn/prefer-array-flat-map', + 'prefer-node-append': 'unicorn/prefer-dom-node-append', + 'prefer-node-remove': 'unicorn/prefer-dom-node-remove', + 'prefer-object-has-own': 'prefer-object-has-own', + 'prefer-replace-all': 'unicorn/prefer-string-replace-all', + 'prefer-starts-ends-with': 'unicorn/prefer-string-starts-ends-with', + 'prefer-text-content': 'unicorn/prefer-dom-node-text-content', + 'prefer-trim-start-end': 'unicorn/prefer-string-trim-start-end', + 'regex-shorthand': 'unicorn/better-regex', +}); + +export default { + rules: { + ...loadRules(), + ...deprecatedRules, + }, +} diff --git a/package.json b/package.json index 0c71be0e1c..a6111fe18c 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,16 @@ "engines": { "node": ">=14.18" }, + "main": "index.js", + "exports": { + ".": { + "import": "./index.mjs", + "require": "./index.js" + }, + "./all": "./configs/all.mjs", + "./recommended": "./configs/recommended.mjs", + "./package.json": "./package.json" + }, "scripts": { "create-rule": "node ./scripts/create-rule.mjs && npm run generate-rule-notices && npm run generate-rules-table", "fix": "run-p --continue-on-error fix:*", @@ -32,8 +42,10 @@ }, "files": [ "index.js", + "experimental.mjs", "rules", - "configs" + "configs", + "configs-legacy" ], "keywords": [ "eslint", From 27459a73ca4a2eda723b1a7b9b0bb93ad261f657 Mon Sep 17 00:00:00 2001 From: Sindre Sorhus Date: Sat, 10 Sep 2022 14:50:06 +0700 Subject: [PATCH 02/33] Update index.mjs --- index.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.mjs b/index.mjs index 4d2f1a7ac0..bb1fdceb91 100644 --- a/index.mjs +++ b/index.mjs @@ -1,5 +1,5 @@ import createDeprecatedRules from './rules/utils/create-deprecated-rules.js'; -import { loadRules } from './rules/utils/rule.js'; +import {loadRules} from './rules/utils/rule.js'; const deprecatedRules = createDeprecatedRules({ // {ruleId: ReplacementRuleId | ReplacementRuleId[]}, if no replacement, use `{ruleId: []}` From 612da7d2b361dde76456ab2f09929d824b543258 Mon Sep 17 00:00:00 2001 From: Sindre Sorhus Date: Sat, 10 Sep 2022 14:50:32 +0700 Subject: [PATCH 03/33] Update recommended.mjs --- configs/recommended.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configs/recommended.mjs b/configs/recommended.mjs index 37615f3a9f..282ce569ed 100644 --- a/configs/recommended.mjs +++ b/configs/recommended.mjs @@ -1,4 +1,4 @@ -import unicorn from '../index.mjs' +import unicorn from '../index.mjs'; export default { plugins: { From 580fa2985ebc555f06171a18fdd816b834f33164 Mon Sep 17 00:00:00 2001 From: jjangga0214 Date: Sat, 10 Sep 2022 18:03:25 +0900 Subject: [PATCH 04/33] refactor: rm dup --- configs/recommended.mjs | 114 +--------------------------------------- 1 file changed, 2 insertions(+), 112 deletions(-) diff --git a/configs/recommended.mjs b/configs/recommended.mjs index 282ce569ed..3f34f626c3 100644 --- a/configs/recommended.mjs +++ b/configs/recommended.mjs @@ -1,119 +1,9 @@ import unicorn from '../index.mjs'; +import {rules} from '../configs-legacy/recommended.js'; export default { plugins: { unicorn, }, - rules: { - 'unicorn/better-regex': 'error', - 'unicorn/catch-error-name': 'error', - 'unicorn/consistent-destructuring': 'error', - 'unicorn/consistent-function-scoping': 'error', - 'unicorn/custom-error-definition': 'off', - 'unicorn/empty-brace-spaces': 'error', - 'unicorn/error-message': 'error', - 'unicorn/escape-case': 'error', - 'unicorn/expiring-todo-comments': 'error', - 'unicorn/explicit-length-check': 'error', - 'unicorn/filename-case': 'error', - 'unicorn/import-style': 'error', - 'unicorn/new-for-builtins': 'error', - 'unicorn/no-abusive-eslint-disable': 'error', - 'unicorn/no-array-callback-reference': 'error', - 'unicorn/no-array-for-each': 'error', - 'unicorn/no-array-method-this-argument': 'error', - 'unicorn/no-array-push-push': 'error', - 'unicorn/no-array-reduce': 'error', - 'unicorn/no-await-expression-member': 'error', - 'unicorn/no-console-spaces': 'error', - 'unicorn/no-document-cookie': 'error', - 'unicorn/no-empty-file': 'error', - 'unicorn/no-for-loop': 'error', - 'unicorn/no-hex-escape': 'error', - 'unicorn/no-instanceof-array': 'error', - 'unicorn/no-invalid-remove-event-listener': 'error', - 'unicorn/no-keyword-prefix': 'off', - 'unicorn/no-lonely-if': 'error', - 'no-nested-ternary': 'off', - 'unicorn/no-nested-ternary': 'error', - 'unicorn/no-new-array': 'error', - 'unicorn/no-new-buffer': 'error', - 'unicorn/no-null': 'error', - 'unicorn/no-object-as-default-parameter': 'error', - 'unicorn/no-process-exit': 'error', - 'unicorn/no-static-only-class': 'error', - 'unicorn/no-thenable': 'error', - 'unicorn/no-this-assignment': 'error', - 'unicorn/no-unreadable-array-destructuring': 'error', - 'unicorn/no-unreadable-iife': 'error', - 'unicorn/no-unsafe-regex': 'off', - 'unicorn/no-unused-properties': 'off', - 'unicorn/no-useless-fallback-in-spread': 'error', - 'unicorn/no-useless-length-check': 'error', - 'unicorn/no-useless-promise-resolve-reject': 'error', - 'unicorn/no-useless-spread': 'error', - 'unicorn/no-useless-switch-case': 'error', - 'unicorn/no-useless-undefined': 'error', - 'unicorn/no-zero-fractions': 'error', - 'unicorn/number-literal-case': 'error', - 'unicorn/numeric-separators-style': 'error', - 'unicorn/prefer-add-event-listener': 'error', - 'unicorn/prefer-array-find': 'error', - 'unicorn/prefer-array-flat': 'error', - 'unicorn/prefer-array-flat-map': 'error', - 'unicorn/prefer-array-index-of': 'error', - 'unicorn/prefer-array-some': 'error', - // TODO: Enable this by default when targeting a Node.js version that supports `Array#at`. - 'unicorn/prefer-at': 'off', - 'unicorn/prefer-code-point': 'error', - 'unicorn/prefer-date-now': 'error', - 'unicorn/prefer-default-parameters': 'error', - 'unicorn/prefer-dom-node-append': 'error', - 'unicorn/prefer-dom-node-dataset': 'error', - 'unicorn/prefer-dom-node-remove': 'error', - 'unicorn/prefer-dom-node-text-content': 'error', - // TODO: Enable this by default when targeting Node.js 16. - 'unicorn/prefer-event-target': 'off', - 'unicorn/prefer-export-from': 'error', - 'unicorn/prefer-includes': 'error', - 'unicorn/prefer-json-parse-buffer': 'off', - 'unicorn/prefer-keyboard-event-key': 'error', - 'unicorn/prefer-logical-operator-over-ternary': 'error', - 'unicorn/prefer-math-trunc': 'error', - 'unicorn/prefer-modern-dom-apis': 'error', - 'unicorn/prefer-modern-math-apis': 'error', - 'unicorn/prefer-module': 'error', - 'unicorn/prefer-native-coercion-functions': 'error', - 'unicorn/prefer-negative-index': 'error', - 'unicorn/prefer-node-protocol': 'error', - 'unicorn/prefer-number-properties': 'error', - 'unicorn/prefer-object-from-entries': 'error', - 'unicorn/prefer-optional-catch-binding': 'error', - 'unicorn/prefer-prototype-methods': 'error', - 'unicorn/prefer-query-selector': 'error', - 'unicorn/prefer-reflect-apply': 'error', - 'unicorn/prefer-regexp-test': 'error', - 'unicorn/prefer-set-has': 'error', - 'unicorn/prefer-spread': 'error', - // TODO: Enable this by default when targeting Node.js 16. - 'unicorn/prefer-string-replace-all': 'off', - 'unicorn/prefer-string-slice': 'error', - 'unicorn/prefer-string-starts-ends-with': 'error', - 'unicorn/prefer-string-trim-start-end': 'error', - 'unicorn/prefer-switch': 'error', - 'unicorn/prefer-ternary': 'error', - 'unicorn/prefer-top-level-await': 'error', - 'unicorn/prefer-type-error': 'error', - 'unicorn/prevent-abbreviations': 'error', - 'unicorn/relative-url-style': 'error', - 'unicorn/require-array-join-separator': 'error', - 'unicorn/require-number-to-fixed-digits-argument': 'error', - // Turned off because we can't distinguish `widow.postMessage` and `{Worker,MessagePort,Client,BroadcastChannel}#postMessage()` - // See #1396 - 'unicorn/require-post-message-target-origin': 'off', - 'unicorn/string-content': 'off', - 'unicorn/template-indent': 'error', - 'unicorn/text-encoding-identifier-case': 'error', - 'unicorn/throw-new-error': 'error', - }, + rules, }; From 33f11c8977225056d53b6cd77ad20bb9ba9422d6 Mon Sep 17 00:00:00 2001 From: jjangga0214 Date: Sun, 11 Sep 2022 20:04:48 +0900 Subject: [PATCH 05/33] style: format --- configs/all.mjs | 8 +++++--- configs/recommended.mjs | 4 +++- index.mjs | 6 ++++-- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/configs/all.mjs b/configs/all.mjs index 5a4fe59feb..deee3c419f 100644 --- a/configs/all.mjs +++ b/configs/all.mjs @@ -1,8 +1,10 @@ -import recommended from './recommended.mjs' +import recommended from './recommended.mjs'; -export default { +const all = { ...recommended, rules: Object.fromEntries(Object.entries(recommended.rules).map( ([ruleId, severity]) => [ruleId, ruleId.startsWith('unicorn/') ? 'error' : severity], )), -} +}; + +export default all; diff --git a/configs/recommended.mjs b/configs/recommended.mjs index 3f34f626c3..723e68339c 100644 --- a/configs/recommended.mjs +++ b/configs/recommended.mjs @@ -1,9 +1,11 @@ import unicorn from '../index.mjs'; import {rules} from '../configs-legacy/recommended.js'; -export default { +const recommended = { plugins: { unicorn, }, rules, }; + +export default recommended; diff --git a/index.mjs b/index.mjs index bb1fdceb91..5ee7b06a93 100644 --- a/index.mjs +++ b/index.mjs @@ -21,9 +21,11 @@ const deprecatedRules = createDeprecatedRules({ 'regex-shorthand': 'unicorn/better-regex', }); -export default { +const plugin = { rules: { ...loadRules(), ...deprecatedRules, }, -} +}; + +export default plugin; From dfd515966a27dc774c6f1c9251ae931a425a22a3 Mon Sep 17 00:00:00 2001 From: jjangga0214 Date: Sun, 11 Sep 2022 20:16:01 +0900 Subject: [PATCH 06/33] feat: add languageOptions and files to the new config --- configs/all.mjs | 5 ++--- configs/recommended.mjs | 8 ++++++++ package.json | 1 + 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/configs/all.mjs b/configs/all.mjs index deee3c419f..8cf6a053d0 100644 --- a/configs/all.mjs +++ b/configs/all.mjs @@ -1,10 +1,9 @@ import recommended from './recommended.mjs'; +import {rules} from '../configs-legacy/all.js'; const all = { ...recommended, - rules: Object.fromEntries(Object.entries(recommended.rules).map( - ([ruleId, severity]) => [ruleId, ruleId.startsWith('unicorn/') ? 'error' : severity], - )), + rules, }; export default all; diff --git a/configs/recommended.mjs b/configs/recommended.mjs index 723e68339c..65a960b333 100644 --- a/configs/recommended.mjs +++ b/configs/recommended.mjs @@ -1,7 +1,15 @@ import unicorn from '../index.mjs'; import {rules} from '../configs-legacy/recommended.js'; +import globals from 'globals'; const recommended = { + files: ['**/*.{js,cjs,mjs,jsx,ts,tsx}'], + languageOptions: { + globals: { + ...globals.node, + ...globals.es2021 + } + }, plugins: { unicorn, }, diff --git a/package.json b/package.json index a6111fe18c..dd0b2f3dc1 100644 --- a/package.json +++ b/package.json @@ -63,6 +63,7 @@ "clean-regexp": "^1.0.0", "eslint-utils": "^3.0.0", "esquery": "^1.4.0", + "globals": "^13.17.0", "indent-string": "^4.0.0", "is-builtin-module": "^3.1.0", "lodash": "^4.17.21", From 0084e5e68c6a8dfc61dde22b24ae8acc2ba71cc1 Mon Sep 17 00:00:00 2001 From: jjangga0214 Date: Sun, 11 Sep 2022 21:31:02 +0900 Subject: [PATCH 07/33] style: format --- configs/all.mjs | 2 +- configs/recommended.mjs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/configs/all.mjs b/configs/all.mjs index 8cf6a053d0..35d4e3d5f1 100644 --- a/configs/all.mjs +++ b/configs/all.mjs @@ -1,5 +1,5 @@ -import recommended from './recommended.mjs'; import {rules} from '../configs-legacy/all.js'; +import recommended from './recommended.mjs'; const all = { ...recommended, diff --git a/configs/recommended.mjs b/configs/recommended.mjs index 65a960b333..2343510207 100644 --- a/configs/recommended.mjs +++ b/configs/recommended.mjs @@ -1,14 +1,14 @@ +import globals from 'globals'; import unicorn from '../index.mjs'; import {rules} from '../configs-legacy/recommended.js'; -import globals from 'globals'; const recommended = { files: ['**/*.{js,cjs,mjs,jsx,ts,tsx}'], languageOptions: { globals: { ...globals.node, - ...globals.es2021 - } + ...globals.es2021, + }, }, plugins: { unicorn, From ff1cacf11881397eee36fc4c4ea3a52c3c7d2e26 Mon Sep 17 00:00:00 2001 From: jjangga0214 Date: Tue, 13 Sep 2022 13:53:59 +0900 Subject: [PATCH 08/33] refactor: import dup --- index.mjs | 28 ++-------------------------- 1 file changed, 2 insertions(+), 26 deletions(-) diff --git a/index.mjs b/index.mjs index 5ee7b06a93..2048e0dd4a 100644 --- a/index.mjs +++ b/index.mjs @@ -1,31 +1,7 @@ -import createDeprecatedRules from './rules/utils/create-deprecated-rules.js'; -import {loadRules} from './rules/utils/rule.js'; - -const deprecatedRules = createDeprecatedRules({ - // {ruleId: ReplacementRuleId | ReplacementRuleId[]}, if no replacement, use `{ruleId: []}` - 'import-index': [], - 'no-array-instanceof': 'unicorn/no-instanceof-array', - 'no-fn-reference-in-iterator': 'unicorn/no-array-callback-reference', - 'no-reduce': 'unicorn/no-array-reduce', - 'prefer-dataset': 'unicorn/prefer-dom-node-dataset', - 'prefer-event-key': 'unicorn/prefer-keyboard-event-key', - 'prefer-exponentiation-operator': 'prefer-exponentiation-operator', - 'prefer-flat-map': 'unicorn/prefer-array-flat-map', - 'prefer-node-append': 'unicorn/prefer-dom-node-append', - 'prefer-node-remove': 'unicorn/prefer-dom-node-remove', - 'prefer-object-has-own': 'prefer-object-has-own', - 'prefer-replace-all': 'unicorn/prefer-string-replace-all', - 'prefer-starts-ends-with': 'unicorn/prefer-string-starts-ends-with', - 'prefer-text-content': 'unicorn/prefer-dom-node-text-content', - 'prefer-trim-start-end': 'unicorn/prefer-string-trim-start-end', - 'regex-shorthand': 'unicorn/better-regex', -}); +import {rules} from './index.js'; const plugin = { - rules: { - ...loadRules(), - ...deprecatedRules, - }, + rules, }; export default plugin; From 8dff114ab321e0fa9a4238312ca78ad54b6d7f7d Mon Sep 17 00:00:00 2001 From: jjangga0214 Date: Tue, 13 Sep 2022 14:06:37 +0900 Subject: [PATCH 09/33] docs: guide the new config system --- readme.md | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 98 insertions(+), 2 deletions(-) diff --git a/readme.md b/readme.md index 23e4637f06..aa1b272c03 100644 --- a/readme.md +++ b/readme.md @@ -15,7 +15,7 @@ You might want to check out [XO](https://github.com/xojs/xo), which includes thi npm install --save-dev eslint eslint-plugin-unicorn ``` -## Usage +## Usage (legacy) Use a [preset config](#preset-configs) or configure each rules in `package.json`. @@ -41,6 +41,58 @@ Use a [preset config](#preset-configs) or configure each rules in `package.json` } ``` +## Usage (new) + +From [`v8.21.0`](https://github.com/eslint/eslint/releases/tag/v8.21.0), eslint announced a new config system. +In the new system, `.eslintrc*` is no longer used. `eslint.config.js` would be the default config file name. +In eslint `v8`, the legacy system (`.eslintrc*`) would still be supported, while in eslint `v9`, only the new system would be supported. + +And from [`v8.23.0`](https://github.com/eslint/eslint/releases/tag/v8.23.0), eslint CLI starts to look up `eslint.config.js`. +**So, if your eslint is `>=8.23.0`, you're 100% ready to use the new config system.** + +You might want to check out the official blog posts, + +- +- +- + +and the [official docs](https://eslint.org/docs/latest/user-guide/configuring/configuration-files-new). + +The default export of `eslint-plugin-react` is a plugin object. + +If your `eslint.config.js` is ESM, you can import and use the plugin like this. + +```js +import unicorn from 'eslint-plugin-unicorn' + +export default [ + // --- snip --- + { + files: ['**/*.{js,ts}'], + languageOptions: { + globals: { + ...globals.node, + ...globals.es2021, + }, + }, + plugins: { + unicorn, + }, + rules: { + // ... any rules you want + 'unicorn/better-regex': 'error', + 'unicorn/catch-error-name': 'error', + }, + // ... others are omitted for brevity + }, + // --- snip --- +] +``` + +If your `eslint.config.js` is CJS, please change it to ESM. + +Note that this plugin itself would transition to [Pure ESM](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c) in future. + ## Rules Each rule has emojis denoting: @@ -163,7 +215,7 @@ Each rule has emojis denoting: See [docs/deprecated-rules.md](docs/deprecated-rules.md) -## Preset configs +## Preset configs (legacy) See the [ESLint docs](https://eslint.org/docs/user-guide/configuring/configuration-files#extending-configuration-files) for more information about extending config files. @@ -195,6 +247,50 @@ This plugin exports an [`all` config](configs/all.js) that makes use of all rule } ``` +## Shareable configs (new) + +If you use the new config system (`eslint.config.js`), there're 2 shareable configs. + +- `eslint-plugin-unicorn/all` +- `eslint-plugin-unicorn/recommended` + +**Note**: Shareable configs will enable the [`globals`](https://eslint.org/docs/latest/user-guide/configuring/configuration-files-new#configuration-objects). + +In the new config system, `plugin:` protocol(e.g. `plugin:react/recommended`) is no longer valid. +As eslint does not automatically import the preset config (shareable config), you explicitly do it by yourself. + +**Note**: The new plugin object does not have `configs` property as well. + +```js +import unicorn from 'eslint-plugin-unicorn/all' // <== trailing '/all' + +export default [ + // --- snip --- + unicorn, // This is not a plugin object, but a shareable config object + // --- snip --- +] +``` + +You can of course add/override some properties. + +```js +import unicorn from 'eslint-plugin-unicorn/recommended' +import globals from 'globals' + +export default [ + // --- snip --- + { + ...unicorn, + files: ['**/*.{js,jsx}'], + globals: { + ...globals.browser, + // and so on + }, + }, + // --- snip --- +] +``` + ## Maintainers - [Sindre Sorhus](https://github.com/sindresorhus) From 5f4d2a07909928623c16e42ccef870841ef0b390 Mon Sep 17 00:00:00 2001 From: jjangga0214 Date: Tue, 13 Sep 2022 14:10:14 +0900 Subject: [PATCH 10/33] docs: align a word --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index aa1b272c03..6f28539dc8 100644 --- a/readme.md +++ b/readme.md @@ -284,7 +284,7 @@ export default [ files: ['**/*.{js,jsx}'], globals: { ...globals.browser, - // and so on + // and so on }, }, // --- snip --- From 9c9afff32dd446342fc06cafae4d0e6c829cc1dd Mon Sep 17 00:00:00 2001 From: jjangga0214 Date: Wed, 14 Sep 2022 15:35:09 +0900 Subject: [PATCH 11/33] fix: path to configs-legacy --- docs/new-rule.md | 2 +- readme.md | 78 +++++++++++++++-------------- scripts/create-rule.mjs | 4 +- test/run-rules-on-codebase/lint.mjs | 2 +- 4 files changed, 44 insertions(+), 42 deletions(-) diff --git a/docs/new-rule.md b/docs/new-rule.md index abd2be0c78..535ba2bc2b 100644 --- a/docs/new-rule.md +++ b/docs/new-rule.md @@ -17,7 +17,7 @@ Use the [`astexplorer` site](https://astexplorer.net) with the `espree` parser a - Open “rules/{RULE_ID}.js” and implement the rule logic. - Add the correct [`meta.type`](https://eslint.org/docs/developer-guide/working-with-rules#rule-basics) to the rule. - Open “docs/rules/{RULE_ID}.js” and write some documentation. -- Double check `configs/recommended.js` and `readme.md`, make sure the new rule is correctly added. +- Double check `configs-legacy/recommended.js` and `readme.md`, make sure the new rule is correctly added. - Run `$ npm test` to ensure the tests pass. - Run `$ npm run integration` to run the rules against real projects to ensure your rule does not fail on real-world code. - Open a pull request with a title in exactly the format `` Add `rule-name` rule ``, for example, `` Add `no-unused-properties` rule ``. diff --git a/readme.md b/readme.md index 6f28539dc8..5b7287ebb4 100644 --- a/readme.md +++ b/readme.md @@ -15,9 +15,9 @@ You might want to check out [XO](https://github.com/xojs/xo), which includes thi npm install --save-dev eslint eslint-plugin-unicorn ``` -## Usage (legacy) +## Usage (legacy: `eslintrc*`) -Use a [preset config](#preset-configs) or configure each rules in `package.json`. +Use a preset config or configure each rules in `package.json`. ```json { @@ -41,7 +41,7 @@ Use a [preset config](#preset-configs) or configure each rules in `package.json` } ``` -## Usage (new) +## Usage (new: `eslint.config.js`) From [`v8.21.0`](https://github.com/eslint/eslint/releases/tag/v8.21.0), eslint announced a new config system. In the new system, `.eslintrc*` is no longer used. `eslint.config.js` would be the default config file name. @@ -66,26 +66,26 @@ If your `eslint.config.js` is ESM, you can import and use the plugin like this. import unicorn from 'eslint-plugin-unicorn' export default [ - // --- snip --- - { - files: ['**/*.{js,ts}'], - languageOptions: { - globals: { - ...globals.node, - ...globals.es2021, - }, - }, - plugins: { - unicorn, + // --- snip --- + { + files: ['**/*.{js,ts}'], + languageOptions: { + globals: { + ...globals.node, + ...globals.es2021, + }, + }, + plugins: { + unicorn, + }, + rules: { + // ... any rules you want + 'unicorn/better-regex': 'error', + 'unicorn/catch-error-name': 'error', + }, + // ... others are omitted for brevity }, - rules: { - // ... any rules you want - 'unicorn/better-regex': 'error', - 'unicorn/catch-error-name': 'error', - }, - // ... others are omitted for brevity - }, - // --- snip --- + // --- snip --- ] ``` @@ -215,7 +215,7 @@ Each rule has emojis denoting: See [docs/deprecated-rules.md](docs/deprecated-rules.md) -## Preset configs (legacy) +## Preset configs (legacy: `eslintrc*`) See the [ESLint docs](https://eslint.org/docs/user-guide/configuring/configuration-files#extending-configuration-files) for more information about extending config files. @@ -223,7 +223,7 @@ See the [ESLint docs](https://eslint.org/docs/user-guide/configuring/configurati ### Recommended config -This plugin exports a [`recommended` config](configs/recommended.js) that enforces good practices. +This plugin exports a [`recommended` config](configs-legacy/recommended.js) that enforces good practices. ```json { @@ -236,7 +236,7 @@ This plugin exports a [`recommended` config](configs/recommended.js) that enforc ### All config -This plugin exports an [`all` config](configs/all.js) that makes use of all rules (except for deprecated ones). +This plugin exports an [`all` config](configs-legacy/all.js) that makes use of all rules (except for deprecated ones). ```json { @@ -247,7 +247,7 @@ This plugin exports an [`all` config](configs/all.js) that makes use of all rule } ``` -## Shareable configs (new) +## Shareable configs (new: `eslint.config.js`) If you use the new config system (`eslint.config.js`), there're 2 shareable configs. @@ -265,9 +265,9 @@ As eslint does not automatically import the preset config (shareable config), yo import unicorn from 'eslint-plugin-unicorn/all' // <== trailing '/all' export default [ - // --- snip --- - unicorn, // This is not a plugin object, but a shareable config object - // --- snip --- + // --- snip --- + unicorn, // This is not a plugin object, but a shareable config object + // --- snip --- ] ``` @@ -278,16 +278,18 @@ import unicorn from 'eslint-plugin-unicorn/recommended' import globals from 'globals' export default [ - // --- snip --- - { - ...unicorn, - files: ['**/*.{js,jsx}'], - globals: { - ...globals.browser, - // and so on + // --- snip --- + { + ...unicorn, + files: ['**/*.{js,jsx}'], + languageOptions: { + globals: { + ...globals.browser, + // and so on + }, + }, }, - }, - // --- snip --- + // --- snip --- ] ``` diff --git a/scripts/create-rule.mjs b/scripts/create-rule.mjs index dca13025ee..16a625b17f 100644 --- a/scripts/create-rule.mjs +++ b/scripts/create-rule.mjs @@ -42,14 +42,14 @@ function updateRecommended(id) { const RULE_INDENT = '\t'.repeat(2); let ruleContent = `${RULE_INDENT}'unicorn/${id}': 'error',`; - const file = path.join(ROOT, 'configs/recommended.js'); + const file = path.join(ROOT, 'configs-legacy/recommended.js'); const content = fs.readFileSync(file, 'utf8'); const [before, rest] = content.split(RULE_START); const [rules, after] = rest.split(RULE_END); const lines = rules.split('\n'); if (!lines.every(line => line.startsWith(RULE_INDENT))) { - throw new Error('Unexpected content in “configs/recommended.js”.'); + throw new Error('Unexpected content in “configs-legacy/recommended.js”.'); } const unicornRuleLines = lines.filter(line => line.startsWith(`${RULE_INDENT}'unicorn/`)); diff --git a/test/run-rules-on-codebase/lint.mjs b/test/run-rules-on-codebase/lint.mjs index 47e04c15ed..2efaceec3f 100644 --- a/test/run-rules-on-codebase/lint.mjs +++ b/test/run-rules-on-codebase/lint.mjs @@ -2,7 +2,7 @@ import process from 'node:process'; import {ESLint} from 'eslint'; import unicorn from '../../index.js'; -import allConfig from '../../configs/all.js'; +import allConfig from '../../configs-legacy/all.js'; const files = [process.argv[2] || '.']; const fix = process.argv.includes('--fix'); From c7c4a948c1c3cd64f758e719920727aea2d2275f Mon Sep 17 00:00:00 2001 From: jjangga0214 Date: Thu, 15 Sep 2022 15:20:50 +0900 Subject: [PATCH 12/33] docs: globals -> languageOptions.globals --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 5b7287ebb4..3b92551eb6 100644 --- a/readme.md +++ b/readme.md @@ -254,7 +254,7 @@ If you use the new config system (`eslint.config.js`), there're 2 shareable conf - `eslint-plugin-unicorn/all` - `eslint-plugin-unicorn/recommended` -**Note**: Shareable configs will enable the [`globals`](https://eslint.org/docs/latest/user-guide/configuring/configuration-files-new#configuration-objects). +**Note**: Shareable configs will enable the [`languageOptions.globals`](https://eslint.org/docs/latest/user-guide/configuring/configuration-files-new#configuration-objects). In the new config system, `plugin:` protocol(e.g. `plugin:react/recommended`) is no longer valid. As eslint does not automatically import the preset config (shareable config), you explicitly do it by yourself. From 30a8bc02213eb036f976daa87e8484c0a0e61e8f Mon Sep 17 00:00:00 2001 From: Sindre Sorhus Date: Tue, 20 Sep 2022 15:49:23 +0700 Subject: [PATCH 13/33] Update readme.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Ari Perkkiö --- readme.md | 1 - 1 file changed, 1 deletion(-) diff --git a/readme.md b/readme.md index 3b92551eb6..7308160ed6 100644 --- a/readme.md +++ b/readme.md @@ -45,7 +45,6 @@ Use a preset config or configure each rules in `package.json`. From [`v8.21.0`](https://github.com/eslint/eslint/releases/tag/v8.21.0), eslint announced a new config system. In the new system, `.eslintrc*` is no longer used. `eslint.config.js` would be the default config file name. -In eslint `v8`, the legacy system (`.eslintrc*`) would still be supported, while in eslint `v9`, only the new system would be supported. And from [`v8.23.0`](https://github.com/eslint/eslint/releases/tag/v8.23.0), eslint CLI starts to look up `eslint.config.js`. **So, if your eslint is `>=8.23.0`, you're 100% ready to use the new config system.** From 6a1659be4143e2cdbfa8d5ca7d737540693eb45b Mon Sep 17 00:00:00 2001 From: Sindre Sorhus Date: Tue, 20 Sep 2022 15:55:41 +0700 Subject: [PATCH 14/33] Update readme.md --- readme.md | 69 ++++++++++++++++++++++++++----------------------------- 1 file changed, 33 insertions(+), 36 deletions(-) diff --git a/readme.md b/readme.md index 7308160ed6..449de700c8 100644 --- a/readme.md +++ b/readme.md @@ -43,54 +43,52 @@ Use a preset config or configure each rules in `package.json`. ## Usage (new: `eslint.config.js`) -From [`v8.21.0`](https://github.com/eslint/eslint/releases/tag/v8.21.0), eslint announced a new config system. -In the new system, `.eslintrc*` is no longer used. `eslint.config.js` would be the default config file name. +From [ESLint `v8.21.0`](https://github.com/eslint/eslint/releases/tag/v8.21.0), there is a new config system. In the new system, `.eslintrc*` is no longer used. `eslint.config.js` would be the default config file name. -And from [`v8.23.0`](https://github.com/eslint/eslint/releases/tag/v8.23.0), eslint CLI starts to look up `eslint.config.js`. -**So, if your eslint is `>=8.23.0`, you're 100% ready to use the new config system.** +And from [`v8.23.0`](https://github.com/eslint/eslint/releases/tag/v8.23.0), the ESLint CLI starts to look up `eslint.config.js`. +**So, if you are using ESLint `>=8.23.0`, you are 100% ready to use the new config system.** You might want to check out the official blog posts, -- -- -- +- https://eslint.org/blog/2022/08/new-config-system-part-1/ +- https://eslint.org/blog/2022/08/new-config-system-part-2/ +- https://eslint.org/blog/2022/08/new-config-system-part-3/ and the [official docs](https://eslint.org/docs/latest/user-guide/configuring/configuration-files-new). -The default export of `eslint-plugin-react` is a plugin object. +The default export of `eslint-plugin-unicorn` is a plugin object. -If your `eslint.config.js` is ESM, you can import and use the plugin like this. +If your `eslint.config.js` is ESM, you can import and use the plugin like this: ```js -import unicorn from 'eslint-plugin-unicorn' +import unicorn from 'eslint-plugin-unicorn'; export default [ - // --- snip --- - { - files: ['**/*.{js,ts}'], - languageOptions: { - globals: { - ...globals.node, - ...globals.es2021, - }, - }, - plugins: { - unicorn, - }, - rules: { - // ... any rules you want - 'unicorn/better-regex': 'error', - 'unicorn/catch-error-name': 'error', - }, - // ... others are omitted for brevity - }, - // --- snip --- -] + // … + { + files: ['**/*.{js,ts}'], + languageOptions: { + globals: { + ...globals.node, + ...globals.es2021, + }, + }, + plugins: { + unicorn, + }, + rules: { + 'unicorn/better-regex': 'error', + 'unicorn/catch-error-name': 'error', + }, + // ... others are omitted for brevity + }, + // … +]; ``` If your `eslint.config.js` is CJS, please change it to ESM. -Note that this plugin itself would transition to [Pure ESM](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c) in future. +Note that this plugin itself will transition to [Pure ESM](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c) in the future. ## Rules @@ -248,20 +246,19 @@ This plugin exports an [`all` config](configs-legacy/all.js) that makes use of a ## Shareable configs (new: `eslint.config.js`) -If you use the new config system (`eslint.config.js`), there're 2 shareable configs. +If you use the new config system (`eslint.config.js`), there are two shareable configs: - `eslint-plugin-unicorn/all` - `eslint-plugin-unicorn/recommended` **Note**: Shareable configs will enable the [`languageOptions.globals`](https://eslint.org/docs/latest/user-guide/configuring/configuration-files-new#configuration-objects). -In the new config system, `plugin:` protocol(e.g. `plugin:react/recommended`) is no longer valid. -As eslint does not automatically import the preset config (shareable config), you explicitly do it by yourself. +In the new config system, the `plugin:` protocol (e.g. `plugin:react/recommended`) is no longer valid. As ESLint does not automatically import the preset config (shareable config), you explicitly do it by yourself. **Note**: The new plugin object does not have `configs` property as well. ```js -import unicorn from 'eslint-plugin-unicorn/all' // <== trailing '/all' +import unicorn from 'eslint-plugin-unicorn/all'; // <== trailing '/all' export default [ // --- snip --- From dce48df79d6535cd422797fcf83392113351fc9e Mon Sep 17 00:00:00 2001 From: jjangga0214 Date: Wed, 21 Sep 2022 13:15:07 +0900 Subject: [PATCH 15/33] docs: fix style --- readme.md | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/readme.md b/readme.md index 449de700c8..4707dcc503 100644 --- a/readme.md +++ b/readme.md @@ -261,32 +261,31 @@ In the new config system, the `plugin:` protocol (e.g. `plugin:react/recommended import unicorn from 'eslint-plugin-unicorn/all'; // <== trailing '/all' export default [ - // --- snip --- + // … unicorn, // This is not a plugin object, but a shareable config object - // --- snip --- -] + // … +]; ``` You can of course add/override some properties. ```js -import unicorn from 'eslint-plugin-unicorn/recommended' -import globals from 'globals' +import unicorn from 'eslint-plugin-unicorn/recommended'; +import globals from 'globals'; export default [ - // --- snip --- + // … { ...unicorn, files: ['**/*.{js,jsx}'], - languageOptions: { + languageOptions: { globals: { ...globals.browser, - // and so on }, }, }, - // --- snip --- -] + // … +]; ``` ## Maintainers From 4f9204579c505f091387681d2a62ef97f49832be Mon Sep 17 00:00:00 2001 From: fisker Date: Wed, 20 Dec 2023 18:32:13 +0800 Subject: [PATCH 16/33] Switch back to commonjs --- configs/all.mjs | 7 ++++--- configs/recommended.js | 18 ++++++++++++++++++ configs/recommended.mjs | 19 ------------------- index.mjs | 7 ------- package.json | 10 +++------- 5 files changed, 25 insertions(+), 36 deletions(-) create mode 100644 configs/recommended.js delete mode 100644 configs/recommended.mjs delete mode 100644 index.mjs diff --git a/configs/all.mjs b/configs/all.mjs index 35d4e3d5f1..1a75cc8e8f 100644 --- a/configs/all.mjs +++ b/configs/all.mjs @@ -1,9 +1,10 @@ -import {rules} from '../configs-legacy/all.js'; -import recommended from './recommended.mjs'; +'use strict'; +const eslintPluginUnicorn = require('../index.js'); +const recommended = require('./recommended.js'); const all = { ...recommended, - rules, + rules: eslintPluginUnicorn.configs.all.rules, }; export default all; diff --git a/configs/recommended.js b/configs/recommended.js new file mode 100644 index 0000000000..c39fd89ba0 --- /dev/null +++ b/configs/recommended.js @@ -0,0 +1,18 @@ +'use strict'; +const eslintPluginUnicorn = require('../index.js'); + +const recommended = { + files: ['**/*.{js,cjs,mjs,jsx,ts,tsx}'], + languageOptions: { + globals: { + ...globals.node, + ...globals.es2021, + }, + }, + plugins: { + unicorn: eslintPluginUnicorn, + }, + rules: eslintPluginUnicorn.configs.rules, +}; + +module.exports = recommended; diff --git a/configs/recommended.mjs b/configs/recommended.mjs deleted file mode 100644 index 2343510207..0000000000 --- a/configs/recommended.mjs +++ /dev/null @@ -1,19 +0,0 @@ -import globals from 'globals'; -import unicorn from '../index.mjs'; -import {rules} from '../configs-legacy/recommended.js'; - -const recommended = { - files: ['**/*.{js,cjs,mjs,jsx,ts,tsx}'], - languageOptions: { - globals: { - ...globals.node, - ...globals.es2021, - }, - }, - plugins: { - unicorn, - }, - rules, -}; - -export default recommended; diff --git a/index.mjs b/index.mjs deleted file mode 100644 index 2048e0dd4a..0000000000 --- a/index.mjs +++ /dev/null @@ -1,7 +0,0 @@ -import {rules} from './index.js'; - -const plugin = { - rules, -}; - -export default plugin; diff --git a/package.json b/package.json index 49b5a9564e..b2fdec2941 100644 --- a/package.json +++ b/package.json @@ -15,12 +15,9 @@ }, "main": "index.js", "exports": { - ".": { - "import": "./index.mjs", - "require": "./index.js" - }, - "./all": "./configs/all.mjs", - "./recommended": "./configs/recommended.mjs", + ".": "./index.js", + "./configs/all": "./configs/all.js", + "./configs/recommended": "./configs/recommended.js", "./package.json": "./package.json" }, "scripts": { @@ -43,7 +40,6 @@ }, "files": [ "index.js", - "experimental.mjs", "rules", "configs", "configs-legacy" From 66893940b2ed51914a41073d9329d3328c2bdeb8 Mon Sep 17 00:00:00 2001 From: fisker Date: Wed, 20 Dec 2023 18:34:26 +0800 Subject: [PATCH 17/33] Fix file name --- configs/{all.mjs => all.js} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename configs/{all.mjs => all.js} (100%) diff --git a/configs/all.mjs b/configs/all.js similarity index 100% rename from configs/all.mjs rename to configs/all.js From 24093f23a763becd18144217a12edfc230450e2b Mon Sep 17 00:00:00 2001 From: fisker Date: Wed, 20 Dec 2023 19:01:52 +0800 Subject: [PATCH 18/33] Fix config --- configs/all.js | 2 +- configs/recommended.js | 14 +++++----- package.json | 2 +- readme.md | 60 ++++++++++++++++++++++-------------------- 4 files changed, 41 insertions(+), 37 deletions(-) diff --git a/configs/all.js b/configs/all.js index 1a75cc8e8f..847ee2c55f 100644 --- a/configs/all.js +++ b/configs/all.js @@ -7,4 +7,4 @@ const all = { rules: eslintPluginUnicorn.configs.all.rules, }; -export default all; +module.exports = all; diff --git a/configs/recommended.js b/configs/recommended.js index c39fd89ba0..17103c3305 100644 --- a/configs/recommended.js +++ b/configs/recommended.js @@ -1,18 +1,20 @@ 'use strict'; +const eslintrc = require('@eslint/eslintrc') const eslintPluginUnicorn = require('../index.js'); +const {parserOptions:{ecmaVersion, sourceType}, rules} = eslintPluginUnicorn.configs.recommended +const {globals}= eslintrc.Legacy.environments.get('es2024') + const recommended = { - files: ['**/*.{js,cjs,mjs,jsx,ts,tsx}'], languageOptions: { - globals: { - ...globals.node, - ...globals.es2021, - }, + ecmaVersion, + sourceType, + globals, }, plugins: { unicorn: eslintPluginUnicorn, }, - rules: eslintPluginUnicorn.configs.rules, + rules, }; module.exports = recommended; diff --git a/package.json b/package.json index b2fdec2941..92ff49932f 100644 --- a/package.json +++ b/package.json @@ -57,12 +57,12 @@ "dependencies": { "@babel/helper-validator-identifier": "^7.22.20", "@eslint-community/eslint-utils": "^4.4.0", + "@eslint/eslintrc": "^2.1.4", "ci-info": "^4.0.0", "clean-regexp": "^1.0.0", "eslint-utils": "^3.0.0", "core-js-compat": "^3.34.0", "esquery": "^1.5.0", - "globals": "^13.24.0", "indent-string": "^4.0.0", "is-builtin-module": "^3.2.1", "jsesc": "^3.0.2", diff --git a/readme.md b/readme.md index 1ba549d6e3..2dbe0ede49 100644 --- a/readme.md +++ b/readme.md @@ -15,37 +15,9 @@ You might want to check out [XO](https://github.com/xojs/xo), which includes thi npm install --save-dev eslint eslint-plugin-unicorn ``` -## Usage (legacy: `eslintrc*`) - -Use a [preset config](#preset-configs) or configure each rule in `package.json`. - -If you don't use the preset, ensure you use the same `env` and `parserOptions` config as below. - -```json -{ - "name": "my-awesome-project", - "eslintConfig": { - "env": { - "es2024": true - }, - "parserOptions": { - "ecmaVersion": "latest", - "sourceType": "module" - }, - "plugins": [ - "unicorn" - ], - "rules": { - "unicorn/better-regex": "error", - "unicorn/…": "error" - } - } -} -``` - ## Usage (new: `eslint.config.js`) -From [ESLint `v8.21.0`](https://github.com/eslint/eslint/releases/tag/v8.21.0), there is a new config system. In the new system, `.eslintrc*` is no longer used. `eslint.config.js` would be the default config file name. +From [ESLint `v8.21.0`](https://github.com/eslint/eslint/releases/tag/v8.21.0), there is a new config system. In the new system, `.eslintrc.*` is no longer used. `eslint.config.js` would be the default config file name. And from [`v8.23.0`](https://github.com/eslint/eslint/releases/tag/v8.23.0), the ESLint CLI starts to look up `eslint.config.js`. **So, if you are using ESLint `>=8.23.0`, you are 100% ready to use the new config system.** @@ -55,6 +27,7 @@ You might want to check out the official blog posts, - https://eslint.org/blog/2022/08/new-config-system-part-1/ - https://eslint.org/blog/2022/08/new-config-system-part-2/ - https://eslint.org/blog/2022/08/new-config-system-part-3/ +- https://eslint.org/blog/2023/10/flat-config-rollout-plans/ and the [official docs](https://eslint.org/docs/latest/user-guide/configuring/configuration-files-new). @@ -92,6 +65,35 @@ If your `eslint.config.js` is CJS, please change it to ESM. Note that this plugin itself will transition to [Pure ESM](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c) in the future. + +## Usage (legacy: `eslintrc*`) + +Use a [preset config](#preset-configs) or configure each rule in `package.json`. + +If you don't use the preset, ensure you use the same `env` and `parserOptions` config as below. + +```json +{ + "name": "my-awesome-project", + "eslintConfig": { + "env": { + "es2024": true + }, + "parserOptions": { + "ecmaVersion": "latest", + "sourceType": "module" + }, + "plugins": [ + "unicorn" + ], + "rules": { + "unicorn/better-regex": "error", + "unicorn/…": "error" + } + } +} +``` + ## Rules From c8180d4732d0970daddb6a8d08dddca7f8d4c121 Mon Sep 17 00:00:00 2001 From: fisker Date: Wed, 20 Dec 2023 19:45:26 +0800 Subject: [PATCH 19/33] Add test --- configs/recommended.js | 11 +++++++---- package.json | 2 +- test/package.mjs | 13 +++++++++++++ 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/configs/recommended.js b/configs/recommended.js index 17103c3305..43def296ab 100644 --- a/configs/recommended.js +++ b/configs/recommended.js @@ -1,15 +1,18 @@ 'use strict'; -const eslintrc = require('@eslint/eslintrc') const eslintPluginUnicorn = require('../index.js'); -const {parserOptions:{ecmaVersion, sourceType}, rules} = eslintPluginUnicorn.configs.recommended -const {globals}= eslintrc.Legacy.environments.get('es2024') +const { + parserOptions:{ + ecmaVersion, + sourceType, + }, + rules, +} = eslintPluginUnicorn.configs.recommended; const recommended = { languageOptions: { ecmaVersion, sourceType, - globals, }, plugins: { unicorn: eslintPluginUnicorn, diff --git a/package.json b/package.json index 92ff49932f..182164dc89 100644 --- a/package.json +++ b/package.json @@ -57,7 +57,6 @@ "dependencies": { "@babel/helper-validator-identifier": "^7.22.20", "@eslint-community/eslint-utils": "^4.4.0", - "@eslint/eslintrc": "^2.1.4", "ci-info": "^4.0.0", "clean-regexp": "^1.0.0", "eslint-utils": "^3.0.0", @@ -77,6 +76,7 @@ "@babel/code-frame": "^7.23.5", "@babel/core": "^7.23.6", "@babel/eslint-parser": "^7.23.3", + "@eslint/eslintrc": "^2.1.4", "@lubien/fixture-beta-package": "^1.0.0-beta.1", "@typescript-eslint/parser": "^6.15.0", "ava": "^6.0.1", diff --git a/test/package.mjs b/test/package.mjs index 6163453c51..e7de95ca9a 100644 --- a/test/package.mjs +++ b/test/package.mjs @@ -4,6 +4,9 @@ import test from 'ava'; import {ESLint} from 'eslint'; import * as eslintrc from '@eslint/eslintrc'; import eslintPluginUnicorn from '../index.js'; +import flatConfigRecommended from '../configs/recommended.js'; +import allConfigRecommended from '../configs/all.js'; +const flatConfigs = {recommended: flatConfigRecommended, all: allConfigRecommended}; let ruleFiles; @@ -215,3 +218,13 @@ test('Plugin should have metadata', t => { t.is(typeof eslintPluginUnicorn.meta.name, 'string'); t.is(typeof eslintPluginUnicorn.meta.version, 'string'); }); + +test.only('flat configs', t => { + const compat = new eslintrc.FlatCompat({ + baseDirectory: process.cwd(), + resolvePluginsRelativeTo: process.cwd(), + }); + + t.deepEqual(compat.config(eslintPluginUnicorn.configs.recommended)[1], flatConfigs.recommended) + t.deepEqual(compat.config(eslintPluginUnicorn.configs.all)[1], flatConfigs.all) +}); From 37b3aa109c8bab1469b00f2240df00113eb6ab3d Mon Sep 17 00:00:00 2001 From: fisker Date: Wed, 20 Dec 2023 19:53:54 +0800 Subject: [PATCH 20/33] Fix --- configs/recommended.js | 5 ++++- package.json | 2 +- test/package.mjs | 20 +++++++++++++++++--- 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/configs/recommended.js b/configs/recommended.js index 43def296ab..922a68338d 100644 --- a/configs/recommended.js +++ b/configs/recommended.js @@ -1,18 +1,21 @@ 'use strict'; +const eslintrc = require('@eslint/eslintrc'); const eslintPluginUnicorn = require('../index.js'); const { - parserOptions:{ + parserOptions: { ecmaVersion, sourceType, }, rules, } = eslintPluginUnicorn.configs.recommended; +const {globals} = eslintrc.Legacy.environments.get('es2024'); const recommended = { languageOptions: { ecmaVersion, sourceType, + globals, }, plugins: { unicorn: eslintPluginUnicorn, diff --git a/package.json b/package.json index 182164dc89..92ff49932f 100644 --- a/package.json +++ b/package.json @@ -57,6 +57,7 @@ "dependencies": { "@babel/helper-validator-identifier": "^7.22.20", "@eslint-community/eslint-utils": "^4.4.0", + "@eslint/eslintrc": "^2.1.4", "ci-info": "^4.0.0", "clean-regexp": "^1.0.0", "eslint-utils": "^3.0.0", @@ -76,7 +77,6 @@ "@babel/code-frame": "^7.23.5", "@babel/core": "^7.23.6", "@babel/eslint-parser": "^7.23.3", - "@eslint/eslintrc": "^2.1.4", "@lubien/fixture-beta-package": "^1.0.0-beta.1", "@typescript-eslint/parser": "^6.15.0", "ava": "^6.0.1", diff --git a/test/package.mjs b/test/package.mjs index e7de95ca9a..aa9f17e622 100644 --- a/test/package.mjs +++ b/test/package.mjs @@ -1,11 +1,13 @@ import fs, {promises as fsAsync} from 'node:fs'; import path from 'node:path'; +import process from 'node:process'; import test from 'ava'; import {ESLint} from 'eslint'; import * as eslintrc from '@eslint/eslintrc'; import eslintPluginUnicorn from '../index.js'; import flatConfigRecommended from '../configs/recommended.js'; import allConfigRecommended from '../configs/all.js'; + const flatConfigs = {recommended: flatConfigRecommended, all: allConfigRecommended}; let ruleFiles; @@ -219,12 +221,24 @@ test('Plugin should have metadata', t => { t.is(typeof eslintPluginUnicorn.meta.version, 'string'); }); -test.only('flat configs', t => { +function getCompactConfig(config) { const compat = new eslintrc.FlatCompat({ baseDirectory: process.cwd(), resolvePluginsRelativeTo: process.cwd(), }); - t.deepEqual(compat.config(eslintPluginUnicorn.configs.recommended)[1], flatConfigs.recommended) - t.deepEqual(compat.config(eslintPluginUnicorn.configs.all)[1], flatConfigs.all) + const result = {}; + + for (const part of compat.config(config)) { + for (const [key, value] of Object.entries(part)) { + result[key] = key === 'languageOptions' ? {...result[key], ...value} : value; + } + } + + return result; +} + +test('flat configs', t => { + t.deepEqual(getCompactConfig(eslintPluginUnicorn.configs.recommended), flatConfigs.recommended); + t.deepEqual(getCompactConfig(eslintPluginUnicorn.configs.all), flatConfigs.all); }); From d35eb369c94dc654fe092ec83979fbe283ef17b1 Mon Sep 17 00:00:00 2001 From: fisker Date: Wed, 20 Dec 2023 20:20:15 +0800 Subject: [PATCH 21/33] Update readme.md --- readme.md | 192 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 119 insertions(+), 73 deletions(-) diff --git a/readme.md b/readme.md index 2dbe0ede49..93645202f8 100644 --- a/readme.md +++ b/readme.md @@ -15,58 +15,68 @@ You might want to check out [XO](https://github.com/xojs/xo), which includes thi npm install --save-dev eslint eslint-plugin-unicorn ``` -## Usage (new: `eslint.config.js`) +## Usage (`eslint.config.js`) -From [ESLint `v8.21.0`](https://github.com/eslint/eslint/releases/tag/v8.21.0), there is a new config system. In the new system, `.eslintrc.*` is no longer used. `eslint.config.js` would be the default config file name. +**Requires ESLint `>=8.23.0`.** -And from [`v8.23.0`](https://github.com/eslint/eslint/releases/tag/v8.23.0), the ESLint CLI starts to look up `eslint.config.js`. -**So, if you are using ESLint `>=8.23.0`, you are 100% ready to use the new config system.** +Use a [preset config](#preset-configs) or configure each rule in `eslint.config.js`. -You might want to check out the official blog posts, +If you don't use the preset, ensure you use the same `languageOptions` config as below. -- https://eslint.org/blog/2022/08/new-config-system-part-1/ -- https://eslint.org/blog/2022/08/new-config-system-part-2/ -- https://eslint.org/blog/2022/08/new-config-system-part-3/ -- https://eslint.org/blog/2023/10/flat-config-rollout-plans/ - -and the [official docs](https://eslint.org/docs/latest/user-guide/configuring/configuration-files-new). - -The default export of `eslint-plugin-unicorn` is a plugin object. - -If your `eslint.config.js` is ESM, you can import and use the plugin like this: +### ES Module ```js -import unicorn from 'eslint-plugin-unicorn'; +import eslintPluginUnicorn from 'eslint-plugin-unicorn'; +import * as eslintrc from '@eslint/eslintrc'; export default [ - // … { - files: ['**/*.{js,ts}'], + files: ['**/*.{js,cjs,mjs}'], languageOptions: { - globals: { - ...globals.node, - ...globals.es2021, - }, + ecmaVersion: latest, + sourceType: module, + globals: eslintrc.Legacy.environments.get('es2024'), }, plugins: { - unicorn, + unicorn: eslintPluginUnicorn, }, rules: { 'unicorn/better-regex': 'error', - 'unicorn/catch-error-name': 'error', + 'unicorn/…': 'error', }, - // ... others are omitted for brevity }, // … ]; ``` -If your `eslint.config.js` is CJS, please change it to ESM. +### CommonJS -Note that this plugin itself will transition to [Pure ESM](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c) in the future. +```js +'use strict'; +const eslintPluginUnicorn = require('eslint-plugin-unicorn'); +const eslintrc = require('@eslint/eslintrc'); +module.exports = [ + { + files: ['**/*.{js,cjs,mjs}'], + languageOptions: { + ecmaVersion: latest, + sourceType: module, + globals: eslintrc.Legacy.environments.get('es2024'), + }, + plugins: { + unicorn: eslintPluginUnicorn, + }, + rules: { + 'unicorn/better-regex': 'error', + 'unicorn/…': 'error', + }, + }, + // … +]; +``` -## Usage (legacy: `eslintrc*`) +## Usage (legacy: `.eslintrc.*` or `package.json`) Use a [preset config](#preset-configs) or configure each rule in `package.json`. @@ -223,7 +233,87 @@ If you don't use the preset, ensure you use the same `env` and `parserOptions` c See [docs/deprecated-rules.md](docs/deprecated-rules.md) -## Preset configs (legacy: `eslintrc*`) +## Preset configs (`eslint.config.js`) + +See the [ESLint docs](https://eslint.org/docs/latest/user-guide/configuring/configuration-files-new) for more information about extending config files. + +**Note**: Preset configs will also enable the correct [language options](https://eslint.org/docs/latest/use/configure/configuration-files-new#configuring-language-options). + +### Recommended config + +This plugin exports a [`recommended` config](configs/recommended.js) that enforces good practices. + +#### ES Module (Recommended) + +```js +import eslintPluginUnicornConfigRecommended from 'eslint-plugin-unicorn/configs/recommended'; + +export default [ + // … + eslintPluginUnicornConfigRecommended, + { + rules: { + 'unicorn/better-regex': 'warn', + }, + }, +]; +``` + +#### CommonJS + +```js +'use strict'; +const eslintPluginUnicornConfigRecommended = require('eslint-plugin-unicorn/configs/recommended'); + +module.exports = [ + // … + eslintPluginUnicornConfigRecommended, + { + rules: { + 'unicorn/better-regex': 'warn', + }, + }, +]; +``` + +### All config + +This plugin exports an [`all` config](configs/all.js) that makes use of all rules (except for deprecated ones). + +#### ES Module (Recommended) + +```js +import eslintPluginUnicornConfigAll from 'eslint-plugin-unicorn/configs/all'; + +export default [ + // … + eslintPluginUnicornConfigAll, + { + rules: { + 'unicorn/better-regex': 'warn', + }, + }, +]; +``` + +#### CommonJS + +```js +'use strict'; +const eslintPluginUnicornConfigAll = require('eslint-plugin-unicorn/configs/all'); + +module.exports = [ + // … + eslintPluginUnicornConfigAll, + { + rules: { + 'unicorn/better-regex': 'warn', + }, + }, +]; +``` + +## Preset configs (`.eslintrc.*` or `package.json`) See the [ESLint docs](https://eslint.org/docs/user-guide/configuring/configuration-files#extending-configuration-files) for more information about extending config files. @@ -255,50 +345,6 @@ This plugin exports an [`all` config](configs-legacy/all.js) that makes use of a } ``` -## Shareable configs (new: `eslint.config.js`) - -If you use the new config system (`eslint.config.js`), there are two shareable configs: - -- `eslint-plugin-unicorn/all` -- `eslint-plugin-unicorn/recommended` - -**Note**: Shareable configs will enable the [`languageOptions.globals`](https://eslint.org/docs/latest/user-guide/configuring/configuration-files-new#configuration-objects). - -In the new config system, the `plugin:` protocol (e.g. `plugin:react/recommended`) is no longer valid. As ESLint does not automatically import the preset config (shareable config), you explicitly do it by yourself. - -**Note**: The new plugin object does not have `configs` property as well. - -```js -import unicorn from 'eslint-plugin-unicorn/all'; // <== trailing '/all' - -export default [ - // … - unicorn, // This is not a plugin object, but a shareable config object - // … -]; -``` - -You can of course add/override some properties. - -```js -import unicorn from 'eslint-plugin-unicorn/recommended'; -import globals from 'globals'; - -export default [ - // … - { - ...unicorn, - files: ['**/*.{js,jsx}'], - languageOptions: { - globals: { - ...globals.browser, - }, - }, - }, - // … -]; -``` - ## Maintainers - [Sindre Sorhus](https://github.com/sindresorhus) From 165e34d3a98ae63812abb1180eda9ddf82206cf9 Mon Sep 17 00:00:00 2001 From: fisker Date: Wed, 20 Dec 2023 20:22:54 +0800 Subject: [PATCH 22/33] Fix anchor --- readme.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 93645202f8..4c3b097f99 100644 --- a/readme.md +++ b/readme.md @@ -78,7 +78,7 @@ module.exports = [ ## Usage (legacy: `.eslintrc.*` or `package.json`) -Use a [preset config](#preset-configs) or configure each rule in `package.json`. +Use a [preset config](#preset-configs-legacy) or configure each rule in `package.json`. If you don't use the preset, ensure you use the same `env` and `parserOptions` config as below. @@ -233,6 +233,7 @@ If you don't use the preset, ensure you use the same `env` and `parserOptions` c See [docs/deprecated-rules.md](docs/deprecated-rules.md) + ## Preset configs (`eslint.config.js`) See the [ESLint docs](https://eslint.org/docs/latest/user-guide/configuring/configuration-files-new) for more information about extending config files. @@ -313,6 +314,7 @@ module.exports = [ ]; ``` + ## Preset configs (`.eslintrc.*` or `package.json`) See the [ESLint docs](https://eslint.org/docs/user-guide/configuring/configuration-files#extending-configuration-files) for more information about extending config files. From 3e46955bc4d9b3219cba5143a2a61d48f6ce2d9e Mon Sep 17 00:00:00 2001 From: fisker Date: Wed, 20 Dec 2023 20:30:29 +0800 Subject: [PATCH 23/33] Fix linting --- .markdownlint.json | 1 + readme.md | 9 ++++----- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.markdownlint.json b/.markdownlint.json index f547864a81..77d49b79c2 100644 --- a/.markdownlint.json +++ b/.markdownlint.json @@ -2,6 +2,7 @@ "line-length": false, "no-duplicate-heading": false, "no-hard-tabs": false, + "no-inline-html": false, "ul-style": { "style": "dash" } diff --git a/readme.md b/readme.md index 4c3b097f99..5db1fc6da7 100644 --- a/readme.md +++ b/readme.md @@ -23,7 +23,7 @@ Use a [preset config](#preset-configs) or configure each rule in `eslint.config. If you don't use the preset, ensure you use the same `languageOptions` config as below. -### ES Module +### ES Module (Recommended) ```js import eslintPluginUnicorn from 'eslint-plugin-unicorn'; @@ -233,8 +233,8 @@ If you don't use the preset, ensure you use the same `env` and `parserOptions` c See [docs/deprecated-rules.md](docs/deprecated-rules.md) - -## Preset configs (`eslint.config.js`) + +## Preset configs (`eslint.config.js`) See the [ESLint docs](https://eslint.org/docs/latest/user-guide/configuring/configuration-files-new) for more information about extending config files. @@ -314,8 +314,7 @@ module.exports = [ ]; ``` - -## Preset configs (`.eslintrc.*` or `package.json`) +## Preset configs (`.eslintrc.*` or `package.json`) See the [ESLint docs](https://eslint.org/docs/user-guide/configuring/configuration-files#extending-configuration-files) for more information about extending config files. From 0942d71e6f457fe8794868e0c80e29ff408ab650 Mon Sep 17 00:00:00 2001 From: fisker Date: Wed, 20 Dec 2023 20:35:03 +0800 Subject: [PATCH 24/33] Linting --- .markdownlint.json | 1 + package.json | 4 ++-- readme.md | 1 - 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.markdownlint.json b/.markdownlint.json index 77d49b79c2..b8ac7bec6f 100644 --- a/.markdownlint.json +++ b/.markdownlint.json @@ -3,6 +3,7 @@ "no-duplicate-heading": false, "no-hard-tabs": false, "no-inline-html": false, + "link-fragments": false, "ul-style": { "style": "dash" } diff --git a/package.json b/package.json index 92ff49932f..e0f7b95dfc 100644 --- a/package.json +++ b/package.json @@ -25,12 +25,12 @@ "fix": "run-p --continue-on-error fix:*", "fix:eslint-docs": "eslint-doc-generator", "fix:js": "npm run lint:js -- --fix", - "fix:md": "npm run lint:md -- --fix", + "fix:markdown": "npm run lint:markdown -- --fix", "integration": "node ./test/integration/test.mjs", "lint": "run-p --continue-on-error lint:*", "lint:eslint-docs": "npm run fix:eslint-docs -- --check", "lint:js": "xo", - "lint:md": "markdownlint \"**/*.md\"", + "lint:markdown": "markdownlint \"**/*.md\"", "lint:package-json": "npmPkgJsonLint .", "run-rules-on-codebase": "node ./test/run-rules-on-codebase/lint.mjs", "bundle-lodash": "echo \"export {defaultsDeep, camelCase, kebabCase, snakeCase, upperFirst, lowerFirst} from 'lodash-es';\" | npx esbuild --bundle --outfile=rules/utils/lodash.js --format=cjs", diff --git a/readme.md b/readme.md index 5db1fc6da7..850fac6aba 100644 --- a/readme.md +++ b/readme.md @@ -233,7 +233,6 @@ If you don't use the preset, ensure you use the same `env` and `parserOptions` c See [docs/deprecated-rules.md](docs/deprecated-rules.md) - ## Preset configs (`eslint.config.js`) See the [ESLint docs](https://eslint.org/docs/latest/user-guide/configuring/configuration-files-new) for more information about extending config files. From 4b3b4876629cb9296143900136aabd86c69dc95b Mon Sep 17 00:00:00 2001 From: fisker Date: Wed, 20 Dec 2023 20:41:59 +0800 Subject: [PATCH 25/33] Fix example --- readme.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/readme.md b/readme.md index 850fac6aba..66dd58b1f0 100644 --- a/readme.md +++ b/readme.md @@ -31,10 +31,9 @@ import * as eslintrc from '@eslint/eslintrc'; export default [ { - files: ['**/*.{js,cjs,mjs}'], languageOptions: { - ecmaVersion: latest, - sourceType: module, + ecmaVersion: 'latest', + sourceType: 'module', globals: eslintrc.Legacy.environments.get('es2024'), }, plugins: { @@ -58,10 +57,9 @@ const eslintrc = require('@eslint/eslintrc'); module.exports = [ { - files: ['**/*.{js,cjs,mjs}'], languageOptions: { - ecmaVersion: latest, - sourceType: module, + ecmaVersion: 'latest', + sourceType: 'module', globals: eslintrc.Legacy.environments.get('es2024'), }, plugins: { @@ -327,7 +325,10 @@ This plugin exports a [`recommended` config](configs-legacy/recommended.js) that { "name": "my-awesome-project", "eslintConfig": { - "extends": "plugin:unicorn/recommended" + "extends": "plugin:unicorn/recommended", + "rules": { + "unicorn/better-regex": "warn" + } } } ``` From b099569f2841b50204d2e9c9eba4616bd56626c5 Mon Sep 17 00:00:00 2001 From: fisker Date: Wed, 20 Dec 2023 20:50:29 +0800 Subject: [PATCH 26/33] Remove useless dependency --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index e0f7b95dfc..385524d8b2 100644 --- a/package.json +++ b/package.json @@ -60,7 +60,6 @@ "@eslint/eslintrc": "^2.1.4", "ci-info": "^4.0.0", "clean-regexp": "^1.0.0", - "eslint-utils": "^3.0.0", "core-js-compat": "^3.34.0", "esquery": "^1.5.0", "indent-string": "^4.0.0", From 3809656fdd3011f3565d37f3626f2fe0ee98e7b0 Mon Sep 17 00:00:00 2001 From: fisker Date: Wed, 20 Dec 2023 20:53:13 +0800 Subject: [PATCH 27/33] Fix anchor --- readme.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/readme.md b/readme.md index 66dd58b1f0..fcc4233317 100644 --- a/readme.md +++ b/readme.md @@ -231,7 +231,7 @@ If you don't use the preset, ensure you use the same `env` and `parserOptions` c See [docs/deprecated-rules.md](docs/deprecated-rules.md) -## Preset configs (`eslint.config.js`) +## Preset configs (`eslint.config.js`) See the [ESLint docs](https://eslint.org/docs/latest/user-guide/configuring/configuration-files-new) for more information about extending config files. @@ -311,7 +311,7 @@ module.exports = [ ]; ``` -## Preset configs (`.eslintrc.*` or `package.json`) +## Preset configs (`.eslintrc.*` or `package.json`) See the [ESLint docs](https://eslint.org/docs/user-guide/configuring/configuration-files#extending-configuration-files) for more information about extending config files. From 8985321aed5c1a57c6fc457f534862b1e5e8fb86 Mon Sep 17 00:00:00 2001 From: fisker Date: Wed, 20 Dec 2023 20:56:43 +0800 Subject: [PATCH 28/33] Use auto generated anchor --- .markdownlint.json | 2 -- readme.md | 8 ++++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/.markdownlint.json b/.markdownlint.json index b8ac7bec6f..f547864a81 100644 --- a/.markdownlint.json +++ b/.markdownlint.json @@ -2,8 +2,6 @@ "line-length": false, "no-duplicate-heading": false, "no-hard-tabs": false, - "no-inline-html": false, - "link-fragments": false, "ul-style": { "style": "dash" } diff --git a/readme.md b/readme.md index fcc4233317..dd006162e0 100644 --- a/readme.md +++ b/readme.md @@ -19,7 +19,7 @@ npm install --save-dev eslint eslint-plugin-unicorn **Requires ESLint `>=8.23.0`.** -Use a [preset config](#preset-configs) or configure each rule in `eslint.config.js`. +Use a [preset config](#preset-configs-eslintconfigjs) or configure each rule in `eslint.config.js`. If you don't use the preset, ensure you use the same `languageOptions` config as below. @@ -76,7 +76,7 @@ module.exports = [ ## Usage (legacy: `.eslintrc.*` or `package.json`) -Use a [preset config](#preset-configs-legacy) or configure each rule in `package.json`. +Use a [preset config](#preset-configs-eslintrc-or-packagejson) or configure each rule in `package.json`. If you don't use the preset, ensure you use the same `env` and `parserOptions` config as below. @@ -231,7 +231,7 @@ If you don't use the preset, ensure you use the same `env` and `parserOptions` c See [docs/deprecated-rules.md](docs/deprecated-rules.md) -## Preset configs (`eslint.config.js`) +## Preset configs (`eslint.config.js`) See the [ESLint docs](https://eslint.org/docs/latest/user-guide/configuring/configuration-files-new) for more information about extending config files. @@ -311,7 +311,7 @@ module.exports = [ ]; ``` -## Preset configs (`.eslintrc.*` or `package.json`) +## Preset configs (`.eslintrc.*` or `package.json`) See the [ESLint docs](https://eslint.org/docs/user-guide/configuring/configuration-files#extending-configuration-files) for more information about extending config files. From 151b3fd33864191a12fc34f00f7eb49d24daa45b Mon Sep 17 00:00:00 2001 From: fisker Date: Wed, 20 Dec 2023 22:10:18 +0800 Subject: [PATCH 29/33] Move to `flat/*` --- .eslint-doc-generatorrc.js | 2 +- configs-legacy/all.js | 9 --- configs-legacy/recommended.js | 129 ------------------------------- configs/all.js | 10 +-- configs/flat-config-base.js | 20 +++++ configs/legacy-config-base.js | 10 +++ configs/recommended.js | 139 ++++++++++++++++++++++++++++------ docs/new-rule.md | 2 +- index.js | 27 +++++-- package.json | 9 +-- readme.md | 20 ++--- scripts/create-rule.mjs | 4 +- test/package.mjs | 26 ++++--- 13 files changed, 200 insertions(+), 207 deletions(-) delete mode 100644 configs-legacy/all.js delete mode 100644 configs-legacy/recommended.js create mode 100644 configs/flat-config-base.js create mode 100644 configs/legacy-config-base.js diff --git a/.eslint-doc-generatorrc.js b/.eslint-doc-generatorrc.js index cafa0a8c90..876d722447 100644 --- a/.eslint-doc-generatorrc.js +++ b/.eslint-doc-generatorrc.js @@ -2,7 +2,7 @@ /** @type {import('eslint-doc-generator').GenerateOptions} */ const config = { - ignoreConfig: ['all'], + ignoreConfig: ['all','flat/all','flat/recommended'], ignoreDeprecatedRules: true, ruleDocTitleFormat: 'desc', ruleListColumns: [ diff --git a/configs-legacy/all.js b/configs-legacy/all.js deleted file mode 100644 index d1ab5d77c3..0000000000 --- a/configs-legacy/all.js +++ /dev/null @@ -1,9 +0,0 @@ -'use strict'; -const {rules, ...baseConfigs} = require('./recommended.js'); - -module.exports = { - ...baseConfigs, - rules: Object.fromEntries(Object.entries(rules).map( - ([ruleId, severity]) => [ruleId, ruleId.startsWith('unicorn/') ? 'error' : severity], - )), -}; diff --git a/configs-legacy/recommended.js b/configs-legacy/recommended.js deleted file mode 100644 index ecbedcd90c..0000000000 --- a/configs-legacy/recommended.js +++ /dev/null @@ -1,129 +0,0 @@ -'use strict'; -module.exports = { - env: { - es2024: true, - }, - parserOptions: { - ecmaVersion: 'latest', - sourceType: 'module', - }, - plugins: [ - 'unicorn', - ], - rules: { - 'unicorn/better-regex': 'error', - 'unicorn/catch-error-name': 'error', - 'unicorn/consistent-destructuring': 'error', - 'unicorn/consistent-function-scoping': 'error', - 'unicorn/custom-error-definition': 'off', - 'unicorn/empty-brace-spaces': 'error', - 'unicorn/error-message': 'error', - 'unicorn/escape-case': 'error', - 'unicorn/expiring-todo-comments': 'error', - 'unicorn/explicit-length-check': 'error', - 'unicorn/filename-case': 'error', - 'unicorn/import-style': 'error', - 'unicorn/new-for-builtins': 'error', - 'unicorn/no-abusive-eslint-disable': 'error', - 'unicorn/no-array-callback-reference': 'error', - 'unicorn/no-array-for-each': 'error', - 'unicorn/no-array-method-this-argument': 'error', - 'unicorn/no-array-push-push': 'error', - 'unicorn/no-array-reduce': 'error', - 'unicorn/no-await-expression-member': 'error', - 'unicorn/no-console-spaces': 'error', - 'unicorn/no-document-cookie': 'error', - 'unicorn/no-empty-file': 'error', - 'unicorn/no-for-loop': 'error', - 'unicorn/no-hex-escape': 'error', - 'unicorn/no-instanceof-array': 'error', - 'unicorn/no-invalid-remove-event-listener': 'error', - 'unicorn/no-keyword-prefix': 'off', - 'unicorn/no-lonely-if': 'error', - 'no-negated-condition': 'off', - 'unicorn/no-negated-condition': 'error', - 'no-nested-ternary': 'off', - 'unicorn/no-nested-ternary': 'error', - 'unicorn/no-new-array': 'error', - 'unicorn/no-new-buffer': 'error', - 'unicorn/no-null': 'error', - 'unicorn/no-object-as-default-parameter': 'error', - 'unicorn/no-process-exit': 'error', - 'unicorn/no-static-only-class': 'error', - 'unicorn/no-thenable': 'error', - 'unicorn/no-this-assignment': 'error', - 'unicorn/no-typeof-undefined': 'error', - 'unicorn/no-unnecessary-await': 'error', - 'unicorn/no-unnecessary-polyfills': 'error', - 'unicorn/no-unreadable-array-destructuring': 'error', - 'unicorn/no-unreadable-iife': 'error', - 'unicorn/no-unused-properties': 'off', - 'unicorn/no-useless-fallback-in-spread': 'error', - 'unicorn/no-useless-length-check': 'error', - 'unicorn/no-useless-promise-resolve-reject': 'error', - 'unicorn/no-useless-spread': 'error', - 'unicorn/no-useless-switch-case': 'error', - 'unicorn/no-useless-undefined': 'error', - 'unicorn/no-zero-fractions': 'error', - 'unicorn/number-literal-case': 'error', - 'unicorn/numeric-separators-style': 'error', - 'unicorn/prefer-add-event-listener': 'error', - 'unicorn/prefer-array-find': 'error', - 'unicorn/prefer-array-flat': 'error', - 'unicorn/prefer-array-flat-map': 'error', - 'unicorn/prefer-array-index-of': 'error', - 'unicorn/prefer-array-some': 'error', - 'unicorn/prefer-at': 'error', - 'unicorn/prefer-blob-reading-methods': 'error', - 'unicorn/prefer-code-point': 'error', - 'unicorn/prefer-date-now': 'error', - 'unicorn/prefer-default-parameters': 'error', - 'unicorn/prefer-dom-node-append': 'error', - 'unicorn/prefer-dom-node-dataset': 'error', - 'unicorn/prefer-dom-node-remove': 'error', - 'unicorn/prefer-dom-node-text-content': 'error', - 'unicorn/prefer-event-target': 'error', - 'unicorn/prefer-export-from': 'error', - 'unicorn/prefer-includes': 'error', - 'unicorn/prefer-json-parse-buffer': 'off', - 'unicorn/prefer-keyboard-event-key': 'error', - 'unicorn/prefer-logical-operator-over-ternary': 'error', - 'unicorn/prefer-math-trunc': 'error', - 'unicorn/prefer-modern-dom-apis': 'error', - 'unicorn/prefer-modern-math-apis': 'error', - 'unicorn/prefer-module': 'error', - 'unicorn/prefer-native-coercion-functions': 'error', - 'unicorn/prefer-negative-index': 'error', - 'unicorn/prefer-node-protocol': 'error', - 'unicorn/prefer-number-properties': 'error', - 'unicorn/prefer-object-from-entries': 'error', - 'unicorn/prefer-optional-catch-binding': 'error', - 'unicorn/prefer-prototype-methods': 'error', - 'unicorn/prefer-query-selector': 'error', - 'unicorn/prefer-reflect-apply': 'error', - 'unicorn/prefer-regexp-test': 'error', - 'unicorn/prefer-set-has': 'error', - 'unicorn/prefer-set-size': 'error', - 'unicorn/prefer-spread': 'error', - 'unicorn/prefer-string-replace-all': 'error', - 'unicorn/prefer-string-slice': 'error', - 'unicorn/prefer-string-starts-ends-with': 'error', - 'unicorn/prefer-string-trim-start-end': 'error', - 'unicorn/prefer-switch': 'error', - 'unicorn/prefer-ternary': 'error', - 'unicorn/prefer-top-level-await': 'error', - 'unicorn/prefer-type-error': 'error', - 'unicorn/prevent-abbreviations': 'error', - 'unicorn/relative-url-style': 'error', - 'unicorn/require-array-join-separator': 'error', - 'unicorn/require-number-to-fixed-digits-argument': 'error', - // Turned off because we can't distinguish `widow.postMessage` and `{Worker,MessagePort,Client,BroadcastChannel}#postMessage()` - // See #1396 - 'unicorn/require-post-message-target-origin': 'off', - 'unicorn/string-content': 'off', - 'unicorn/switch-case-braces': 'error', - 'unicorn/template-indent': 'error', - 'unicorn/text-encoding-identifier-case': 'error', - 'unicorn/throw-new-error': 'error', - }, -}; diff --git a/configs/all.js b/configs/all.js index 847ee2c55f..743845a378 100644 --- a/configs/all.js +++ b/configs/all.js @@ -1,10 +1,6 @@ 'use strict'; -const eslintPluginUnicorn = require('../index.js'); const recommended = require('./recommended.js'); -const all = { - ...recommended, - rules: eslintPluginUnicorn.configs.all.rules, -}; - -module.exports = all; +module.exports = Object.fromEntries(Object.entries(recommended).map( + ([ruleId, severity]) => [ruleId, ruleId.startsWith('unicorn/') ? 'error' : severity], +)); diff --git a/configs/flat-config-base.js b/configs/flat-config-base.js new file mode 100644 index 0000000000..4325e66d1e --- /dev/null +++ b/configs/flat-config-base.js @@ -0,0 +1,20 @@ +'use strict'; +const eslintrc = require('@eslint/eslintrc'); +const legacyConfigBase = require('./legacy-config-base.js'); + +const { + parserOptions: { + ecmaVersion, + sourceType, + }, +} = legacyConfigBase; + +const {globals} = eslintrc.Legacy.environments.get('es2024'); + +module.exports = { + languageOptions: { + ecmaVersion, + sourceType, + globals, + }, +}; diff --git a/configs/legacy-config-base.js b/configs/legacy-config-base.js new file mode 100644 index 0000000000..6a828fcb01 --- /dev/null +++ b/configs/legacy-config-base.js @@ -0,0 +1,10 @@ +'use strict'; +module.exports = { + env: { + es2024: true, + }, + parserOptions: { + ecmaVersion: 'latest', + sourceType: 'module', + }, +}; diff --git a/configs/recommended.js b/configs/recommended.js index 922a68338d..42ea8e9730 100644 --- a/configs/recommended.js +++ b/configs/recommended.js @@ -1,26 +1,117 @@ 'use strict'; -const eslintrc = require('@eslint/eslintrc'); -const eslintPluginUnicorn = require('../index.js'); - -const { - parserOptions: { - ecmaVersion, - sourceType, - }, - rules, -} = eslintPluginUnicorn.configs.recommended; -const {globals} = eslintrc.Legacy.environments.get('es2024'); - -const recommended = { - languageOptions: { - ecmaVersion, - sourceType, - globals, - }, - plugins: { - unicorn: eslintPluginUnicorn, - }, - rules, +module.exports = { + 'unicorn/better-regex': 'error', + 'unicorn/catch-error-name': 'error', + 'unicorn/consistent-destructuring': 'error', + 'unicorn/consistent-function-scoping': 'error', + 'unicorn/custom-error-definition': 'off', + 'unicorn/empty-brace-spaces': 'error', + 'unicorn/error-message': 'error', + 'unicorn/escape-case': 'error', + 'unicorn/expiring-todo-comments': 'error', + 'unicorn/explicit-length-check': 'error', + 'unicorn/filename-case': 'error', + 'unicorn/import-style': 'error', + 'unicorn/new-for-builtins': 'error', + 'unicorn/no-abusive-eslint-disable': 'error', + 'unicorn/no-array-callback-reference': 'error', + 'unicorn/no-array-for-each': 'error', + 'unicorn/no-array-method-this-argument': 'error', + 'unicorn/no-array-push-push': 'error', + 'unicorn/no-array-reduce': 'error', + 'unicorn/no-await-expression-member': 'error', + 'unicorn/no-console-spaces': 'error', + 'unicorn/no-document-cookie': 'error', + 'unicorn/no-empty-file': 'error', + 'unicorn/no-for-loop': 'error', + 'unicorn/no-hex-escape': 'error', + 'unicorn/no-instanceof-array': 'error', + 'unicorn/no-invalid-remove-event-listener': 'error', + 'unicorn/no-keyword-prefix': 'off', + 'unicorn/no-lonely-if': 'error', + 'no-negated-condition': 'off', + 'unicorn/no-negated-condition': 'error', + 'no-nested-ternary': 'off', + 'unicorn/no-nested-ternary': 'error', + 'unicorn/no-new-array': 'error', + 'unicorn/no-new-buffer': 'error', + 'unicorn/no-null': 'error', + 'unicorn/no-object-as-default-parameter': 'error', + 'unicorn/no-process-exit': 'error', + 'unicorn/no-static-only-class': 'error', + 'unicorn/no-thenable': 'error', + 'unicorn/no-this-assignment': 'error', + 'unicorn/no-typeof-undefined': 'error', + 'unicorn/no-unnecessary-await': 'error', + 'unicorn/no-unnecessary-polyfills': 'error', + 'unicorn/no-unreadable-array-destructuring': 'error', + 'unicorn/no-unreadable-iife': 'error', + 'unicorn/no-unused-properties': 'off', + 'unicorn/no-useless-fallback-in-spread': 'error', + 'unicorn/no-useless-length-check': 'error', + 'unicorn/no-useless-promise-resolve-reject': 'error', + 'unicorn/no-useless-spread': 'error', + 'unicorn/no-useless-switch-case': 'error', + 'unicorn/no-useless-undefined': 'error', + 'unicorn/no-zero-fractions': 'error', + 'unicorn/number-literal-case': 'error', + 'unicorn/numeric-separators-style': 'error', + 'unicorn/prefer-add-event-listener': 'error', + 'unicorn/prefer-array-find': 'error', + 'unicorn/prefer-array-flat': 'error', + 'unicorn/prefer-array-flat-map': 'error', + 'unicorn/prefer-array-index-of': 'error', + 'unicorn/prefer-array-some': 'error', + 'unicorn/prefer-at': 'error', + 'unicorn/prefer-blob-reading-methods': 'error', + 'unicorn/prefer-code-point': 'error', + 'unicorn/prefer-date-now': 'error', + 'unicorn/prefer-default-parameters': 'error', + 'unicorn/prefer-dom-node-append': 'error', + 'unicorn/prefer-dom-node-dataset': 'error', + 'unicorn/prefer-dom-node-remove': 'error', + 'unicorn/prefer-dom-node-text-content': 'error', + 'unicorn/prefer-event-target': 'error', + 'unicorn/prefer-export-from': 'error', + 'unicorn/prefer-includes': 'error', + 'unicorn/prefer-json-parse-buffer': 'off', + 'unicorn/prefer-keyboard-event-key': 'error', + 'unicorn/prefer-logical-operator-over-ternary': 'error', + 'unicorn/prefer-math-trunc': 'error', + 'unicorn/prefer-modern-dom-apis': 'error', + 'unicorn/prefer-modern-math-apis': 'error', + 'unicorn/prefer-module': 'error', + 'unicorn/prefer-native-coercion-functions': 'error', + 'unicorn/prefer-negative-index': 'error', + 'unicorn/prefer-node-protocol': 'error', + 'unicorn/prefer-number-properties': 'error', + 'unicorn/prefer-object-from-entries': 'error', + 'unicorn/prefer-optional-catch-binding': 'error', + 'unicorn/prefer-prototype-methods': 'error', + 'unicorn/prefer-query-selector': 'error', + 'unicorn/prefer-reflect-apply': 'error', + 'unicorn/prefer-regexp-test': 'error', + 'unicorn/prefer-set-has': 'error', + 'unicorn/prefer-set-size': 'error', + 'unicorn/prefer-spread': 'error', + 'unicorn/prefer-string-replace-all': 'error', + 'unicorn/prefer-string-slice': 'error', + 'unicorn/prefer-string-starts-ends-with': 'error', + 'unicorn/prefer-string-trim-start-end': 'error', + 'unicorn/prefer-switch': 'error', + 'unicorn/prefer-ternary': 'error', + 'unicorn/prefer-top-level-await': 'error', + 'unicorn/prefer-type-error': 'error', + 'unicorn/prevent-abbreviations': 'error', + 'unicorn/relative-url-style': 'error', + 'unicorn/require-array-join-separator': 'error', + 'unicorn/require-number-to-fixed-digits-argument': 'error', + // Turned off because we can't distinguish `widow.postMessage` and `{Worker,MessagePort,Client,BroadcastChannel}#postMessage()` + // See #1396 + 'unicorn/require-post-message-target-origin': 'off', + 'unicorn/string-content': 'off', + 'unicorn/switch-case-braces': 'error', + 'unicorn/template-indent': 'error', + 'unicorn/text-encoding-identifier-case': 'error', + 'unicorn/throw-new-error': 'error', }; - -module.exports = recommended; diff --git a/docs/new-rule.md b/docs/new-rule.md index 535ba2bc2b..abd2be0c78 100644 --- a/docs/new-rule.md +++ b/docs/new-rule.md @@ -17,7 +17,7 @@ Use the [`astexplorer` site](https://astexplorer.net) with the `espree` parser a - Open “rules/{RULE_ID}.js” and implement the rule logic. - Add the correct [`meta.type`](https://eslint.org/docs/developer-guide/working-with-rules#rule-basics) to the rule. - Open “docs/rules/{RULE_ID}.js” and write some documentation. -- Double check `configs-legacy/recommended.js` and `readme.md`, make sure the new rule is correctly added. +- Double check `configs/recommended.js` and `readme.md`, make sure the new rule is correctly added. - Run `$ npm test` to ensure the tests pass. - Run `$ npm run integration` to run the rules against real projects to ensure your rule does not fail on real-world code. - Open a pull request with a title in exactly the format `` Add `rule-name` rule ``, for example, `` Add `no-unused-properties` rule ``. diff --git a/index.js b/index.js index 4a5996d277..ed98665e25 100644 --- a/index.js +++ b/index.js @@ -1,8 +1,10 @@ 'use strict'; const createDeprecatedRules = require('./rules/utils/create-deprecated-rules.js'); const {loadRules} = require('./rules/utils/rule.js'); -const recommendedConfig = require('./configs-legacy/recommended.js'); -const allRulesEnabledConfig = require('./configs-legacy/all.js'); +const legacyConfigBase = require('./configs/legacy-config-base.js'); +const flatConfigBase = require('./configs/flat-config-base.js'); +const recommendedRules = require('./configs/recommended.js'); +const allRules = require('./configs/all.js'); const {name, version} = require('./package.json'); const deprecatedRules = createDeprecatedRules({ @@ -26,7 +28,13 @@ const deprecatedRules = createDeprecatedRules({ 'regex-shorthand': 'unicorn/better-regex', }); -module.exports = { +const createConfig = (rules, isLegacyConfig = false) => ({ + ...(isLegacyConfig ? legacyConfigBase : flatConfigBase), + plugins: isLegacyConfig ? ['unicorn'] : {unicorn}, + rules, +}); + +const unicorn = { meta: { name, version, @@ -35,8 +43,13 @@ module.exports = { ...loadRules(), ...deprecatedRules, }, - configs: { - recommended: recommendedConfig, - all: allRulesEnabledConfig, - }, }; + +const configs = { + recommended: createConfig(recommendedRules, /* isLegacyConfig */ true), + all: createConfig(allRules, /* isLegacyConfig */ true), + 'flat/recommended': createConfig(recommendedRules), + 'flat/all': createConfig(allRules), +}; + +module.exports = {...unicorn, configs}; diff --git a/package.json b/package.json index 385524d8b2..42dde5e513 100644 --- a/package.json +++ b/package.json @@ -14,12 +14,6 @@ "node": ">=16" }, "main": "index.js", - "exports": { - ".": "./index.js", - "./configs/all": "./configs/all.js", - "./configs/recommended": "./configs/recommended.js", - "./package.json": "./package.json" - }, "scripts": { "create-rule": "node ./scripts/create-rule.mjs && npm run fix:eslint-docs", "fix": "run-p --continue-on-error fix:*", @@ -41,8 +35,7 @@ "files": [ "index.js", "rules", - "configs", - "configs-legacy" + "configs" ], "keywords": [ "eslint", diff --git a/readme.md b/readme.md index dd006162e0..080dfa6d6d 100644 --- a/readme.md +++ b/readme.md @@ -244,11 +244,11 @@ This plugin exports a [`recommended` config](configs/recommended.js) that enforc #### ES Module (Recommended) ```js -import eslintPluginUnicornConfigRecommended from 'eslint-plugin-unicorn/configs/recommended'; +import eslintPluginUnicorn from 'eslint-plugin-unicorn'; export default [ // … - eslintPluginUnicornConfigRecommended, + eslintPluginUnicorn.config['flat/recommended'], { rules: { 'unicorn/better-regex': 'warn', @@ -261,11 +261,11 @@ export default [ ```js 'use strict'; -const eslintPluginUnicornConfigRecommended = require('eslint-plugin-unicorn/configs/recommended'); +const eslintPluginUnicorn = require('eslint-plugin-unicorn'); module.exports = [ // … - eslintPluginUnicornConfigRecommended, + eslintPluginUnicorn.config['flat/recommended'], { rules: { 'unicorn/better-regex': 'warn', @@ -281,11 +281,11 @@ This plugin exports an [`all` config](configs/all.js) that makes use of all rule #### ES Module (Recommended) ```js -import eslintPluginUnicornConfigAll from 'eslint-plugin-unicorn/configs/all'; +import eslintPluginUnicorn from 'eslint-plugin-unicorn'; export default [ // … - eslintPluginUnicornConfigAll, + eslintPluginUnicorn.config['flat/all'], { rules: { 'unicorn/better-regex': 'warn', @@ -298,11 +298,11 @@ export default [ ```js 'use strict'; -const eslintPluginUnicornConfigAll = require('eslint-plugin-unicorn/configs/all'); +const eslintPluginUnicorn = require('eslint-plugin-unicorn'); module.exports = [ // … - eslintPluginUnicornConfigAll, + eslintPluginUnicorn.config['flat/all'], { rules: { 'unicorn/better-regex': 'warn', @@ -319,7 +319,7 @@ See the [ESLint docs](https://eslint.org/docs/user-guide/configuring/configurati ### Recommended config -This plugin exports a [`recommended` config](configs-legacy/recommended.js) that enforces good practices. +This plugin exports a [`recommended` config](configs/recommended.js) that enforces good practices. ```json { @@ -335,7 +335,7 @@ This plugin exports a [`recommended` config](configs-legacy/recommended.js) that ### All config -This plugin exports an [`all` config](configs-legacy/all.js) that makes use of all rules (except for deprecated ones). +This plugin exports an [`all` config](configs/all.js) that makes use of all rules (except for deprecated ones). ```json { diff --git a/scripts/create-rule.mjs b/scripts/create-rule.mjs index 88c2525cf8..976e0c1297 100644 --- a/scripts/create-rule.mjs +++ b/scripts/create-rule.mjs @@ -41,14 +41,14 @@ function updateRecommended(id) { const RULE_INDENT = '\t'.repeat(2); let ruleContent = `${RULE_INDENT}'unicorn/${id}': 'error',`; - const file = path.join(ROOT, 'configs-legacy/recommended.js'); + const file = path.join(ROOT, 'configs/recommended.js'); const content = fs.readFileSync(file, 'utf8'); const [before, rest] = content.split(RULE_START); const [rules, after] = rest.split(RULE_END); const lines = rules.split('\n'); if (!lines.every(line => line.startsWith(RULE_INDENT))) { - throw new Error('Unexpected content in “configs-legacy/recommended.js”.'); + throw new Error('Unexpected content in “configs/recommended.js”.'); } const unicornRuleLines = lines.filter(line => line.startsWith(`${RULE_INDENT}'unicorn/`)); diff --git a/test/package.mjs b/test/package.mjs index aa9f17e622..f4989a5957 100644 --- a/test/package.mjs +++ b/test/package.mjs @@ -5,10 +5,6 @@ import test from 'ava'; import {ESLint} from 'eslint'; import * as eslintrc from '@eslint/eslintrc'; import eslintPluginUnicorn from '../index.js'; -import flatConfigRecommended from '../configs/recommended.js'; -import allConfigRecommended from '../configs/all.js'; - -const flatConfigs = {recommended: flatConfigRecommended, all: allConfigRecommended}; let ruleFiles; @@ -80,7 +76,7 @@ test('Every rule is defined in index file in alphabetical order', t => { test('validate configuration', async t => { const results = await Promise.all( - Object.entries(eslintPluginUnicorn.configs).map(async ([name, config]) => { + Object.entries(eslintPluginUnicorn.configs).filter(([name]) => !name.startsWith('flat/')).map(async ([name, config]) => { const eslint = new ESLint({ baseConfig: config, useEslintrc: false, @@ -227,11 +223,17 @@ function getCompactConfig(config) { resolvePluginsRelativeTo: process.cwd(), }); - const result = {}; + const result = {plugins: undefined}; for (const part of compat.config(config)) { for (const [key, value] of Object.entries(part)) { - result[key] = key === 'languageOptions' ? {...result[key], ...value} : value; + if (key === 'languageOptions') { + result[key] = {...result[key], ...value}; + } else if (key === 'plugins') { + result[key] = undefined; + } else { + result[key] = value; + } } } @@ -239,6 +241,12 @@ function getCompactConfig(config) { } test('flat configs', t => { - t.deepEqual(getCompactConfig(eslintPluginUnicorn.configs.recommended), flatConfigs.recommended); - t.deepEqual(getCompactConfig(eslintPluginUnicorn.configs.all), flatConfigs.all); + t.deepEqual( + getCompactConfig(eslintPluginUnicorn.configs.recommended), + {...eslintPluginUnicorn.configs['flat/recommended'], plugins: undefined}, + ); + t.deepEqual( + getCompactConfig(eslintPluginUnicorn.configs.all), + {...eslintPluginUnicorn.configs['flat/all'], plugins: undefined}, + ); }); From dce30534106c987ddd4a04940293cd68e63f767d Mon Sep 17 00:00:00 2001 From: fisker Date: Wed, 20 Dec 2023 22:23:07 +0800 Subject: [PATCH 30/33] Fix create-rule.mjs --- scripts/create-rule.mjs | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/scripts/create-rule.mjs b/scripts/create-rule.mjs index 976e0c1297..0a9841b409 100644 --- a/scripts/create-rule.mjs +++ b/scripts/create-rule.mjs @@ -36,21 +36,22 @@ function renderTemplate({source, target, data}) { } function updateRecommended(id) { - const RULE_START = '\n\trules: {\n'; - const RULE_END = '\n\t}'; - const RULE_INDENT = '\t'.repeat(2); - let ruleContent = `${RULE_INDENT}'unicorn/${id}': 'error',`; - + const RULE_INDENT = '\t'; const file = path.join(ROOT, 'configs/recommended.js'); const content = fs.readFileSync(file, 'utf8'); - const [before, rest] = content.split(RULE_START); - const [rules, after] = rest.split(RULE_END); + const {before, rules, after} = content.match(/(?.*?{\n)(?.*?)(?\n};\s*)/s)?.groups ?? {}; + if (!rules) { + throw new Error('Unexpected content in “configs/recommended.js”.'); + } const lines = rules.split('\n'); + if (!lines.every(line => line.startsWith(RULE_INDENT))) { throw new Error('Unexpected content in “configs/recommended.js”.'); } + let ruleContent = `${RULE_INDENT}'unicorn/${id}': 'error',`; + const unicornRuleLines = lines.filter(line => line.startsWith(`${RULE_INDENT}'unicorn/`)); let insertIndex; if (ruleContent.localeCompare(unicornRuleLines[0]) === -1) { @@ -68,7 +69,7 @@ function updateRecommended(id) { lines.splice(insertIndex, 0, ruleContent); - const updated = `${before}${RULE_START}${lines.join('\n')}${RULE_END}${after}`; + const updated = `${before}${lines.join('\n')}${after}`; fs.writeFileSync(file, updated); } @@ -154,12 +155,12 @@ renderTemplate({ }); updateRecommended(id); -try { - await execa('code', [ - '--new-window', - '.', - `docs/rules/${id}.md`, - `rules/${id}.js`, - `test/${id}.mjs`, - ], {cwd: ROOT}); -} catch {} +// try { +// await execa('code', [ +// '--new-window', +// '.', +// `docs/rules/${id}.md`, +// `rules/${id}.js`, +// `test/${id}.mjs`, +// ], {cwd: ROOT}); +// } catch {} From 2161a475bad1b7c043d20c4d16c09a8f1520a5ba Mon Sep 17 00:00:00 2001 From: fisker Date: Wed, 20 Dec 2023 22:26:22 +0800 Subject: [PATCH 31/33] Open editor --- scripts/create-rule.mjs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/scripts/create-rule.mjs b/scripts/create-rule.mjs index 0a9841b409..e04b8e590c 100644 --- a/scripts/create-rule.mjs +++ b/scripts/create-rule.mjs @@ -155,12 +155,12 @@ renderTemplate({ }); updateRecommended(id); -// try { -// await execa('code', [ -// '--new-window', -// '.', -// `docs/rules/${id}.md`, -// `rules/${id}.js`, -// `test/${id}.mjs`, -// ], {cwd: ROOT}); -// } catch {} +try { + await execa('code', [ + '--new-window', + '.', + `docs/rules/${id}.md`, + `rules/${id}.js`, + `test/${id}.mjs`, + ], {cwd: ROOT}); +} catch {} From 9452c7f7ccc6959e51a3ef34302f641b91d1fef5 Mon Sep 17 00:00:00 2001 From: fisker Cheung Date: Wed, 20 Dec 2023 22:33:40 +0800 Subject: [PATCH 32/33] Update .eslint-doc-generatorrc.js --- .eslint-doc-generatorrc.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.eslint-doc-generatorrc.js b/.eslint-doc-generatorrc.js index 876d722447..0f1f832fab 100644 --- a/.eslint-doc-generatorrc.js +++ b/.eslint-doc-generatorrc.js @@ -2,7 +2,7 @@ /** @type {import('eslint-doc-generator').GenerateOptions} */ const config = { - ignoreConfig: ['all','flat/all','flat/recommended'], + ignoreConfig: ['all', 'flat/all', 'flat/recommended'], ignoreDeprecatedRules: true, ruleDocTitleFormat: 'desc', ruleListColumns: [ From 3895cc7d8c82c4a920a25e1e6c8a5cb4c88c59a1 Mon Sep 17 00:00:00 2001 From: Sindre Sorhus Date: Wed, 20 Dec 2023 18:46:35 +0100 Subject: [PATCH 33/33] Update package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 42dde5e513..11bd5e1acf 100644 --- a/package.json +++ b/package.json @@ -10,10 +10,10 @@ "email": "sindresorhus@gmail.com", "url": "https://sindresorhus.com" }, + "main": "index.js", "engines": { "node": ">=16" }, - "main": "index.js", "scripts": { "create-rule": "node ./scripts/create-rule.mjs && npm run fix:eslint-docs", "fix": "run-p --continue-on-error fix:*",