@dr.pogodin/eslint-configs 0.1.4 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -21,9 +21,11 @@ This project is invisioned as a replacement for AirBnB ESLint configurations
21
21
  - [Getting Started]
22
22
  - [Provided Configs]
23
23
  - [`configs.javascript`]
24
+ - [`configs.javascriptNoPerf`]
24
25
  - [`configs.jest`]
25
26
  - [`configs.react`]
26
27
  - [`configs.typescript`]
28
+ - [`configs.typescriptNoPerf`]
27
29
 
28
30
  ## Getting Started
29
31
  [Getting Started]: #getting-started
@@ -98,8 +100,10 @@ combined and extended as necessary for the needs of host projects.
98
100
  [`configs.javascript`]: #configsjavascript
99
101
 
100
102
  Intended for JavaScript code, it applies to the files [ESLint] considers as
101
- JavaScript by default: `**/*.js`, `**/*.cjs`, `**/*.mjs`; and it applies to
102
- them the following rule sets:
103
+ JavaScript by default: `**/*.js`, `**/*.cjs`, `**/*.mjs`, as well as to any
104
+ other files matched by other config objects in your config (_i.e._ it does not
105
+ include `files` key, see [ESLint docs for related configuration details](https://eslint.org/docs/latest/use/configure/configuration-files#specifying-files-and-ignores));
106
+ and it applies to them the following rule sets:
103
107
 
104
108
  - [ESLint Core Rules](https://eslint.org/docs/latest/rules) —
105
109
  the `recommended` rule set, with minor overrides, and many additional rules
@@ -116,6 +120,18 @@ them the following rule sets:
116
120
  the `recommended` rule set, with minor overrides, and many additional rules
117
121
  enabled.
118
122
 
123
+ - [Perfectionist] — the recommended rule set, with minor overrides,
124
+ such as the custom alphabet that places uppercase characters before lowercase
125
+ ones, and allowance to use empty lines to separate entities into different
126
+ sorting groups.
127
+
128
+ ### `configs.javascriptNoPerf`
129
+ [`configs.javascriptNoPerf`]: #configsjavascriptnoperf
130
+
131
+ The same as [`configs.javascript`] above, but without [Perfectionist] rules.
132
+ Essentially, it is equivalent to [`configs.javascript`] from this library prior
133
+ to its [v0.2.0](https://github.com/birdofpreyru/eslint-configs/releases/tag/v0.2.0) release.
134
+
119
135
  ### `configs.jest`
120
136
  [`configs.jest`]: #configsjest
121
137
 
@@ -162,6 +178,14 @@ and it applies to them the following rule sets:
162
178
  the `recommendedTypeChecked` and `stylisticTypeChecked` rule sets, with minor
163
179
  overrides, and many additional rules enabled.
164
180
 
181
+ ### `configs.typescriptNoPerf`
182
+ [`configs.typescriptNoPerf`]: #configstypescriptnoperf
183
+
184
+ The same as [`configs.typescript`] above, but without [Perfectionist] rules.
185
+ Essentially, it is equivalent to [`configs.typescript`] from this library prior
186
+ to its [v0.2.0](https://github.com/birdofpreyru/eslint-configs/releases/tag/v0.2.0) release.
187
+
165
188
  [Babel]: https://babeljs.io
166
189
  [ESLint]: https://eslint.org
167
- [eslint-config-airbnb]: https://www.npmjs.com/package/eslint-config-airbnb
190
+ [eslint-config-airbnb]: https://www.npmjs.com/package/eslint-config-airbnb
191
+ [Perfectionist]: https://perfectionist.dev
package/config/index.js CHANGED
@@ -1,13 +1,15 @@
1
- import javascript from './javascript.js';
1
+ import javascript, { javascriptNoPerf } from './javascript.js';
2
2
  import jest from './jest.js';
3
3
  import react from './react.js';
4
- import typescript from './typescript.js';
4
+ import typescript, { typescriptNoPerf } from './typescript.js';
5
5
 
6
6
  export default {
7
7
  configs: {
8
8
  javascript,
9
+ javascriptNoPerf,
9
10
  jest,
10
11
  react,
11
12
  typescript,
13
+ typescriptNoPerf,
12
14
  },
13
15
  };
@@ -2,32 +2,22 @@
2
2
 
3
3
  import { defineConfig } from 'eslint/config';
4
4
  import importPlugin from 'eslint-plugin-import';
5
+ import perfectionist from 'eslint-plugin-perfectionist';
6
+ import { Alphabet } from 'eslint-plugin-perfectionist/alphabet';
5
7
 
6
8
  import babelParser from '@babel/eslint-parser';
7
9
  import babelPlugin from '@babel/eslint-plugin';
8
10
  import js from '@eslint/js';
9
11
  import stylisticPlugin from '@stylistic/eslint-plugin';
10
12
 
11
- export default defineConfig([{
12
- extends: [
13
+ function newConfig({ noPerf } = {}) {
14
+ const extentions = [
13
15
  'js/recommended',
14
16
  '@stylistic/recommended',
15
17
  importPlugin.flatConfigs.recommended,
16
- ],
17
- languageOptions: {
18
- parser: babelParser,
19
- },
20
- linterOptions: {
21
- reportUnusedDisableDirectives: 'error',
22
- reportUnusedInlineConfigs: 'error',
23
- },
24
- name: 'dr.pogodin/javascript',
25
- plugins: {
26
- '@babel': babelPlugin,
27
- '@stylistic': stylisticPlugin,
28
- js,
29
- },
30
- rules: {
18
+ ];
19
+
20
+ const rules = {
31
21
  // These rules are provided by "@babel/eslint-plugin", and they require
32
22
  // to disable (to not enable) their counterparts from ESLint core.
33
23
  '@babel/new-cap': 'error',
@@ -72,9 +62,6 @@ export default defineConfig([{
72
62
  'import/no-unused-modules': 'error',
73
63
  'import/no-useless-path-segments': 'error',
74
64
  'import/no-webpack-loader-syntax': 'error',
75
- 'import/order': ['error', {
76
- groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index'],
77
- }],
78
65
 
79
66
  // These rules are provided by "@stylistic/eslint-plugin",
80
67
  // and (re-)configured for our taste, somewhat differently from
@@ -265,28 +252,71 @@ export default defineConfig([{
265
252
  'require-atomic-updates': 'error',
266
253
  'require-await': 'error',
267
254
  'require-yield': 'error',
268
-
269
- // TODO: Disabled for now, as there is one thing I don't like about it:
270
- // in TypeScript it sorts type imports together with other imported members,
271
- // while I'd prefer to have all type member imports first, followed by other
272
- // imported members after.
273
- /*
274
- 'sort-imports': ['error', {
275
- ignoreDeclarationSort: true,
276
- }],
277
- */
278
-
279
- 'sort-keys': ['error', 'asc', {
280
- allowLineSeparatedGroups: true,
281
- }],
282
255
  'symbol-description': 'error',
283
256
  'unicode-bom': 'error',
284
257
  yoda: 'error',
285
- },
286
- settings: {
258
+ };
259
+
260
+ const settings = {
287
261
  'import/resolver': {
288
262
  node: true,
289
263
  typescript: true,
290
264
  },
291
- },
292
- }]);
265
+ };
266
+
267
+ if (noPerf) {
268
+ // Without Perfectionist. These rules are similar to those Perfectionist
269
+ // provides, but they are provided by other plugins, and we used them in
270
+ // older config versions, thus we keep enabling them for the legacy,
271
+ // "no Perfectionist" config variant.
272
+ rules['import/order'] = ['error', {
273
+ groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index'],
274
+ }];
275
+ rules['sort-keys'] = ['error', 'asc', {
276
+ allowLineSeparatedGroups: true,
277
+ }];
278
+ } else {
279
+ // With Perfectionist.
280
+ // eslint-disable-next-line import/no-named-as-default-member
281
+ extentions.push(perfectionist.configs['recommended-custom']);
282
+
283
+ // TODO: For now it is disabled because of the following Perfectionist bug:
284
+ // https://github.com/azat-io/eslint-plugin-perfectionist/issues/688
285
+ // and we'll keep using "import/order" rule here until the issue is addressed.
286
+ rules['perfectionist/sort-imports'] = 'off';
287
+ rules['import/order'] = ['error', {
288
+ groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index'],
289
+ }];
290
+
291
+ settings.perfectionist = {
292
+ alphabet: Alphabet.generateRecommendedAlphabet()
293
+ .placeAllWithCaseBeforeAllWithOtherCase('uppercase')
294
+ .getCharacters(),
295
+ ignoreCase: false,
296
+ partitionByNewLine: true,
297
+ };
298
+ }
299
+
300
+ return defineConfig([{
301
+ extends: extentions,
302
+ languageOptions: {
303
+ parser: babelParser,
304
+ },
305
+ linterOptions: {
306
+ reportUnusedDisableDirectives: 'error',
307
+ reportUnusedInlineConfigs: 'error',
308
+ },
309
+ name: 'dr.pogodin/javascript',
310
+ plugins: {
311
+ '@babel': babelPlugin,
312
+ '@stylistic': stylisticPlugin,
313
+ js,
314
+ },
315
+ rules,
316
+ settings,
317
+ }]);
318
+ }
319
+
320
+ export const javascriptNoPerf = newConfig({ noPerf: true });
321
+
322
+ export default newConfig();
package/config/jest.js CHANGED
@@ -17,9 +17,7 @@ export default defineConfig([{
17
17
  'jest/no-conditional-in-test': 'error',
18
18
  'jest/no-confusing-set-timeout': 'error',
19
19
  'jest/no-duplicate-hooks': 'error',
20
- 'jest/no-error-equal': 'error',
21
20
  'jest/no-test-return-statement': 'error',
22
- 'jest/no-unnecessary-assertion': 'error',
23
21
  'jest/no-unneeded-async-expect-function': 'error',
24
22
  'jest/no-untyped-mock-factory': 'error',
25
23
  'jest/padding-around-after-all-blocks': 'error',
@@ -44,11 +42,22 @@ export default defineConfig([{
44
42
  'jest/prefer-to-have-been-called-times': 'error',
45
43
  'jest/prefer-todo': 'error',
46
44
  'jest/require-to-throw-message': 'error',
47
- 'jest/valid-expect-with-promise': 'error',
48
45
  'jest/valid-mock-module-path': 'error',
49
46
 
50
47
  'no-console': 'off',
51
48
 
52
49
  '@typescript-eslint/unbound-method': 'off',
53
50
  },
51
+ }, {
52
+ // NOTE: These rules require type information, hence they are applied for TS
53
+ // files only.
54
+ names: 'dr.pogodin/jest/typescript',
55
+
56
+ files: ['**/ts', '**/tsx'],
57
+ plugins: { jest: pluginJest },
58
+ rules: {
59
+ 'jest/no-error-equal': 'error',
60
+ 'jest/no-unnecessary-assertion': 'error',
61
+ 'jest/valid-expect-with-promise': 'error',
62
+ },
54
63
  }]);
package/config/react.js CHANGED
@@ -1,7 +1,6 @@
1
1
  import { defineConfig } from 'eslint/config';
2
2
 
3
3
  import jsxA11y from 'eslint-plugin-jsx-a11y';
4
- import perfectionist from 'eslint-plugin-perfectionist';
5
4
  import react from 'eslint-plugin-react';
6
5
  import reactHooks from 'eslint-plugin-react-hooks';
7
6
 
@@ -18,7 +17,6 @@ export default defineConfig([{
18
17
  },
19
18
  },
20
19
  plugins: {
21
- perfectionist,
22
20
  react,
23
21
  },
24
22
  settings: {
@@ -28,11 +26,6 @@ export default defineConfig([{
28
26
  },
29
27
 
30
28
  rules: {
31
- // Rules provided by "eslint-plugin-perfectionist"
32
- 'perfectionist/sort-jsx-props': ['error', {
33
- type: 'natural',
34
- }],
35
-
36
29
  // Rules provided by "eslint-plugin-jsx-a11y".
37
30
  'jsx-a11y/anchor-ambiguous-text': 'error',
38
31
  'jsx-a11y/control-has-associated-label': 'error',
@@ -1,101 +1,120 @@
1
+ import { defineConfig } from 'eslint/config';
1
2
  import tsEsLint from 'typescript-eslint';
2
3
 
3
- import jsConfig from './javascript.js';
4
-
5
- export default tsEsLint.config(
6
- {
7
- name: 'dr.pogodin/typescript',
8
-
9
- extends: [
10
- jsConfig,
11
- tsEsLint.configs.recommendedTypeChecked,
12
- tsEsLint.configs.stylisticTypeChecked,
13
- ],
14
- files: ['**/*.ts', '**/*.tsx'],
15
- languageOptions: {
16
- parserOptions: {
17
- projectService: true,
4
+ import jsConfig, { javascriptNoPerf } from './javascript.js';
5
+
6
+ function newConfig({ noPerf } = {}) {
7
+ let extentions = [
8
+ jsConfig,
9
+ tsEsLint.configs.recommendedTypeChecked,
10
+ tsEsLint.configs.stylisticTypeChecked,
11
+ ];
12
+
13
+ const rules = {
14
+ // TypeScript takes care of the same, in a better way.
15
+ '@babel/new-cap': 'off',
16
+ '@babel/no-undef': 'off',
17
+
18
+ // It does not support type imports, and TypeScript itself does necessary
19
+ // checks for imports anyway.
20
+ 'import/named': 'off',
21
+
22
+ '@typescript-eslint/array-type': ['error', {
23
+ default: 'array-simple',
24
+ }],
25
+ '@typescript-eslint/class-methods-use-this': 'error',
26
+ '@typescript-eslint/consistent-return': 'error',
27
+ '@typescript-eslint/consistent-type-definitions': ['error', 'type'],
28
+ '@typescript-eslint/consistent-type-exports': 'error',
29
+ '@typescript-eslint/consistent-type-imports': 'error',
30
+ '@typescript-eslint/default-param-last': 'error',
31
+ '@typescript-eslint/explicit-module-boundary-types': 'error',
32
+ '@typescript-eslint/no-confusing-void-expression': 'error',
33
+ '@typescript-eslint/no-deprecated': 'warn',
34
+ '@typescript-eslint/no-dupe-class-members': 'error',
35
+ '@typescript-eslint/no-empty-interface': 'error',
36
+ '@typescript-eslint/no-extraneous-class': 'error',
37
+ '@typescript-eslint/no-import-type-side-effects': 'error',
38
+ '@typescript-eslint/no-inferrable-types': 'off',
39
+ '@typescript-eslint/no-invalid-this': 'error',
40
+ '@typescript-eslint/no-invalid-void-type': 'error',
41
+ '@typescript-eslint/no-loop-func': 'error',
42
+ '@typescript-eslint/no-loss-of-precision': 'error',
43
+ '@typescript-eslint/no-meaningless-void-operator': 'error',
44
+ '@typescript-eslint/no-misused-spread': 'error',
45
+ '@typescript-eslint/no-mixed-enums': 'error',
46
+ '@typescript-eslint/no-non-null-asserted-nullish-coalescing': 'error',
47
+ '@typescript-eslint/no-redeclare': 'error',
48
+ '@typescript-eslint/no-unnecessary-type-conversion': 'error',
49
+ '@typescript-eslint/no-useless-default-assignment': 'error',
50
+
51
+ // NOTE: The core rule variant reports incorrect errors on TypeScript
52
+ // code, thus disabled.
53
+ '@typescript-eslint/no-shadow': 'error',
54
+ 'no-shadow': 'off',
55
+
56
+ '@typescript-eslint/no-unnecessary-boolean-literal-compare': 'error',
57
+ '@typescript-eslint/no-unnecessary-condition': 'error',
58
+ '@typescript-eslint/no-unnecessary-parameter-property-assignment': 'error',
59
+ '@typescript-eslint/no-unnecessary-qualifier': 'error',
60
+ '@typescript-eslint/no-unnecessary-template-expression': 'error',
61
+ '@typescript-eslint/no-unnecessary-type-arguments': 'error',
62
+
63
+ // NOTE: Disables the base rule as it can report incorrect errors.
64
+ '@typescript-eslint/no-unused-private-class-members': 'error',
65
+ 'no-unused-private-class-members': 'off',
66
+
67
+ '@typescript-eslint/no-use-before-define': 'error',
68
+ '@typescript-eslint/no-useless-constructor': 'error',
69
+ '@typescript-eslint/no-useless-empty-export': 'error',
70
+ '@typescript-eslint/parameter-properties': ['error', {
71
+ prefer: 'parameter-property',
72
+ }],
73
+
74
+ // NOTE: The core variant of this rule, disabled below, does not work
75
+ // correctly for TypeScript code in some edge cases.
76
+ '@typescript-eslint/prefer-destructuring': 'error',
77
+ 'prefer-destructuring': 'off',
78
+
79
+ '@typescript-eslint/prefer-enum-initializers': 'error',
80
+ '@typescript-eslint/prefer-literal-enum-member': 'error',
81
+ '@typescript-eslint/prefer-reduce-type-parameter': 'error',
82
+ '@typescript-eslint/prefer-regexp-exec': 'off',
83
+ '@typescript-eslint/prefer-return-this-type': 'error',
84
+ '@typescript-eslint/promise-function-async': 'error',
85
+ '@typescript-eslint/related-getter-setter-pairs': 'error',
86
+ '@typescript-eslint/require-array-sort-compare': 'error',
87
+ '@typescript-eslint/strict-void-return': 'error',
88
+ '@typescript-eslint/switch-exhaustiveness-check': 'error',
89
+ '@typescript-eslint/typedef': 'error',
90
+ '@typescript-eslint/unified-signatures': 'error',
91
+ '@typescript-eslint/use-unknown-in-catch-callback-variable': 'error',
92
+ };
93
+
94
+ if (noPerf) {
95
+ extentions = [javascriptNoPerf, ...extentions];
96
+ } else {
97
+ extentions = [jsConfig, ...extentions];
98
+
99
+ rules['adjacent-overload-signatures'] = 'off';
100
+ }
101
+
102
+ return defineConfig(
103
+ {
104
+ name: 'dr.pogodin/typescript',
105
+
106
+ extends: extentions,
107
+ files: ['**/*.ts', '**/*.tsx'],
108
+ languageOptions: {
109
+ parserOptions: {
110
+ projectService: true,
111
+ },
18
112
  },
113
+ rules,
19
114
  },
20
- rules: {
21
- // TypeScript takes care of the same, in a better way.
22
- '@babel/new-cap': 'off',
23
- '@babel/no-undef': 'off',
24
-
25
- // It does not support type imports, and TypeScript itself does necessary
26
- // checks for imports anyway.
27
- 'import/named': 'off',
28
-
29
- '@typescript-eslint/array-type': ['error', {
30
- default: 'array-simple',
31
- }],
32
- '@typescript-eslint/class-methods-use-this': 'error',
33
- '@typescript-eslint/consistent-return': 'error',
34
- '@typescript-eslint/consistent-type-definitions': ['error', 'type'],
35
- '@typescript-eslint/consistent-type-exports': 'error',
36
- '@typescript-eslint/consistent-type-imports': 'error',
37
- '@typescript-eslint/default-param-last': 'error',
38
- '@typescript-eslint/explicit-module-boundary-types': 'error',
39
- '@typescript-eslint/no-confusing-void-expression': 'error',
40
- '@typescript-eslint/no-deprecated': 'warn',
41
- '@typescript-eslint/no-dupe-class-members': 'error',
42
- '@typescript-eslint/no-empty-interface': 'error',
43
- '@typescript-eslint/no-extraneous-class': 'error',
44
- '@typescript-eslint/no-import-type-side-effects': 'error',
45
- '@typescript-eslint/no-inferrable-types': 'off',
46
- '@typescript-eslint/no-invalid-this': 'error',
47
- '@typescript-eslint/no-invalid-void-type': 'error',
48
- '@typescript-eslint/no-loop-func': 'error',
49
- '@typescript-eslint/no-loss-of-precision': 'error',
50
- '@typescript-eslint/no-meaningless-void-operator': 'error',
51
- '@typescript-eslint/no-misused-spread': 'error',
52
- '@typescript-eslint/no-mixed-enums': 'error',
53
- '@typescript-eslint/no-non-null-asserted-nullish-coalescing': 'error',
54
- '@typescript-eslint/no-redeclare': 'error',
55
- '@typescript-eslint/no-unnecessary-type-conversion': 'error',
56
- '@typescript-eslint/no-useless-default-assignment': 'error',
57
-
58
- // NOTE: The core rule variant reports incorrect errors on TypeScript
59
- // code, thus disabled.
60
- '@typescript-eslint/no-shadow': 'error',
61
- 'no-shadow': 'off',
62
-
63
- '@typescript-eslint/no-unnecessary-boolean-literal-compare': 'error',
64
- '@typescript-eslint/no-unnecessary-condition': 'error',
65
- '@typescript-eslint/no-unnecessary-parameter-property-assignment': 'error',
66
- '@typescript-eslint/no-unnecessary-qualifier': 'error',
67
- '@typescript-eslint/no-unnecessary-template-expression': 'error',
68
- '@typescript-eslint/no-unnecessary-type-arguments': 'error',
69
-
70
- // NOTE: Disables the base rule as it can report incorrect errors.
71
- '@typescript-eslint/no-unused-private-class-members': 'error',
72
- 'no-unused-private-class-members': 'off',
73
-
74
- '@typescript-eslint/no-use-before-define': 'error',
75
- '@typescript-eslint/no-useless-constructor': 'error',
76
- '@typescript-eslint/no-useless-empty-export': 'error',
77
- '@typescript-eslint/parameter-properties': ['error', {
78
- prefer: 'parameter-property',
79
- }],
80
-
81
- // NOTE: The core variant of this rule, disabled below, does not work
82
- // correctly for TypeScript code in some edge cases.
83
- '@typescript-eslint/prefer-destructuring': 'error',
84
- 'prefer-destructuring': 'off',
85
-
86
- '@typescript-eslint/prefer-enum-initializers': 'error',
87
- '@typescript-eslint/prefer-literal-enum-member': 'error',
88
- '@typescript-eslint/prefer-reduce-type-parameter': 'error',
89
- '@typescript-eslint/prefer-regexp-exec': 'off',
90
- '@typescript-eslint/prefer-return-this-type': 'error',
91
- '@typescript-eslint/promise-function-async': 'error',
92
- '@typescript-eslint/related-getter-setter-pairs': 'error',
93
- '@typescript-eslint/require-array-sort-compare': 'error',
94
- '@typescript-eslint/strict-void-return': 'error',
95
- '@typescript-eslint/switch-exhaustiveness-check': 'error',
96
- '@typescript-eslint/typedef': 'error',
97
- '@typescript-eslint/unified-signatures': 'error',
98
- '@typescript-eslint/use-unknown-in-catch-callback-variable': 'error',
99
- },
100
- },
101
- );
115
+ );
116
+ }
117
+
118
+ export const typescriptNoPerf = newConfig({ noPerf: true });
119
+
120
+ export default newConfig();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dr.pogodin/eslint-configs",
3
- "version": "0.1.4",
3
+ "version": "0.2.1",
4
4
  "description": "ESLint configurations for TypeScript and/or React projects",
5
5
  "type": "module",
6
6
  "main": "./config/index.js",
@@ -40,7 +40,7 @@
40
40
  "eslint-plugin-import": "^2.32.0",
41
41
  "eslint-plugin-jest": "^29.12.1",
42
42
  "eslint-plugin-jsx-a11y": "^6.10.2",
43
- "eslint-plugin-perfectionist": "^5.3.1",
43
+ "eslint-plugin-perfectionist": "^5.4.0",
44
44
  "eslint-plugin-react": "^7.37.4",
45
45
  "eslint-plugin-react-hooks": "^6.1.1",
46
46
  "typescript": "^5.9.3",