@thermarthae/eslint-config 4.1.0 → 6.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.
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env node
2
+
3
+ const {existsSync} = require(`fs`);
4
+ const {createRequire, register} = require(`module`);
5
+ const {resolve} = require(`path`);
6
+ const {pathToFileURL} = require(`url`);
7
+
8
+ const relPnpApiPath = "../../../../../.pnp.cjs";
9
+
10
+ const absPnpApiPath = resolve(__dirname, relPnpApiPath);
11
+ const absUserWrapperPath = resolve(__dirname, `./sdk.user.cjs`);
12
+ const absRequire = createRequire(absPnpApiPath);
13
+
14
+ const absPnpLoaderPath = resolve(absPnpApiPath, `../.pnp.loader.mjs`);
15
+ const isPnpLoaderEnabled = existsSync(absPnpLoaderPath);
16
+
17
+ if (existsSync(absPnpApiPath)) {
18
+ if (!process.versions.pnp) {
19
+ // Setup the environment to be able to require eslint
20
+ require(absPnpApiPath).setup();
21
+ if (isPnpLoaderEnabled && register) {
22
+ register(pathToFileURL(absPnpLoaderPath));
23
+ }
24
+ }
25
+ }
26
+
27
+ const wrapWithUserWrapper = existsSync(absUserWrapperPath)
28
+ ? exports => absRequire(absUserWrapperPath)(exports)
29
+ : exports => exports;
30
+
31
+ // Defer to the real eslint your application uses
32
+ module.exports = wrapWithUserWrapper(absRequire(`eslint`));
package/README.md CHANGED
@@ -9,36 +9,34 @@ 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
22
22
 
23
- Add `"extends": "@thermarthae/eslint-config"` to your ESLint config file.
23
+ An example `eslint.config.js`:
24
24
 
25
- An example `.eslintrc.cjs`:
25
+ **Note**: You may have to set the `tsconfigRootDir` path!
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,137 @@
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
+ indent: 'tab',
8
+ semi: true,
9
+ jsx: false,
10
+ braceStyle: '1tbs',
11
+ quoteProps: 'as-needed',
12
+ });
13
+
14
+ /** @type {typeof import('typescript-eslint').configs.all} */
15
+ const base = [
16
+ //
17
+ // eslint
18
+ //
19
+ eslint.configs.recommended,
20
+ {
21
+ rules: {
22
+ 'object-shorthand': ['error', 'always', { avoidQuotes: true }],
23
+ 'no-duplicate-imports': 'error',
24
+ 'no-param-reassign': ['error', {
25
+ ignorePropertyModificationsFor: [
26
+ 'request',
27
+ 'reply',
28
+ 'session',
29
+ 'state',
30
+ ],
31
+ props: true,
32
+ }],
33
+ 'no-void': ['error', { allowAsStatement: true }],
34
+ yoda: ['error', 'never', { exceptRange: true }],
35
+ },
36
+ },
37
+ //
38
+ // typescript-eslint
39
+ //
40
+ ...tsEslint.configs.recommendedTypeChecked,
41
+ ...tsEslint.configs.stylisticTypeChecked,
42
+ {
43
+ ...tsEslint.configs.disableTypeChecked,
44
+ files: ['*.cjs', '*.js'],
45
+ },
46
+ {
47
+ languageOptions: {
48
+ parserOptions: {
49
+ projectService: true,
50
+ ecmaVersion: 'latest',
51
+ },
52
+ },
53
+ rules: {
54
+ '@typescript-eslint/array-type': ['error', {
55
+ default: 'array-simple',
56
+ }],
57
+ '@typescript-eslint/consistent-type-assertions': ['error', {
58
+ assertionStyle: 'as',
59
+ objectLiteralTypeAssertions: 'allow-as-parameter',
60
+ }],
61
+ '@typescript-eslint/consistent-type-definitions': 0,
62
+ '@typescript-eslint/no-unused-vars': 0,
63
+ '@typescript-eslint/no-empty-function': 0,
64
+ '@typescript-eslint/no-misused-promises': ['error', {
65
+ checksVoidReturn: false,
66
+ }],
67
+ '@typescript-eslint/no-unnecessary-type-arguments': 'warn',
68
+ '@typescript-eslint/no-shadow': 'error',
69
+ '@typescript-eslint/promise-function-async': 'error',
70
+ },
71
+ },
72
+ //
73
+ // stylistic
74
+ //
75
+ {
76
+ // `disable-legacy` without rules that starts with 'react/'
77
+ ...stylistic.configs['disable-legacy'],
78
+ rules: Object.fromEntries(Object.entries(stylistic.configs['disable-legacy'].rules ?? {})
79
+ .filter(r => !r[0].startsWith('react/'))),
80
+ },
81
+ {
82
+ ...stylisticCustomized,
83
+ rules: {
84
+ ...stylisticCustomized.rules,
85
+ '@stylistic/arrow-parens': ['error', 'as-needed', {
86
+ requireForBlockBody: true,
87
+ }],
88
+ '@stylistic/linebreak-style': ['error', 'windows'],
89
+ '@stylistic/max-len': ['error', { code: 120 }],
90
+ '@stylistic/no-multiple-empty-lines': ['error', {
91
+ max: 3,
92
+ maxBOF: 0,
93
+ maxEOF: 1,
94
+ }],
95
+ '@stylistic/max-statements-per-line': 0,
96
+ '@stylistic/indent-binary-ops': 0,
97
+ },
98
+ },
99
+ //
100
+ // simple-import-sort
101
+ //
102
+ {
103
+ plugins: {
104
+ 'simple-import-sort': simpleImportSort,
105
+ },
106
+ rules: {
107
+ 'simple-import-sort/imports': ['warn', {
108
+ groups: [
109
+ // Side effect imports.
110
+ ['^\\u0000'],
111
+ [
112
+ '^node:',
113
+ 'react',
114
+ // Things that start with a letter (or digit or underscore), or `@` followed by a letter.
115
+ '^@?\\w',
116
+ ],
117
+ // Absolute imports and other imports such as Vue-style `@/foo`.
118
+ ['^'],
119
+ [
120
+ // ../whatever/
121
+ '^\\.\\./(?=.*/)',
122
+ // ../
123
+ '^\\.\\./',
124
+ ],
125
+ [
126
+ // ./whatever/
127
+ '^\\./(?=.*/)',
128
+ // ./
129
+ '^\\./',
130
+ ],
131
+ ],
132
+ }],
133
+ },
134
+ },
135
+ ];
136
+
137
+ 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,84 @@
1
+ import react from 'eslint-plugin-react';
2
+ import reactHooks from 'eslint-plugin-react-hooks';
3
+ import stylistic from '@stylistic/eslint-plugin';
4
+ import jsxA11y from 'eslint-plugin-jsx-a11y';
5
+
6
+ import base from './base.js';
7
+
8
+ const stylisticCustomizedWithJSX = stylistic.configs.customize({
9
+ indent: 'tab',
10
+ semi: true,
11
+ jsx: true,
12
+ braceStyle: '1tbs',
13
+ quoteProps: 'as-needed',
14
+ });
15
+
16
+ // all `stylisticCustomizedWithJSX` rules that starts with '@stylistic/jsx'
17
+ const jsxStylisticRules = Object.fromEntries(Object.entries(stylisticCustomizedWithJSX.rules ?? {})
18
+ .filter(r => r[0].startsWith('@stylistic/jsx')));
19
+
20
+ /** @type {typeof import('typescript-eslint').configs.all} */
21
+ const main = [
22
+ ...base,
23
+ //
24
+ // react
25
+ //
26
+ react.configs.flat.recommended,
27
+ react.configs.flat['jsx-runtime'],
28
+ {
29
+ settings: {
30
+ react: {
31
+ version: 'detect',
32
+ },
33
+ },
34
+ rules: {
35
+ 'react/react-in-jsx-scope': 0,
36
+ 'react/no-unknown-property': 0,
37
+ 'react/no-children-prop': 0,
38
+ 'react/prop-types': 0,
39
+ 'react/jsx-boolean-value': ['error', 'never', { always: [] }],
40
+ 'react/void-dom-elements-no-children': 'error',
41
+ 'react/button-has-type': ['error', {
42
+ button: true,
43
+ submit: true,
44
+ reset: false,
45
+ }],
46
+ 'react/jsx-no-useless-fragment': 'error',
47
+ 'react/jsx-no-constructed-context-values': 'error',
48
+ 'react/no-unstable-nested-components': 'error',
49
+ },
50
+ },
51
+ //
52
+ // react-hooks
53
+ //
54
+ reactHooks.configs['recommended-latest'],
55
+ //
56
+ // jsx-a11y
57
+ //
58
+ jsxA11y.flatConfigs.recommended,
59
+ //
60
+ // stylistic
61
+ //
62
+ {
63
+ // all `disable-legacy` rules that starts with 'react/'
64
+ ...stylistic.configs['disable-legacy'],
65
+ rules: Object.fromEntries(Object.entries(stylistic.configs['disable-legacy'].rules ?? {})
66
+ .filter(r => r[0].startsWith('react/'))),
67
+ },
68
+ {
69
+ rules: {
70
+ ...jsxStylisticRules,
71
+ '@stylistic/jsx-closing-bracket-location': ['error', 'line-aligned'],
72
+ '@stylistic/jsx-curly-brace-presence': ['error', {
73
+ props: 'never',
74
+ children: 'never',
75
+ propElementValues: 'always',
76
+ }],
77
+ '@stylistic/jsx-curly-spacing': ['error', 'never', { allowMultiline: true }],
78
+ '@stylistic/jsx-self-closing-comp': 'error',
79
+ '@stylistic/jsx-props-no-multi-spaces': 'error',
80
+ },
81
+ },
82
+ ];
83
+
84
+ export default main;
package/package.json CHANGED
@@ -1,8 +1,20 @@
1
1
  {
2
2
  "name": "@thermarthae/eslint-config",
3
- "version": "4.1.0",
4
- "main": "index.cjs",
3
+ "version": "6.0.0",
4
+ "exports": {
5
+ ".": {
6
+ "types": "./index.d.ts",
7
+ "import": "./index.js",
8
+ "default": "./index.js"
9
+ },
10
+ "./base": {
11
+ "types": "./base.d.ts",
12
+ "import": "./base.js",
13
+ "default": "./base.js"
14
+ }
15
+ },
5
16
  "description": "Just a personal eslint config",
17
+ "type": "module",
6
18
  "license": "MIT",
7
19
  "author": "thermarthae <thermarthae@protonmail.com>",
8
20
  "repository": {
@@ -10,42 +22,40 @@
10
22
  "url": "git+https://github.com/thermarthae/eslint-config.git"
11
23
  },
12
24
  "files": [
13
- "base.cjs",
14
- "index.cjs",
15
- "shared.cjs"
25
+ "base.js",
26
+ "base.d.ts",
27
+ "index.js",
28
+ "index.d.ts"
16
29
  ],
17
- "packageManager": "yarn@4.3.1",
30
+ "packageManager": "yarn@4.9.2+sha512.1fc009bc09d13cfd0e19efa44cbfc2b9cf6ca61482725eb35bbc5e257e093ebf4130db6dfe15d604ff4b79efd8e1e8e99b25fa7d0a6197c9f9826358d4d65c3c",
18
31
  "scripts": {
19
32
  "pnpify": "yarn dlx @yarnpkg/sdks vscode"
20
33
  },
21
- "resolutions": {
22
- "@stylistic/eslint-plugin-plus/@typescript-eslint/utils": "^7.15.0",
23
- "@stylistic/eslint-plugin-ts/@typescript-eslint/utils": "^7.15.0"
24
- },
25
34
  "devDependencies": {
26
- "@stylistic/eslint-plugin": "^2.3.0",
27
- "@typescript-eslint/eslint-plugin": "^7.15.0",
28
- "@typescript-eslint/parser": "^7.15.0",
29
- "eslint": "^8.57.0",
30
- "eslint-plugin-import": "npm:eslint-plugin-i@^2.29.1",
31
- "eslint-plugin-simple-import-sort": "^12.1.0",
32
- "typescript": "^5.5.3"
35
+ "@eslint/js": "^9.29.0",
36
+ "@stylistic/eslint-plugin": "^4.4.1",
37
+ "@types/eslint-plugin-jsx-a11y": "^6.10.0",
38
+ "@types/node": "^24.0.3",
39
+ "eslint": "^9.29.0",
40
+ "eslint-plugin-jsx-a11y": "^6.10.2",
41
+ "eslint-plugin-react": "^7.37.5",
42
+ "eslint-plugin-react-hooks": "^5.2.0",
43
+ "eslint-plugin-simple-import-sort": "^12.1.1",
44
+ "typescript": "^5.8.3",
45
+ "typescript-eslint": "^8.34.1"
33
46
  },
34
47
  "peerDependencies": {
35
- "@stylistic/eslint-plugin": "^1.6.2 || ^2.0.0",
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"
48
+ "@eslint/js": "^9.29.0",
49
+ "@stylistic/eslint-plugin": "^4.4.1 || ^5.0.0",
50
+ "eslint": "^9.29.0",
51
+ "eslint-plugin-jsx-a11y": "^6.10.2",
52
+ "eslint-plugin-react": "^7.37.5",
53
+ "eslint-plugin-react-hooks": "^5.2.0",
54
+ "eslint-plugin-simple-import-sort": "^12.1.1",
55
+ "typescript": "^5.8.3",
56
+ "typescript-eslint": "^8.34.1"
44
57
  },
45
58
  "peerDependenciesMeta": {
46
- "eslint-config-prettier": {
47
- "optional": true
48
- },
49
59
  "eslint-plugin-jsx-a11y": {
50
60
  "optional": true
51
61
  },
package/base.cjs DELETED
@@ -1,5 +0,0 @@
1
- module.exports = {
2
- extends: [
3
- './shared.cjs',
4
- ],
5
- };
package/index.cjs DELETED
@@ -1,55 +0,0 @@
1
- const stylistic = require('@stylistic/eslint-plugin');
2
-
3
- const customized = stylistic.configs.customize({
4
- indent: 'tab',
5
- semi: true,
6
- jsx: true,
7
- braceStyle: '1tbs',
8
- quoteProps: 'as-needed',
9
- });
10
-
11
- const jsxStylisticRules = Object.fromEntries(Object.entries(customized.rules ?? {})
12
- .filter(r => r[0].startsWith('@stylistic/jsx')));
13
-
14
- module.exports = {
15
- extends: [
16
- './shared.cjs',
17
- 'plugin:react/recommended',
18
- 'plugin:react/jsx-runtime',
19
- 'plugin:react-hooks/recommended',
20
- 'plugin:jsx-a11y/recommended',
21
- 'plugin:@stylistic/disable-legacy',
22
- ],
23
- plugins: ['jsx-a11y'],
24
- settings: {
25
- react: {
26
- version: 'detect',
27
- },
28
- },
29
- rules: {
30
- ...jsxStylisticRules,
31
- '@stylistic/jsx-closing-bracket-location': ['error', 'line-aligned'],
32
- '@stylistic/jsx-curly-brace-presence': ['error', {
33
- props: 'never',
34
- children: 'never',
35
- propElementValues: 'always',
36
- }],
37
- '@stylistic/jsx-curly-spacing': ['error', 'never', { allowMultiline: true }],
38
- '@stylistic/jsx-self-closing-comp': 'error',
39
- '@stylistic/jsx-props-no-multi-spaces': 'error',
40
- //
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
- };
package/shared.cjs DELETED
@@ -1,128 +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
- 'object-shorthand': ['error', 'always', { avoidQuotes: true }],
116
- 'no-param-reassign': ['error', {
117
- ignorePropertyModificationsFor: [
118
- 'request',
119
- 'reply',
120
- 'session',
121
- 'state',
122
- ],
123
- props: true,
124
- }],
125
- 'no-void': ['error', { allowAsStatement: true }],
126
- yoda: ['error', 'never', { exceptRange: true }],
127
- },
128
- };