@guardian/eslint-config 9.0.0 → 10.0.0-beta.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/CHANGELOG.md +18 -0
- package/README.md +94 -10
- package/configs/comments.js +32 -0
- package/configs/imports.js +80 -0
- package/configs/javascript.base.js +31 -0
- package/configs/javascript.cjs.js +17 -0
- package/configs/javascript.esm.js +17 -0
- package/configs/javascript.js +27 -0
- package/configs/jest.js +16 -0
- package/configs/react.js +36 -0
- package/configs/recommended.js +16 -0
- package/configs/storybook.js +8 -0
- package/configs/typescript.js +122 -0
- package/eslint.config.js +14 -0
- package/index.js +23 -78
- package/package.json +17 -23
- package/.eslintrc.cjs +0 -24
- package/tsconfig.json +0 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# @guardian/eslint-config
|
|
2
2
|
|
|
3
|
+
## 10.0.0-beta.0
|
|
4
|
+
|
|
5
|
+
### Major Changes
|
|
6
|
+
|
|
7
|
+
This is pre-release that requires [ESLint 9](https://eslint.org/blog/2024/04/eslint-v9.0.0-released/).
|
|
8
|
+
|
|
9
|
+
It should be feature complete, but this release is to allow for feedback and testing.
|
|
10
|
+
|
|
11
|
+
It replaces both `@guardian/eslint-config@9` and `@guardian/eslint-config-typescript@12` with a single package.
|
|
12
|
+
|
|
13
|
+
It also includes configs for `jest`, `storybook` and `react`.
|
|
14
|
+
|
|
15
|
+
See the [README](README.md) for full details.
|
|
16
|
+
|
|
17
|
+
> ESLint 9 contains a lot of breaking changes, including a new config format. See their [migration guide](https://eslint.org/docs/latest/use/migrate-to-9.0.0) for more details.
|
|
18
|
+
>
|
|
19
|
+
> Note that [ESLint 8 is EOL 2024-10-05](https://eslint.org/version-support/).
|
|
20
|
+
|
|
3
21
|
## 9.0.0
|
|
4
22
|
|
|
5
23
|
### Major Changes
|
package/README.md
CHANGED
|
@@ -1,24 +1,108 @@
|
|
|
1
1
|
# `@guardian/eslint-config`
|
|
2
2
|
|
|
3
|
-
> ESLint
|
|
3
|
+
> ESLint configs for Guardian JavaScript and TypeScript projects.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
|
|
9
|
-
```
|
|
8
|
+
npm install --save-dev @guardian/eslint-config
|
|
10
9
|
|
|
11
|
-
or
|
|
10
|
+
# or
|
|
11
|
+
yarn add --dev @guardian/eslint-config
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
# or
|
|
14
|
+
pnpm install --save-dev @guardian/eslint-config
|
|
15
15
|
```
|
|
16
16
|
|
|
17
17
|
## Usage
|
|
18
18
|
|
|
19
|
+
#### Example
|
|
20
|
+
|
|
19
21
|
```js
|
|
20
|
-
//
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
// eslint.config.js
|
|
23
|
+
|
|
24
|
+
import guardian from '@guardian/eslint-config';
|
|
25
|
+
|
|
26
|
+
export default [
|
|
27
|
+
...guardian.configs.recommended,
|
|
28
|
+
...guardian.configs.jest,
|
|
29
|
+
...guardian.configs.react,
|
|
30
|
+
...guardian.configs.storybook,
|
|
31
|
+
];
|
|
24
32
|
```
|
|
33
|
+
|
|
34
|
+
### Configs
|
|
35
|
+
|
|
36
|
+
The package's default export is an object with a `configs` property that provides configs for different projects.
|
|
37
|
+
|
|
38
|
+
Some of them are single-purpose, and others compose the single-purpose configs into useful presets.
|
|
39
|
+
|
|
40
|
+
#### [`configs.recommended`](./configs/recommended.js)
|
|
41
|
+
|
|
42
|
+
Provides a recommended collection of useful configs covering both JavaScript and TypeScript.
|
|
43
|
+
|
|
44
|
+
Composes:
|
|
45
|
+
|
|
46
|
+
- `configs.javascript`
|
|
47
|
+
- `configs.typescript`
|
|
48
|
+
- `configs.imports`
|
|
49
|
+
- `configs.comments`
|
|
50
|
+
|
|
51
|
+
#### [`configs.javascript`](./configs/javascript.js)
|
|
52
|
+
|
|
53
|
+
_Included in `configs.recommended`._
|
|
54
|
+
|
|
55
|
+
Provides a collection of configs for checking JavaScript, which are also applied to TypeScript files.
|
|
56
|
+
|
|
57
|
+
It automatically detects your project type (using `package.json#type`), and uses an appropriate config for each file.
|
|
58
|
+
|
|
59
|
+
Composes:
|
|
60
|
+
|
|
61
|
+
- `configs.esm`
|
|
62
|
+
- `configs.cjs`
|
|
63
|
+
|
|
64
|
+
#### [`configs.esm`](./configs/esm.js)
|
|
65
|
+
|
|
66
|
+
_Included in `configs.javascript`._
|
|
67
|
+
|
|
68
|
+
Provides a collection of configs for ECMAScript modules.
|
|
69
|
+
|
|
70
|
+
It assumes everything will be ECMAScript, and will error if you use it on a CommonJS module.
|
|
71
|
+
|
|
72
|
+
#### [`configs.cjs`](./configs/cjs.js)
|
|
73
|
+
|
|
74
|
+
_Included in `configs.javascript`._
|
|
75
|
+
|
|
76
|
+
Provides a collection of configs for CommonJS modules.
|
|
77
|
+
|
|
78
|
+
It assumes everything will be CommonJS, and will error if you use it on an ECMAScript module.
|
|
79
|
+
|
|
80
|
+
#### [`configs.typescript`](./configs/typescript.js)
|
|
81
|
+
|
|
82
|
+
_Included in `configs.recommended`._
|
|
83
|
+
|
|
84
|
+
Provides a collection of configs for checking TypeScript.
|
|
85
|
+
|
|
86
|
+
#### [`configs.imports`](./configs/imports.js)
|
|
87
|
+
|
|
88
|
+
_Included in `configs.recommended`._
|
|
89
|
+
|
|
90
|
+
Provides a collection of configs ensuring best practice around module imports and exports.
|
|
91
|
+
|
|
92
|
+
#### [`configs.comments`](./configs/comments.js)
|
|
93
|
+
|
|
94
|
+
_Included in `configs.recommended`._
|
|
95
|
+
|
|
96
|
+
Provides a collection of configs ensuring best practice around code comments.
|
|
97
|
+
|
|
98
|
+
#### [`configs.jest`](./configs/jest.js)
|
|
99
|
+
|
|
100
|
+
Provides a collection of configs for checking Jest units tests.
|
|
101
|
+
|
|
102
|
+
#### [`configs.react`](./configs/react.js)
|
|
103
|
+
|
|
104
|
+
Provides a collection of configs for checking React components.
|
|
105
|
+
|
|
106
|
+
#### [`configs.storybook`](./configs/storybook.js)
|
|
107
|
+
|
|
108
|
+
Provides a collection of configs for checking Storybook stories.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { fixupPluginRules } from '@eslint/compat';
|
|
2
|
+
import eslintComments from 'eslint-plugin-eslint-comments';
|
|
3
|
+
|
|
4
|
+
export default [
|
|
5
|
+
{
|
|
6
|
+
name: '@guardian/comments',
|
|
7
|
+
plugins: {
|
|
8
|
+
'eslint-comments': fixupPluginRules(eslintComments),
|
|
9
|
+
},
|
|
10
|
+
rules: {
|
|
11
|
+
// require a `eslint-enable` comment for every `eslint-disable` comment
|
|
12
|
+
'eslint-comments/disable-enable-pair': [
|
|
13
|
+
'error',
|
|
14
|
+
{ allowWholeFile: true },
|
|
15
|
+
],
|
|
16
|
+
|
|
17
|
+
// disallow duplicate `eslint-disable` comments
|
|
18
|
+
'eslint-comments/no-duplicate-disable': 'error',
|
|
19
|
+
|
|
20
|
+
// disallow unused eslint-en/disable comments
|
|
21
|
+
// (make sure they're not left in after a fix)
|
|
22
|
+
'eslint-comments/no-unused-disable': 'error',
|
|
23
|
+
'eslint-comments/no-unused-enable': 'error',
|
|
24
|
+
|
|
25
|
+
// require an explanation if you disable eslint
|
|
26
|
+
'eslint-comments/require-description': [
|
|
27
|
+
'error',
|
|
28
|
+
{ ignore: ['eslint-enable'] },
|
|
29
|
+
],
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
];
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
// https://github.com/import-js/eslint-plugin-import/issues/2948#issuecomment-2119214365
|
|
2
|
+
import importX from 'eslint-plugin-import-x';
|
|
3
|
+
|
|
4
|
+
export default [
|
|
5
|
+
{
|
|
6
|
+
name: '@guardian/imports',
|
|
7
|
+
plugins: {
|
|
8
|
+
import: importX,
|
|
9
|
+
},
|
|
10
|
+
rules: {
|
|
11
|
+
// recommended defaults
|
|
12
|
+
'import/no-unresolved': 'error',
|
|
13
|
+
'import/named': 'error',
|
|
14
|
+
'import/namespace': 'error',
|
|
15
|
+
'import/default': 'error',
|
|
16
|
+
'import/export': 'error',
|
|
17
|
+
|
|
18
|
+
// encourages consistent token use across code bases
|
|
19
|
+
// (you have to deliberately rename an import) and
|
|
20
|
+
// makes the location of errors easier to discover:
|
|
21
|
+
// https://twitter.com/addyosmani/status/1411233253948747777
|
|
22
|
+
'import/no-default-export': 'error',
|
|
23
|
+
'import/prefer-default-export': 'off',
|
|
24
|
+
|
|
25
|
+
// less diff noise (they're hoisted anyway)
|
|
26
|
+
'import/first': 'error',
|
|
27
|
+
|
|
28
|
+
// fixable import formatting, designed to minimise diff noise
|
|
29
|
+
'sort-imports': [
|
|
30
|
+
'error',
|
|
31
|
+
{
|
|
32
|
+
ignoreCase: true,
|
|
33
|
+
ignoreDeclarationSort: true,
|
|
34
|
+
ignoreMemberSort: false,
|
|
35
|
+
},
|
|
36
|
+
],
|
|
37
|
+
'import/newline-after-import': 'error',
|
|
38
|
+
'import/order': [
|
|
39
|
+
'error',
|
|
40
|
+
{
|
|
41
|
+
groups: [
|
|
42
|
+
'builtin',
|
|
43
|
+
'external',
|
|
44
|
+
'internal',
|
|
45
|
+
'parent',
|
|
46
|
+
'sibling',
|
|
47
|
+
'index',
|
|
48
|
+
'object',
|
|
49
|
+
'unknown',
|
|
50
|
+
],
|
|
51
|
+
'newlines-between': 'never',
|
|
52
|
+
alphabetize: {
|
|
53
|
+
order: 'asc',
|
|
54
|
+
caseInsensitive: true,
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
],
|
|
58
|
+
|
|
59
|
+
// prevent circular dependencies
|
|
60
|
+
'import/no-cycle': ['error', { ignoreExternal: true }],
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
name: '@guardian/imports-default-exceptions',
|
|
65
|
+
files: [
|
|
66
|
+
'**/.lintstagedrc.*',
|
|
67
|
+
'**/astro.config.*',
|
|
68
|
+
'**/eslint.config.*',
|
|
69
|
+
'**/jest.config.*',
|
|
70
|
+
'**/rollup.config.*',
|
|
71
|
+
'**/svelte.config.*',
|
|
72
|
+
'**/*.stories.*',
|
|
73
|
+
'**/.storybook/main.*',
|
|
74
|
+
],
|
|
75
|
+
rules: {
|
|
76
|
+
'import/no-default-export': 'off',
|
|
77
|
+
'import/prefer-default-export': 'error',
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
];
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import js from '@eslint/js';
|
|
2
|
+
import stylistic from '@stylistic/eslint-plugin';
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
name: '@guardian/javascript',
|
|
6
|
+
plugins: {
|
|
7
|
+
'@stylistic': stylistic,
|
|
8
|
+
},
|
|
9
|
+
rules: {
|
|
10
|
+
...js.configs.recommended.rules,
|
|
11
|
+
|
|
12
|
+
// prevent dangling returns without braces
|
|
13
|
+
curly: ['error', 'all'],
|
|
14
|
+
|
|
15
|
+
// delimit members with semi-colons and require
|
|
16
|
+
// one at the end to keep diffs simpler
|
|
17
|
+
'@stylistic/member-delimiter-style': [
|
|
18
|
+
2,
|
|
19
|
+
{
|
|
20
|
+
multiline: {
|
|
21
|
+
delimiter: 'semi',
|
|
22
|
+
requireLast: true,
|
|
23
|
+
},
|
|
24
|
+
singleline: {
|
|
25
|
+
delimiter: 'semi',
|
|
26
|
+
requireLast: false,
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
],
|
|
30
|
+
},
|
|
31
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import globals from 'globals';
|
|
2
|
+
import js from './javascript.base.js';
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
...js,
|
|
6
|
+
name: '@guardian/cjs',
|
|
7
|
+
languageOptions: {
|
|
8
|
+
globals: {
|
|
9
|
+
...globals.commonjs,
|
|
10
|
+
...globals.node,
|
|
11
|
+
},
|
|
12
|
+
parserOptions: {
|
|
13
|
+
sourceType: 'commonjs',
|
|
14
|
+
ecmaVersion: 'latest',
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import globals from 'globals';
|
|
2
|
+
import js from './javascript.base.js';
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
...js,
|
|
6
|
+
name: '@guardian/esm',
|
|
7
|
+
languageOptions: {
|
|
8
|
+
globals: {
|
|
9
|
+
...globals.browser,
|
|
10
|
+
...globals.nodeBuiltin,
|
|
11
|
+
},
|
|
12
|
+
parserOptions: {
|
|
13
|
+
sourceType: 'module',
|
|
14
|
+
ecmaVersion: 'latest',
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { readPackageUp } from 'read-package-up';
|
|
2
|
+
import cjs from './javascript.cjs.js';
|
|
3
|
+
import esm from './javascript.esm.js';
|
|
4
|
+
|
|
5
|
+
const isModule = (await readPackageUp()).packageJson.type === 'module';
|
|
6
|
+
|
|
7
|
+
export default isModule
|
|
8
|
+
? [
|
|
9
|
+
{
|
|
10
|
+
files: ['**/*.{js,mjs,jsx,mjsx,ts,mts,tsx,mtsx}'],
|
|
11
|
+
...esm,
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
files: ['**/*.cjs', '**/*.cts'],
|
|
15
|
+
...cjs,
|
|
16
|
+
},
|
|
17
|
+
]
|
|
18
|
+
: [
|
|
19
|
+
{
|
|
20
|
+
files: ['**/*.{js,cjs,jsx,ts,cts,tsx}'],
|
|
21
|
+
...cjs,
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
files: ['**/*.{mjs,mjsx,mts,mtsx}'],
|
|
25
|
+
...esm,
|
|
26
|
+
},
|
|
27
|
+
];
|
package/configs/jest.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import globals from 'globals';
|
|
2
|
+
|
|
3
|
+
export default [
|
|
4
|
+
{
|
|
5
|
+
name: '@guardian/jest',
|
|
6
|
+
files: [
|
|
7
|
+
'**/*.test.{js,mjs,cjs,jsx,mjsx,ts,mts,cts,tsx,mtsx}',
|
|
8
|
+
'**/*.spec.{js,mjs,cjs,jsx,mjsx,ts,mts,cts,tsx,mtsx}',
|
|
9
|
+
],
|
|
10
|
+
languageOptions: {
|
|
11
|
+
globals: {
|
|
12
|
+
...globals.jest,
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
];
|
package/configs/react.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import jsxA11y from 'eslint-plugin-jsx-a11y';
|
|
2
|
+
import react from 'eslint-plugin-react';
|
|
3
|
+
import globals from 'globals';
|
|
4
|
+
|
|
5
|
+
export default [
|
|
6
|
+
{
|
|
7
|
+
name: '@guardian/react',
|
|
8
|
+
files: ['**/*.{jsx,mjsx,tsx,mtsx}'],
|
|
9
|
+
languageOptions: {
|
|
10
|
+
...react.configs.flat.recommended.languageOptions,
|
|
11
|
+
globals: {
|
|
12
|
+
...globals.serviceworker,
|
|
13
|
+
...globals.browser,
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
...react.configs.flat.recommended,
|
|
17
|
+
...react.configs.flat['jsx-runtime'],
|
|
18
|
+
plugins: {
|
|
19
|
+
react,
|
|
20
|
+
'jsx-a11y': jsxA11y,
|
|
21
|
+
},
|
|
22
|
+
rules: {
|
|
23
|
+
'react/no-unknown-property': [
|
|
24
|
+
'error',
|
|
25
|
+
{
|
|
26
|
+
ignore: ['css'],
|
|
27
|
+
},
|
|
28
|
+
],
|
|
29
|
+
},
|
|
30
|
+
settings: {
|
|
31
|
+
react: {
|
|
32
|
+
version: 'detect',
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
];
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import comments from './comments.js';
|
|
2
|
+
import imports from './imports.js';
|
|
3
|
+
import javascript from './javascript.js';
|
|
4
|
+
import typescript from './typescript.js';
|
|
5
|
+
|
|
6
|
+
export default [
|
|
7
|
+
...javascript,
|
|
8
|
+
...imports,
|
|
9
|
+
...typescript, // needs to come after `imports`
|
|
10
|
+
...comments,
|
|
11
|
+
{
|
|
12
|
+
linterOptions: {
|
|
13
|
+
reportUnusedDisableDirectives: 'error',
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
];
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
// https://typescript-eslint.io/getting-started/
|
|
2
|
+
|
|
3
|
+
import importX from 'eslint-plugin-import-x';
|
|
4
|
+
// eslint-disable-next-line import/no-unresolved -- why can't this be resolved? literally no one knows
|
|
5
|
+
import { config, configs } from 'typescript-eslint';
|
|
6
|
+
|
|
7
|
+
export default config({
|
|
8
|
+
files: ['**/*.{ts,tsx,mtsx,mts,cts}'],
|
|
9
|
+
extends: [
|
|
10
|
+
...configs.recommended,
|
|
11
|
+
...configs.recommendedTypeChecked,
|
|
12
|
+
importX.configs.typescript,
|
|
13
|
+
],
|
|
14
|
+
languageOptions: {
|
|
15
|
+
parserOptions: {
|
|
16
|
+
projectService: true,
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
rules: {
|
|
20
|
+
// Performance boost, as TypeScript provides the same checks as part
|
|
21
|
+
// of standard type checking. See
|
|
22
|
+
// https://typescript-eslint.io/linting/troubleshooting/performance-troubleshooting/#eslint-plugin-import
|
|
23
|
+
'import/no-unresolved': 'off',
|
|
24
|
+
'import/named': 'off',
|
|
25
|
+
'import/namespace': 'off',
|
|
26
|
+
'import/default': 'off',
|
|
27
|
+
|
|
28
|
+
/*
|
|
29
|
+
FIXABLE STYLISTIC CHOICES THAT DIFFER FROM THE DEFAULT The intention
|
|
30
|
+
is to maximise clarity and consistency, not direct or inhibit what
|
|
31
|
+
can be done with code.
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
// use `string[]` for simple arrays, `Array<string>` for complex
|
|
35
|
+
// ones
|
|
36
|
+
// https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/array-type.md#array-simple
|
|
37
|
+
'@typescript-eslint/array-type': [
|
|
38
|
+
'error',
|
|
39
|
+
{
|
|
40
|
+
default: 'array-simple',
|
|
41
|
+
},
|
|
42
|
+
],
|
|
43
|
+
|
|
44
|
+
// use `Record<string, unknown>` instead of `{ [key: string]:
|
|
45
|
+
// unknown }`
|
|
46
|
+
'@typescript-eslint/consistent-indexed-object-style': ['error', 'record'],
|
|
47
|
+
|
|
48
|
+
// be explicit when you only want to import a type: `import type {
|
|
49
|
+
// Foo } from 'Foo';`
|
|
50
|
+
'@typescript-eslint/consistent-type-imports': [
|
|
51
|
+
'error',
|
|
52
|
+
{
|
|
53
|
+
prefer: 'type-imports',
|
|
54
|
+
},
|
|
55
|
+
],
|
|
56
|
+
|
|
57
|
+
// use `(1 + foo.num!) == 'error'` instead of `1 + foo.num! ==
|
|
58
|
+
// 'error'`
|
|
59
|
+
'@typescript-eslint/no-confusing-non-null-assertion': 'error',
|
|
60
|
+
|
|
61
|
+
'@typescript-eslint/no-unnecessary-boolean-literal-compare': 'error',
|
|
62
|
+
'@typescript-eslint/no-unnecessary-condition': 'error',
|
|
63
|
+
'@typescript-eslint/no-unnecessary-qualifier': 'error',
|
|
64
|
+
'@typescript-eslint/no-unnecessary-type-arguments': 'error',
|
|
65
|
+
'@typescript-eslint/no-unused-vars': [
|
|
66
|
+
'error',
|
|
67
|
+
{
|
|
68
|
+
caughtErrors: 'none',
|
|
69
|
+
},
|
|
70
|
+
],
|
|
71
|
+
|
|
72
|
+
// use `str.includes(value)` instead of `str.indexOf(value) !== -1`
|
|
73
|
+
'@typescript-eslint/prefer-includes': 'error',
|
|
74
|
+
|
|
75
|
+
// https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/prefer-reduce-type-parameter.md
|
|
76
|
+
'@typescript-eslint/prefer-reduce-type-parameter': 'error',
|
|
77
|
+
|
|
78
|
+
// use String#startsWith or String#endsWith instead of
|
|
79
|
+
// String#indexOf et al
|
|
80
|
+
'@typescript-eslint/prefer-string-starts-ends-with': 'error',
|
|
81
|
+
|
|
82
|
+
// require explanation for changing compiler behaviour
|
|
83
|
+
'@typescript-eslint/ban-ts-comment': [
|
|
84
|
+
'error',
|
|
85
|
+
{
|
|
86
|
+
'ts-expect-error': 'allow-with-description',
|
|
87
|
+
'ts-ignore': true,
|
|
88
|
+
'ts-nocheck': true,
|
|
89
|
+
'ts-check': false,
|
|
90
|
+
minimumDescriptionLength: 3,
|
|
91
|
+
},
|
|
92
|
+
],
|
|
93
|
+
|
|
94
|
+
/* NOT FIXABLE BUT USEFUL */
|
|
95
|
+
|
|
96
|
+
// Enforce TypeScript naming conventions
|
|
97
|
+
// https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/naming-convention.md
|
|
98
|
+
'@typescript-eslint/naming-convention': [
|
|
99
|
+
'error',
|
|
100
|
+
|
|
101
|
+
// types are 'PascalCase'
|
|
102
|
+
{
|
|
103
|
+
selector: ['typeLike', 'enumMember'],
|
|
104
|
+
format: ['PascalCase'],
|
|
105
|
+
},
|
|
106
|
+
|
|
107
|
+
// booleans are descriptive
|
|
108
|
+
// {
|
|
109
|
+
// selector: 'variable', types: ['boolean'], format:
|
|
110
|
+
// ['PascalCase'], prefix: ['is', 'should', 'has', 'can',
|
|
111
|
+
// 'did', 'will'],
|
|
112
|
+
// },
|
|
113
|
+
],
|
|
114
|
+
|
|
115
|
+
// use `foo ?? 'a string'` instead of `foo !== null && foo !==
|
|
116
|
+
// undefined ? foo : 'a string'`
|
|
117
|
+
'@typescript-eslint/prefer-nullish-coalescing': 'error',
|
|
118
|
+
|
|
119
|
+
// use `a?.b` instead of `a && a.b`
|
|
120
|
+
'@typescript-eslint/prefer-optional-chain': 'error',
|
|
121
|
+
},
|
|
122
|
+
});
|
package/eslint.config.js
ADDED
package/index.js
CHANGED
|
@@ -1,80 +1,25 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
// disallow unused eslint-en/disable comments
|
|
25
|
-
// (make sure they're not left in after a fix)
|
|
26
|
-
'eslint-comments/no-unused-disable': 2,
|
|
27
|
-
'eslint-comments/no-unused-enable': 2,
|
|
28
|
-
|
|
29
|
-
// require an explanation if you disable eslint
|
|
30
|
-
'eslint-comments/require-description': [2, { ignore: ['eslint-enable'] }],
|
|
31
|
-
|
|
32
|
-
// this doesn't catch bugs or make things more readable
|
|
33
|
-
// and sometimes tools or 3rd parties require it
|
|
34
|
-
'no-underscore-dangle': 0,
|
|
35
|
-
|
|
36
|
-
// encourages consistent token use across code bases
|
|
37
|
-
// (you have to deliberately rename an import) and
|
|
38
|
-
// makes the location of errors easier to discover:
|
|
39
|
-
// https://twitter.com/addyosmani/status/1411233253948747777
|
|
40
|
-
'import/no-default-export': 2,
|
|
41
|
-
'import/prefer-default-export': 0,
|
|
42
|
-
|
|
43
|
-
// less diff noise (they're hoisted anyway)
|
|
44
|
-
'import/first': 2,
|
|
45
|
-
|
|
46
|
-
// fixable import formatting, designed to minimise diff noise
|
|
47
|
-
'sort-imports': [
|
|
48
|
-
'error',
|
|
49
|
-
{
|
|
50
|
-
ignoreCase: true,
|
|
51
|
-
ignoreDeclarationSort: true,
|
|
52
|
-
ignoreMemberSort: false,
|
|
53
|
-
},
|
|
54
|
-
],
|
|
55
|
-
'import/newline-after-import': 2,
|
|
56
|
-
'import/order': [
|
|
57
|
-
'error',
|
|
58
|
-
{
|
|
59
|
-
groups: [
|
|
60
|
-
'builtin',
|
|
61
|
-
'external',
|
|
62
|
-
'internal',
|
|
63
|
-
'parent',
|
|
64
|
-
'sibling',
|
|
65
|
-
'index',
|
|
66
|
-
'object',
|
|
67
|
-
'unknown',
|
|
68
|
-
],
|
|
69
|
-
'newlines-between': 'never',
|
|
70
|
-
alphabetize: {
|
|
71
|
-
order: 'asc',
|
|
72
|
-
caseInsensitive: true,
|
|
73
|
-
},
|
|
74
|
-
},
|
|
75
|
-
],
|
|
76
|
-
|
|
77
|
-
// prevent circular dependencies
|
|
78
|
-
'import/no-cycle': ['error', { ignoreExternal: true }],
|
|
1
|
+
import comments from './configs/comments.js';
|
|
2
|
+
import imports from './configs/imports.js';
|
|
3
|
+
import cjs from './configs/javascript.cjs.js';
|
|
4
|
+
import esm from './configs/javascript.esm.js';
|
|
5
|
+
import javascript from './configs/javascript.js';
|
|
6
|
+
import jest from './configs/jest.js';
|
|
7
|
+
import react from './configs/react.js';
|
|
8
|
+
import recommended from './configs/recommended.js';
|
|
9
|
+
import storybook from './configs/storybook.js';
|
|
10
|
+
import typescript from './configs/typescript.js';
|
|
11
|
+
|
|
12
|
+
export default {
|
|
13
|
+
configs: {
|
|
14
|
+
recommended,
|
|
15
|
+
javascript,
|
|
16
|
+
cjs,
|
|
17
|
+
esm,
|
|
18
|
+
typescript,
|
|
19
|
+
imports,
|
|
20
|
+
comments,
|
|
21
|
+
jest,
|
|
22
|
+
storybook,
|
|
23
|
+
react,
|
|
79
24
|
},
|
|
80
25
|
};
|
package/package.json
CHANGED
|
@@ -1,28 +1,37 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@guardian/eslint-config",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "10.0.0-beta.0",
|
|
4
4
|
"description": "ESLint config for Guardian JavaScript projects",
|
|
5
|
+
"type": "module",
|
|
5
6
|
"main": "index.js",
|
|
6
7
|
"dependencies": {
|
|
8
|
+
"@eslint/compat": "1.1.1",
|
|
9
|
+
"@eslint/js": "9.9.1",
|
|
10
|
+
"@stylistic/eslint-plugin": "2.6.4",
|
|
7
11
|
"eslint-config-prettier": "9.1.0",
|
|
12
|
+
"eslint-import-resolver-typescript": "3.6.3",
|
|
8
13
|
"eslint-plugin-eslint-comments": "3.2.0",
|
|
9
|
-
"eslint-plugin-import": "
|
|
14
|
+
"eslint-plugin-import-x": "4.0.0",
|
|
15
|
+
"eslint-plugin-jsx-a11y": "6.9.0",
|
|
16
|
+
"eslint-plugin-react": "7.35.0",
|
|
17
|
+
"eslint-plugin-react-hooks": "4.6.2",
|
|
18
|
+
"eslint-plugin-storybook": "0.8.0",
|
|
19
|
+
"globals": "15.9.0",
|
|
20
|
+
"read-package-up": "11.0.0",
|
|
21
|
+
"typescript-eslint": "8.3.0"
|
|
10
22
|
},
|
|
11
23
|
"devDependencies": {
|
|
12
|
-
"eslint": "
|
|
13
|
-
"tslib": "2.6.2",
|
|
24
|
+
"eslint": "9.9.0",
|
|
14
25
|
"wireit": "0.14.4"
|
|
15
26
|
},
|
|
16
27
|
"peerDependencies": {
|
|
17
|
-
"eslint": "^
|
|
18
|
-
"tslib": "^2.6.2"
|
|
28
|
+
"eslint": "^9.9.0"
|
|
19
29
|
},
|
|
20
30
|
"wireit": {
|
|
21
31
|
"lint": {
|
|
22
32
|
"command": "eslint --cache --color .",
|
|
23
33
|
"files": [
|
|
24
34
|
"**",
|
|
25
|
-
"../../../.eslint*",
|
|
26
35
|
"!.eslintcache"
|
|
27
36
|
],
|
|
28
37
|
"output": []
|
|
@@ -32,30 +41,15 @@
|
|
|
32
41
|
"clean": false,
|
|
33
42
|
"files": [
|
|
34
43
|
"**",
|
|
35
|
-
"../../../.eslint*",
|
|
36
44
|
"!.eslintcache"
|
|
37
45
|
],
|
|
38
46
|
"output": [
|
|
39
47
|
"."
|
|
40
48
|
]
|
|
41
|
-
},
|
|
42
|
-
"tsc": {
|
|
43
|
-
"command": "tsc --pretty",
|
|
44
|
-
"files": [
|
|
45
|
-
"**",
|
|
46
|
-
"tsconfig.json",
|
|
47
|
-
"../tsconfig/tsconfig.json",
|
|
48
|
-
"../../../@types/**",
|
|
49
|
-
"../../../tsconfig.base.json",
|
|
50
|
-
"!(dist)/**",
|
|
51
|
-
"!.eslintcache"
|
|
52
|
-
],
|
|
53
|
-
"output": []
|
|
54
49
|
}
|
|
55
50
|
},
|
|
56
51
|
"scripts": {
|
|
57
52
|
"fix": "wireit",
|
|
58
|
-
"lint": "wireit"
|
|
59
|
-
"tsc": "wireit"
|
|
53
|
+
"lint": "wireit"
|
|
60
54
|
}
|
|
61
55
|
}
|
package/.eslintrc.cjs
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
module.exports = {
|
|
2
|
-
extends: ['../../../.eslintrc.cjs'],
|
|
3
|
-
ignorePatterns: [
|
|
4
|
-
'!**/*',
|
|
5
|
-
'node_modules',
|
|
6
|
-
'jest.dist.*', // depends on build output, so don't lint it
|
|
7
|
-
'.wireit',
|
|
8
|
-
],
|
|
9
|
-
overrides: [
|
|
10
|
-
{
|
|
11
|
-
files: ['*.ts', '*.tsx'],
|
|
12
|
-
parserOptions: {
|
|
13
|
-
tsconfigRootDir: __dirname,
|
|
14
|
-
},
|
|
15
|
-
rules: {},
|
|
16
|
-
},
|
|
17
|
-
{
|
|
18
|
-
files: ['**/*.test.*'],
|
|
19
|
-
env: {
|
|
20
|
-
jest: true,
|
|
21
|
-
},
|
|
22
|
-
},
|
|
23
|
-
],
|
|
24
|
-
};
|