@dr.pogodin/eslint-configs 0.0.1 → 0.0.3

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
@@ -6,42 +6,148 @@
6
6
  [![GitHub Repo stars](https://img.shields.io/github/stars/birdofpreyru/eslint-configs?style=social)](https://github.com/birdofpreyru/eslint-configs)
7
7
  [![Dr. Pogodin Studio](https://raw.githubusercontent.com/birdofpreyru/eslint-configs/master/.README/logo-dr-pogodin-studio.svg)](https://dr.pogodin.studio/docs/eslint-configs)
8
8
 
9
- ESLint configurations for TypeScript and/or React projects. This project is
10
- invisioned as a replacement of AirBnB ESLint Configs, which are completely
11
- neglected by AirBnB lately, and are deaf to well justified complaigns of users.
12
- Thus, the aims of this project are:
9
+ [ESLint] configurations for JavaScript, TypeScript and/or React projects.
10
+ This project is invisioned as a replacement for AirBnB ESLint configurations
11
+ ([eslint-config-airbnb]), which are no longer maintained by AirBnB. Our aims are:
13
12
 
14
- - Code style similar to that of AirBnB configs + Some opionated improvements on
15
- top of them.
13
+ - Code style and rules similar to that of the original AirBnB configs +
14
+ Some opinionated improvements on top them.
16
15
 
17
- - Support of the latest ESLint releases.
18
-
19
- - Timely upgrades of dependencies.
16
+ - Timely support of the latest ESLint and plugin releases.
20
17
 
21
18
  [![Sponsor](https://raw.githubusercontent.com/birdofpreyru/eslint-configs/master/.README/sponsor.svg)](https://github.com/sponsors/birdofpreyru)
22
19
 
20
+ ## Content
21
+ - [Getting Started]
22
+ - [Provided Configs]
23
+ - [`configs.javascript`]
24
+ - [`configs.jest`]
25
+ - [`configs.react`]
26
+ - [`configs.typescript`]
27
+
23
28
  ## Getting Started
29
+ [Getting Started]: #getting-started
30
+
31
+ - We assume that [Babel] is properly installed and configured in the host
32
+ project — some plugins we enable depend on that, and as of now we do not
33
+ provide options to optionally disable them for non-[Babel] host projects.
34
+
35
+ - Install this package and ESLint as developement dependencies:
36
+ ```sh
37
+ npm install --save-dev eslint @dr.pogodin/eslint-configs
38
+ ```
39
+
40
+ - Add necessary configurations into your flat ESLint config file, for example
41
+ (also see [Provided Configs] section below for further details):
42
+ ```js
43
+ // eslint.config.mjs
44
+
45
+ /* eslint-disable import/no-extraneous-dependencies */
46
+
47
+ // defineConfig() is an optional helper provided by ESLint
48
+ import { defineConfig } from 'eslint/config';
49
+
50
+ import eslintConfigs from '@dr.pogodin/react-utils';
51
+
52
+ export default defineConfig([{
53
+ // Global ignore rules: an array of path patterns to be ignored by ESLint
54
+ // for all other objects included into this configuration, in addition to
55
+ // "**/node_modules/" and ".git/" paths which are always ignored; see:
56
+ // https://eslint.org/docs/latest/use/configure/configuration-files#globally-ignoring-files-with-ignores
57
+ ignores: ['build/'],
58
+ }, {
59
+ // This object opts-in for JavaScript, TypeScript, and React code checks
60
+ // inside the project, with exception for a folder with tests, which is
61
+ // checked by different rules below.
62
+ extends: [
63
+ eslintConfigs.configs.javascript,
64
+ eslintConfigs.configs.typescript,
65
+ eslintConfigs.configs.react,
66
+ ],
67
+ ignores: ['__tests__/**'],
68
+ }, {
69
+ // This is a separate set of rules for a folder with Jest-based unit tests.
70
+ extends: [
71
+ eslintConfigs.configs.javascript,
72
+ eslintConfigs.configs.typescript,
73
+ eslintConfigs.configs.react,
74
+ eslintConfigs.configs.jest,
75
+ ],
76
+ files: ['__tests__/**'],
77
+ }]);
78
+ ```
79
+
80
+ ## Provided Configs
81
+ [Provided Configs]: #provided-configs
82
+
83
+ This package provides the following base configurations, that are meant to be
84
+ combined and extended as necessary for the needs of host projects.
85
+
86
+ ### `configs.javascript`
87
+ [`configs.javascript`]: #configsjavascript
88
+
89
+ Intended for JavaScript code, it applies to the files [ESLint] considers as
90
+ JavaScript by default: `**/*.js`, `**/*.cjs`, `**/*.mjs`; and it applies to
91
+ them the following rule sets:
92
+
93
+ - [ESLint Core Rules](https://eslint.org/docs/latest/rules) —
94
+ the `recommended` rule set, with minor overrides, and many additional rules
95
+ enabled.
96
+
97
+ - [@babel/eslint-plugin](https://www.npmjs.com/package/@babel/eslint-plugin) —
98
+ all rules enabled, with minor overrides of their default settings.
99
+
100
+ - [@stylistic/eslint-plugin](https://eslint.style/rules) —
101
+ the `recommended` rule set, with minor overrides, and many additional rules
102
+ enabled.
103
+
104
+ - [eslint-plugin-import](https://www.npmjs.com/package/eslint-plugin-import) —
105
+ the `recommended` rule set, with minor overrides, and many additional rules
106
+ enabled.
107
+
108
+ ### `configs.jest`
109
+ [`configs.jest`]: #configsjest
110
+
111
+ Intended for [Jest](https://jestjs.io)-based unit test code, it applies to all
112
+ files (assuming the consumer himself will configure the correct paths to apply
113
+ it to); and it applies to them the following rule sets:
114
+
115
+ - [eslint-plugin-jest](https://www.npmjs.com/package/eslint-plugin-jest) —
116
+ the `recommended` and `style` rule sets, with a bunch of additional rules
117
+ enabled.
118
+
119
+ ### `configs.react`
120
+ [`configs.react`]: #configsreact
121
+
122
+ Intended for React code, it applies to `**/*.jsx` and `**/*.tsx` files;
123
+ and it applies to them the following rule sets:
124
+
125
+ - [eslint-plugin-jsx-a11y](https://www.npmjs.com/package/eslint-plugin-jsx-a11y) —
126
+ the `recommended` rule set, and a few additional rules enabled.
127
+
128
+ - [eslint-plugin-react](https://www.npmjs.com/package/eslint-plugin-react) —
129
+ the `recommended` rule set, with minor overrides, and many additional rules
130
+ enabled.
131
+
132
+ - [eslint-plugin-react-hooks](https://www.npmjs.com/package/eslint-plugin-react-hooks) —
133
+ all rules enabled.
24
134
 
25
- **BEWARE:** These early releases are the very first take on the problem, to get
26
- things moving. It is definitely needs more attention both to the configurations,
27
- and to their necessary customization options, and for the config variants
28
- necessary for different kinds of projects and use cases.
135
+ Additionally, it applies to all other files matched by any other [ESLint]
136
+ configuration object, to forbid using JSX syntax in files with extensions
137
+ different from `.jsx` or `.tsx`.
29
138
 
30
- For now, if you want to try on your own risk, you can install the package as
31
- ```sh
32
- npm install --save-dev @dr.pogodin/eslint-configs
33
- ```
139
+ ### `configs.typescript`
140
+ [`configs.typescript`]: #configstypescript
34
141
 
35
- Then use it in your ESLint config:
36
- ```js
37
- // eslint.config.mjs
142
+ Intended for TypeScript code, it applies to `**/*.ts` and `**/*.tsx` files;
143
+ and it applies to them the following rule sets:
38
144
 
39
- import base from '@dr.pogodin/eslint-configs/react-ts';
40
- // or import from '@dr.pogodin/eslint-config/typescript'; for non-react projects.
145
+ - Everything from our [`configs.javascript`], with minor necessary overrides.
41
146
 
42
- export default base;
43
- // or you may further tune imported "base" config to your project needs.
44
- ```
147
+ - [typescript-eslint](https://typescript-eslint.io/rules) —
148
+ the `recommendedTypeChecked` and `stylisticTypeChecked` rule sets, with minor
149
+ overrides, and many additional rules enabled.
45
150
 
46
- These configs assume that Babel is configured in the host project to transpile
47
- TypeScript code into JS.
151
+ [Babel]: https://babeljs.io
152
+ [ESLint]: https://eslint.org
153
+ [eslint-config-airbnb]: https://www.npmjs.com/package/eslint-config-airbnb
package/babel.config.cjs CHANGED
@@ -1,3 +1,8 @@
1
+ /* global module */
2
+
3
+ // NOTE: For now we keep it CJS, as ES modules support in Babel config is still
4
+ // expertimentary.
5
+ // eslint-disable-next-line import/no-commonjs
1
6
  module.exports = {
2
7
  presets: [
3
8
  ['@babel/env', {
@@ -0,0 +1,13 @@
1
+ import javascript from './javascript.js';
2
+ import jest from './jest.js';
3
+ import react from './react.js';
4
+ import typescript from './typescript.js';
5
+
6
+ export default {
7
+ configs: {
8
+ javascript,
9
+ jest,
10
+ react,
11
+ typescript,
12
+ },
13
+ };
@@ -0,0 +1,272 @@
1
+ // Base configuration for all JavaScript and TypeScript files.
2
+
3
+ import { defineConfig } from 'eslint/config';
4
+ import importPlugin from 'eslint-plugin-import';
5
+
6
+ import babelParser from '@babel/eslint-parser';
7
+ import babelPlugin from '@babel/eslint-plugin';
8
+ import js from '@eslint/js';
9
+ import stylisticPlugin from '@stylistic/eslint-plugin';
10
+
11
+ export default defineConfig([{
12
+ extends: [
13
+ 'js/recommended',
14
+ '@stylistic/recommended',
15
+ 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: {
31
+ // These rules are provided by "@babel/eslint-plugin", and they require
32
+ // to disable (to not enable) their counterparts from ESLint core.
33
+ '@babel/new-cap': 'error',
34
+ '@babel/no-invalid-this': 'error',
35
+
36
+ '@babel/no-undef': 'error',
37
+ 'no-undef': 'off',
38
+
39
+ '@babel/no-unused-expressions': 'error',
40
+
41
+ '@babel/object-curly-spacing': ['error', 'always'],
42
+ '@stylistic/object-curly-spacing': 'off',
43
+
44
+ '@babel/semi': 'error',
45
+
46
+ // Rules provided by "eslint-plugin-import".
47
+ 'import/dynamic-import-chunkname': 'error',
48
+ 'import/first': 'error',
49
+ 'import/newline-after-import': 'error',
50
+ 'import/no-absolute-path': 'error',
51
+ 'import/no-amd': 'warn',
52
+ 'import/no-commonjs': 'warn',
53
+ 'import/no-cycle': 'error',
54
+ 'import/no-deprecated': 'error',
55
+ 'import/no-duplicates': 'error',
56
+ 'import/no-dynamic-require': 'error',
57
+ 'import/no-empty-named-blocks': 'error',
58
+ 'import/no-extraneous-dependencies': ['error', {
59
+ devDependencies: false,
60
+ optionalDependencies: false,
61
+ }],
62
+ 'import/no-import-module-exports': 'warn',
63
+ 'import/no-mutable-exports': 'error',
64
+ 'import/no-named-as-default': 'error',
65
+ 'import/no-named-as-default-member': 'error',
66
+ 'import/no-relative-packages': 'error',
67
+ 'import/no-self-import': 'error',
68
+ 'import/no-unassigned-import': ['error', {
69
+ allow: ['**/*.css', '**/*.scss'],
70
+ }],
71
+ 'import/no-unused-modules': 'error',
72
+ 'import/no-useless-path-segments': 'error',
73
+ 'import/no-webpack-loader-syntax': 'error',
74
+
75
+ // These rules are provided by "@stylistic/eslint-plugin",
76
+ // and (re-)configured for our taste, somewhat differently from
77
+ // defaults of "@stylistic/recommended".
78
+ '@stylistic/array-bracket-newline': ['error', 'consistent'],
79
+ '@stylistic/array-element-newline': ['error', 'consistent'],
80
+ '@stylistic/arrow-parens': ['error', 'always'],
81
+ '@stylistic/brace-style': ['error', '1tbs'],
82
+ '@stylistic/comma-dangle': ['error', 'always-multiline'],
83
+ '@stylistic/curly-newline': ['error', {
84
+ consistent: true,
85
+ minElements: 4,
86
+ }],
87
+ '@stylistic/dot-location': ['error', 'property'],
88
+ '@stylistic/function-call-argument-newline': ['error', 'consistent'],
89
+ '@stylistic/function-call-spacing': 'error',
90
+ '@stylistic/function-paren-newline': ['error', 'multiline-arguments'],
91
+ '@stylistic/implicit-arrow-linebreak': 'error',
92
+ '@stylistic/indent': ['error', 2, {
93
+ SwitchCase: 1,
94
+ }],
95
+ '@stylistic/jsx-child-element-spacing': 'error',
96
+
97
+ // This rule is quite annoying at times, better switch it off and let
98
+ // developer to buitify his code as needed in each situation.
99
+ '@stylistic/jsx-one-expression-per-line': 'off',
100
+
101
+ '@stylistic/jsx-pascal-case': 'error',
102
+ '@stylistic/jsx-self-closing-comp': 'error',
103
+ '@stylistic/jsx-sort-props': 'error',
104
+ '@stylistic/linebreak-style': 'error',
105
+ '@stylistic/lines-around-comment': ['error', {
106
+ allowBlockStart: true,
107
+ allowClassStart: true,
108
+ allowObjectStart: true,
109
+ allowTypeStart: true,
110
+ }],
111
+ '@stylistic/max-len': ['error', {
112
+ ignoreComments: true,
113
+ ignoreStrings: true,
114
+ ignoreTemplateLiterals: true,
115
+ }],
116
+ '@stylistic/member-delimiter-style': ['error', {
117
+ multiline: {
118
+ delimiter: 'semi',
119
+ requireLast: true,
120
+ },
121
+ }],
122
+ '@stylistic/multiline-ternary': 'off',
123
+ '@stylistic/no-confusing-arrow': 'error',
124
+ '@stylistic/no-extra-parens': ['error', 'all', {
125
+ enforceForArrowConditionals: false,
126
+ ignoreJSX: 'multi-line',
127
+ nestedBinaryExpressions: false,
128
+ returnAssign: false,
129
+ }],
130
+ '@stylistic/no-extra-semi': 'error',
131
+ '@stylistic/no-multiple-empty-lines': ['error', { max: 1 }],
132
+ '@stylistic/nonblock-statement-body-position': 'error',
133
+ '@stylistic/object-curly-newline': ['error', {
134
+ consistent: true,
135
+ minProperties: 4,
136
+ }],
137
+ '@stylistic/object-property-newline': ['error', {
138
+ allowAllPropertiesOnSameLine: true,
139
+ }],
140
+ '@stylistic/one-var-declaration-per-line': 'error',
141
+ '@stylistic/operator-linebreak': ['error', 'before'],
142
+ '@stylistic/padded-blocks': ['error', 'never'],
143
+ '@stylistic/padding-line-between-statements': 'error',
144
+ '@stylistic/quote-props': ['error', 'as-needed'],
145
+ '@stylistic/quotes': ['error', 'single', {
146
+ avoidEscape: true,
147
+ }],
148
+ '@stylistic/semi': ['error', 'always'],
149
+ '@stylistic/semi-style': 'error',
150
+ '@stylistic/space-before-function-paren': ['error', {
151
+ named: 'never',
152
+ }],
153
+ '@stylistic/switch-colon-spacing': 'error',
154
+ '@stylistic/wrap-regex': 'error',
155
+
156
+ // These rules are provided by ESLint core, and they are not included by
157
+ // by default into "js/recommended" config we extend.
158
+ 'arrow-body-style': 'error',
159
+ 'block-scoped-var': 'error',
160
+ camelcase: 'error',
161
+ 'class-methods-use-this': 'error',
162
+ complexity: 'error',
163
+ 'consistent-return': 'error',
164
+ 'consistent-this': 'error',
165
+ curly: ['error', 'multi-line'],
166
+ 'default-case': 'error',
167
+ 'default-case-last': 'error',
168
+ 'default-param-last': 'error',
169
+ 'dot-notation': 'error',
170
+ eqeqeq: 'error',
171
+ 'func-name-matching': 'error',
172
+ 'func-names': ['error', 'never'],
173
+ 'func-style': ['error', 'declaration', {
174
+ allowArrowFunctions: true,
175
+ }],
176
+ 'guard-for-in': 'error',
177
+ 'logical-assignment-operators': 'error',
178
+ 'max-nested-callbacks': 'error',
179
+ 'no-alert': 'error',
180
+ 'no-array-constructor': 'error',
181
+ 'no-bitwise': 'error',
182
+ 'no-caller': 'error',
183
+ 'no-console': 'error',
184
+ 'no-constructor-return': 'error',
185
+ 'no-continue': 'error',
186
+ 'no-duplicate-imports': 'error',
187
+ 'no-else-return': 'error',
188
+ 'no-empty-function': 'error',
189
+ 'no-eq-null': 'error',
190
+ 'no-eval': 'error',
191
+ 'no-extend-native': 'error',
192
+ 'no-extra-bind': 'error',
193
+ 'no-extra-label': 'error',
194
+ 'no-implicit-coercion': ['error', {
195
+ boolean: false,
196
+ }],
197
+ 'no-implicit-globals': 'error',
198
+ 'no-implied-eval': 'error',
199
+ 'no-inner-declarations': ['error', 'both'],
200
+ 'no-iterator': 'error',
201
+ 'no-label-var': 'error',
202
+ 'no-labels': 'error',
203
+ 'no-lone-blocks': 'error',
204
+ 'no-lonely-if': 'error',
205
+ 'no-loop-func': 'error',
206
+ 'no-multi-assign': 'error',
207
+ 'no-multi-str': 'error',
208
+ 'no-negated-condition': 'error',
209
+ 'no-nested-ternary': 'error',
210
+ 'no-new': 'error',
211
+ 'no-new-func': 'error',
212
+ 'no-new-wrappers': 'error',
213
+ 'no-object-constructor': 'error',
214
+ 'no-octal-escape': 'error',
215
+ 'no-param-reassign': 'error',
216
+ 'no-promise-executor-return': 'error',
217
+ 'no-proto': 'error',
218
+ 'no-return-assign': 'error',
219
+ 'no-script-url': 'error',
220
+ 'no-self-compare': 'error',
221
+ 'no-sequences': 'error',
222
+ 'no-shadow': 'error',
223
+ 'no-template-curly-in-string': 'error',
224
+ 'no-throw-literal': 'error',
225
+ 'no-undef-init': 'error',
226
+ 'no-underscore-dangle': 'error',
227
+ 'no-unmodified-loop-condition': 'error',
228
+ 'no-unneeded-ternary': 'error',
229
+ 'no-unreachable-loop': 'error',
230
+ 'no-use-before-define': 'error',
231
+ 'no-useless-assignment': 'error',
232
+ 'no-useless-call': 'error',
233
+ 'no-useless-computed-key': 'error',
234
+ 'no-useless-concat': 'error',
235
+ 'no-useless-constructor': 'error',
236
+ 'no-useless-rename': 'error',
237
+ 'no-useless-return': 'error',
238
+ 'no-var': 'error',
239
+ 'no-warning-comments': 'warn',
240
+ 'object-shorthand': 'error',
241
+ 'one-var': ['error', 'never'],
242
+ 'operator-assignment': 'error',
243
+ 'prefer-arrow-callback': 'error',
244
+ 'prefer-const': 'error',
245
+ 'prefer-destructuring': 'error',
246
+ 'prefer-exponentiation-operator': 'error',
247
+ 'prefer-numeric-literals': 'error',
248
+ 'prefer-object-has-own': 'error',
249
+ 'prefer-object-spread': 'error',
250
+ 'prefer-promise-reject-errors': 'error',
251
+ 'prefer-regex-literals': 'error',
252
+ 'prefer-rest-params': 'error',
253
+ 'prefer-spread': 'error',
254
+ 'prefer-template': 'error',
255
+ radix: ['error', 'as-needed'],
256
+ 'require-atomic-updates': 'error',
257
+ 'require-await': 'error',
258
+ 'require-yield': 'error',
259
+ 'sort-keys': ['error', 'asc', {
260
+ allowLineSeparatedGroups: true,
261
+ }],
262
+ 'symbol-description': 'error',
263
+ 'unicode-bom': 'error',
264
+ yoda: 'error',
265
+ },
266
+ settings: {
267
+ 'import/resolver': {
268
+ node: true,
269
+ typescript: true,
270
+ },
271
+ },
272
+ }]);
package/config/jest.js ADDED
@@ -0,0 +1,42 @@
1
+ import { defineConfig } from 'eslint/config';
2
+ import pluginJest from 'eslint-plugin-jest';
3
+
4
+ export default defineConfig([{
5
+ name: 'dr.pogodin/jest',
6
+
7
+ extends: [
8
+ pluginJest.configs['flat/recommended'],
9
+ pluginJest.configs['flat/style'],
10
+ ],
11
+ rules: {
12
+ 'import/no-extraneous-dependencies': ['error', {
13
+ optionalDependencies: false,
14
+ }],
15
+
16
+ 'jest/max-nested-describe': 'error',
17
+ 'jest/no-conditional-in-test': 'error',
18
+ 'jest/no-confusing-set-timeout': 'error',
19
+ 'jest/no-duplicate-hooks': 'error',
20
+ 'jest/no-test-return-statement': 'error',
21
+ 'jest/no-untyped-mock-factory': 'error',
22
+ 'jest/padding-around-after-all-blocks': 'error',
23
+ 'jest/padding-around-after-each-blocks': 'error',
24
+ 'jest/padding-around-before-all-blocks': 'error',
25
+ 'jest/padding-around-before-each-blocks': 'error',
26
+ 'jest/padding-around-describe-blocks': 'error',
27
+ 'jest/padding-around-test-blocks': 'error',
28
+ 'jest/prefer-called-with': 'error',
29
+ 'jest/prefer-comparison-matcher': 'error',
30
+ 'jest/prefer-each': 'error',
31
+ 'jest/prefer-equality-matcher': 'error',
32
+ 'jest/prefer-expect-resolves': 'error',
33
+ 'jest/prefer-hooks-in-order': 'error',
34
+ 'jest/prefer-hooks-on-top': 'error',
35
+ 'jest/prefer-jest-mocked': 'error',
36
+ 'jest/prefer-mock-promise-shorthand': 'error',
37
+ 'jest/prefer-spy-on': 'error',
38
+ 'jest/prefer-strict-equal': 'error',
39
+ 'jest/prefer-todo': 'error',
40
+ 'jest/require-to-throw-message': 'error',
41
+ },
42
+ }]);
@@ -0,0 +1,120 @@
1
+ import { defineConfig } from 'eslint/config';
2
+
3
+ import jsxA11y from 'eslint-plugin-jsx-a11y';
4
+ import react from 'eslint-plugin-react';
5
+ import reactHooks from 'eslint-plugin-react-hooks';
6
+
7
+ export default defineConfig([{
8
+ name: 'dr.pogodin/react',
9
+
10
+ extends: [react.configs.flat.recommended, jsxA11y.flatConfigs.recommended],
11
+ files: ['**/*.jsx', '**/*.tsx'],
12
+ languageOptions: {
13
+ parserOptions: {
14
+ ecmaFeatures: {
15
+ jsx: true,
16
+ },
17
+ },
18
+ },
19
+ plugins: {
20
+ react,
21
+ 'react-hooks': reactHooks,
22
+ },
23
+ settings: {
24
+ react: {
25
+ version: '19',
26
+ },
27
+ },
28
+
29
+ rules: {
30
+ // Rules provided by "eslint-plugin-jsx-a11y".
31
+ 'jsx-a11y/anchor-ambiguous-text': 'error',
32
+ 'jsx-a11y/control-has-associated-label': 'error',
33
+ 'jsx-a11y/lang': 'error',
34
+ 'jsx-a11y/no-aria-hidden-on-focusable': 'error',
35
+
36
+ // Rules provided by "eslint-plugin-react" (and not enabled by its recommended
37
+ // config).
38
+ 'react/button-has-type': 'error',
39
+ 'react/checked-requires-onchange-or-readonly': 'error',
40
+ 'react/destructuring-assignment': 'error',
41
+ 'react/function-component-definition': ['error', {
42
+ namedComponents: 'arrow-function',
43
+ unnamedComponents: 'arrow-function',
44
+ }],
45
+ 'react/hook-use-state': 'error',
46
+ 'react/iframe-missing-sandbox': 'error',
47
+ 'react/jsx-boolean-value': 'error',
48
+ 'react/jsx-closing-bracket-location': 'error',
49
+ 'react/jsx-closing-tag-location': 'error',
50
+ 'react/jsx-curly-brace-presence': 'error',
51
+ 'react/jsx-curly-newline': 'error',
52
+ 'react/jsx-curly-spacing': 'error',
53
+ 'react/jsx-equals-spacing': 'error',
54
+ 'react/jsx-first-prop-new-line': ['error', 'multiline'],
55
+ 'react/jsx-fragments': 'error',
56
+ 'react/jsx-handler-names': 'error',
57
+ 'react/jsx-indent': ['error', 2],
58
+ 'react/jsx-indent-props': ['error', 2],
59
+ 'react/jsx-max-depth': ['warn', { max: 10 }],
60
+ 'react/jsx-no-bind': ['error', {
61
+ allowArrowFunctions: true,
62
+ }],
63
+ 'react/jsx-no-constructed-context-values': 'error',
64
+ 'react/jsx-no-leaked-render': 'error',
65
+ 'react/jsx-no-script-url': 'error',
66
+ 'react/jsx-no-useless-fragment': 'error',
67
+ 'react/jsx-pascal-case': 'error',
68
+ 'react/jsx-props-no-spread-multi': 'error',
69
+ 'react/jsx-props-no-spreading': 'error',
70
+ 'react/jsx-sort-props': 'error',
71
+ 'react/jsx-tag-spacing': 'error',
72
+ 'react/no-access-state-in-setstate': 'error',
73
+ 'react/no-array-index-key': 'error',
74
+ 'react/no-arrow-function-lifecycle': 'error',
75
+ 'react/no-danger': 'error',
76
+ 'react/no-did-mount-set-state': 'error',
77
+ 'react/no-did-update-set-state': 'error',
78
+ 'react/no-invalid-html-attribute': 'error',
79
+ 'react/no-namespace': 'error',
80
+ 'react/no-object-type-as-default-prop': 'error',
81
+ 'react/no-redundant-should-component-update': 'error',
82
+ 'react/no-this-in-sfc': 'error',
83
+ 'react/no-typos': 'error',
84
+ 'react/no-unknown-property': ['error', {
85
+ ignore: ['styleName'],
86
+ }],
87
+ 'react/no-unsafe': 'error',
88
+ 'react/no-unstable-nested-components': 'error',
89
+ 'react/no-unused-class-component-methods': 'error',
90
+ 'react/no-unused-state': 'error',
91
+ 'react/no-will-update-set-state': 'error',
92
+ 'react/prefer-stateless-function': 'error',
93
+
94
+ // NOTE: Starting with React 19, propTypes type-checks are deprecated,
95
+ // and if TypeScript is used (as it is recommended now), it will take care
96
+ // of prop types validations anyway.
97
+ 'react/prop-types': 'off',
98
+
99
+ 'react/react-in-jsx-scope': 'off',
100
+ 'react/self-closing-comp': 'error',
101
+ 'react/sort-comp': 'error',
102
+ 'react/style-prop-object': 'error',
103
+ 'react/void-dom-elements-no-children': 'error',
104
+
105
+ // Rules provided by eslint-plugin-react-hooks.
106
+ 'react-hooks/exhaustive-deps': 'error',
107
+ 'react-hooks/rules-of-hooks': 'error',
108
+ },
109
+ }, {
110
+ name: 'dr.pogodin/react/global',
111
+ plugins: {
112
+ react,
113
+ },
114
+ rules: {
115
+ 'react/jsx-filename-extension': ['error', {
116
+ allow: 'as-needed',
117
+ extensions: ['.jsx', '.tsx'],
118
+ }],
119
+ },
120
+ }]);
@@ -0,0 +1,92 @@
1
+ import tsEsLint from 'typescript-eslint';
2
+
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,
18
+ },
19
+ },
20
+ rules: {
21
+ // TypeScript takes care of the same, in a better way.
22
+ '@babel/no-undef': 'off',
23
+
24
+ // It does not support type imports, and TypeScript itself does necessary
25
+ // checks for imports anyway.
26
+ 'import/named': 'off',
27
+
28
+ '@typescript-eslint/array-type': ['error', {
29
+ default: 'array-simple',
30
+ }],
31
+ '@typescript-eslint/class-methods-use-this': 'error',
32
+ '@typescript-eslint/consistent-return': 'error',
33
+ '@typescript-eslint/consistent-type-definitions': ['error', 'type'],
34
+ '@typescript-eslint/consistent-type-exports': 'error',
35
+ '@typescript-eslint/consistent-type-imports': 'error',
36
+ '@typescript-eslint/default-param-last': 'error',
37
+ '@typescript-eslint/explicit-module-boundary-types': 'error',
38
+ '@typescript-eslint/no-confusing-void-expression': 'error',
39
+ '@typescript-eslint/no-deprecated': 'warn',
40
+ '@typescript-eslint/no-dupe-class-members': 'error',
41
+ '@typescript-eslint/no-empty-interface': 'error',
42
+ '@typescript-eslint/no-extraneous-class': 'error',
43
+ '@typescript-eslint/no-import-type-side-effects': 'error',
44
+ '@typescript-eslint/no-inferrable-types': 'off',
45
+ '@typescript-eslint/no-invalid-this': 'error',
46
+ '@typescript-eslint/no-invalid-void-type': 'error',
47
+ '@typescript-eslint/no-loop-func': 'error',
48
+ '@typescript-eslint/no-loss-of-precision': 'error',
49
+ '@typescript-eslint/no-meaningless-void-operator': 'error',
50
+ '@typescript-eslint/no-misused-spread': 'error',
51
+ '@typescript-eslint/no-mixed-enums': 'error',
52
+ '@typescript-eslint/no-non-null-asserted-nullish-coalescing': 'error',
53
+ '@typescript-eslint/no-redeclare': 'error',
54
+
55
+ // NOTE: The core rule variant reports incorrect errors on TypeScript
56
+ // code, thus disabled.
57
+ '@typescript-eslint/no-shadow': 'error',
58
+ 'no-shadow': 'off',
59
+
60
+ '@typescript-eslint/no-unnecessary-boolean-literal-compare': 'error',
61
+ '@typescript-eslint/no-unnecessary-condition': 'error',
62
+ '@typescript-eslint/no-unnecessary-parameter-property-assignment': 'error',
63
+ '@typescript-eslint/no-unnecessary-qualifier': 'error',
64
+ '@typescript-eslint/no-unnecessary-template-expression': 'error',
65
+ '@typescript-eslint/no-unnecessary-type-arguments': 'error',
66
+ '@typescript-eslint/no-use-before-define': 'error',
67
+ '@typescript-eslint/no-useless-constructor': 'error',
68
+ '@typescript-eslint/no-useless-empty-export': 'error',
69
+ '@typescript-eslint/parameter-properties': ['error', {
70
+ prefer: 'parameter-property',
71
+ }],
72
+
73
+ // NOTE: The core variant of this rule, disabled below, does not work
74
+ // correctly for TypeScript code in some edge cases.
75
+ '@typescript-eslint/prefer-destructuring': 'error',
76
+ 'prefer-destructuring': 'off',
77
+
78
+ '@typescript-eslint/prefer-enum-initializers': 'error',
79
+ '@typescript-eslint/prefer-literal-enum-member': 'error',
80
+ '@typescript-eslint/prefer-reduce-type-parameter': 'error',
81
+ '@typescript-eslint/prefer-regexp-exec': 'off',
82
+ '@typescript-eslint/prefer-return-this-type': 'error',
83
+ '@typescript-eslint/promise-function-async': 'error',
84
+ '@typescript-eslint/related-getter-setter-pairs': 'error',
85
+ '@typescript-eslint/require-array-sort-compare': 'error',
86
+ '@typescript-eslint/switch-exhaustiveness-check': 'error',
87
+ '@typescript-eslint/typedef': 'error',
88
+ '@typescript-eslint/unified-signatures': 'error',
89
+ '@typescript-eslint/use-unknown-in-catch-callback-variable': 'error',
90
+ },
91
+ },
92
+ );
@@ -0,0 +1,3 @@
1
+ import config from './config/javascript.js';
2
+
3
+ export default config;
package/package.json CHANGED
@@ -1,14 +1,15 @@
1
1
  {
2
2
  "name": "@dr.pogodin/eslint-configs",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "description": "ESLint configurations for TypeScript and/or React projects",
5
5
  "type": "module",
6
+ "main": "./config/index.js",
6
7
  "exports": {
7
- "./react-ts": "./react-ts.mjs",
8
- "./typescript": "./typescript.mjs"
8
+ "*": "./config/*.js",
9
+ "default": "./config/index.js"
9
10
  },
10
11
  "scripts": {
11
- "lint": "eslint -c typescript.mjs",
12
+ "lint": "eslint",
12
13
  "test": "npm run lint"
13
14
  },
14
15
  "repository": "github:birdofpreyru/eslint-configs",
@@ -33,16 +34,18 @@
33
34
  "@babel/preset-env": "^7.26.9",
34
35
  "@babel/preset-react": "^7.26.3",
35
36
  "@babel/preset-typescript": "^7.26.0",
36
- "@eslint/js": "^9.21.0",
37
+ "@eslint/js": "^9.25.0",
37
38
  "@stylistic/eslint-plugin": "^4.1.0",
38
- "eslint": "^9.21.0",
39
39
  "eslint-import-resolver-typescript": "^4.3.2",
40
40
  "eslint-plugin-import": "^2.31.0",
41
41
  "eslint-plugin-jest": "^28.11.0",
42
+ "eslint-plugin-jsx-a11y": "^6.10.2",
42
43
  "eslint-plugin-react": "^7.37.4",
43
44
  "eslint-plugin-react-hooks": "^5.2.0",
44
- "globals": "^16.0.0",
45
45
  "typescript": "^5.7.0",
46
- "typescript-eslint": "^8.25.0"
46
+ "typescript-eslint": "^8.30.1"
47
+ },
48
+ "peerDependencies": {
49
+ "eslint": "9"
47
50
  }
48
51
  }
package/react-ts.mjs DELETED
@@ -1,37 +0,0 @@
1
- import reactPlugin from 'eslint-plugin-react';
2
- import reactHooks from 'eslint-plugin-react-hooks';
3
-
4
- import base from './typescript.mjs';
5
-
6
- export default [
7
- ...base,
8
- {
9
- files: ['**/*.{js,mjs,cjs,ts,jsx,tsx}'],
10
- settings: {
11
- react: { version: '19' },
12
- },
13
- },
14
-
15
- reactPlugin.configs.flat.recommended,
16
- reactPlugin.configs.flat['jsx-runtime'],
17
-
18
- // TODO: This does not work because a bug in eslint-plugin-react-hooks:
19
- // https://github.com/facebook/react/issues/32431
20
- // thus, the workaround below.
21
- // reactHooks.configs.recommended
22
- {
23
- plugins: { 'react-hooks': reactHooks },
24
- rules: { ...reactHooks.configs.recommended.rules },
25
- },
26
-
27
- {
28
- rules: {
29
- 'react/function-component-definition': ['error', {
30
- namedComponents: 'arrow-function',
31
- unnamedComponents: 'arrow-function',
32
- }],
33
- 'react-hooks/exhaustive-deps': 'error',
34
- 'react/prop-types': 'off',
35
- },
36
- },
37
- ];
package/typescript.mjs DELETED
@@ -1,141 +0,0 @@
1
- import babelParser from '@babel/eslint-parser';
2
- import babelPlugin from '@babel/eslint-plugin';
3
- import pluginJest from 'eslint-plugin-jest';
4
- import importPlugin from 'eslint-plugin-import';
5
- import globals from 'globals';
6
- import tseslint from 'typescript-eslint';
7
-
8
- import pluginJs from '@eslint/js';
9
- import stylisticPlugin from '@stylistic/eslint-plugin';
10
-
11
- export default tseslint.config(
12
- { ignores: ['__coverage__', 'build/'] },
13
- {
14
- files: ['**/*.{js,mjs,cjs,ts,jsx,tsx}'],
15
- languageOptions: {
16
- globals: { ...globals.browser, ...globals.node },
17
- parser: babelParser,
18
- },
19
- linterOptions: {
20
- reportUnusedDisableDirectives: 'error',
21
- reportUnusedInlineConfigs: 'error',
22
- },
23
- plugins: {
24
- '@babel': babelPlugin,
25
- },
26
- settings: {
27
- 'import/resolver': {
28
- node: true,
29
- typescript: true,
30
- },
31
- },
32
- },
33
-
34
- importPlugin.flatConfigs.recommended,
35
-
36
- pluginJs.configs.recommended,
37
-
38
- stylisticPlugin.configs.all,
39
-
40
- {
41
- rules: {
42
- '@babel/new-cap': 'error',
43
- '@babel/no-invalid-this': 'error',
44
- '@babel/no-undef': 'error',
45
- '@babel/no-unused-expressions': 'error',
46
-
47
- '@stylistic/object-curly-spacing': 'off',
48
- '@babel/object-curly-spacing': ['error', 'always'],
49
-
50
- '@babel/semi': 'error',
51
- '@stylistic/array-bracket-newline': ['error', 'consistent'],
52
- '@stylistic/array-element-newline': ['error', 'consistent'],
53
- '@stylistic/comma-dangle': ['error', 'always-multiline'],
54
- '@stylistic/dot-location': ['error', 'property'],
55
- '@stylistic/function-call-argument-newline': ['error', 'consistent'],
56
- '@stylistic/function-paren-newline': ['error', 'multiline-arguments'],
57
- '@stylistic/indent': ['error', 2, {
58
- SwitchCase: 1,
59
- }],
60
- '@stylistic/lines-around-comment': ['error', {
61
- allowBlockStart: true,
62
- allowClassStart: true,
63
- allowObjectStart: true,
64
- allowTypeStart: true,
65
- }],
66
- '@stylistic/max-len': ['error', {
67
- ignoreStrings: true,
68
- ignoreTemplateLiterals: true,
69
- }],
70
- '@stylistic/multiline-comment-style': 'off',
71
- '@stylistic/multiline-ternary': ['error', 'always-multiline'],
72
- '@stylistic/no-extra-parens': ['error', 'all', {
73
- enforceForArrowConditionals: false,
74
- ignoreJSX: 'multi-line',
75
- nestedBinaryExpressions: false,
76
- returnAssign: false,
77
- }],
78
- '@stylistic/no-multiple-empty-lines': ['error', { max: 1 }],
79
- '@stylistic/object-curly-newline': ['error', {
80
- consistent: true,
81
- minProperties: 4,
82
- }],
83
-
84
- '@stylistic/object-property-newline': ['error', {
85
- allowAllPropertiesOnSameLine: true,
86
- }],
87
- '@stylistic/operator-linebreak': ['error', 'before'],
88
- '@stylistic/padded-blocks': ['error', 'never'],
89
- '@stylistic/quote-props': ['error', 'as-needed'],
90
- '@stylistic/quotes': ['error', 'single'],
91
- '@stylistic/space-before-function-paren': ['error', {
92
- named: 'never',
93
- }],
94
- 'import/no-cycle': 'error',
95
- 'import/no-extraneous-dependencies': 'error',
96
-
97
- 'no-use-before-define': 'error',
98
- },
99
- },
100
-
101
- {
102
- // TypeScript-specific configuration.
103
- files: ['**/*.{ts,tsx}'],
104
- languageOptions: {
105
- parserOptions: {
106
- projectService: true,
107
- tsconfigRootDir: import.meta.dirname,
108
- },
109
- },
110
- extends: [
111
- ...tseslint.configs.recommendedTypeChecked,
112
- ...tseslint.configs.stylisticTypeChecked,
113
- ],
114
- rules: {
115
- '@typescript-eslint/array-type': 'off',
116
- '@typescript-eslint/consistent-type-definitions': ['error', 'type'],
117
- '@typescript-eslint/no-inferrable-types': 'off',
118
-
119
- // TODO: Its current implementation seems to give false positive.
120
- '@typescript-eslint/no-invalid-void-type': 'off',
121
-
122
- // NOTE: According to its documentation
123
- // "@typescript-eslint/no-unused-vars"
124
- // requires to disable "no-unused-vars".
125
- 'no-unused-vars': 'off',
126
- '@typescript-eslint/no-unused-vars': 'error',
127
-
128
- '@typescript-eslint/prefer-nullish-coalescing': 'error',
129
- '@typescript-eslint/unbound-method': 'off',
130
- },
131
- },
132
-
133
- {
134
- files: ['__tests__/**/*.{js,mjs,cjs,ts,jsx,tsx}'],
135
- // TODO: Is this "extends" really necessary?
136
- extends: [pluginJest.configs['flat/recommended']],
137
- rules: {
138
- 'jest/unbound-method': 'error',
139
- },
140
- },
141
- );