@thermarthae/eslint-config 4.0.2 → 5.0.0

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
@@ -9,13 +9,13 @@ Just an Eslint config.
9
9
  This step assumes that you have already installed Eslint and Typescript.
10
10
 
11
11
  ```bash
12
- yarn add -D @thermarthae/eslint-config @typescript-eslint/eslint-plugin @typescript-eslint/parser eslint-plugin-import@npm:eslint-plugin-i@latest eslint-plugin-jsx-a11y eslint-plugin-react eslint-plugin-react-hooks eslint-plugin-simple-import-sort @stylistic/eslint-plugin
12
+ yarn add -D @thermarthae/eslint-config @eslint/js typescript-eslint eslint-plugin-simple-import-sort @stylistic/eslint-plugin eslint-plugin-react eslint-plugin-react-hooks eslint-plugin-jsx-a11y
13
13
  ```
14
14
 
15
15
  If you don't need React support:
16
16
 
17
17
  ```bash
18
- yarn add -D @thermarthae/eslint-config @typescript-eslint/eslint-plugin @typescript-eslint/parser eslint-plugin-import@npm:eslint-plugin-i@latest eslint-plugin-simple-import-sort @stylistic/eslint-plugin
18
+ yarn add -D @thermarthae/eslint-config @eslint/js typescript-eslint eslint-plugin-simple-import-sort @stylistic/eslint-plugin
19
19
  ```
20
20
 
21
21
  ### 2) Configure ESLint
@@ -25,20 +25,18 @@ Add `"extends": "@thermarthae/eslint-config"` to your ESLint config file.
25
25
  An example `.eslintrc.cjs`:
26
26
 
27
27
  ```js
28
- module.exports = {
29
- // If you don't need React support:
30
- // extends: ['@thermarthae/eslint-config/base.cjs'],
31
- extends: ['@thermarthae/eslint-config'],
32
- };
33
- ```
34
-
35
- **Note**: If your `tsconfig.json` is not in the same directory as `package.json`, you will have to set the path yourself:
36
-
37
- ```diff
38
- module.exports = {
39
- extends: ['@thermarthae/eslint-config'],
40
- + parserOptions: {
41
- + project: './foo/bar/tsconfig.json',
42
- + },
43
- };
28
+ // If you don't need React support:
29
+ // import config from '@thermarthae/eslint-config/base';
30
+ import config from '@thermarthae/eslint-config';
31
+
32
+ export default [
33
+ ...config,
34
+ {
35
+ languageOptions: {
36
+ parserOptions: {
37
+ tsconfigRootDir: import.meta.dirname,
38
+ },
39
+ },
40
+ },
41
+ ];
44
42
  ```
package/base.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ import { Linter } from 'eslint';
2
+
3
+ const base: Linter.Config[];
4
+
5
+ export default base;
package/base.js ADDED
@@ -0,0 +1,138 @@
1
+ import eslint from '@eslint/js';
2
+ import stylistic from '@stylistic/eslint-plugin';
3
+ import simpleImportSort from 'eslint-plugin-simple-import-sort';
4
+ import tsEslint from 'typescript-eslint';
5
+
6
+ const stylisticCustomized = stylistic.configs.customize({
7
+ flat: true,
8
+ indent: 'tab',
9
+ semi: true,
10
+ jsx: false,
11
+ braceStyle: '1tbs',
12
+ quoteProps: 'as-needed',
13
+ });
14
+
15
+ /** @type {typeof import('typescript-eslint').configs.all} */
16
+ const base = [
17
+ //
18
+ // eslint
19
+ //
20
+ eslint.configs.recommended,
21
+ {
22
+ rules: {
23
+ 'object-shorthand': ['error', 'always', { avoidQuotes: true }],
24
+ 'no-duplicate-imports': 'error',
25
+ 'no-param-reassign': ['error', {
26
+ ignorePropertyModificationsFor: [
27
+ 'request',
28
+ 'reply',
29
+ 'session',
30
+ 'state',
31
+ ],
32
+ props: true,
33
+ }],
34
+ 'no-void': ['error', { allowAsStatement: true }],
35
+ yoda: ['error', 'never', { exceptRange: true }],
36
+ },
37
+ },
38
+ //
39
+ // typescript-eslint
40
+ //
41
+ ...tsEslint.configs.recommendedTypeChecked,
42
+ ...tsEslint.configs.stylisticTypeChecked,
43
+ {
44
+ ...tsEslint.configs.disableTypeChecked,
45
+ files: ['*.cjs', '*.js'],
46
+ },
47
+ {
48
+ languageOptions: {
49
+ parserOptions: {
50
+ projectService: true,
51
+ ecmaVersion: 'latest',
52
+ },
53
+ },
54
+ rules: {
55
+ '@typescript-eslint/array-type': ['error', {
56
+ default: 'array-simple',
57
+ }],
58
+ '@typescript-eslint/consistent-type-assertions': ['error', {
59
+ assertionStyle: 'as',
60
+ objectLiteralTypeAssertions: 'allow-as-parameter',
61
+ }],
62
+ '@typescript-eslint/consistent-type-definitions': 0,
63
+ '@typescript-eslint/no-unused-vars': 0,
64
+ '@typescript-eslint/no-empty-function': 0,
65
+ '@typescript-eslint/no-misused-promises': ['error', {
66
+ checksVoidReturn: false,
67
+ }],
68
+ '@typescript-eslint/no-unnecessary-type-arguments': 'warn',
69
+ '@typescript-eslint/no-shadow': 'error',
70
+ '@typescript-eslint/promise-function-async': 'error',
71
+ },
72
+ },
73
+ //
74
+ // stylistic
75
+ //
76
+ {
77
+ // `disable-legacy` without rules that starts with 'react/'
78
+ ...stylistic.configs['disable-legacy'],
79
+ rules: Object.fromEntries(Object.entries(stylistic.configs['disable-legacy'].rules ?? {})
80
+ .filter(r => !r[0].startsWith('react/'))),
81
+ },
82
+ {
83
+ ...stylisticCustomized,
84
+ rules: {
85
+ ...stylisticCustomized.rules,
86
+ '@stylistic/arrow-parens': ['error', 'as-needed', {
87
+ requireForBlockBody: true,
88
+ }],
89
+ '@stylistic/linebreak-style': ['error', 'windows'],
90
+ '@stylistic/max-len': ['error', { code: 120 }],
91
+ '@stylistic/no-multiple-empty-lines': ['error', {
92
+ max: 3,
93
+ maxBOF: 0,
94
+ maxEOF: 1,
95
+ }],
96
+ '@stylistic/max-statements-per-line': 0,
97
+ '@stylistic/indent-binary-ops': 0,
98
+ },
99
+ },
100
+ //
101
+ // simple-import-sort
102
+ //
103
+ {
104
+ plugins: {
105
+ 'simple-import-sort': simpleImportSort,
106
+ },
107
+ rules: {
108
+ 'simple-import-sort/imports': ['warn', {
109
+ groups: [
110
+ // Side effect imports.
111
+ ['^\\u0000'],
112
+ [
113
+ '^node:',
114
+ 'react',
115
+ // Things that start with a letter (or digit or underscore), or `@` followed by a letter.
116
+ '^@?\\w',
117
+ ],
118
+ // Absolute imports and other imports such as Vue-style `@/foo`.
119
+ ['^'],
120
+ [
121
+ // ../whatever/
122
+ '^\\.\\./(?=.*/)',
123
+ // ../
124
+ '^\\.\\./',
125
+ ],
126
+ [
127
+ // ./whatever/
128
+ '^\\./(?=.*/)',
129
+ // ./
130
+ '^\\./',
131
+ ],
132
+ ],
133
+ }],
134
+ },
135
+ },
136
+ ];
137
+
138
+ export default base;
package/index.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ import { Linter } from 'eslint';
2
+
3
+ const main: Linter.Config[];
4
+
5
+ export default main;
package/index.js ADDED
@@ -0,0 +1,96 @@
1
+ import react from 'eslint-plugin-react';
2
+ // @ts-expect-error no types :/
3
+ import reactHooks from 'eslint-plugin-react-hooks';
4
+ import stylistic from '@stylistic/eslint-plugin';
5
+ import jsxA11y from 'eslint-plugin-jsx-a11y';
6
+
7
+ import base from './base.js';
8
+
9
+ const stylisticCustomizedWithJSX = stylistic.configs.customize({
10
+ flat: true,
11
+ indent: 'tab',
12
+ semi: true,
13
+ jsx: true,
14
+ braceStyle: '1tbs',
15
+ quoteProps: 'as-needed',
16
+ });
17
+
18
+ // all `stylisticCustomizedWithJSX` rules that starts with '@stylistic/jsx'
19
+ const jsxStylisticRules = Object.fromEntries(Object.entries(stylisticCustomizedWithJSX.rules ?? {})
20
+ .filter(r => r[0].startsWith('@stylistic/jsx')));
21
+
22
+ /** @type {typeof import('typescript-eslint').configs.all} */
23
+ const main = [
24
+ ...base,
25
+ //
26
+ // react
27
+ //
28
+ // react.configs.flat.recommended,
29
+ // react.configs.flat['jsx-runtime'],
30
+ // TODO: wait for a types fix
31
+ /** @type {typeof import('typescript-eslint').configs.base} */ (react.configs.flat.recommended),
32
+ /** @type {typeof import('typescript-eslint').configs.base} */ (react.configs.flat['jsx-runtime']),
33
+ {
34
+ settings: {
35
+ react: {
36
+ version: 'detect',
37
+ },
38
+ },
39
+ rules: {
40
+ 'react/react-in-jsx-scope': 0,
41
+ 'react/no-unknown-property': 0,
42
+ 'react/no-children-prop': 0,
43
+ 'react/prop-types': 0,
44
+ 'react/jsx-boolean-value': ['error', 'never', { always: [] }],
45
+ 'react/void-dom-elements-no-children': 'error',
46
+ 'react/button-has-type': ['error', {
47
+ button: true,
48
+ submit: true,
49
+ reset: false,
50
+ }],
51
+ 'react/jsx-no-useless-fragment': 'error',
52
+ 'react/jsx-no-constructed-context-values': 'error',
53
+ 'react/no-unstable-nested-components': 'error',
54
+ },
55
+ },
56
+ //
57
+ // react-hooks
58
+ //
59
+ // TODO: wait for a native flat support
60
+ {
61
+ files: ['**/**/*.{js,ts,jsx,tsx}'],
62
+ plugins: {
63
+ 'react-hooks': reactHooks,
64
+ },
65
+ rules: reactHooks.configs.recommended.rules,
66
+ },
67
+ //
68
+ // jsx-a11y
69
+ //
70
+ jsxA11y.flatConfigs.recommended,
71
+ //
72
+ // stylistic
73
+ //
74
+ {
75
+ // all `disable-legacy` rules that starts with 'react/'
76
+ ...stylistic.configs['disable-legacy'],
77
+ rules: Object.fromEntries(Object.entries(stylistic.configs['disable-legacy'].rules ?? {})
78
+ .filter(r => r[0].startsWith('react/'))),
79
+ },
80
+ {
81
+ rules: {
82
+ ...jsxStylisticRules,
83
+ '@stylistic/jsx-closing-bracket-location': ['error', 'line-aligned'],
84
+ '@stylistic/jsx-curly-brace-presence': ['error', {
85
+ props: 'never',
86
+ children: 'never',
87
+ propElementValues: 'always',
88
+ }],
89
+ '@stylistic/jsx-curly-spacing': ['error', 'never', { allowMultiline: true }],
90
+ '@stylistic/jsx-self-closing-comp': 'error',
91
+ '@stylistic/jsx-props-no-multi-spaces': 'error',
92
+ },
93
+ },
94
+ ];
95
+
96
+ export default main;
package/package.json CHANGED
@@ -1,8 +1,9 @@
1
1
  {
2
2
  "name": "@thermarthae/eslint-config",
3
- "version": "4.0.2",
4
- "main": "index.cjs",
3
+ "version": "5.0.0",
4
+ "main": "index.js",
5
5
  "description": "Just a personal eslint config",
6
+ "type": "module",
6
7
  "license": "MIT",
7
8
  "author": "thermarthae <thermarthae@protonmail.com>",
8
9
  "repository": {
@@ -10,42 +11,41 @@
10
11
  "url": "git+https://github.com/thermarthae/eslint-config.git"
11
12
  },
12
13
  "files": [
13
- "base.cjs",
14
- "index.cjs",
15
- "shared.cjs"
14
+ "base.js",
15
+ "base.d.ts",
16
+ "index.js",
17
+ "index.d.ts"
16
18
  ],
17
- "packageManager": "yarn@4.1.0+sha256.81a00df816059803e6b5148acf03ce313cad36b7f6e5af6efa040a15981a6ffb",
19
+ "packageManager": "yarn@4.5.1+sha512.341db9396b6e289fecc30cd7ab3af65060e05ebff4b3b47547b278b9e67b08f485ecd8c79006b405446262142c7a38154445ef7f17c1d5d1de7d90bf9ce7054d",
18
20
  "scripts": {
19
21
  "pnpify": "yarn dlx @yarnpkg/sdks vscode"
20
22
  },
21
- "resolutions": {
22
- "@stylistic/eslint-plugin-plus/@typescript-eslint/utils": "^7.1.0",
23
- "@stylistic/eslint-plugin-ts/@typescript-eslint/utils": "^7.1.0"
24
- },
25
23
  "devDependencies": {
26
- "@stylistic/eslint-plugin": "^1.6.2",
27
- "@typescript-eslint/eslint-plugin": "^7.1.0",
28
- "@typescript-eslint/parser": "^7.1.0",
29
- "eslint": "^8.57.0",
30
- "eslint-plugin-import": "npm:eslint-plugin-i@^2.29.1",
31
- "eslint-plugin-simple-import-sort": "^12.0.0",
32
- "typescript": "^5.3.3"
24
+ "@eslint/js": "^9.13.0",
25
+ "@stylistic/eslint-plugin": "^2.9.0",
26
+ "@types/eslint-plugin-jsx-a11y": "^6.9.0",
27
+ "@types/eslint__js": "^8.42.3",
28
+ "@types/node": "^22.7.8",
29
+ "eslint": "^9.13.0",
30
+ "eslint-plugin-jsx-a11y": "^6.10.1",
31
+ "eslint-plugin-react": "^7.37.1",
32
+ "eslint-plugin-react-hooks": "^5.0.0",
33
+ "eslint-plugin-simple-import-sort": "^12.1.1",
34
+ "typescript": "^5.6.3",
35
+ "typescript-eslint": "^8.11.0"
33
36
  },
34
37
  "peerDependencies": {
35
- "@stylistic/eslint-plugin": "^1.6.2",
36
- "@typescript-eslint/parser": "^6.20.0 || ^7.1.0",
37
- "eslint": "^8.56.0",
38
- "eslint-plugin-import": "^2.29.1",
39
- "eslint-plugin-jsx-a11y": "^6.8.0",
40
- "eslint-plugin-react": "^7.33.2",
41
- "eslint-plugin-react-hooks": "^4.6.0",
42
- "eslint-plugin-simple-import-sort": "^12.0.0",
43
- "typescript": "^5.3.3"
38
+ "@eslint/js": "^9.13.0",
39
+ "@stylistic/eslint-plugin": "^2.9.0",
40
+ "eslint": "^9.13.0",
41
+ "eslint-plugin-jsx-a11y": "^6.10.1",
42
+ "eslint-plugin-react": "^7.37.1",
43
+ "eslint-plugin-react-hooks": "^5.0.0",
44
+ "eslint-plugin-simple-import-sort": "^12.1.1",
45
+ "typescript": "^5.6.3",
46
+ "typescript-eslint": "^8.11.0"
44
47
  },
45
48
  "peerDependenciesMeta": {
46
- "eslint-config-prettier": {
47
- "optional": true
48
- },
49
49
  "eslint-plugin-jsx-a11y": {
50
50
  "optional": true
51
51
  },
package/base.cjs DELETED
@@ -1,5 +0,0 @@
1
- module.exports = {
2
- extends: [
3
- './shared.cjs',
4
- ],
5
- };
package/index.cjs DELETED
@@ -1,57 +0,0 @@
1
- module.exports = {
2
- extends: [
3
- './shared.cjs',
4
- 'plugin:react/recommended',
5
- 'plugin:react/jsx-runtime',
6
- 'plugin:react-hooks/recommended',
7
- 'plugin:jsx-a11y/recommended',
8
- ],
9
- plugins: ['jsx-a11y'],
10
- settings: {
11
- react: {
12
- version: 'detect',
13
- },
14
- },
15
- rules: {
16
- 'react/jsx-indent': ['error', 'tab', { checkAttributes: true, indentLogicalExpressions: true }],
17
- 'react/jsx-indent-props': ['error', 'tab'],
18
- 'react/no-unknown-property': 0,
19
- 'react/no-children-prop': 0,
20
- 'react/prop-types': 0,
21
- 'react/jsx-boolean-value': ['error', 'never', { always: [] }],
22
- 'react/jsx-closing-bracket-location': ['error', 'line-aligned'],
23
- 'react/jsx-closing-tag-location': 'error',
24
- 'react/jsx-curly-spacing': ['error', 'never', { allowMultiline: true }],
25
- 'react/jsx-max-props-per-line': ['error', { maximum: 1, when: 'multiline' }],
26
- 'react/self-closing-comp': 'error',
27
- 'react/jsx-wrap-multilines': ['error', {
28
- declaration: 'parens-new-line',
29
- assignment: 'parens-new-line',
30
- return: 'parens-new-line',
31
- arrow: 'parens-new-line',
32
- condition: 'parens-new-line',
33
- logical: 'parens-new-line',
34
- prop: 'parens-new-line',
35
- }],
36
- 'react/jsx-first-prop-new-line': 'error',
37
- 'react/jsx-tag-spacing': ['error', {
38
- closingSlash: 'never',
39
- beforeSelfClosing: 'always',
40
- afterOpening: 'never',
41
- beforeClosing: 'never',
42
- }],
43
- 'react/void-dom-elements-no-children': 'error',
44
- 'react/jsx-curly-brace-presence': ['error', { props: 'never', children: 'never', propElementValues: 'always' }],
45
- 'react/jsx-one-expression-per-line': ['error', { allow: 'single-child' }],
46
- 'react/button-has-type': ['error', {
47
- button: true,
48
- submit: true,
49
- reset: false,
50
- }],
51
- 'react/jsx-props-no-multi-spaces': 'error',
52
- 'react/jsx-curly-newline': 'error',
53
- 'react/jsx-no-useless-fragment': 'error',
54
- 'react/jsx-no-constructed-context-values': 'error',
55
- 'react/no-unstable-nested-components': 'error',
56
- },
57
- };
package/shared.cjs DELETED
@@ -1,127 +0,0 @@
1
- const stylistic = require('@stylistic/eslint-plugin');
2
-
3
- const customized = stylistic.configs.customize({
4
- indent: 'tab',
5
- semi: true,
6
- jsx: false,
7
- braceStyle: '1tbs',
8
- quoteProps: 'as-needed',
9
- });
10
-
11
- module.exports = {
12
- extends: [
13
- 'eslint:recommended',
14
- 'plugin:@typescript-eslint/recommended-type-checked',
15
- 'plugin:@typescript-eslint/stylistic-type-checked',
16
- 'plugin:@stylistic/disable-legacy',
17
- 'plugin:import/recommended',
18
- 'plugin:import/typescript',
19
- ],
20
- plugins: [
21
- '@typescript-eslint',
22
- 'simple-import-sort',
23
- '@stylistic',
24
- ],
25
- parser: '@typescript-eslint/parser',
26
- parserOptions: {
27
- project: true,
28
- sourceType: 'module',
29
- ecmaVersion: 'latest',
30
- },
31
- settings: {
32
- 'import/external-module-folders': ['.yarn', 'node_modules', 'node_modules/@types'],
33
- },
34
- overrides: [
35
- {
36
- files: ['*.cjs'],
37
- env: {
38
- node: true,
39
- },
40
- },
41
- {
42
- files: ['*.cjs', '*.js'],
43
- rules: {
44
- '@typescript-eslint/ban-ts-comment': 0,
45
- '@typescript-eslint/no-unsafe-assignment': 0,
46
- '@typescript-eslint/no-unsafe-call': 0,
47
- '@typescript-eslint/no-unsafe-member-access': 0,
48
- '@typescript-eslint/no-var-requires': 0,
49
- },
50
- },
51
- ],
52
- rules: {
53
- ...customized.rules,
54
- '@stylistic/arrow-parens': ['error', 'as-needed', {
55
- requireForBlockBody: true,
56
- }],
57
- '@stylistic/linebreak-style': ['error', 'windows'],
58
- '@stylistic/max-len': ['error', { code: 120 }],
59
- '@stylistic/no-multiple-empty-lines': ['error', {
60
- max: 3,
61
- maxBOF: 0,
62
- maxEOF: 1,
63
- }],
64
- '@stylistic/max-statements-per-line': 0,
65
- '@stylistic/indent-binary-ops': 0,
66
- //
67
- '@typescript-eslint/array-type': ['error', {
68
- default: 'array-simple',
69
- }],
70
- '@typescript-eslint/consistent-type-assertions': ['error', {
71
- assertionStyle: 'as',
72
- objectLiteralTypeAssertions: 'allow-as-parameter',
73
- }],
74
- '@typescript-eslint/consistent-type-definitions': 0,
75
- '@typescript-eslint/no-unused-vars': 0,
76
- '@typescript-eslint/no-empty-function': 0,
77
- '@typescript-eslint/no-misused-promises': ['error', {
78
- checksVoidReturn: false,
79
- }],
80
- '@typescript-eslint/no-unnecessary-type-arguments': 'warn',
81
- '@typescript-eslint/no-shadow': 'error',
82
- '@typescript-eslint/promise-function-async': 'error',
83
- //
84
- 'import/no-unresolved': 0,
85
- // TODO: https://github.com/import-js/eslint-plugin-import/pull/2813
86
- // 'import/extensions': ['error', 'always', { ignorePackages: true }],
87
- //
88
- 'simple-import-sort/imports': ['warn', {
89
- groups: [
90
- // Side effect imports.
91
- ['^\\u0000'],
92
- [
93
- '^node:',
94
- 'react',
95
- // Things that start with a letter (or digit or underscore), or `@` followed by a letter.
96
- '^@?\\w',
97
- ],
98
- // Absolute imports and other imports such as Vue-style `@/foo`.
99
- ['^'],
100
- [
101
- // ../whatever/
102
- '^\\.\\./(?=.*/)',
103
- // ../
104
- '^\\.\\./',
105
- ],
106
- [
107
- // ./whatever/
108
- '^\\./(?=.*/)',
109
- // ./
110
- '^\\./',
111
- ],
112
- ],
113
- }],
114
- //
115
- 'no-param-reassign': ['error', {
116
- ignorePropertyModificationsFor: [
117
- 'request',
118
- 'reply',
119
- 'session',
120
- 'state',
121
- ],
122
- props: true,
123
- }],
124
- 'no-void': ['error', { allowAsStatement: true }],
125
- yoda: ['error', 'never', { exceptRange: true }],
126
- },
127
- };