Skip to content

Commit 6dbf551

Browse files
authored
Refactor ESLint configuration and update dependencies (#900)
Signed-off-by: achour94 <[email protected]>
1 parent 9032007 commit 6dbf551

File tree

12 files changed

+1253
-1675
lines changed

12 files changed

+1253
-1675
lines changed

.eslintrc.json

Lines changed: 0 additions & 58 deletions
This file was deleted.

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,16 @@ Library for sharing GridSuite apps commons components
77
The commons-ui library have a demo app in which you can call your components to test them.
88
The `npm start` command install the library's dependencies then launches the demo app.
99

10+
##### Development Scripts
11+
12+
- **`npm run type-check`** - Runs TypeScript type checking without emitting files. This ensures all developers use the project's local TypeScript version from `node_modules` rather than a potentially different globally-installed version. Run this to verify your code has no type errors before committing.
13+
14+
- **`npm run build`** - Builds the library. Note: This automatically runs `npm run prebuild` first.
15+
16+
- **`npm run prebuild`** - Runs linting and type checking before the build. This script is executed automatically by npm before `npm run build` and ensures that the build is not executed if linting or type checking fails. You don't need to call this manually unless you want to verify code quality without building.
17+
18+
##### Local Testing
19+
1020
If you want to test your library integration with a consumer application my-app you have first
1121
to build commons-ui via
1222

demo/data/TreeViewFinder.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import {
1515
Whatshot as WhatshotIcon,
1616
} from '@mui/icons-material';
1717

18-
// eslint-disable-next-line import/no-mutable-exports
18+
// eslint-disable-next-line import-x/no-mutable-exports
1919
let PokemonTree = [
2020
{
2121
id: 'D1',
@@ -117,7 +117,7 @@ let PokemonTree = [
117117
},
118118
];
119119

120-
// eslint-disable-next-line import/no-mutable-exports
120+
// eslint-disable-next-line import-x/no-mutable-exports
121121
let PokemonList = [
122122
{
123123
id: '1',

demo/src/app.jsx

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* License, v. 2.0. If a copy of the MPL was not distributed with this
55
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
66
*/
7-
/* eslint-disable func-names, no-nested-ternary, no-return-assign, @typescript-eslint/no-unused-vars, no-promise-executor-return, @typescript-eslint/no-unused-expressions, no-alert, no-undef, @typescript-eslint/no-shadow, react/jsx-no-bind, react/prop-types, import/no-extraneous-dependencies */
7+
/* eslint-disable func-names, no-nested-ternary, no-return-assign, no-promise-executor-return, no-alert, no-undef, react/jsx-no-bind, react/prop-types */
88

99
import {
1010
Box,
@@ -32,7 +32,7 @@ import { BrowserRouter, useLocation, useMatch, useNavigate } from 'react-router'
3232
import { IntlProvider, useIntl } from 'react-intl';
3333
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
3434
import translations from './demo_intl';
35-
import PowsyblLogo from '../images/powsybl_logo.svg?react'; // eslint-disable-line import/no-unresolved
35+
import PowsyblLogo from '../images/powsybl_logo.svg?react';
3636
import AppPackage from '../../package.json';
3737
import TreeViewFinderConfig from './TreeViewFinderConfig';
3838
import {
@@ -197,7 +197,6 @@ const CustomTreeViewFinder = styled(TreeViewFinder)(TreeViewFinderCustomStylesEm
197197
function Crasher() {
198198
const [crash, setCrash] = useState(false);
199199
if (crash) {
200-
// eslint-disable-next-line no-undef
201200
window.foonotexists.bar();
202201
}
203202
return <Button onClick={() => setCrash(true)}>CRASH ME</Button>;
@@ -298,7 +297,6 @@ function PermanentSnackButton() {
298297
const validateUser = () => {
299298
// change to false to simulate user unauthorized access
300299
return new Promise((resolve) => {
301-
// eslint-disable-next-line no-undef
302300
window.setTimeout(() => resolve(true), 500);
303301
});
304302
};
@@ -378,9 +376,11 @@ function AppContent({ language, onLanguageClick }) {
378376
};
379377
const displayEquipment = (equipment) => {
380378
if (equipment != null) {
381-
equipment.type === EQUIPMENT_TYPE.SUBSTATION.name
382-
? alert(`Equipment ${equipment.label} found !`)
383-
: alert(`Equipment ${equipment.label} (${equipment.voltageLevelLabel}) found !`);
379+
if (equipment.type === EQUIPMENT_TYPE.SUBSTATION.name) {
380+
alert(`Equipment ${equipment.label} found !`);
381+
} else {
382+
alert(`Equipment ${equipment.label} (${equipment.voltageLevelLabel}) found !`);
383+
}
384384
}
385385
};
386386
const [searchTermDisableReason] = useState('search disabled');

demo/src/index.jsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import { createRoot } from 'react-dom/client';
99

1010
import App from './app';
1111

12-
// eslint-disable-next-line no-undef
1312
const container = document.querySelector('#demo');
1413
const root = createRoot(container);
1514
root.render(<App />);

demo/src/right-resizable-box.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* License, v. 2.0. If a copy of the MPL was not distributed with this
55
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
66
*/
7-
/* eslint-disable import/no-extraneous-dependencies */
7+
/* eslint-disable import-x/no-extraneous-dependencies */
88

99
import { useState } from 'react';
1010
import { MoreVert as ResizePanelHandleIcon } from '@mui/icons-material';
@@ -64,7 +64,7 @@ function RightResizableBox(props) {
6464
setResizedTreePercentage(newPercentage);
6565
}
6666
};
67-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
67+
6868
const onResize = (event, { element, size }) => {
6969
updateResizedTreePercentage(size.width, windowWidth);
7070
};

eslint.config.js

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
/**
2+
* Copyright (c) 2025, RTE (http://www.rte-france.com)
3+
* This Source Code Form is subject to the terms of the Mozilla Public
4+
* License, v. 2.0. If a copy of the MPL was not distributed with this
5+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
6+
*/
7+
8+
/**
9+
* Base ESLint config initially generated by `eslint-config-airbnb-extended` (v2.3.2)
10+
* using the React + Prettier + TypeScript template, then manually adapted for Commons-ui.
11+
* Source template:
12+
* https://eslint-airbnb-extended.nishargshah.dev/cli/guide
13+
* https://github.com/NishargShah/eslint-config-airbnb-extended/blob/v2.3.2/packages/create-airbnb-x-config/templates/react/prettier/ts/default/eslint.config.mjs
14+
*/
15+
16+
import { configs, plugins } from 'eslint-config-airbnb-extended';
17+
import { rules as prettierConfigRules } from 'eslint-config-prettier';
18+
import prettierPlugin from 'eslint-plugin-prettier';
19+
import js from '@eslint/js';
20+
21+
const jsConfig = [
22+
// ESLint Recommended Rules
23+
{
24+
name: 'js/config',
25+
...js.configs.recommended,
26+
},
27+
// Stylistic Plugin
28+
plugins.stylistic,
29+
// Import X Plugin
30+
plugins.importX,
31+
// Airbnb Base Recommended Config
32+
...configs.base.recommended,
33+
];
34+
35+
const reactConfig = [
36+
// React Plugin
37+
plugins.react,
38+
// React Hooks Plugin
39+
plugins.reactHooks,
40+
// React JSX A11y Plugin
41+
plugins.reactA11y,
42+
// Airbnb React Recommended Config
43+
...configs.react.recommended,
44+
];
45+
46+
const typescriptConfig = [
47+
// TypeScript ESLint Plugin
48+
plugins.typescriptEslint,
49+
// Airbnb Base TypeScript Config
50+
...configs.base.typescript,
51+
// Airbnb React TypeScript Config
52+
...configs.react.typescript,
53+
];
54+
55+
const prettierConfig = [
56+
// Prettier Plugin
57+
{
58+
name: 'prettier/plugin/config',
59+
plugins: {
60+
prettier: prettierPlugin,
61+
},
62+
},
63+
// Prettier Config (disable conflicting rules)
64+
{
65+
name: 'prettier/config',
66+
rules: {
67+
...prettierConfigRules,
68+
'prettier/prettier': 'warn',
69+
},
70+
},
71+
];
72+
73+
const projectConfig = [
74+
{
75+
name: 'project/ignores',
76+
ignores: ['dist', 'coverage'],
77+
},
78+
// Settings
79+
{
80+
name: 'project/settings',
81+
settings: {
82+
react: {
83+
version: 'detect',
84+
},
85+
},
86+
},
87+
// React JSX Runtime (prevents "React must be in scope" errors)
88+
{
89+
name: 'project/react-jsx-runtime',
90+
files: ['**/*.{jsx,tsx}'],
91+
rules: {
92+
'react/react-in-jsx-scope': 'off',
93+
'react/jsx-uses-react': 'off',
94+
},
95+
},
96+
// Custom rules
97+
{
98+
name: 'project/rules',
99+
rules: {
100+
// Code style
101+
curly: 'error',
102+
'no-console': 'off',
103+
'no-plusplus': ['error', { allowForLoopAfterthoughts: true }],
104+
105+
// React rules
106+
'react/jsx-props-no-spreading': 'off',
107+
'react/require-default-props': 'off',
108+
109+
// Import rules
110+
'import-x/prefer-default-export': 'off',
111+
'import-x/extensions': 'off',
112+
'import-x/no-unresolved': 'off',
113+
'import-x/no-useless-path-segments': 'off',
114+
'import-x/no-extraneous-dependencies': [
115+
'error',
116+
{
117+
devDependencies: [
118+
'test/**',
119+
'tests/**',
120+
'spec/**',
121+
'**/__tests__/**',
122+
'**/__mocks__/**',
123+
'test.{js,jsx,ts,tsx}',
124+
'test-*.{js,jsx,ts,tsx}',
125+
'**/*{.,_}{test,spec}.{js,jsx,ts,tsx}',
126+
'**/jest.config.ts',
127+
'**/jest.setup.ts',
128+
'**/prettier.config.js',
129+
'**/vite.config.ts',
130+
'**/eslint.config.js',
131+
],
132+
optionalDependencies: false,
133+
},
134+
],
135+
136+
// MUI deep imports restriction
137+
'no-restricted-imports': [
138+
'warn',
139+
{
140+
patterns: [
141+
{
142+
group: [
143+
'@mui/*/*',
144+
'!@mui/material/colors',
145+
'!@mui/material/locale',
146+
'!@mui/icons-material/*',
147+
],
148+
message:
149+
'Deep imports from MUI libraries are forbidden. Import only from the library root.',
150+
},
151+
],
152+
},
153+
],
154+
155+
// Disable strict type-aware rules that weren't in old config
156+
'@typescript-eslint/no-unsafe-enum-comparison': 'off',
157+
'@typescript-eslint/consistent-type-definitions': 'off',
158+
'@typescript-eslint/no-inferrable-types': 'off',
159+
'@typescript-eslint/consistent-indexed-object-style': 'off',
160+
'@typescript-eslint/no-empty-object-type': 'off',
161+
'@typescript-eslint/no-unnecessary-template-expression': 'off',
162+
'@typescript-eslint/no-duplicate-enum-values': 'off',
163+
'@typescript-eslint/no-wrapper-object-types': 'off',
164+
'@typescript-eslint/array-type': 'off',
165+
'@typescript-eslint/no-unnecessary-type-arguments': 'off',
166+
'arrow-body-style': 'off',
167+
'no-shadow': 'off',
168+
'no-unused-expressions': ['error', { allowShortCircuit: true }],
169+
'prefer-arrow-callback': 'off',
170+
'no-unused-vars': ['off', { argsIgnorePattern: '^_' }],
171+
'@typescript-eslint/no-unnecessary-type-assertion': 'off',
172+
'prefer-object-has-own': 'off',
173+
},
174+
},
175+
];
176+
177+
export default [...jsConfig, ...reactConfig, ...typescriptConfig, ...prettierConfig, ...projectConfig];

0 commit comments

Comments
 (0)