@todoist/eslint-config 0.0.0-stage → 13.1.2
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/CHANGELOG.md +144 -0
- package/README.md +116 -2
- package/eslintrc/index.js +3 -0
- package/eslintrc/react.js +34 -0
- package/eslintrc/recommended-type-checked.js +12 -0
- package/eslintrc/recommended.js +63 -0
- package/eslintrc/simple-import-sort.js +9 -0
- package/flat/react.js +42 -0
- package/flat/recommended-type-checked.js +23 -0
- package/flat/recommended.js +80 -0
- package/flat/simple-import-sort.js +14 -0
- package/index.d.ts +11 -0
- package/index.js +21 -0
- package/lib/create-simple-import-sort-config.js +53 -0
- package/package.json +62 -5
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# 13.1.2
|
|
2
|
+
|
|
3
|
+
- Publish as `@todoist/eslint-config`, retaining CommonJS and flat/eslintrc entrypoints.
|
|
4
|
+
- Use `@todoist/eslint-plugin-doist@2.0.2` with the `@todoist/doist` rule namespace and ESLint 8.57/9 support.
|
|
5
|
+
- Require Node 24.10 or later to match the plugin's current toolchain policy.
|
|
6
|
+
- Group current and legacy package scopes together when sorting imports.
|
|
7
|
+
- Retain one release artifact for public npm publication and the private GitHub mirror.
|
|
8
|
+
|
|
9
|
+
# 13.0.0
|
|
10
|
+
|
|
11
|
+
- Add flat config support
|
|
12
|
+
- Move .eslintrc to `@doist/eslint-config/eslintrc`
|
|
13
|
+
|
|
14
|
+
See README.md for configuration guidance.
|
|
15
|
+
|
|
16
|
+
# 12.0.1
|
|
17
|
+
|
|
18
|
+
- Enable trusted publishing and npm provenance
|
|
19
|
+
|
|
20
|
+
# 12.0.0
|
|
21
|
+
|
|
22
|
+
- Update `eslint-plugin-react-hooks` to v7.0.1
|
|
23
|
+
|
|
24
|
+
# 11.2.1
|
|
25
|
+
|
|
26
|
+
- Update ESLint rule from `@typescript-eslint/no-throw-literal` to `@typescript-eslint/only-throw-error`
|
|
27
|
+
|
|
28
|
+
# 11.2.0
|
|
29
|
+
|
|
30
|
+
- Add support for typescript-eslint v7 and 8
|
|
31
|
+
|
|
32
|
+
# 11.1.0
|
|
33
|
+
|
|
34
|
+
- Add support for latest `eslint-plugin-simple-import-sort` v12
|
|
35
|
+
|
|
36
|
+
# 11.0.0
|
|
37
|
+
|
|
38
|
+
- Update `@doist/prettier-config` to v4, and drops support for ESLint v7.
|
|
39
|
+
|
|
40
|
+
# 10.0.0
|
|
41
|
+
|
|
42
|
+
- Update the `@typescript-eslint/*` dependencies to v6. This is a breaking change as it requires changing from `recommended-requiring-type-checking` to `recommended-type-checked`. This keeps the package inline with the @typescript-eslint team's naming.
|
|
43
|
+
|
|
44
|
+
# 9.0.0
|
|
45
|
+
|
|
46
|
+
- This change sorts our side effects so that all external dependencies, including css, are imported before our own internal modules.
|
|
47
|
+
|
|
48
|
+
# 8.1.3
|
|
49
|
+
|
|
50
|
+
- Move [eslint-plugin-doist](https://github.com/Doist/eslint-plugin-doist) to dependencies.
|
|
51
|
+
|
|
52
|
+
# 8.1.2
|
|
53
|
+
|
|
54
|
+
- Move [eslint-plugin-doist](https://github.com/Doist/eslint-plugin-doist) to peerDependencies.
|
|
55
|
+
|
|
56
|
+
# 8.1.1
|
|
57
|
+
|
|
58
|
+
- Recommend `gettext-literal-arg`, `import-file-naming` and `static-path-literal-arg` from [eslint-plugin-doist](https://github.com/Doist/eslint-plugin-doist).
|
|
59
|
+
|
|
60
|
+
# 8.0.1
|
|
61
|
+
|
|
62
|
+
- Allow expressions for `react/jsx-no-useless-fragment` ([#120](https://github.com/Doist/eslint-config/pull/120))
|
|
63
|
+
|
|
64
|
+
# 8.0.0
|
|
65
|
+
|
|
66
|
+
- Restrict default and wildcard React imports ([#119](https://github.com/Doist/eslint-config/pull/119))
|
|
67
|
+
|
|
68
|
+
# 7.5.0
|
|
69
|
+
|
|
70
|
+
- _Nothing changed. Trying to fix deploy process._
|
|
71
|
+
|
|
72
|
+
# 7.4.0
|
|
73
|
+
|
|
74
|
+
- _Nothing changed. Trying to fix deploy process._
|
|
75
|
+
|
|
76
|
+
# 7.3.0
|
|
77
|
+
|
|
78
|
+
- _Nothing changed. Trying to fix deploy process._
|
|
79
|
+
|
|
80
|
+
# 7.2.0
|
|
81
|
+
|
|
82
|
+
- Add support for `eslint-plugin-simple-import-sort@8`
|
|
83
|
+
|
|
84
|
+
# 7.1.2
|
|
85
|
+
|
|
86
|
+
- Fixes to work with eslint-config-prettier 8.x.
|
|
87
|
+
|
|
88
|
+
# 7.1.1
|
|
89
|
+
|
|
90
|
+
- Add support for Eslint 8 ([#111](https://github.com/Doist/eslint-config/pull/111))
|
|
91
|
+
- Add `@typescript-eslint/no-useless-constructor` ([#107](https://github.com/Doist/eslint-config/pull/107))
|
|
92
|
+
|
|
93
|
+
# 7.1.0
|
|
94
|
+
|
|
95
|
+
- Add optional configuration with `eslint-plugin-simple-import-sort` ([#106](https://github.com/Doist/eslint-config/pull/106))
|
|
96
|
+
- Update most dependencies to current versions ([#105](https://github.com/Doist/eslint-config/pull/105))
|
|
97
|
+
|
|
98
|
+
# 7.0.0
|
|
99
|
+
|
|
100
|
+
- Add rule `no-useless-return` ([#101](https://github.com/Doist/eslint-config/pull/101))
|
|
101
|
+
- Ignore unused vars prefixed with `_`. ([#99](https://github.com/Doist/eslint-config/pull/99))
|
|
102
|
+
|
|
103
|
+
# 6.0.2
|
|
104
|
+
|
|
105
|
+
- Publish to public npm registry.
|
|
106
|
+
|
|
107
|
+
# 6.0.1
|
|
108
|
+
|
|
109
|
+
- Fix: move `@typescript-eslint/no-implicit-any-catch` to rule to `recommended-requiring-type-checking` config.
|
|
110
|
+
|
|
111
|
+
# 6.0.0
|
|
112
|
+
|
|
113
|
+
- Add [@typescript-eslint/no-implicit-any-catch](https://github.com/Doist/eslint-config/pull/88)
|
|
114
|
+
- Add [no-implicit-coercion](https://github.com/Doist/eslint-config/pull/87)
|
|
115
|
+
|
|
116
|
+
# 5.0.1
|
|
117
|
+
|
|
118
|
+
- Fix: move `no-throw-literal` to rule to `recommended-requiring-type-checking` config.
|
|
119
|
+
|
|
120
|
+
# 5.0.0
|
|
121
|
+
|
|
122
|
+
- Add [no-throw-literal](https://github.com/Doist/eslint-config/pull/82)
|
|
123
|
+
- Add [react/no-unstable-nested-components](https://github.com/Doist/eslint-config/pull/81)
|
|
124
|
+
- Add [react/self-closing-comp](https://github.com/Doist/eslint-config/pull/77)
|
|
125
|
+
- Add [@typescript-eslint/prefer-reduce-type-parameter](https://github.com/Doist/eslint-config/pull/73)
|
|
126
|
+
|
|
127
|
+
# 4.0.0
|
|
128
|
+
|
|
129
|
+
- [Updated peer dependencies](https://github.com/Doist/eslint-config/pull/68)
|
|
130
|
+
- Add [consistent-type-assertions `as`](https://github.com/Doist/eslint-config/pull/67)
|
|
131
|
+
- Add [prefer-optional-chain](https://github.com/Doist/eslint-config/pull/64)
|
|
132
|
+
- Add [prefer-stateless-function](https://github.com/Doist/eslint-config/pull/63)
|
|
133
|
+
- Add [no-unused-expressions](https://github.com/Doist/eslint-config/pull/58)
|
|
134
|
+
- Add [no-void](https://github.com/Doist/eslint-config/pull/57)
|
|
135
|
+
|
|
136
|
+
# 3.0.0
|
|
137
|
+
|
|
138
|
+
- Add [array-callback-return](https://github.com/Doist/eslint-config/pull/45) rule.
|
|
139
|
+
- Add [import/first](https://github.com/Doist/eslint-config/issues/43) rule.
|
|
140
|
+
- Add [import/no-default-export](https://github.com/Doist/eslint-config/issues/41) rule.
|
|
141
|
+
|
|
142
|
+
# 2.0.0
|
|
143
|
+
|
|
144
|
+
- First stable release.
|
package/README.md
CHANGED
|
@@ -1,3 +1,117 @@
|
|
|
1
|
-
#
|
|
1
|
+
# `@todoist/eslint-config`
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Doist [ESLint](https://eslint.org) config.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
### Install
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
npm install --save-dev @todoist/eslint-config
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Requires Node.js **24.10 or later**, ESLint **8.57 or 9**, and the declared plugin peers.
|
|
14
|
+
The current-forward `@todoist/eslint-plugin-doist@2.0.2` retains all three rules in
|
|
15
|
+
both configuration formats. Import sorting groups `@todoist` and legacy `@doist`
|
|
16
|
+
packages together during migration.
|
|
17
|
+
|
|
18
|
+
### Flat Config
|
|
19
|
+
|
|
20
|
+
```js
|
|
21
|
+
// eslint.config.js
|
|
22
|
+
import eslintConfig from '@todoist/eslint-config'
|
|
23
|
+
|
|
24
|
+
export default [
|
|
25
|
+
// Core set of rules, recommended for all JS projects
|
|
26
|
+
...eslintConfig.recommended,
|
|
27
|
+
// OR
|
|
28
|
+
// Core set of rules, recommended for all TS projects
|
|
29
|
+
...eslintConfig.recommendedTypeChecked,
|
|
30
|
+
|
|
31
|
+
// Additional rules for sorting/grouping import statements (optional)
|
|
32
|
+
...eslintConfig.simpleImportSort,
|
|
33
|
+
|
|
34
|
+
// Recommended for projects using React.
|
|
35
|
+
...eslintConfig.react,
|
|
36
|
+
]
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### .eslintrc Config (Legacy)
|
|
40
|
+
|
|
41
|
+
In `.eslintrc`:
|
|
42
|
+
|
|
43
|
+
```jsonc
|
|
44
|
+
{
|
|
45
|
+
// ...
|
|
46
|
+
"extends": [
|
|
47
|
+
// ...
|
|
48
|
+
|
|
49
|
+
// Core set of rules, recommended for all projects.
|
|
50
|
+
"@todoist/eslint-config/eslintrc/recommended",
|
|
51
|
+
|
|
52
|
+
// Additional rules requiring type information (recommended for TypeScript projects).
|
|
53
|
+
"@todoist/eslint-config/eslintrc/recommended-type-checked",
|
|
54
|
+
|
|
55
|
+
// Additional rules for sorting/grouping import statements (optional)
|
|
56
|
+
"@todoist/eslint-config/eslintrc/simple-import-sort",
|
|
57
|
+
|
|
58
|
+
// Recommended for projects using React.
|
|
59
|
+
"@todoist/eslint-config/eslintrc/react",
|
|
60
|
+
],
|
|
61
|
+
|
|
62
|
+
// When using `recommended-type-checked`,
|
|
63
|
+
// you need to link to `tsconfig.eslint.json` file (see section below) for the project.
|
|
64
|
+
"parserOptions": {
|
|
65
|
+
"project": "tsconfig.eslint.json",
|
|
66
|
+
},
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Path alias support for import sorting
|
|
71
|
+
|
|
72
|
+
If your project uses path aliases (e.g. `@components` maps to `src/components/`), you can configure `simple-import-sort` to group them together, between third-party and relative imports, by using `simpleImportSortFactory`.
|
|
73
|
+
|
|
74
|
+
**Flat config:**
|
|
75
|
+
|
|
76
|
+
```js
|
|
77
|
+
// eslint.config.js
|
|
78
|
+
import eslintConfig from '@todoist/eslint-config'
|
|
79
|
+
|
|
80
|
+
export default [
|
|
81
|
+
...eslintConfig.recommended,
|
|
82
|
+
// Replace ...eslintConfig.simpleImportSort with a custom config:
|
|
83
|
+
...eslintConfig.simpleImportSortFactory({ aliases: ['@app', '@components'] }),
|
|
84
|
+
]
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
**Legacy config** — override the rule in `.eslintrc`:
|
|
88
|
+
|
|
89
|
+
```js
|
|
90
|
+
const config = {
|
|
91
|
+
extends: ['@todoist/eslint-config/eslintrc/simple-import-sort'],
|
|
92
|
+
rules: {
|
|
93
|
+
'simple-import-sort/imports':
|
|
94
|
+
require('@todoist/eslint-config/lib/create-simple-import-sort-config').createSimpleImportSortConfig(
|
|
95
|
+
{ aliases: ['@app', '@components'] },
|
|
96
|
+
),
|
|
97
|
+
},
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Aliases are grouped together (no blank lines between them), ordered by their position in the array.
|
|
102
|
+
|
|
103
|
+
### Configuring with type-checking
|
|
104
|
+
|
|
105
|
+
For type-based rules to work, project's `tsconfig.json` file needs to be specified in `parserOptions.project`. If you want to lint files not included in build, we recommend
|
|
106
|
+
creating a separate `tsconfig.eslint.json` config and specifying it instead of the default one.
|
|
107
|
+
|
|
108
|
+
Note: In flat config, `recommendedTypeChecked` sets `project: true` by default, which auto-detects `tsconfig.json`.
|
|
109
|
+
|
|
110
|
+
## Releasing
|
|
111
|
+
|
|
112
|
+
See [the release runbook](docs/releasing.md) for the pack-only first release,
|
|
113
|
+
registry setup, and retrying a missing mirror with the same artifact.
|
|
114
|
+
|
|
115
|
+
## Links
|
|
116
|
+
|
|
117
|
+
- [ESLint shareable configs](https://eslint.org/docs/developer-guide/shareable-configs)
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
plugins: ['react', 'react-hooks'],
|
|
3
|
+
extends: [
|
|
4
|
+
'plugin:react/recommended',
|
|
5
|
+
'plugin:react-hooks/recommended',
|
|
6
|
+
'prettier',
|
|
7
|
+
],
|
|
8
|
+
rules: {
|
|
9
|
+
'react/no-did-mount-set-state': 'error',
|
|
10
|
+
'react/no-did-update-set-state': 'error',
|
|
11
|
+
'react/prefer-stateless-function': 'error',
|
|
12
|
+
'react/prop-types': ['error', { skipUndeclared: true }],
|
|
13
|
+
'react/self-closing-comp': 'error',
|
|
14
|
+
'react/no-unstable-nested-components': 'error',
|
|
15
|
+
'react/jsx-no-useless-fragment': [
|
|
16
|
+
'error',
|
|
17
|
+
{
|
|
18
|
+
allowExpressions: true,
|
|
19
|
+
},
|
|
20
|
+
],
|
|
21
|
+
'no-restricted-imports': [
|
|
22
|
+
'error',
|
|
23
|
+
{
|
|
24
|
+
paths: [
|
|
25
|
+
{
|
|
26
|
+
name: 'react',
|
|
27
|
+
importNames: ['*', 'default'],
|
|
28
|
+
message: 'Please use named imports instead.',
|
|
29
|
+
},
|
|
30
|
+
],
|
|
31
|
+
},
|
|
32
|
+
],
|
|
33
|
+
},
|
|
34
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
extends: ['./recommended', 'plugin:@typescript-eslint/recommended-type-checked'],
|
|
3
|
+
rules: {
|
|
4
|
+
'@typescript-eslint/prefer-includes': 'error',
|
|
5
|
+
'@typescript-eslint/prefer-string-starts-ends-with': 'error',
|
|
6
|
+
'@typescript-eslint/prefer-reduce-type-parameter': 'error',
|
|
7
|
+
'no-throw-literal': 'off',
|
|
8
|
+
'@typescript-eslint/only-throw-error': ['error'],
|
|
9
|
+
'@typescript-eslint/no-duplicate-type-constituents': 'off',
|
|
10
|
+
'@typescript-eslint/no-redundant-type-constituents': 'off'
|
|
11
|
+
},
|
|
12
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
parser: '@typescript-eslint/parser',
|
|
3
|
+
plugins: ['import', '@typescript-eslint', '@todoist/doist'],
|
|
4
|
+
extends: [
|
|
5
|
+
'eslint:recommended',
|
|
6
|
+
'plugin:prettier/recommended',
|
|
7
|
+
|
|
8
|
+
'plugin:import/recommended',
|
|
9
|
+
'plugin:import/typescript',
|
|
10
|
+
|
|
11
|
+
'plugin:@typescript-eslint/recommended',
|
|
12
|
+
'prettier',
|
|
13
|
+
],
|
|
14
|
+
rules: {
|
|
15
|
+
'array-callback-return': 'error',
|
|
16
|
+
eqeqeq: ['error', 'smart'],
|
|
17
|
+
'func-style': ['error', 'declaration'],
|
|
18
|
+
'no-console': 'error',
|
|
19
|
+
'no-implicit-coercion': 'error',
|
|
20
|
+
'no-unused-expressions': 'error',
|
|
21
|
+
'no-unused-vars': 'off', // Disabled because of @typescript-eslint/no-unused-vars, see: https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-unused-vars.md#how-to-use
|
|
22
|
+
'@typescript-eslint/no-unused-vars': [
|
|
23
|
+
'error',
|
|
24
|
+
{ argsIgnorePattern: '^_', ignoreRestSiblings: true },
|
|
25
|
+
],
|
|
26
|
+
'no-use-before-define': 'off', // See: https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-use-before-define.md#how-to-use
|
|
27
|
+
'@typescript-eslint/no-use-before-define': ['error', { functions: false }],
|
|
28
|
+
'no-useless-constructor': 'off', // See: https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/docs/rules/no-useless-constructor.md#how-to-use
|
|
29
|
+
'@typescript-eslint/no-useless-constructor': 'error',
|
|
30
|
+
'@typescript-eslint/prefer-optional-chain': 'error',
|
|
31
|
+
'@typescript-eslint/consistent-type-assertions': [
|
|
32
|
+
'error',
|
|
33
|
+
{ assertionStyle: 'as', objectLiteralTypeAssertions: 'allow' },
|
|
34
|
+
],
|
|
35
|
+
'no-useless-return': 'error',
|
|
36
|
+
'no-var': 'error',
|
|
37
|
+
'no-void': 'error',
|
|
38
|
+
'prefer-promise-reject-errors': 'error',
|
|
39
|
+
|
|
40
|
+
// eslint-config-prettier
|
|
41
|
+
// ref.: https://github.com/prettier/eslint-config-prettier/blob/main/README.md#example-single-quote-configuration
|
|
42
|
+
quotes: ['error', 'single', { avoidEscape: true, allowTemplateLiterals: false }],
|
|
43
|
+
|
|
44
|
+
// eslint-plugin-import
|
|
45
|
+
'import/first': 'error',
|
|
46
|
+
'import/newline-after-import': 'error',
|
|
47
|
+
'import/no-named-as-default': 'error',
|
|
48
|
+
'import/no-named-as-default-member': 'error',
|
|
49
|
+
'import/no-duplicates': 'error',
|
|
50
|
+
'import/no-default-export': 'error',
|
|
51
|
+
|
|
52
|
+
// eslint-plugin-doist
|
|
53
|
+
'@todoist/doist/gettext-literal-arg': 'error',
|
|
54
|
+
'@todoist/doist/static-path-literal-arg': 'error',
|
|
55
|
+
'@todoist/doist/import-file-naming': [
|
|
56
|
+
'error',
|
|
57
|
+
{
|
|
58
|
+
camelcase: ['jpg', 'png', 'mp4'],
|
|
59
|
+
pascalcase: ['svg'],
|
|
60
|
+
},
|
|
61
|
+
],
|
|
62
|
+
},
|
|
63
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
const { createSimpleImportSortConfig } = require('../lib/create-simple-import-sort-config')
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
plugins: ['simple-import-sort'],
|
|
5
|
+
rules: {
|
|
6
|
+
'simple-import-sort/imports': createSimpleImportSortConfig(),
|
|
7
|
+
'simple-import-sort/exports': 'warn',
|
|
8
|
+
},
|
|
9
|
+
}
|
package/flat/react.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
const react = require('eslint-plugin-react')
|
|
2
|
+
const reactHooks = require('eslint-plugin-react-hooks')
|
|
3
|
+
const prettier = require('eslint-config-prettier/flat')
|
|
4
|
+
|
|
5
|
+
module.exports = [
|
|
6
|
+
react.configs.flat.recommended,
|
|
7
|
+
reactHooks.configs.flat["recommended-latest"],
|
|
8
|
+
prettier,
|
|
9
|
+
{
|
|
10
|
+
settings: {
|
|
11
|
+
react: {
|
|
12
|
+
version: 'detect',
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
rules: {
|
|
16
|
+
'react/no-did-mount-set-state': 'error',
|
|
17
|
+
'react/no-did-update-set-state': 'error',
|
|
18
|
+
'react/prefer-stateless-function': 'error',
|
|
19
|
+
'react/prop-types': ['error', { skipUndeclared: true }],
|
|
20
|
+
'react/self-closing-comp': 'error',
|
|
21
|
+
'react/no-unstable-nested-components': 'error',
|
|
22
|
+
'react/jsx-no-useless-fragment': [
|
|
23
|
+
'error',
|
|
24
|
+
{
|
|
25
|
+
allowExpressions: true,
|
|
26
|
+
},
|
|
27
|
+
],
|
|
28
|
+
'no-restricted-imports': [
|
|
29
|
+
'error',
|
|
30
|
+
{
|
|
31
|
+
paths: [
|
|
32
|
+
{
|
|
33
|
+
name: 'react',
|
|
34
|
+
importNames: ['*', 'default'],
|
|
35
|
+
message: 'Please use named imports instead.',
|
|
36
|
+
},
|
|
37
|
+
],
|
|
38
|
+
},
|
|
39
|
+
],
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
]
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
const tseslint = require('typescript-eslint')
|
|
2
|
+
const recommended = require('./recommended')
|
|
3
|
+
|
|
4
|
+
module.exports = [
|
|
5
|
+
...recommended,
|
|
6
|
+
...tseslint.configs.recommendedTypeChecked,
|
|
7
|
+
{
|
|
8
|
+
languageOptions: {
|
|
9
|
+
parserOptions: {
|
|
10
|
+
project: true,
|
|
11
|
+
},
|
|
12
|
+
},
|
|
13
|
+
rules: {
|
|
14
|
+
'@typescript-eslint/prefer-includes': 'error',
|
|
15
|
+
'@typescript-eslint/prefer-string-starts-ends-with': 'error',
|
|
16
|
+
'@typescript-eslint/prefer-reduce-type-parameter': 'error',
|
|
17
|
+
'no-throw-literal': 'off',
|
|
18
|
+
'@typescript-eslint/only-throw-error': ['error'],
|
|
19
|
+
'@typescript-eslint/no-duplicate-type-constituents': 'off',
|
|
20
|
+
'@typescript-eslint/no-redundant-type-constituents': 'off',
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
]
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
const eslint = require('@eslint/js')
|
|
2
|
+
const tseslint = require('typescript-eslint')
|
|
3
|
+
const importPlugin = require('eslint-plugin-import')
|
|
4
|
+
const prettierConfig = require('eslint-config-prettier')
|
|
5
|
+
const doistPlugin = require('@todoist/eslint-plugin-doist')
|
|
6
|
+
const globals = require('globals')
|
|
7
|
+
|
|
8
|
+
module.exports = [
|
|
9
|
+
eslint.configs.recommended,
|
|
10
|
+
...tseslint.configs.recommended,
|
|
11
|
+
importPlugin.flatConfigs.recommended,
|
|
12
|
+
importPlugin.flatConfigs.typescript,
|
|
13
|
+
prettierConfig,
|
|
14
|
+
{
|
|
15
|
+
plugins: {
|
|
16
|
+
'@todoist/doist': doistPlugin,
|
|
17
|
+
},
|
|
18
|
+
languageOptions: {
|
|
19
|
+
parser: tseslint.parser,
|
|
20
|
+
globals: {
|
|
21
|
+
...globals.browser,
|
|
22
|
+
...globals.node,
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
settings: {
|
|
26
|
+
'import/resolver': {
|
|
27
|
+
typescript: true,
|
|
28
|
+
node: true,
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
rules: {
|
|
32
|
+
'array-callback-return': 'error',
|
|
33
|
+
eqeqeq: ['error', 'smart'],
|
|
34
|
+
'func-style': ['error', 'declaration'],
|
|
35
|
+
'no-console': 'error',
|
|
36
|
+
'no-implicit-coercion': 'error',
|
|
37
|
+
'no-unused-expressions': 'error',
|
|
38
|
+
'no-unused-vars': 'off',
|
|
39
|
+
'@typescript-eslint/no-unused-vars': [
|
|
40
|
+
'error',
|
|
41
|
+
{ argsIgnorePattern: '^_', ignoreRestSiblings: true },
|
|
42
|
+
],
|
|
43
|
+
'no-use-before-define': 'off',
|
|
44
|
+
'@typescript-eslint/no-use-before-define': ['error', { functions: false }],
|
|
45
|
+
'no-useless-constructor': 'off',
|
|
46
|
+
'@typescript-eslint/no-useless-constructor': 'error',
|
|
47
|
+
'@typescript-eslint/prefer-optional-chain': 'error',
|
|
48
|
+
'@typescript-eslint/consistent-type-assertions': [
|
|
49
|
+
'error',
|
|
50
|
+
{ assertionStyle: 'as', objectLiteralTypeAssertions: 'allow' },
|
|
51
|
+
],
|
|
52
|
+
'no-useless-return': 'error',
|
|
53
|
+
'no-var': 'error',
|
|
54
|
+
'no-void': 'error',
|
|
55
|
+
'prefer-promise-reject-errors': 'error',
|
|
56
|
+
|
|
57
|
+
// eslint-config-prettier
|
|
58
|
+
quotes: ['error', 'single', { avoidEscape: true, allowTemplateLiterals: false }],
|
|
59
|
+
|
|
60
|
+
// eslint-plugin-import
|
|
61
|
+
'import/first': 'error',
|
|
62
|
+
'import/newline-after-import': 'error',
|
|
63
|
+
'import/no-named-as-default': 'error',
|
|
64
|
+
'import/no-named-as-default-member': 'error',
|
|
65
|
+
'import/no-duplicates': 'error',
|
|
66
|
+
'import/no-default-export': 'error',
|
|
67
|
+
|
|
68
|
+
// eslint-plugin-doist
|
|
69
|
+
'@todoist/doist/gettext-literal-arg': 'error',
|
|
70
|
+
'@todoist/doist/static-path-literal-arg': 'error',
|
|
71
|
+
'@todoist/doist/import-file-naming': [
|
|
72
|
+
'error',
|
|
73
|
+
{
|
|
74
|
+
camelcase: ['jpg', 'png', 'mp4'],
|
|
75
|
+
pascalcase: ['svg'],
|
|
76
|
+
},
|
|
77
|
+
],
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
]
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
const simpleImportSort = require('eslint-plugin-simple-import-sort')
|
|
2
|
+
const { createSimpleImportSortConfig } = require('../lib/create-simple-import-sort-config')
|
|
3
|
+
|
|
4
|
+
module.exports = [
|
|
5
|
+
{
|
|
6
|
+
plugins: {
|
|
7
|
+
'simple-import-sort': simpleImportSort,
|
|
8
|
+
},
|
|
9
|
+
rules: {
|
|
10
|
+
'simple-import-sort/imports': createSimpleImportSortConfig(),
|
|
11
|
+
'simple-import-sort/exports': 'warn',
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
]
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Linter } from 'eslint'
|
|
2
|
+
|
|
3
|
+
declare const config: {
|
|
4
|
+
recommended: Linter.Config[]
|
|
5
|
+
recommendedTypeChecked: Linter.Config[]
|
|
6
|
+
react: Linter.Config[]
|
|
7
|
+
simpleImportSort: Linter.Config[]
|
|
8
|
+
simpleImportSortFactory: (options?: { aliases?: string[] }) => Linter.Config[]
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export = config
|
package/index.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const simpleImportSortPlugin = require('eslint-plugin-simple-import-sort')
|
|
2
|
+
const { createSimpleImportSortConfig } = require('./lib/create-simple-import-sort-config')
|
|
3
|
+
|
|
4
|
+
module.exports = {
|
|
5
|
+
recommended: require('./flat/recommended'),
|
|
6
|
+
recommendedTypeChecked: require('./flat/recommended-type-checked'),
|
|
7
|
+
react: require('./flat/react'),
|
|
8
|
+
simpleImportSort: require('./flat/simple-import-sort'),
|
|
9
|
+
/** @param {Parameters<typeof createSimpleImportSortConfig>[0]} options */
|
|
10
|
+
simpleImportSortFactory(options) {
|
|
11
|
+
return [
|
|
12
|
+
{
|
|
13
|
+
plugins: { 'simple-import-sort': simpleImportSortPlugin },
|
|
14
|
+
rules: {
|
|
15
|
+
'simple-import-sort/imports': createSimpleImportSortConfig(options),
|
|
16
|
+
'simple-import-sort/exports': 'warn',
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
]
|
|
20
|
+
},
|
|
21
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generates simple-import-sort groups with optional alias support.
|
|
3
|
+
* Aliases share a single group (no blank lines between them), ordered by their
|
|
4
|
+
* position in the array, placed between third-party and relative imports.
|
|
5
|
+
*
|
|
6
|
+
* @param { object } [options]
|
|
7
|
+
* @param { string[] } [options.aliases] - Ordered array of alias prefixes (e.g. ['@app', '@pages', '@state'])
|
|
8
|
+
* @returns {import('eslint').Linter.RuleLevelAndOptions} The rule value for 'simple-import-sort/imports'
|
|
9
|
+
*/
|
|
10
|
+
function createSimpleImportSortConfig({ aliases = [] } = {}) {
|
|
11
|
+
const aliasGroup = aliases.map((a) => `^${a}(/|$)`)
|
|
12
|
+
|
|
13
|
+
const aliasNames = aliases
|
|
14
|
+
.filter((a) => a.startsWith('@'))
|
|
15
|
+
.map((a) => a.slice(1).replace(/[.*+?^${}()|[\]\\]/g, '\\$&'))
|
|
16
|
+
const scopedThirdParty =
|
|
17
|
+
aliasNames.length > 0 ? `^@(?!(${aliasNames.join('|')})(/|$))\\w` : '^@\\w'
|
|
18
|
+
|
|
19
|
+
const groups = [
|
|
20
|
+
// Node.js builtins (supports both 'fs' and 'node:fs')
|
|
21
|
+
[`^(node:)?(${require('module').builtinModules.join('|')})(/|$)`],
|
|
22
|
+
// Third-party modules (side effects)
|
|
23
|
+
['^\\u0000@?\\w'],
|
|
24
|
+
// Current and legacy Doist stylesheets (side effects)
|
|
25
|
+
['^\\u0000@(todoist|doist)/.*\\.(s?css|less)$'],
|
|
26
|
+
// Third-party stylesheets (side effects)
|
|
27
|
+
['^\\u0000@?\\w.*\\.(s?css|less)$'],
|
|
28
|
+
// Internal modules (side effects)
|
|
29
|
+
['^\\u0000\\..*'],
|
|
30
|
+
// Internal stylesheets (side effects)
|
|
31
|
+
['^\\u0000\\..*\\.(s?css|less)$'],
|
|
32
|
+
// React and related modules
|
|
33
|
+
['^react'],
|
|
34
|
+
// Current and legacy Doist modules
|
|
35
|
+
['^@(todoist|doist)/'],
|
|
36
|
+
// Third-party modules (excluding aliases)
|
|
37
|
+
[scopedThirdParty, '^\\w'],
|
|
38
|
+
// Aliases (ordered)
|
|
39
|
+
...(aliasGroup.length > 0 ? [aliasGroup] : []),
|
|
40
|
+
// Internal parent-level modules
|
|
41
|
+
['^\\.\\.(?!/?$)', '^\\.\\./?$'],
|
|
42
|
+
// Internal same-level modules
|
|
43
|
+
['^\\./(?=.*/)(?!/?$)', '^\\.(?!/?$)', '^\\./?$'],
|
|
44
|
+
// Internal CSS Modules
|
|
45
|
+
['^.*\\.module\\.css$'],
|
|
46
|
+
// Internal type imports as a separate group
|
|
47
|
+
['^@?\\w.*\\u0000$', '^[^.].*\\u0000$', '^\\..*\\u0000$'],
|
|
48
|
+
]
|
|
49
|
+
|
|
50
|
+
return ['warn', { groups }]
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
module.exports = { createSimpleImportSortConfig }
|
package/package.json
CHANGED
|
@@ -1,6 +1,63 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
"name": "@todoist/eslint-config",
|
|
3
|
+
"version": "13.1.2",
|
|
4
|
+
"description": "Doist global [eslint](https://eslint.org) config.",
|
|
5
|
+
"repository": "https://github.com/todoist/eslint-config",
|
|
6
|
+
"main": "index.js",
|
|
7
|
+
"types": "index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": "./index.js",
|
|
10
|
+
"./eslintrc": "./eslintrc/index.js",
|
|
11
|
+
"./eslintrc/*": "./eslintrc/*.js",
|
|
12
|
+
"./lib/*": "./lib/*.js"
|
|
13
|
+
},
|
|
14
|
+
"author": "David Miotti <davidm@doist.com>",
|
|
15
|
+
"license": "MIT",
|
|
16
|
+
"prettier": "@todoist/prettier-config",
|
|
17
|
+
"engines": {
|
|
18
|
+
"node": ">=24.10.0"
|
|
19
|
+
},
|
|
20
|
+
"peerDependencies": {
|
|
21
|
+
"@typescript-eslint/eslint-plugin": "^6.0.0 || ^7.0.0 || ^8.0.0",
|
|
22
|
+
"@typescript-eslint/parser": "^6.0.0 || ^7.0.0 || ^8.0.0",
|
|
23
|
+
"eslint": "^8.57.0 || ^9.0.0",
|
|
24
|
+
"eslint-plugin-import": "^2.29.0",
|
|
25
|
+
"eslint-plugin-prettier": "^5.0.0",
|
|
26
|
+
"eslint-plugin-react": "^7.29.4",
|
|
27
|
+
"eslint-plugin-react-hooks": "^7.0.1",
|
|
28
|
+
"eslint-plugin-simple-import-sort": "^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0 || ^12.0.0"
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"@todoist/eslint-plugin-doist": "2.0.2",
|
|
32
|
+
"@eslint/js": "^9.0.0",
|
|
33
|
+
"eslint-config-prettier": "^10.1.1",
|
|
34
|
+
"globals": "^15.0.0",
|
|
35
|
+
"typescript-eslint": "^8.0.0"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@todoist/prettier-config": "4.0.2",
|
|
39
|
+
"@types/eslint": "8.44.1",
|
|
40
|
+
"@types/eslint-config-prettier": "6.11.3",
|
|
41
|
+
"@types/jest": "29.5.1",
|
|
42
|
+
"eslint": "8.57.0",
|
|
43
|
+
"eslint-import-resolver-typescript": "4.4.4",
|
|
44
|
+
"eslint-plugin-react": "7.37.5",
|
|
45
|
+
"eslint-plugin-simple-import-sort": "10.0.0",
|
|
46
|
+
"jest": "29.5.0",
|
|
47
|
+
"ts-jest": "29.1.0"
|
|
48
|
+
},
|
|
49
|
+
"scripts": {
|
|
50
|
+
"test": "jest",
|
|
51
|
+
"test:watch": "jest --watch",
|
|
52
|
+
"test:compat": "node --test tests/config-compatibility.cjs",
|
|
53
|
+
"test:release": "node --test .github/scripts/release.test.mjs"
|
|
54
|
+
},
|
|
55
|
+
"files": [
|
|
56
|
+
"index.js",
|
|
57
|
+
"index.d.ts",
|
|
58
|
+
"flat/",
|
|
59
|
+
"eslintrc/",
|
|
60
|
+
"lib/",
|
|
61
|
+
"CHANGELOG.md"
|
|
62
|
+
]
|
|
63
|
+
}
|