Skip to content
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

eslint v9 #9

Merged
merged 5 commits into from
Jan 22, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
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 README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ The configuration is based on the recommended rulesets from [ESLint](https://esl

It also includes [ESLint Stylistic](https://eslint.style/) which replaces deprecated rules from eslint and typescript-eslint.

Currently, it uses ESLint v8 and typescript-eslint v6. (nodejs v16.10+ required)
The upgrade to ESLint v9 and typescript-eslint v8 is planned for the next major release.
Currently, it uses ESLint v9 and typescript-eslint v8. (nodejs v18.18+ required)
If you need to use this package on older nodejs v16, you may switch to older v2.x version, which is based on ESLint v8 (nodejs v16.10+ required)


`@ovos-media/coding-standard/eslint` exports a function that accepts an object with the following options:
Expand Down
78 changes: 30 additions & 48 deletions eslint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ type CustomizeOptions = {

// shared settings - for js + ts equivalent rules
const shared: Linter.RulesRecord = {
'no-unused-vars': ['error', { varsIgnorePattern: '^_', args: 'none' }],
'no-unused-expressions': ['error', { allowShortCircuit: true, allowTernary: true }],
'no-unused-vars': ['error', { varsIgnorePattern: '^_', args: 'none', caughtErrors: 'none' }],
};

/**
Expand Down Expand Up @@ -91,7 +92,7 @@ function customize(options: CustomizeOptions = {}) {
parser: tsParser,
parserOptions: {
// https://typescript-eslint.io/packages/parser/
project: true,
projectService: true,
},
},
plugins: {
Expand Down Expand Up @@ -121,7 +122,7 @@ function customize(options: CustomizeOptions = {}) {
'*.setup.ts',
...disableTypeChecked,
],
languageOptions: { parserOptions: { project: null } }, // this is what basically the 'disable-type-checked' config does, when 'recommended-type-checked' is not used
languageOptions: { parserOptions: { projectService: null } }, // this is what basically the 'disable-type-checked' config does, when 'recommended-type-checked' is not used
},
];

Expand All @@ -132,6 +133,7 @@ function customize(options: CustomizeOptions = {}) {
files: ['**/*.?(m|c)js?(x)'],
rules: {
// ** eslint:recommended overrides:
'no-unused-expressions': shared['no-unused-expressions'],
'no-unused-vars': shared['no-unused-vars'],
// ** end eslint:recommended overrides

Expand All @@ -158,10 +160,14 @@ function customize(options: CustomizeOptions = {}) {
'@typescript-eslint/no-explicit-any': 'off',
// allow @ts-ignore
'@typescript-eslint/ban-ts-comment': 'off',
// even though `no-unused-vars` is already reconfigured, this needs to be reconfigured again for typescript files, with the same options repeated
'@typescript-eslint/no-unused-vars': shared['no-unused-vars'],
// we still sometimes want to use dynamic, sync `require()` instead of `await import()`
'@typescript-eslint/no-var-requires': 'off',
'@typescript-eslint/no-require-imports': 'off',
// allow `interface I extends Base<Param> {}` syntax
'@typescript-eslint/no-empty-object-type': ['error', { allowInterfaces: 'with-single-extends' }],
// even though the rules blow are already reconfigured for eslint:recommended,
// they need to be reconfigured again for typescript files, with the same options repeated
'@typescript-eslint/no-unused-expressions': shared['no-unused-expressions'],
'@typescript-eslint/no-unused-vars': shared['no-unused-vars'],
// ** end typescript-eslint:recommended overrides

// additional rules
Expand Down Expand Up @@ -248,50 +254,30 @@ function customize(options: CustomizeOptions = {}) {
indent,
{
SwitchCase: 1,
// indenting parameters on multiline function calls is sometimes broken
CallExpression: { arguments: 'off' },
// @typescript-eslint/indent is broken and unmaintained,
// but there is no other, better option available at the moment. (except the prettier itself?)
// Eslint cuts ties with stylistic lints while leaving them in broken state
// https://github.com/eslint/eslint/issues/17522
// Maybe it'll be fixed one day at https://github.com/eslint-stylistic/eslint-stylistic/ 🙄
//
// Apply workarounds posted in https://github.com/typescript-eslint/typescript-eslint/issues/1824 et al.
// only enable when 'indent' is 2 spaces, as it's broken otherwise -> https://github.com/eslint-stylistic/eslint-stylistic/issues/514
offsetTernaryExpressions: indent === 2,
ignoredNodes: [
// https://github.com/typescript-eslint/typescript-eslint/issues/1824#issuecomment-1378327382
'PropertyDefinition[decorators]',
'FunctionExpression[params]:has(Identifier[decorators])',
// copied list of ignoredNodes from https://github.com/eslint-stylistic/eslint-stylistic/blob/main/packages/eslint-plugin/configs/customize.ts
// which just disables indent rules for cases not properly supported by the plugin
// (issues have been carried over from the original indent and @typescript-eslint/indent rules
// and now are being addressed occasionally, one by one, in eslint-stylistic)
'TSUnionType',
'TSIntersectionType',
// https://github.com/typescript-eslint/typescript-eslint/issues/1824#issuecomment-943783564
// Generics are not properly indented
'TSTypeParameterInstantiation',
'FunctionExpression > .params[decorators.length > 0]',
'FunctionExpression > .params > :matches(Decorator, :not(:first-child))',
// some more exclusions are needed:
// does not indent multiline interface extends (conflicts with prettier)
'TSInterfaceHeritage',
// checking indentation of multiline ternary expression is broken
// https://github.com/eslint/eslint/issues/14058
'.superTypeArguments',
// multiline generic type parameters in function calls
'CallExpression > .typeArguments',
// checking indentation of multiline ternary expression is broken in some cases (i.a. nested function calls)
'ConditionalExpression *',
// breaking on nested arrow functions
// still breaking on nested (chained) arrow functions () => () => {}
'ArrowFunctionExpression',
// https://stackoverflow.com/questions/52178093/ignore-the-indentation-in-a-template-literal-with-the-eslint-indent-rule
'TemplateLiteral *',
// ignore jsx indentation - copied from https://github.com/eslint-stylistic/eslint-stylistic/blob/main/packages/eslint-plugin/configs/customize.ts
// use jsx-indent rule instead
'JSXElement',
'JSXElement > *',
'JSXAttribute',
'JSXIdentifier',
'JSXNamespacedName',
'JSXMemberExpression',
'JSXSpreadAttribute',
'JSXExpressionContainer',
'JSXOpeningElement',
'JSXClosingElement',
'JSXFragment',
'JSXOpeningFragment',
'JSXClosingFragment',
'JSXText',
'JSXEmptyExpression',
'JSXSpreadChild',
'TemplateLiteral *', // even after some fixes in @stylistic, still not handling multiline expressions in template literals properly
],
},
],
Expand Down Expand Up @@ -390,10 +376,7 @@ function customize(options: CustomizeOptions = {}) {
rules: {
// allow i.a. `type Props = {}` in react components
// https://github.com/typescript-eslint/typescript-eslint/issues/2063#issuecomment-675156492
'@typescript-eslint/ban-types': [
'error',
{ extendDefaults: true, types: { '{}': false } },
],
'@typescript-eslint/no-empty-object-type': ['error', { allowWithName: 'Props$' }],
},
},
// our rules and overrides (react 2/2: jsx+tsx)
Expand Down Expand Up @@ -429,7 +412,6 @@ function customize(options: CustomizeOptions = {}) {
'@stylistic/jsx-equals-spacing': 'error',
'@stylistic/jsx-first-prop-new-line': 'error',
'@stylistic/jsx-function-call-newline': 'error',
'@stylistic/jsx-indent': ['error', indent],
'@stylistic/jsx-indent-props': ['error', indent],
'@stylistic/jsx-props-no-multi-spaces': 'error',
'@stylistic/jsx-quotes': 'error',
Expand Down Expand Up @@ -540,7 +522,7 @@ function customize(options: CustomizeOptions = {}) {
}

if (vitest) {
const vitestPlugin = require('eslint-plugin-vitest');
const vitestPlugin = require('@vitest/eslint-plugin');
config.push({
name: 'vitest',
files: [
Expand Down
47 changes: 23 additions & 24 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@ovos-media/coding-standard",
"version": "2.0.2",
"version": "3.0.0-rc.0",
"description": "ovos-media coding standard",
"main": "index.js",
"types": "index.d.ts",
Expand All @@ -9,35 +9,34 @@
"repository": "https://github.com/ovos/coding-standard",
"homepage": "https://github.com/ovos/coding-standard",
"scripts": {
"prepublish": "yarn run build",
"lint": "yarn run eslint .",
"build": "tsc -p ./tsconfig.json",
"release": "standard-version"
"prepublish": "yarn build",
"lint": "eslint .",
"build": "tsc -p ./tsconfig.json"
},
"dependencies": {
"@stylistic/eslint-plugin": "^1.8.1",
"@types/eslint": "8.56.10",
"@typescript-eslint/eslint-plugin": "^6.21.0",
"@typescript-eslint/parser": "^6.21.0",
"eslint": "^8.57.0",
"eslint-import-resolver-typescript": "^3.6.1",
"eslint-plugin-check-file": "2.6.2",
"eslint-plugin-cypress": "^3.3.0",
"eslint-plugin-import": "npm:[email protected]",
"eslint-plugin-jest": "28.4.0",
"eslint-plugin-mocha": "^10.4.3",
"eslint-plugin-react": "^7.34.2",
"eslint-plugin-react-hooks": "^4.6.2",
"eslint-plugin-vitest": "0.3.10",
"globals": "^13.24.0"
"@stylistic/eslint-plugin": "^2.12.1",
"@types/eslint": "^9.6.1",
"@typescript-eslint/eslint-plugin": "^8.19.1",
"@typescript-eslint/parser": "^8.19.1",
"@typescript-eslint/utils": "^8.19.1",
"@vitest/eslint-plugin": "^1.1.24",
"eslint": "^9.17.0",
"eslint-import-resolver-typescript": "^3.7.0",
"eslint-plugin-check-file": "^2.8.0",
"eslint-plugin-cypress": "^4.1.0",
"eslint-plugin-import": "npm:eslint-plugin-import-x@^4.6.1",
"eslint-plugin-jest": "^28.10.0",
"eslint-plugin-mocha": "^10.5.0",
"eslint-plugin-react": "^7.37.3",
"eslint-plugin-react-hooks": "^5.1.0",
"globals": "^15.14.0"
},
"devDependencies": {
"@types/eslint-plugin-mocha": "10.4.0",
"@types/eslint__js": "8.42.3",
"@types/node": "20.14.1",
"@types/node": "20.17.10",
"@types/prettier": "3.0.0",
"prettier": "3.3.0",
"typescript": "5.4.5"
"prettier": "3.4.2",
"typescript": "5.7.2"
},
"engines": {
"node": ">=16.10"
Expand Down