8000 Upgrade eslint to V9 by omer-azmon · Pull Request #592 · argoproj/argo-ui · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Upgrade eslint to V9 #592

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .storybook/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ module.exports = {
check: false, // typecheck separately
reactDocgen: false, // substantially improves performance: https://github.com/storybookjs/storybook/issues/22164#issuecomment-1603627308
},
webpackFinal: async (config, {configType}) => {
webpackFinal: async (config) => {
config.devtool = false; // perf per: https://github.com/storybookjs/storybook/issues/19736#issuecomment-1478103817
config.module.rules.push({
test: /\.scss$/,
exclude: /node_modules/,
include: path.resolve(__dirname, '../'),
sideEffects: true, // get side-effect styles to load per: https://github.com/storybookjs/storybook/issues/4690#issuecomment-435909433
loader: 'style-loader!raw-loader!sass-loader'
use: ['style-loader', 'css-loader', 'sass-loader']
});
return config;
},
Expand Down
260 changes: 260 additions & 0 deletions eslint.config.mjs
10000
Original file line number Diff line number Diff line change
@@ -0,0 +1,260 @@
import typescriptEslintPlugin from "@typescript-eslint/eslint-plugin";
import reactPlugin from "eslint-plugin-react";
import tsParser from "@typescript-eslint/parser";
import js from "@eslint/js";
import globals from "globals";

// console.log("Available typescriptEslintPlugin.configs:", typescriptEslintPlugin.configs); // Removed log

// Workaround for https://github.com/sindresorhus/globals/issues/239
const browserGlobals = Object.fromEntries(
Object.entries(globals.browser).map(([key, value]) => [
key.trim(),
value,
])
);

// mergeRulesFromConfigs might not be needed if we apply configs directly
// const mergeRulesFromConfigs = (configsArray) => { ... };

export default [
// 1. Global Ignores
{
ignores: [
"dist/", "node_modules/", "storybook-static/", "coverage/",
"build/", "lib/", ".cache/", ".vscode/", ".idea/", "*.log",
"**/*.stories.tsx" // Exclude stories from global type-checking early on
]
},

// 2. ESLint Recommended (for JS files primarily, but base for others)
js.configs.recommended,

// 3. TypeScript Recommended Type-Checked Configurations
// Spread each config object from the plugin's recommended set, ensuring file scope and plugin def
...(typescriptEslintPlugin.configs['flat/recommended-type-checked'] || []).map(config => ({
...config,
files: ["**/*.ts", "**/*.tsx"],
plugins: {
'@typescript-eslint': typescriptEslintPlugin,
...(config.plugins || {})
},
languageOptions: {
...(config.languageOptions || {}),
parser: tsParser, // Ensure parser for these specific configs
parserOptions: {
...(config.languageOptions?.parserOptions || {}),
project: true,
tsconfigRootDir: import.meta.dirname,
}
}
})),

// 4. React Recommended Flat Config
// Apply as a single object, ensuring file scope and plugin def
{
...(reactPlugin.configs.flat.recommended || {}),
files: ["**/*.{ts,tsx,jsx}"],
plugins: {
'react': reactPlugin,
...(reactPlugin.configs.flat.recommended?.plugins || {})
},
settings: {
react: { version: "detect" },
...(reactPlugin.configs.flat.recommended?.settings || {})
}
},

// 5. Main Project-Specific Overrides for ALL TS/TSX files (excluding stories)
// This comes AFTER the recommended sets to ensure its rules take precedence.
{
files: ["**/*.ts", "**/*.tsx"],
plugins: {
'@typescript-eslint': typescriptEslintPlugin,
'react': reactPlugin
},
languageOptions: { // Only define what's not covered or needs override from above
parser: tsParser, // Could be inherited, but explicit for clarity
parserOptions: { // Could be inherited
project: true,
tsconfigRootDir: import.meta.dirname,
ecmaVersion: "latest",
sourceType: "module",
},
globals: { ...browserGlobals, ...globals.node },
},
settings: { // Could be inherited
react: { version: "detect" }
},
rules: {
// All our specific overrides
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-non-null-assertion": "off",
"@typescript-eslint/no-require-imports": "off",
"@typescript-eslint/no-unused-vars": ["warn", { "argsIgnorePattern": "^_", "varsIgnorePattern": "^_" }],
"@typescript-eslint/no-unsafe-assignment": "off",
"@typescript-eslint/no-unsafe-member-access": "off",
"@typescript-eslint/no-unsafe-call": "off",
"@typescript-eslint/no-unsafe-argument": "off",
"@typescript-eslint/no-unsafe-return": "off",
"@typescript-eslint/unbound-method": "off",
"@typescript-eslint/no-floating-promises": "off",
"@typescript-eslint/restrict-plus-operands": "off",
"@typescript-eslint/no-base-to-string": "off",
"@typescript-eslint/restrict-template-expressions": "off",
"@typescript-eslint/no-redundant-type-constituents": "off",
"@typescript-eslint/no-unsafe-enum-comparison": "off",
"@typescript-eslint/no-unnecessary-type-assertion": "off",
"@typescript-eslint/no-unsafe-function-type": "off",
"@typescript-eslint/no-duplicate-enum-values": "off",

"react/no-unknown-property": ["error", { "ignore": ["qe-id"] }],
"react/prop-types": "off",
"react/react-in-jsx-scope": "off",
// no-undef should be handled by TS itself for TS files if `project` is correct
},
},

// JS/CJS files config (block #6)
{
files: ["*.js", "*.cjs", "scripts/**/*.js"],
languageOptions: {
sourceType: "commonjs",
ecmaVersion: "latest",
globals: { ...globals.node },
},
rules: {
"@typescript-eslint/no-require-imports": "off",
"no-unused-vars": ["warn", { "argsIgnorePattern": "^_" , "varsIgnorePattern": "^_"}],
"no-undef": "error",
"no-useless-escape": "off",
}
},

// Storybook JS files (ESM) config (block #7)
{
files: [".storybook/**/*.js", "v2/.storybook/**/*.js"],
languageOptions: {
sourceType: "module",
ecmaVersion: "latest",
globals: { ...globals.node },
},
rules: {
"no-unused-vars": "off",
"no-undef": "error",
}
},

// Story files (*.stories.tsx) config - Non-type-checked (block #8)
{
files: ["**/*.stories.tsx"],
plugins: {
'@typescript-eslint': typescriptEslintPlugin,
'react': reactPlugin
},
languageOptions: {
parser: tsParser,
parserOptions: {
ecmaVersion: "latest",
sourceType: "module",
},
globals: { ...browserGlobals, ...globals.node },
},
settings: { react: { version: "detect" } },
rules: {
// Apply non-type-checked recommended TS rules
...((typescriptEslintPlugin.configs['flat/recommended'] || []).reduce((acc, config) => ({ ...acc, ...(config.rules || {}) }), {})),
// Apply React recommended rules
...((reactPlugin.configs.flat.recommended?.rules || {})),
// Story-specific overrides
"react/display-name": "off",
"@typescript-eslint/no-unused-vars": "off",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-require-imports": "off",
"no-undef": "off"
},
},

// Test files (*.spec.tsx) config - Type-checked (block #9)
{
files: ["**/*.spec.tsx"],
plugins: { '@typescript-eslint': typescriptEslintPlugin, 'react': reactPlugin },
languageOptions: {
globals: { ...globals.jest },
parser: tsParser,
parserOptions: {
project: true,
tsconfigRootDir: import.meta.dirname,
ecmaVersion: "latest",
sourceType: "module",
},
},
settings: { react: { version: "detect" } },
rules: {
// Apply type-checked rules for tests
...((typescriptEslintPlugin.configs['flat/recommended-type-checked'] || []).reduce((acc, config) => ({ ...acc, ...(config.rules || {}) }), {})),
...((reactPlugin.configs.flat.recommended?.rules || {})),
// Test-specific overrides
"no-undef": "error",
"@typescript-eslint/no-unused-vars": ["warn", { "argsIgnorePattern": "^_" , "varsIgnorePattern": "^_"}],
"@typescript-eslint/no-unnecessary-type-assertion": "off",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-unsafe-assignment": "off",
"@typescript-eslint/no-unsafe-member-access": "off",
"@typescript-eslint/no-unsafe-call": "off",
"@typescript-eslint/no-unsafe-argument": "off",
"@typescript-eslint/no-unsafe-return": "off",
"@typescript-eslint/unbound-method": "off"
}
},

// Specific config for v2 components to try and resolve ban-types issue
{
files: ["v2/components/**/*.tsx"], // Target v2 components specifically
plugins: {
'@typescript-eslint': typescriptEslintPlugin,
'react': reactPlugin // Include react if react rules also apply/need override here
},
languageOptions: {
parser: tsParser,
parserOptions: {
project: true,
tsconfigRootDir: import.meta.dirname,
ecmaVersion: "latest",
sourceType: "module",
},
globals: { ...browserGlobals, ...globals.node },
},
settings: {
react: { version: "detect" }
},
rules: {
// Rules from recommended-type-checked, to ensure context
...(typescriptEslintPlugin.configs['flat/recommended-type-checked'] || []).reduce((acc, config) => ({...acc, ...(config.rules || {})}), {}),
...(reactPlugin.configs.flat.recommended.rules || {}),

// OUR CRITICAL OVERRIDES - these should be the final word for these rules
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-non-null-assertion": "off",
"@typescript-eslint/no-require-imports": "off",
"@typescript-eslint/no-unused-vars": ["warn", { "argsIgnorePattern": "^_" , "varsIgnorePattern": "^_"}],
"@typescript-eslint/no-unsafe-assignment": "off",
"@typescript-eslint/no-unsafe-member-access": "off",
"@typescript-eslint/no-unsafe-call": "off",
"@typescript-eslint/no-unsafe-argument": "off",
"@typescript-eslint/no-unsafe-return": "off",
"@typescript-eslint/unbound-method": "off",
"@typescript-eslint/no-floating-promises": "off",
"@typescript-eslint/restrict-plus-operands": "off",
"@typescript-eslint/no-base-to-string": "off",
"@typescript-eslint/restrict-template-expressions": "off",
"@typescript-eslint/no-redundant-type-constituents": "off",
"@typescript-eslint/no-unsafe-enum-comparison": "off",
"@typescript-eslint/no-unnecessary-type-assertion": "off",
"@typescript-eslint/no-unsafe-function-type": "off",
"@typescript-eslint/no-duplicate-enum-values": "off",
"react/prop-types": "off",
"react/react-in-jsx-scope": "off",
}
}
];
12 changes: 7 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"v2"
],
"scripts": {
"lint": "eslint --ext .tsx .",
"lint": "eslint .",
"deduplicate": "yarn-deduplicate -s fewer yarn.lock",
"test": "jest",
"utils:icons": "rm -f src/assets/fonts/* && node ./scripts/icons/generator.js",
Expand Down Expand Up @@ -44,6 +44,8 @@
},
"devDependencies": {
"@babel/core": "^7.21.3",
"@eslint/eslintrc": "^3.1.0",
"@eslint/js": "^9.26.0",
"@storybook/addon-actions": "6.5.0-beta.1",
"@storybook/addon-controls": "6.5.0-beta.1",
"@storybook/addon-essentials": "6.5.0-beta.1",
Expand All @@ -65,16 +67,16 @@
"@types/react-helmet": "^6.1.6",
"@types/react-router-dom": "^4.2.2",
"@types/uuid": "^9.0.3",
"@typescript-eslint/eslint-plugin": "^5.36.1",
"@typescript-eslint/parser": "^5.36.1",
"@typescript-eslint/eslint-plugin": "^8.32.0",
"@typescript-eslint/parser": "^8.32.0",
"babel-loader": "^8.2.5",
"copy-webpack-plugin": "^4.3.1",
"css-loader": "^3.6.0",
"enzyme": "^3.11.0",
"enzyme-adapter-react-16": "^1.15.7",
"enzyme-to-json": "^3.6.2",
"eslint": "^8.23.0",
"eslint-plugin-react": "^7.31.1",
"eslint": "^9.26.0",
"eslint-plugin-react": "^7.37.5",
"glob": "^8.0.3",
"identity-obj-proxy": "^3.0.0",
"jest": "^26.6.3",
Expand Down
41 changes: 28 additions & 13 deletions scripts/icons/generator.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,42 @@

const webfontsGenerator = require('webfonts-generator');
const path = require('path');
const glob = require('glob');
const fs = require('fs');
const FONT_TYPES = ['svg', 'ttf', 'woff', 'eot'];
const execSync = require('child_process').execSync;

const files = fs.readdirSync('src/assets/icons').map(file => path.join('src/assets/icons', file));

const fontPath = path.join('src/assets/fonts', 'argo-icon');
const fontName = 'argo-icon';

webfontsGenerator({
files: glob.sync('src/styles/icons/*.svg'),
dest: 'src/assets/fonts',
fontName: 'argo-icon',
types: FONT_TYPES,
cssTemplate: path.resolve(__dirname, './scss.hbs'),
templateOptions: {
baseTag: 'i',
classPrefix: 'argo-icon-',
baseSelector: '.argo-icon'
}
files: files,
dest: fontPath,
fontName: fontName,
cssDest: path.join(fontPath, fontName + '.css'),
cssTemplate: 'src/assets/icons-template/template.hbs'
}, function (error) {
if (error) {
console.log('Fail!', error);
} else {
const scss = fs.readFileSync('src/assets/fonts/argo-icon.css', 'utf-8').replace(/url\(\"argo-icon/g, 'url\($argo-icon-fonts-root + \"argo-icon');
// fix issue with generated fonts, ensure that quotes are used for glyps path in SVG font, otherwise it fails to render in Safari/Firefox
const svgContent = fs.readFileSync(
`${fontPath}/${fontName}.svg`
).toString().replace(/glyph-name="([^"]*)"/g, 'glyph-name="$1" unicode="$1"');
fs.writeFileSync(`${fontPath}/${fontName}.svg`, svgContent);
const scss = fs.readFileSync('src/assets/fonts/argo-icon.scss').toString().replace(new RegExp("url\\(\"./argo-icon"), "url(\"../fonts/argo-icon");
fs.writeFileSync('src/styles/argo-icon.scss', scss);
fs.unlinkSync('src/assets/fonts/argo-icon.css');
// set generated files permissions to 644 as git treats 755 as changes
execSync(
'chmod 644 ' + [
`${fontName}.svg`,
`${fontName}.eot`,
`${fontName}.woff2`,
`${fontName}.woff`,
`${fontName}.ttf`
].map(name => path.join(fontPath, name)).join(' ') + ' && yarn lint' // lint after generation
);
console.log('Done!');
}
});
2 changes: 1 addition & 1 deletion v2/.storybook/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const path = require('path');
module.exports = {
stories: ['../components/**/*.stories.tsx'],
addons: ['@storybook/addon-essentials'],
webpackFinal: async (config, {configType}) => {
webpackFinal: async (config) => {
config.module.rules.push({
test: /\.scss$/,
use: ['style-loader', 'css-loader', 'sass-loader'],
Expand Down
3 changes: 2 additions & 1 deletion v2/components/action-button/action-button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {Theme} from '../theme-div/theme-div';
import './action-button.scss';

export interface ActionButtonProps {
// eslint-disable-next-line @typescript-eslint/ban-types
action?: Function;
label?: string;
icon?: string;
Expand All @@ -23,6 +22,8 @@ export interface ActionButtonProps {
indicateSuccess?: boolean;
transparent?: boolean;
loading?: boolean;
children?: React.ReactNode;
className?: string;
}

/**
Expand Down
Loading
0