Skip to content

Commit deac4fd

Browse files
michaelfaithljharb
authored andcommitted
[New] add eslint 9 support
This change adds support for eslint v9. All three example projects have been updated to use the latest eslint, and the root package's dev and peer deps have been updated. In order to make this work with both v9 and older versions, I had to update the parser options helper to adjust the config passed into the `RuleTester`.
1 parent 74d5dec commit deac4fd

File tree

16 files changed

+180
-50
lines changed

16 files changed

+180
-50
lines changed

.flowconfig

+1
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,6 @@
33
<PROJECT_ROOT>/lib/.*
44
<PROJECT_ROOT>/docs/.*
55
<PROJECT_ROOT>/reports/.*
6+
<PROJECT_ROOT>/examples/.*
67
[options]
78
suppress_type=$FlowFixMe

.github/workflows/node-4+.yml

+28-1
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,40 @@ jobs:
2525
matrix:
2626
node-version: ${{ fromJson(needs.matrix.outputs.latest) }}
2727
eslint:
28+
- 9
2829
- 8
2930
- 7
3031
- 6
3132
- 5
3233
- 4
3334
- 3
3435
exclude:
36+
- node-version: 16
37+
eslint: 9
38+
- node-version: 15
39+
eslint: 9
40+
- node-version: 14
41+
eslint: 9
42+
- node-version: 13
43+
eslint: 9
44+
- node-version: 12
45+
eslint: 9
46+
- node-version: 11
47+
eslint: 9
48+
- node-version: 10
49+
eslint: 9
50+
- node-version: 9
51+
eslint: 9
52+
- node-version: 8
53+
eslint: 9
54+
- node-version: 7
55+
eslint: 9
56+
- node-version: 6
57+
eslint: 9
58+
- node-version: 5
59+
eslint: 9
60+
- node-version: 4
61+
eslint: 9
3562
- node-version: 15
3663
eslint: 8
3764
- node-version: 13
@@ -90,7 +117,7 @@ jobs:
90117
steps:
91118
- uses: actions/checkout@v4
92119
with:
93-
fetch-depth: 0
120+
fetch-depth: 0
94121
- uses: ljharb/actions/node/install@main
95122
name: 'nvm install ${{ matrix.node-version }} && npm install'
96123
env:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import assert from 'assert';
2+
3+
export default assert;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import fs from 'fs/promises';
2+
3+
export default fs;
+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import fs from 'fs';
2+
3+
export default fs;
+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import path from 'path';
2+
3+
export default path;
+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import url from 'url';
2+
3+
export default url;
+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import util from 'util';
2+
3+
export default util;
+40-13
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,53 @@
1+
import { version as eslintVersion } from 'eslint/package.json';
2+
import semver from 'semver';
3+
4+
const usingLegacy = semver.major(eslintVersion) < 9;
5+
16
const defaultParserOptions = {
2-
ecmaVersion: 2018,
37
ecmaFeatures: {
48
experimentalObjectRestSpread: true,
59
jsx: true,
610
},
711
};
812

13+
const defaultLegacyParserOptions = {
14+
...defaultParserOptions,
15+
ecmaVersion: 2018,
16+
};
17+
18+
const defaultLanguageOptions = {
19+
ecmaVersion: 'latest',
20+
parserOptions: {
21+
...defaultParserOptions,
22+
},
23+
};
24+
925
export default function parserOptionsMapper({
1026
code,
1127
errors,
1228
options = [],
13-
parserOptions = {},
14-
settings,
29+
languageOptions = {},
30+
settings = {},
1531
}) {
16-
return {
17-
code,
18-
errors,
19-
options,
20-
parserOptions: {
21-
...defaultParserOptions,
22-
...parserOptions,
23-
},
24-
settings,
25-
};
32+
return usingLegacy
33+
? {
34+
code,
35+
errors,
36+
options,
37+
parserOptions: {
38+
...defaultLegacyParserOptions,
39+
...languageOptions,
40+
},
41+
settings,
42+
}
43+
: {
44+
code,
45+
errors,
46+
options,
47+
languageOptions: {
48+
...defaultLanguageOptions,
49+
...languageOptions,
50+
},
51+
settings,
52+
};
2653
}

__tests__/src/rules/img-redundant-alt-test.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,8 @@ ruleTester.run('img-redundant-alt', rule, {
6767
{ code: '<img alt={imageAlt} />' },
6868
{ code: '<img alt={imageAlt.name} />' },
6969
semver.satisfies(eslintVersion, '>= 6') ? [
70-
{ code: '<img alt={imageAlt?.name} />', parserOptions: { ecmaVersion: 2020 } },
71-
{ code: '<img alt="Doing cool things" aria-hidden={foo?.bar}/>', parserOptions: { ecmaVersion: 2020 } },
70+
{ code: '<img alt={imageAlt?.name} />', languageOptions: { ecmaVersion: 2020 } },
71+
{ code: '<img alt="Doing cool things" aria-hidden={foo?.bar}/>', languageOptions: { ecmaVersion: 2020 } },
7272
] : [],
7373
{ code: '<img alt="Photography" />;' },
7474
{ code: '<img alt="ImageMagick" />;' },
+65-23
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,88 @@
1+
import { version as eslintVersion } from 'eslint/package.json';
12
import expect from 'expect';
3+
import semver from 'semver';
24
import parserOptionsMapper from '../../__util__/parserOptionsMapper';
35

6+
const usingLegacy = semver.major(eslintVersion) < 9;
7+
48
describe('parserOptionsMapper', () => {
59
it('should return an test case object', () => {
610
const testCase = {
711
code: '<div />',
812
errors: [],
913
options: {},
1014
};
11-
expect(parserOptionsMapper(testCase)).toEqual({
12-
code: '<div />',
13-
errors: [],
14-
options: {},
15-
parserOptions: {
16-
ecmaVersion: 2018,
17-
ecmaFeatures: {
18-
experimentalObjectRestSpread: true,
19-
jsx: true,
15+
16+
const expectedResult = usingLegacy
17+
? {
18+
code: '<div />',
19+
errors: [],
20+
options: {},
21+
parserOptions: {
22+
ecmaVersion: 2018,
23+
ecmaFeatures: {
24+
experimentalObjectRestSpread: true,
25+
jsx: true,
26+
},
2027
},
21-
},
22-
});
28+
settings: {},
29+
}
30+
: {
31+
code: '<div />',
32+
errors: [],
33+
options: {},
34+
languageOptions: {
35+
ecmaVersion: 'latest',
36+
parserOptions: {
37+
ecmaFeatures: {
38+
experimentalObjectRestSpread: true,
39+
jsx: true,
40+
},
41+
},
42+
},
43+
settings: {},
44+
};
45+
expect(parserOptionsMapper(testCase)).toEqual(expectedResult);
2346
});
2447
it('should allow for overriding parserOptions', () => {
2548
const testCase = {
2649
code: '<div />',
2750
errors: [],
2851
options: {},
29-
parserOptions: {
52+
languageOptions: {
3053
ecmaVersion: 5,
3154
},
3255
};
33-
expect(parserOptionsMapper(testCase)).toEqual({
34-
code: '<div />',
35-
errors: [],
36-
options: {},
37-
parserOptions: {
38-
ecmaVersion: 5,
39-
ecmaFeatures: {
40-
experimentalObjectRestSpread: true,
41-
jsx: true,
56+
57+
const expectedResult = usingLegacy
58+
? {
59+
code: '<div />',
60+
errors: [],
61+
options: {},
62+
parserOptions: {
63+
ecmaVersion: 5,
64+
ecmaFeatures: {
65+
experimentalObjectRestSpread: true,
66+
jsx: true,
67+
},
4268
},
43-
},
44-
});
69+
settings: {},
70+
}
71+
: {
72+
code: '<div />',
73+
errors: [],
74+
options: {},
75+
languageOptions: {
76+
ecmaVersion: 5,
77+
parserOptions: {
78+
ecmaFeatures: {
79+
experimentalObjectRestSpread: true,
80+
jsx: true,
81+
},
82+
},
83+
},
84+
settings: {},
85+
};
86+
expect(parserOptionsMapper(testCase)).toEqual(expectedResult);
4587
});
4688
});

examples/flat-cjs/package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@
1111
"react-dom": "^18.2.0"
1212
},
1313
"devDependencies": {
14-
"@eslint/js": "^9.5.0",
14+
"@eslint/js": "^9.9.1",
1515
"cross-env": "^7.0.3",
16-
"eslint": "^8.57.0",
16+
"eslint": "^9.9.1",
1717
"eslint-plugin-jsx-a11y": "file:../..",
1818
"globals": "^15.6.0"
1919
}

examples/flat-esm/package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@
1111
"react-dom": "^18.2.0"
1212
},
1313
"devDependencies": {
14-
"@eslint/js": "^9.5.0",
14+
"@eslint/js": "^9.9.1",
1515
"cross-env": "^7.0.3",
16-
"eslint": "^8.57.0",
16+
"eslint": "^9.9.1",
1717
"eslint-plugin-jsx-a11y": "file:../..",
1818
"globals": "^15.6.0"
1919
}

examples/legacy/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
},
1313
"devDependencies": {
1414
"cross-env": "^7.0.3",
15-
"eslint": "^8.57.0",
15+
"eslint": "^9.9.1",
1616
"eslint-plugin-jsx-a11y": "file:../.."
1717
}
1818
}

package.json

+19-6
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
"create": "node ./scripts/create-rule",
2323
"flow": "flow",
2424
"lint:fix": "npm run lint -- --fix",
25-
"lint": "eslint --ext=js,mjs,cjs,ts,tsx .",
25+
"lint": "npx eslint@8 --ext=js,mjs,cjs,ts,tsx .",
2626
"prepublish": "not-in-publish || npm run prepublishOnly",
2727
"prepublishOnly": "safe-publish-latest && npm run lint && npm run flow && npm run jest",
2828
"pretest": "npm run lint:fix && npm run flow",
@@ -34,7 +34,7 @@
3434
"test-example:legacy": "cd examples/legacy && npm install && npm run lint",
3535
"test-example:flat-esm": "cd examples/flat-esm && npm install && npm run lint",
3636
"test-example:flat-cjs": "cd examples/flat-cjs && npm install && npm run lint",
37-
"jest": "jest --coverage __tests__/**/*",
37+
"jest": "jest --coverage __tests__",
3838
"pregenerate-list-of-rules": "npm run build",
3939
"generate-list-of-rules": "eslint-doc-generator --rule-doc-title-format prefix-name --rule-doc-section-options false --config-emoji recommended,☑️ --ignore-config flat/recommended --ignore-config flat/strict",
4040
"generate-list-of-rules:check": "npm run generate-list-of-rules -- --check",
@@ -51,7 +51,8 @@
5151
"babel-jest": "^24.9.0",
5252
"babel-plugin-add-module-exports": "^1.0.4",
5353
"babel-preset-airbnb": "^5.0.0",
54-
"eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8",
54+
"core-js": "^3.38.1",
55+
"eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9",
5556
"eslint-config-airbnb-base": "^15.0.0",
5657
"eslint-doc-generator": "^1.7.1",
5758
"eslint-plugin-eslint-plugin": "^4.3.0",
@@ -96,7 +97,7 @@
9697
"string.prototype.includes": "^2.0.0"
9798
},
9899
"peerDependencies": {
99-
"eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8"
100+
"eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9"
100101
},
101102
"jest": {
102103
"coverageReporters": [
@@ -111,7 +112,18 @@
111112
"testPathIgnorePatterns": [
112113
"__tests__/__util__/"
113114
],
114-
"testEnvironment": "node"
115+
"testEnvironment": "node",
116+
"moduleNameMapper": {
117+
"@eslint/config-array": "<rootDir>/node_modules/@eslint/config-array/dist/cjs/index.cjs",
118+
"@eslint/object-schema": "<rootDir>/node_modules/@eslint/object-schema/dist/cjs/index.cjs",
119+
"node:assert": "<rootDir>/__tests__/__util__/nodeReexports/assert.js",
120+
"node:fs/promises": "<rootDir>/__tests__/__util__/nodeReexports/fs-promises.js",
121+
"node:fs": "<rootDir>/__tests__/__util__/nodeReexports/fs.js",
122+
"node:path": "<rootDir>/__tests__/__util__/nodeReexports/path.js",
123+
"node:url": "<rootDir>/__tests__/__util__/nodeReexports/url.js",
124+
"node:util": "<rootDir>/__tests__/__util__/nodeReexports/util.js"
125+
},
126+
"setupFilesAfterEnv": ["<rootDir>/setup.jest.js"]
115127
},
116128
"auto-changelog": {
117129
"output": "CHANGELOG.md",
@@ -132,7 +144,8 @@
132144
"/flow",
133145
"scripts/",
134146
"CONTRIBUTING.md",
135-
"/examples"
147+
"/examples",
148+
"setup.jest.js"
136149
]
137150
}
138151
}

setup.jest.js

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// eslint-disable-next-line import/no-extraneous-dependencies
2+
import 'core-js/stable/structured-clone';

0 commit comments

Comments
 (0)