From 1e6be262c39b6ebe14cd1d1fbaedb2548298f2ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Zasso?= Date: Tue, 2 Jul 2024 10:37:31 +0200 Subject: [PATCH] feat!: migrate to ESLint flat config --- README.md | 26 +- base.js | 608 +++++++++++++++++++++++----------------------- cheminfo.js | 5 + eslintrc.test.yml | 1 - index.js | 5 - jsdoc.js | 57 +++-- package.json | 26 +- test/not-ok.js | 2 + test/test.js | 82 +++---- unicorn.js | 99 ++++---- 10 files changed, 459 insertions(+), 452 deletions(-) create mode 100644 cheminfo.js delete mode 100644 eslintrc.test.yml delete mode 100644 index.js diff --git a/README.md b/README.md index a5daa61..1196455 100644 --- a/README.md +++ b/README.md @@ -5,18 +5,22 @@ Shared ESLint config for cheminfo and ml.js projects. ## Installation ```console -npm i -D eslint-config-cheminfo eslint +npm i -D eslint-config-cheminfo eslint@^8.57.0 ``` ## Usage -Create a `.eslintrc.yml` with the following contents: +Create a `eslint.config.mjs` file with the following contents: -```yml -extends: [cheminfo, cheminfo/jsdoc, cheminfo/unicorn] +```js +import cheminfo from 'eslint-config-cheminfo'; + +export default [ + ...cheminfo, +]; ``` -You can then customize the config for your project by changing rules in this file. +You can then customize the config for your project. Create ESLint scripts in your `package.json`: @@ -43,8 +47,12 @@ https://github.com/cheminfo/eslint-config-cheminfo-react You can extend both of the above configurations as they are compatible between each other: -```yml -extends: - - cheminfo-typescript - - cheminfo-react +```js +import typescript from 'eslint-config-cheminfo-typescript'; +import react from 'eslint-config-cheminfo-react'; + +export default [ + ...typescript, + ...react, +]; ``` diff --git a/base.js b/base.js index 6de0a2e..3600de3 100644 --- a/base.js +++ b/base.js @@ -1,320 +1,322 @@ -'use strict'; +import _import from 'eslint-plugin-import'; +import noLookaheadLookbehindRegexp from 'eslint-plugin-no-lookahead-lookbehind-regexp'; +import { fixupPluginRules } from '@eslint/compat'; +import globals from 'globals'; -module.exports = { - env: { - es6: true, - es2022: true, - 'shared-node-browser': true, - }, - parserOptions: { - ecmaVersion: '2022', - sourceType: 'module', - }, - plugins: ['import', 'no-lookahead-lookbehind-regexp'], - reportUnusedDisableDirectives: true, - overrides: [ - { - // .cjs files are always for Node.js and must be of type script. - files: ['*.cjs'], - parserOptions: { - sourceType: 'script', - }, - env: { - node: true, - }, +export default [ + { + plugins: { + import: fixupPluginRules(_import), + 'no-lookahead-lookbehind-regexp': noLookaheadLookbehindRegexp, }, - { - // .mjs files must be of type module. - files: ['*.mjs'], - parserOptions: { - sourceType: 'module', - }, + + linterOptions: { + reportUnusedDisableDirectives: true, }, - { - // Configuration files are usually for Node.js modules. - files: ['*.config.{js,cjs,mjs,ts,cts,mts}'], - env: { - node: true, + + languageOptions: { + globals: { + ...globals['shared-node-browser'], }, }, - ], - rules: { - // https://eslint.org/docs/latest/rules/ - // Last rules review: v8.56.0 - // https://github.com/import-js/eslint-plugin-import#rules - // Last rules review: v2.26.0 + rules: { + // https://eslint.org/docs/latest/rules/ + // Last rules review: v8.56.0 + + // https://github.com/import-js/eslint-plugin-import#rules + // Last rules review: v2.26.0 - //#region Possible Problems (https://eslint.org/docs/latest/rules/#possible-problems) - 'array-callback-return': 'error', - 'constructor-super': 'error', - 'for-direction': 'error', - 'getter-return': 'error', - 'no-async-promise-executor': 'error', - 'no-await-in-loop': 'error', - 'no-class-assign': 'error', - 'no-compare-neg-zero': 'error', - 'no-cond-assign': 'error', - 'no-const-assign': 'error', - 'no-constant-binary-expression': 'error', - 'no-constant-condition': ['error', { checkLoops: false }], - 'no-constructor-return': 'error', - 'no-control-regex': 'error', - 'no-debugger': 'error', - 'no-dupe-args': 'error', - 'no-dupe-class-members': 'error', - 'no-dupe-else-if': 'error', - 'no-dupe-keys': 'error', - 'no-duplicate-case': 'error', - 'no-duplicate-imports': 'off', - 'no-empty-character-class': 'error', - 'no-empty-pattern': 'error', - 'no-ex-assign': 'error', - 'no-fallthrough': 'error', - 'no-func-assign': 'error', - 'no-import-assign': 'error', - 'no-inner-declarations': 'error', - 'no-invalid-regexp': 'error', - 'no-irregular-whitespace': 'error', - 'no-loss-of-precision': 'error', - 'no-misleading-character-class': 'error', - 'no-new-native-nonconstructor': 'error', - 'no-new-symbol': 'error', - 'no-obj-calls': 'error', - 'no-promise-executor-return': 'error', - 'no-prototype-builtins': 'error', - 'no-self-assign': 'error', - 'no-self-compare': 'error', - 'no-setter-return': 'error', - 'no-sparse-arrays': 'error', - 'no-template-curly-in-string': 'error', - 'no-this-before-super': 'error', - 'no-undef': 'error', - 'no-unexpected-multiline': 'error', - 'no-unmodified-loop-condition': 'error', - 'no-unreachable': 'error', - 'no-unreachable-loop': 'error', - 'no-unsafe-finally': 'error', - 'no-unsafe-negation': 'error', - 'no-unsafe-optional-chaining': 'error', - 'no-unused-private-class-members': 'error', - 'no-unused-vars': 'error', - 'no-use-before-define': 'off', - 'no-useless-backreference': 'error', - 'require-atomic-updates': ['error', { allowProperties: true }], - 'use-isnan': 'error', - 'valid-typeof': 'error', - //#endregion + //#region Possible Problems (https://eslint.org/docs/latest/rules/#possible-problems) + 'array-callback-return': 'error', + 'constructor-super': 'error', + 'for-direction': 'error', + 'getter-return': 'error', + 'no-async-promise-executor': 'error', + 'no-await-in-loop': 'error', + 'no-class-assign': 'error', + 'no-compare-neg-zero': 'error', + 'no-cond-assign': 'error', + 'no-const-assign': 'error', + 'no-constant-binary-expression': 'error', + 'no-constant-condition': ['error', { checkLoops: false }], + 'no-constructor-return': 'error', + 'no-control-regex': 'error', + 'no-debugger': 'error', + 'no-dupe-args': 'error', + 'no-dupe-class-members': 'error', + 'no-dupe-else-if': 'error', + 'no-dupe-keys': 'error', + 'no-duplicate-case': 'error', + 'no-duplicate-imports': 'off', + 'no-empty-character-class': 'error', + 'no-empty-pattern': 'error', + 'no-ex-assign': 'error', + 'no-fallthrough': 'error', + 'no-func-assign': 'error', + 'no-import-assign': 'error', + 'no-inner-declarations': 'error', + 'no-invalid-regexp': 'error', + 'no-irregular-whitespace': 'error', + 'no-loss-of-precision': 'error', + 'no-misleading-character-class': 'error', + 'no-new-native-nonconstructor': 'error', + 'no-new-symbol': 'error', + 'no-obj-calls': 'error', + 'no-promise-executor-return': 'error', + 'no-prototype-builtins': 'error', + 'no-self-assign': 'error', + 'no-self-compare': 'error', + 'no-setter-return': 'error', + 'no-sparse-arrays': 'error', + 'no-template-curly-in-string': 'error', + 'no-this-before-super': 'error', + 'no-undef': 'error', + 'no-unexpected-multiline': 'error', + 'no-unmodified-loop-condition': 'error', + 'no-unreachable': 'error', + 'no-unreachable-loop': 'error', + 'no-unsafe-finally': 'error', + 'no-unsafe-negation': 'error', + 'no-unsafe-optional-chaining': 'error', + 'no-unused-private-class-members': 'error', + 'no-unused-vars': 'error', + 'no-use-before-define': 'off', + 'no-useless-backreference': 'error', + 'require-atomic-updates': ['error', { allowProperties: true }], + 'use-isnan': 'error', + 'valid-typeof': 'error', + //#endregion - //#region Suggestions (https://eslint.org/docs/latest/rules/#suggestions) - 'accessor-pairs': 'off', - 'arrow-body-style': 'off', - 'block-scoped-var': 'error', - camelcase: ['error', { properties: 'always', ignoreDestructuring: true }], - 'capitalized-comments': 'off', - 'class-methods-use-this': 'off', - complexity: 'off', - 'consistent-return': 'off', - 'consistent-this': 'off', - curly: ['error', 'multi-line', 'consistent'], - 'default-case': 'error', - 'default-case-last': 'error', - 'default-param-last': 'error', - 'dot-notation': 'error', - eqeqeq: ['error', 'allow-null'], - 'func-name-matching': 'off', - 'func-names': 'error', - 'func-style': 'off', - 'grouped-accessor-pairs': 'error', - 'guard-for-in': 'off', - 'id-denylist': 'off', - 'id-length': 'off', - 'id-match': 'off', - 'init-declarations': 'off', - 'logical-assignment-operators': 'off', - 'max-classes-per-file': 'off', - 'max-depth': 'off', - 'max-lines': 'off', - 'max-lines-per-function': 'off', - 'max-nested-callbacks': 'off', - 'max-params': 'off', - 'max-statements': 'off', - 'multiline-comment-style': 'off', - 'new-cap': 'error', - 'no-alert': 'error', - 'no-array-constructor': 'error', - 'no-bitwise': 'off', - 'no-caller': 'error', - 'no-case-declarations': 'error', - 'no-console': 'error', - 'no-continue': 'off', - 'no-delete-var': 'error', - 'no-div-regex': 'error', - 'no-else-return': 'off', - 'no-empty': 'error', - 'no-empty-function': 'warn', - 'no-empty-static-block': 'error', - 'no-eq-null': 'off', - 'no-eval': 'error', - 'no-extend-native': 'error', - 'no-extra-bind': 'error', - 'no-extra-boolean-cast': 'error', - 'no-extra-label': 'error', - 'no-global-assign': 'error', - 'no-implicit-coercion': 'off', - 'no-implicit-globals': 'error', - 'no-implied-eval': 'error', - 'no-inline-comments': 'off', - 'no-invalid-this': 'error', - 'no-iterator': 'error', - 'no-label-var': 'error', - 'no-labels': 'off', - 'no-lone-blocks': 'error', - 'no-lonely-if': 'error', - 'no-loop-func': 'error', - 'no-magic-numbers': 'off', - 'no-multi-assign': 'error', - 'no-multi-str': 'error', - 'no-negated-condition': 'off', - 'no-nested-ternary': 'off', - 'no-new': 'error', - 'no-new-func': 'error', - 'no-new-wrappers': 'error', - 'no-nonoctal-decimal-escape': 'error', - 'no-object-constructor': 'error', - 'no-octal': 'error', - 'no-octal-escape': 'error', - 'no-param-reassign': 'off', - 'no-plusplus': 'off', - 'no-proto': 'error', - 'no-redeclare': 'error', - 'no-regex-spaces': 'error', - 'no-restricted-exports': 'off', - 'no-restricted-globals': 'off', - 'no-restricted-imports': 'off', - 'no-restricted-properties': 'off', - 'no-restricted-syntax': 'off', - 'no-return-assign': 'error', - 'no-script-url': 'error', - 'no-sequences': 'error', - 'no-shadow': 'off', - 'no-shadow-restricted-names': 'error', - 'no-ternary': 'off', - 'no-throw-literal': 'error', - 'no-undef-init': 'error', - 'no-undefined': 'off', - 'no-underscore-dangle': 'off', - 'no-unneeded-ternary': 'error', - 'no-unused-expressions': 'error', - 'no-unused-labels': 'error', - 'no-useless-call': 'error', - 'no-useless-catch': 'error', - 'no-useless-computed-key': 'error', - 'no-useless-concat': 'error', - 'no-useless-constructor': 'error', - 'no-useless-escape': 'error', - 'no-useless-rename': 'error', - 'no-useless-return': 'error', - 'no-var': 'error', - // Conflicts with typescript-eslint's no-floating-promises rule. - 'no-void': 'off', - 'no-warning-comments': 'warn', - 'no-with': 'error', - 'object-shorthand': 'error', - 'one-var': ['error', { initialized: 'never' }], - 'operator-assignment': 'off', - 'prefer-arrow-callback': 'off', - 'prefer-const': 'off', - 'prefer-destructuring': 'off', - 'prefer-exponentiation-operator': 'error', - 'prefer-named-capture-group': 'warn', - 'prefer-numeric-literals': 'error', - 'prefer-object-has-own': 'error', - 'prefer-object-spread': 'error', - 'prefer-promise-reject-errors': 'error', - 'prefer-regex-literals': 'error', - 'prefer-rest-params': 'error', - 'prefer-spread': 'error', - 'prefer-template': 'error', - radix: 'error', - 'require-await': 'off', - 'require-unicode-regexp': 'off', - 'require-yield': 'error', - 'sort-imports': 'off', - 'sort-keys': 'off', - 'sort-vars': 'off', - strict: ['error', 'global'], - 'symbol-description': 'error', - 'vars-on-top': 'off', - yoda: 'error', - //#endregion + //#region Suggestions (https://eslint.org/docs/latest/rules/#suggestions) + 'accessor-pairs': 'off', + 'arrow-body-style': 'off', + 'block-scoped-var': 'error', + camelcase: ['error', { properties: 'always', ignoreDestructuring: true }], + 'capitalized-comments': 'off', + 'class-methods-use-this': 'off', + complexity: 'off', + 'consistent-return': 'off', + 'consistent-this': 'off', + curly: ['error', 'multi-line', 'consistent'], + 'default-case': 'error', + 'default-case-last': 'error', + 'default-param-last': 'error', + 'dot-notation': 'error', + eqeqeq: ['error', 'allow-null'], + 'func-name-matching': 'off', + 'func-names': 'error', + 'func-style': 'off', + 'grouped-accessor-pairs': 'error', + 'guard-for-in': 'off', + 'id-denylist': 'off', + 'id-length': 'off', + 'id-match': 'off', + 'init-declarations': 'off', + 'logical-assignment-operators': 'off', + 'max-classes-per-file': 'off', + 'max-depth': 'off', + 'max-lines': 'off', + 'max-lines-per-function': 'off', + 'max-nested-callbacks': 'off', + 'max-params': 'off', + 'max-statements': 'off', + 'multiline-comment-style': 'off', + 'new-cap': 'error', + 'no-alert': 'error', + 'no-array-constructor': 'error', + 'no-bitwise': 'off', + 'no-caller': 'error', + 'no-case-declarations': 'error', + 'no-console': 'error', + 'no-continue': 'off', + 'no-delete-var': 'error', + 'no-div-regex': 'error', + 'no-else-return': 'off', + 'no-empty': 'error', + 'no-empty-function': 'warn', + 'no-empty-static-block': 'error', + 'no-eq-null': 'off', + 'no-eval': 'error', + 'no-extend-native': 'error', + 'no-extra-bind': 'error', + 'no-extra-boolean-cast': 'error', + 'no-extra-label': 'error', + 'no-global-assign': 'error', + 'no-implicit-coercion': 'off', + 'no-implicit-globals': 'error', + 'no-implied-eval': 'error', + 'no-inline-comments': 'off', + 'no-invalid-this': 'error', + 'no-iterator': 'error', + 'no-label-var': 'error', + 'no-labels': 'off', + 'no-lone-blocks': 'error', + 'no-lonely-if': 'error', + 'no-loop-func': 'error', + 'no-magic-numbers': 'off', + 'no-multi-assign': 'error', + 'no-multi-str': 'error', + 'no-negated-condition': 'off', + 'no-nested-ternary': 'off', + 'no-new': 'error', + 'no-new-func': 'error', + 'no-new-wrappers': 'error', + 'no-nonoctal-decimal-escape': 'error', + 'no-object-constructor': 'error', + 'no-octal': 'error', + 'no-octal-escape': 'error', + 'no-param-reassign': 'off', + 'no-plusplus': 'off', + 'no-proto': 'error', + 'no-redeclare': 'error', + 'no-regex-spaces': 'error', + 'no-restricted-exports': 'off', + 'no-restricted-globals': 'off', + 'no-restricted-imports': 'off', + 'no-restricted-properties': 'off', + 'no-restricted-syntax': 'off', + 'no-return-assign': 'error', + 'no-script-url': 'error', + 'no-sequences': 'error', + 'no-shadow': 'off', + 'no-shadow-restricted-names': 'error', + 'no-ternary': 'off', + 'no-throw-literal': 'error', + 'no-undef-init': 'error', + 'no-undefined': 'off', + 'no-underscore-dangle': 'off', + 'no-unneeded-ternary': 'error', + 'no-unused-expressions': 'error', + 'no-unused-labels': 'error', + 'no-useless-call': 'error', + 'no-useless-catch': 'error', + 'no-useless-computed-key': 'error', + 'no-useless-concat': 'error', + 'no-useless-constructor': 'error', + 'no-useless-escape': 'error', + 'no-useless-rename': 'error', + 'no-useless-return': 'error', + 'no-var': 'error', + // Conflicts with typescript-eslint's no-floating-promises rule. + 'no-void': 'off', + 'no-warning-comments': 'warn', + 'no-with': 'error', + 'object-shorthand': 'error', + 'one-var': ['error', { initialized: 'never' }], + 'operator-assignment': 'off', + 'prefer-arrow-callback': 'off', + 'prefer-const': 'off', + 'prefer-destructuring': 'off', + 'prefer-exponentiation-operator': 'error', + 'prefer-named-capture-group': 'warn', + 'prefer-numeric-literals': 'error', + 'prefer-object-has-own': 'error', + 'prefer-object-spread': 'error', + 'prefer-promise-reject-errors': 'error', + 'prefer-regex-literals': 'error', + 'prefer-rest-params': 'error', + 'prefer-spread': 'error', + 'prefer-template': 'error', + radix: 'error', + 'require-await': 'off', + 'require-unicode-regexp': 'off', + 'require-yield': 'error', + 'sort-imports': 'off', + 'sort-keys': 'off', + 'sort-vars': 'off', + strict: ['error', 'global'], + 'symbol-description': 'error', + 'vars-on-top': 'off', + yoda: 'error', + //#endregion - //#region Layout & Formatting (https://eslint.org/docs/latest/rules/#layout--formatting) - 'line-comment-position': 'off', - 'unicode-bom': 'error', - //#endregion + //#region Layout & Formatting (https://eslint.org/docs/latest/rules/#layout--formatting) + 'line-comment-position': 'off', + 'unicode-bom': 'error', + //#endregion - //#region Import plugin (https://github.com/import-js/eslint-plugin-import#rules) - // Static analysis - 'import/named': 'error', - 'import/default': 'warn', - 'import/namespace': 'error', - 'import/no-absolute-path': 'error', - 'import/no-webpack-loader-syntax': 'error', - 'import/no-self-import': 'error', - 'import/no-useless-path-segments': 'error', + //#region Import plugin (https://github.com/import-js/eslint-plugin-import#rules) + // Static analysis + 'import/named': 'error', + 'import/default': 'warn', + 'import/namespace': 'error', + 'import/no-absolute-path': 'error', + 'import/no-webpack-loader-syntax': 'error', + 'import/no-self-import': 'error', + 'import/no-useless-path-segments': 'error', - // Helpful warnings - 'import/export': 'error', - 'import/no-named-as-default-member': 'error', - 'import/no-deprecated': 'warn', + // Helpful warnings + 'import/export': 'error', + 'import/no-named-as-default-member': 'error', + 'import/no-deprecated': 'warn', - // Module systems - 'import/no-amd': 'error', + // Module systems + 'import/no-amd': 'error', - // Style guide - 'import/first': 'error', - 'import/no-duplicates': 'error', - 'import/order': [ - 'warn', - { - groups: [ - 'builtin', - 'external', - 'internal', - 'parent', - 'sibling', - 'index', - ], - 'newlines-between': 'always', - alphabetize: { - order: 'asc', + // Style guide + 'import/first': 'error', + 'import/no-duplicates': 'error', + 'import/order': [ + 'warn', + { + groups: [ + 'builtin', + 'external', + 'internal', + 'parent', + 'sibling', + 'index', + ], + 'newlines-between': 'always', + alphabetize: { + order: 'asc', + }, }, + ], + 'import/newline-after-import': 'error', + 'import/no-unassigned-import': [ + 'warn', + { + allow: [ + 'make-promises-safe', + 'node-report', + 'reflect-metadata', + '**/*.css', + 'react-app-polyfill/*', + ], + }, + ], + 'import/no-named-default': 'error', + //#endregion + + //#region No lookbehind plugin (https://github.com/JonasBa/eslint-plugin-no-lookahead-lookbehind-regexp) + 'no-lookahead-lookbehind-regexp/no-lookahead-lookbehind-regexp': [ + 'error', + 'no-lookbehind', + 'no-negative-lookbehind', + { browserslist: false }, + ], + //#endregion + }, + }, + { + // .cjs files are always for Node.js. + files: ['**/*.cjs'], + languageOptions: { + globals: { + ...globals.node, }, - ], - 'import/newline-after-import': 'error', - 'import/no-unassigned-import': [ - 'warn', - { - allow: [ - 'make-promises-safe', - 'node-report', - 'reflect-metadata', - '**/*.css', - 'react-app-polyfill/*', - ], + sourceType: 'commonjs', + }, + }, + { + // Configuration files are usually for Node.js modules. + files: ['**/*.config.{js,cjs,mjs,ts,cts,mts}'], + languageOptions: { + globals: { + ...globals.node, }, - ], - 'import/no-named-default': 'error', - //#endregion - - //#region No lookbehind plugin (https://github.com/JonasBa/eslint-plugin-no-lookahead-lookbehind-regexp) - 'no-lookahead-lookbehind-regexp/no-lookahead-lookbehind-regexp': [ - 'error', - 'no-lookbehind', - 'no-negative-lookbehind', - { browserslist: false }, - ], - //#endregion + }, }, -}; +]; diff --git a/cheminfo.js b/cheminfo.js new file mode 100644 index 0000000..6394f29 --- /dev/null +++ b/cheminfo.js @@ -0,0 +1,5 @@ +import base from './base.js'; +import jsdoc from './jsdoc.js'; +import unicorn from './unicorn.js'; + +export default [...base, ...jsdoc, ...unicorn]; diff --git a/eslintrc.test.yml b/eslintrc.test.yml deleted file mode 100644 index 973e558..0000000 --- a/eslintrc.test.yml +++ /dev/null @@ -1 +0,0 @@ -extends: ['./base.js', './jsdoc.js', './unicorn.js'] diff --git a/index.js b/index.js deleted file mode 100644 index 94f25a9..0000000 --- a/index.js +++ /dev/null @@ -1,5 +0,0 @@ -'use strict'; - -module.exports = { - extends: ['./base.js'], -}; diff --git a/jsdoc.js b/jsdoc.js index 20c9088..eaa8a37 100644 --- a/jsdoc.js +++ b/jsdoc.js @@ -1,33 +1,32 @@ -'use strict'; +import jsdoc from 'eslint-plugin-jsdoc'; -module.exports = { - plugins: ['jsdoc'], - extends: ['plugin:jsdoc/recommended'], - settings: { - jsdoc: { - ignoreInternal: true, - maxLines: 3, - }, - }, - rules: { - 'jsdoc/require-jsdoc': [ - 'warn', - { - publicOnly: true, +export default [ + jsdoc.configs['flat/recommended'], + { + settings: { + jsdoc: { + ignoreInternal: true, + maxLines: 3, }, - ], - 'jsdoc/require-asterisk-prefix': 'warn', - 'jsdoc/require-description': 'warn', - 'jsdoc/require-hyphen-before-param-description': 'warn', + }, + rules: { + 'jsdoc/require-jsdoc': [ + 'warn', + { + publicOnly: true, + }, + ], + 'jsdoc/require-asterisk-prefix': 'warn', + 'jsdoc/require-description': 'warn', + 'jsdoc/require-hyphen-before-param-description': 'warn', + }, }, - overrides: [ - { - files: ['*.{ts,tsx,cts,mts}'], - rules: { - 'jsdoc/require-param-type': 'off', - 'jsdoc/require-returns-type': 'off', - 'jsdoc/no-types': 'warn', - }, + { + files: ['**/*.{ts,tsx,cts,mts}'], + rules: { + 'jsdoc/require-param-type': 'off', + 'jsdoc/require-returns-type': 'off', + 'jsdoc/no-types': 'warn', }, - ], -}; + }, +]; diff --git a/package.json b/package.json index 4732632..a4485ce 100644 --- a/package.json +++ b/package.json @@ -2,10 +2,16 @@ "name": "eslint-config-cheminfo", "version": "10.0.0", "description": "Shared ESLint config for cheminfo and ml.js projects", - "main": "index.js", + "type": "module", + "exports": { + ".": "./cheminfo.js", + "./base": "./base.js", + "./jsdoc": "./jsdoc.js", + "./unicorn": "./unicorn.js" + }, "files": [ + "cheminfo.js", "base.js", - "index.js", "jsdoc.js", "unicorn.js" ], @@ -23,19 +29,19 @@ "url": "https://github.com/cheminfo/eslint-config/issues" }, "homepage": "https://github.com/cheminfo/eslint-config#readme", - "peerDependencies": { - "eslint": "^8.57.0", + "dependencies": { + "@eslint/compat": "^1.1.0", "eslint-plugin-import": "^2.29.1", "eslint-plugin-jsdoc": "^48.5.0", - "eslint-plugin-no-lookahead-lookbehind-regexp": "0.3.0", - "eslint-plugin-unicorn": "^54.0.0" + "eslint-plugin-no-lookahead-lookbehind-regexp": "^0.3.0", + "eslint-plugin-unicorn": "^54.0.0", + "globals": "^15.7.0" + }, + "peerDependencies": { + "eslint": "^8.57.0" }, "devDependencies": { "eslint": "8.57.0", - "eslint-plugin-import": "2.29.1", - "eslint-plugin-jsdoc": "48.5.0", - "eslint-plugin-no-lookahead-lookbehind-regexp": "0.3.0", - "eslint-plugin-unicorn": "54.0.0", "prettier": "^3.3.2" } } diff --git a/test/not-ok.js b/test/not-ok.js index c9c21e7..8f95184 100644 --- a/test/not-ok.js +++ b/test/not-ok.js @@ -1,5 +1,7 @@ 'use strict'; +import '/absolute/path'; + console.log('abc'); let a; diff --git a/test/test.js b/test/test.js index 228b3e3..7835da2 100644 --- a/test/test.js +++ b/test/test.js @@ -1,49 +1,39 @@ -'use strict'; - -const assert = require('assert'); -const util = require('util'); -const { ESLint } = require('eslint'); - -const eslint = new ESLint({ overrideConfigFile: 'eslintrc.test.yml' }); - -eslint - .lintFiles(['test/ok.js', 'test/not-ok.js']) - .then((results) => { - const [okResult, notOkResult] = results; - - assert.strictEqual( - okResult.errorCount, - 0, - 'ok.js should have no error: ' + util.format(okResult.messages), - ); - - assert.strictEqual( - okResult.warningCount, - 0, - 'ok.js should have no warnings: ' + util.format(okResult.messages), - ); - - const errors = notOkResult.messages - .filter(isError) - .map((error) => error.ruleId) - .sort(); - assert.deepStrictEqual(errors, [ - 'no-console', - 'no-lookahead-lookbehind-regexp/no-lookahead-lookbehind-regexp', - 'no-redeclare', - 'no-unused-vars', - 'no-unused-vars', - 'no-var', - 'no-var', - 'one-var', - 'strict', - 'unicorn/no-array-reduce', - ]); - }) - .catch((error) => { - console.error(error); - process.exit(1); - }); +import assert from 'node:assert'; +import fs from 'node:fs'; + +import { Linter } from 'eslint'; + +import config from '../cheminfo.js'; + +function readTestFile(filename) { + return fs.readFileSync(new URL(`./${filename}`, import.meta.url), 'utf8'); +} + +const linter = new Linter({ configType: 'flat' }); + +const okResult = linter.verify(readTestFile('ok.js'), config); +assert.strictEqual(okResult.length, 0, 'ok.js should have no error'); + +const notOkResult = linter.verify(readTestFile('not-ok.js'), config); + +const errors = notOkResult + .filter(isError) + .map((error) => error.ruleId) + .sort(); + +assert.deepStrictEqual(errors, [ + 'import/no-absolute-path', + 'no-console', + 'no-lookahead-lookbehind-regexp/no-lookahead-lookbehind-regexp', + 'no-redeclare', + 'no-unused-vars', + 'no-unused-vars', + 'no-var', + 'no-var', + 'one-var', + 'strict', + 'unicorn/no-array-reduce', +]); function isError(message) { return message.severity === 2; diff --git a/unicorn.js b/unicorn.js index 00986b7..050c274 100644 --- a/unicorn.js +++ b/unicorn.js @@ -1,51 +1,52 @@ -'use strict'; +import unicorn from 'eslint-plugin-unicorn'; -module.exports = { - plugins: ['unicorn'], - extends: ['plugin:unicorn/recommended'], - rules: { - // We are not consistent enough to enable this rule. - 'unicorn/filename-case': 'off', - // Flags i,j,k, etc. - 'unicorn/prevent-abbreviations': 'off', - // TODO: create issue about risk (>32bit integers) - 'unicorn/prefer-math-trunc': 'off', - // We prefer Array.from(x) over [...x] - 'unicorn/prefer-spread': 'off', - // We prefer new Array(x).fill() over Array.from({ length: x }) - 'unicorn/no-new-array': 'off', - // We don't like separators after the comma - 'unicorn/numeric-separators-style': 'off', - // For loop is used sometimes for performance. - 'unicorn/no-for-loop': 'off', - // We use null in many places. - 'unicorn/no-null': 'off', - 'unicorn/switch-case-braces': 'off', - 'unicorn/prefer-ternary': 'off', - 'unicorn/prefer-type-error': 'off', - // Might want to enable in a future semver-major. - 'unicorn/no-negated-condition': 'off', - 'unicorn/no-useless-undefined': 'off', - // Conflicts with Prettier. - 'unicorn/number-literal-case': 'off', - // Too early for full ESM - 'unicorn/prefer-module': 'off', - // Conflicts with Prettier. - 'unicorn/no-nested-ternary': 'off', - // Problematic with useOnOff - 'unicorn/no-unreadable-array-destructuring': 'off', - 'unicorn/prefer-regexp-test': 'off', - // Unfortunately too annoying on valid cases + conflicts with TS. - 'unicorn/no-array-callback-reference': 'off', - // May conflict with other rule + ugly switch(0) auto-fix. - 'unicorn/prefer-switch': 'off', - // Rare and problematic with APIs that have a find method. - 'unicorn/no-array-method-this-argument': 'off', - // We don't use the feature. - 'unicorn/expiring-todo-comments': 'off', - // Doesn't work with typescript-eslint v6 at the moment. - 'unicorn/no-empty-file': 'off', - // We already have a rule for anonymous functions and tooling often does this with config. - 'unicorn/no-anonymous-default-export': 'off', +export default [ + unicorn.configs['flat/recommended'], + { + rules: { + // We are not consistent enough to enable this rule. + 'unicorn/filename-case': 'off', + // Flags i,j,k, etc. + 'unicorn/prevent-abbreviations': 'off', + // TODO: create issue about risk (>32bit integers) + 'unicorn/prefer-math-trunc': 'off', + // We prefer Array.from(x) over [...x]. + 'unicorn/prefer-spread': 'off', + // We prefer new Array(x).fill() over Array.from({ length: x }). + 'unicorn/no-new-array': 'off', + // We don't like separators after the comma. + 'unicorn/numeric-separators-style': 'off', + // For loop is used sometimes for performance. + 'unicorn/no-for-loop': 'off', + // We use null in many places. + 'unicorn/no-null': 'off', + 'unicorn/switch-case-braces': 'off', + 'unicorn/prefer-ternary': 'off', + 'unicorn/prefer-type-error': 'off', + // Might want to enable in a future semver-major. + 'unicorn/no-negated-condition': 'off', + 'unicorn/no-useless-undefined': 'off', + // Conflicts with Prettier. + 'unicorn/number-literal-case': 'off', + // Too early for full ESM. + 'unicorn/prefer-module': 'off', + // Conflicts with Prettier. + 'unicorn/no-nested-ternary': 'off', + // Problematic with useOnOff. + 'unicorn/no-unreadable-array-destructuring': 'off', + 'unicorn/prefer-regexp-test': 'off', + // Unfortunately too annoying on valid cases + conflicts with TS. + 'unicorn/no-array-callback-reference': 'off', + // May conflict with other rule + ugly switch(0) auto-fix. + 'unicorn/prefer-switch': 'off', + // Rare and problematic with APIs that have a find method. + 'unicorn/no-array-method-this-argument': 'off', + // We don't use the feature. + 'unicorn/expiring-todo-comments': 'off', + // Doesn't work with typescript-eslint v6 at the moment. + 'unicorn/no-empty-file': 'off', + // We already have a rule for anonymous functions and tooling often does this with config. + 'unicorn/no-anonymous-default-export': 'off', + }, }, -}; +];