diff --git a/package.json b/package.json index a78bc250d4..2f34299224 100644 --- a/package.json +++ b/package.json @@ -10,12 +10,12 @@ "lint": "markdownlint --config linters/.markdownlint.json README.md */README.md", "pretest": "npm run --silent lint", "test": "npm run --silent test:config && npm run --silent test:config:base", - "test:config": "cd packages/eslint-config-airbnb; npm test", - "test:config:base": "cd packages/eslint-config-airbnb-base; npm test", + "test:config": "cd packages/eslint-config-airbnb && npm test", + "test:config:base": "cd packages/eslint-config-airbnb-base && npm test", "pretravis": "npm run --silent lint", "travis": "npm run --silent travis:config && npm run --silent travis:config:base", - "travis:config": "cd packages/eslint-config-airbnb; npm run travis", - "travis:config:base": "cd packages/eslint-config-airbnb-base; npm run travis" + "travis:config": "cd packages/eslint-config-airbnb && npm run travis", + "travis:config:base": "cd packages/eslint-config-airbnb-base && npm run travis" }, "repository": { "type": "git", diff --git a/packages/eslint-config-airbnb-base/.eslintrc b/packages/eslint-config-airbnb-base/.eslintrc deleted file mode 100644 index 7606a50a46..0000000000 --- a/packages/eslint-config-airbnb-base/.eslintrc +++ /dev/null @@ -1,10 +0,0 @@ -{ - "extends": "./index.js", - "rules": { - // disable requiring trailing commas because it might be nice to revert to - // being JSON at some point, and I don't want to make big changes now. - "comma-dangle": 0, - - "max-len": 0, - }, -} diff --git a/packages/eslint-config-airbnb-base/eslint.config.js b/packages/eslint-config-airbnb-base/eslint.config.js new file mode 100644 index 0000000000..d77e5444de --- /dev/null +++ b/packages/eslint-config-airbnb-base/eslint.config.js @@ -0,0 +1,14 @@ +const globals = require('globals'); +const airbnbBase = require('./index'); + +module.exports = [ + { + ...airbnbBase, + languageOptions: { + ...airbnbBase.languageOptions, + globals: { + ...globals.node, + }, + }, + }, +]; diff --git a/packages/eslint-config-airbnb-base/index.js b/packages/eslint-config-airbnb-base/index.js index 825456b8a4..5a3bf8b1f7 100644 --- a/packages/eslint-config-airbnb-base/index.js +++ b/packages/eslint-config-airbnb-base/index.js @@ -1,17 +1,33 @@ +const stylisticJs = require('@stylistic/eslint-plugin-js'); +const importPlugin = require('eslint-plugin-import'); +const bestPractices = require('./rules/best-practices'); +const errors = require('./rules/errors'); +const node = require('./rules/node'); +const style = require('./rules/style'); +const variables = require('./rules/variables'); +const es6 = require('./rules/es6'); +const imports = require('./rules/imports'); +const strict = require('./rules/strict'); + module.exports = { - extends: [ - './rules/best-practices', - './rules/errors', - './rules/node', - './rules/style', - './rules/variables', - './rules/es6', - './rules/imports', - './rules/strict', - ].map(require.resolve), - parserOptions: { - ecmaVersion: 2018, - sourceType: 'module', + plugins: { + '@stylistic/js': stylisticJs, + import: importPlugin, + }, + languageOptions: { + parserOptions: { + ecmaVersion: 2022, + sourceType: 'module', + }, + }, + rules: { + ...bestPractices.rules, + ...errors.rules, + ...node.rules, + ...style.rules, + ...variables.rules, + ...es6.rules, + ...imports.rules, + ...strict.rules, }, - rules: {}, }; diff --git a/packages/eslint-config-airbnb-base/legacy.js b/packages/eslint-config-airbnb-base/legacy.js index e5c9089c75..63705ef33c 100644 --- a/packages/eslint-config-airbnb-base/legacy.js +++ b/packages/eslint-config-airbnb-base/legacy.js @@ -4,14 +4,14 @@ module.exports = { './rules/errors', './rules/node', './rules/style', - './rules/variables' + './rules/variables', ].map(require.resolve), env: { browser: true, node: true, amd: false, mocha: false, - jasmine: false + jasmine: false, }, rules: { 'comma-dangle': ['error', 'never'], @@ -30,5 +30,5 @@ module.exports = { 'no-var': 'off', 'prefer-object-spread': 'off', strict: ['error', 'safe'], - } + }, }; diff --git a/packages/eslint-config-airbnb-base/package.json b/packages/eslint-config-airbnb-base/package.json index 8f039d4d7c..ef74e6d26f 100644 --- a/packages/eslint-config-airbnb-base/package.json +++ b/packages/eslint-config-airbnb-base/package.json @@ -18,12 +18,11 @@ "./package.json": "./package.json" }, "scripts": { - "prelint": "eclint check $(git ls-files | xargs find 2> /dev/null | grep -vE 'node_modules|\\.git')", - "lint": "eslint --report-unused-disable-directives .", + "prelint": "eclint check \"**/*.js\"", + "lint": "eslint .", "pretests-only": "node ./test/requires", "tests-only": "babel-tape-runner ./test/test-*.js", - "prepublishOnly": "eslint-find-rules --unused && npm test && safe-publish-latest", - "prepublish": "not-in-publish || npm run prepublishOnly", + "prepublish": "not-in-publish || npm test", "pretest": "npm run --silent lint", "test": "npm run --silent tests-only", "pretravis": ":", @@ -72,21 +71,22 @@ "babel-preset-airbnb": "^4.5.0", "babel-tape-runner": "^3.0.0", "eclint": "^2.8.1", - "eslint": "^7.32.0 || ^8.2.0", - "eslint-find-rules": "^4.1.0", + "eslint": "^9.8.0", "eslint-plugin-import": "^2.30.0", "in-publish": "^2.0.1", - "safe-publish-latest": "^2.0.0", - "tape": "^5.9.0" + "safe-publish-latest": "^2.0.0" }, "peerDependencies": { - "eslint": "^7.32.0 || ^8.2.0", + "eslint": "^9.8.0", "eslint-plugin-import": "^2.30.0" }, "engines": { "node": "^10.12.0 || >=12.0.0" }, "dependencies": { - "confusing-browser-globals": "^1.0.11" + "confusing-browser-globals": "^1.0.11", + "globals": "^15.8.0", + "@stylistic/eslint-plugin-js": "^2.4.0", + "tape": "^5.9.0" } } diff --git a/packages/eslint-config-airbnb-base/rules/best-practices.js b/packages/eslint-config-airbnb-base/rules/best-practices.js index 09c247451a..eb0e6fe56c 100644 --- a/packages/eslint-config-airbnb-base/rules/best-practices.js +++ b/packages/eslint-config-airbnb-base/rules/best-practices.js @@ -97,7 +97,7 @@ module.exports = { 'arrowFunctions', 'functions', 'methods', - ] + ], }], // disallow empty destructuring patterns @@ -248,7 +248,7 @@ module.exports = { 'response', // for Express responses '$scope', // for Angular 1 scopes 'staticContext', // for ReactRouter context - ] + ], }], // disallow usage of __proto__ property @@ -419,6 +419,6 @@ module.exports = { // require or disallow Yoda conditions // https://eslint.org/docs/rules/yoda - yoda: 'error' - } + yoda: 'error', + }, }; diff --git a/packages/eslint-config-airbnb-base/rules/errors.js b/packages/eslint-config-airbnb-base/rules/errors.js index a3dda4e510..4ed6fcd350 100644 --- a/packages/eslint-config-airbnb-base/rules/errors.js +++ b/packages/eslint-config-airbnb-base/rules/errors.js @@ -185,5 +185,5 @@ module.exports = { // ensure that the results of typeof are compared against a valid string // https://eslint.org/docs/rules/valid-typeof 'valid-typeof': ['error', { requireStringLiterals: true }], - } + }, }; diff --git a/packages/eslint-config-airbnb-base/rules/es6.js b/packages/eslint-config-airbnb-base/rules/es6.js index 5e59cbebf4..ef7ec9e053 100644 --- a/packages/eslint-config-airbnb-base/rules/es6.js +++ b/packages/eslint-config-airbnb-base/rules/es6.js @@ -1,14 +1,14 @@ module.exports = { env: { - es6: true + es6: true, }, parserOptions: { ecmaVersion: 6, sourceType: 'module', ecmaFeatures: { generators: false, - objectLiteralDuplicateProperties: false - } + objectLiteralDuplicateProperties: false, + }, }, rules: { @@ -73,7 +73,7 @@ module.exports = { // https://eslint.org/docs/rules/no-restricted-imports 'no-restricted-imports': ['off', { paths: [], - patterns: [] + patterns: [], }], // disallow to use this/super before super() calling in constructors. @@ -180,6 +180,6 @@ module.exports = { // enforce spacing around the * in yield* expressions // https://eslint.org/docs/rules/yield-star-spacing - 'yield-star-spacing': ['error', 'after'] - } + 'yield-star-spacing': ['error', 'after'], + }, }; diff --git a/packages/eslint-config-airbnb-base/rules/imports.js b/packages/eslint-config-airbnb-base/rules/imports.js index d36e4908fa..350b321981 100644 --- a/packages/eslint-config-airbnb-base/rules/imports.js +++ b/packages/eslint-config-airbnb-base/rules/imports.js @@ -1,20 +1,20 @@ module.exports = { env: { - es6: true + es6: true, }, parserOptions: { ecmaVersion: 6, - sourceType: 'module' + sourceType: 'module', }, plugins: [ - 'import' + 'import', ], settings: { 'import/resolver': { node: { - extensions: ['.mjs', '.js', '.json'] - } + extensions: ['.mjs', '.js', '.json'], + }, }, 'import/extensions': [ '.js', @@ -91,7 +91,7 @@ module.exports = { '**/protractor.conf.js', // protractor config '**/protractor.conf.*.js', // protractor config '**/karma.conf.js', // karma config - '**/.eslintrc.js' // eslint config + '**/.eslintrc.js', // eslint config ], optionalDependencies: false, }], @@ -260,8 +260,9 @@ module.exports = { unusedExports: true, }], - // Reports the use of import declarations with CommonJS exports in any module except for the main module. - // https://github.com/import-js/eslint-plugin-import/blob/1012eb951767279ce3b540a4ec4f29236104bb5b/docs/rules/no-import-module-exports.md + // Reports the use of import declarations with CommonJS exports in any module + // except for the main module. + // https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/no-import-module-exports.md 'import/no-import-module-exports': ['error', { exceptions: [], }], diff --git a/packages/eslint-config-airbnb-base/rules/node.js b/packages/eslint-config-airbnb-base/rules/node.js index b178d7f909..75336d41bc 100644 --- a/packages/eslint-config-airbnb-base/rules/node.js +++ b/packages/eslint-config-airbnb-base/rules/node.js @@ -1,6 +1,6 @@ module.exports = { env: { - node: true + node: true, }, rules: { @@ -39,5 +39,5 @@ module.exports = { // disallow use of synchronous methods (off by default) 'no-sync': 'off', - } + }, }; diff --git a/packages/eslint-config-airbnb-base/rules/strict.js b/packages/eslint-config-airbnb-base/rules/strict.js index 67cfd5e8a3..c48e5abb96 100644 --- a/packages/eslint-config-airbnb-base/rules/strict.js +++ b/packages/eslint-config-airbnb-base/rules/strict.js @@ -1,6 +1,6 @@ module.exports = { rules: { // babel inserts `'use strict';` for us - strict: ['error', 'never'] - } + strict: ['error', 'never'], + }, }; diff --git a/packages/eslint-config-airbnb-base/rules/style.js b/packages/eslint-config-airbnb-base/rules/style.js index 2e7f6fed44..c92fdea5c6 100644 --- a/packages/eslint-config-airbnb-base/rules/style.js +++ b/packages/eslint-config-airbnb-base/rules/style.js @@ -1,24 +1,24 @@ module.exports = { rules: { // enforce line breaks after opening and before closing array brackets - // https://eslint.org/docs/rules/array-bracket-newline + // https://eslint.style/rules/default/array-bracket-newline // TODO: enable? semver-major - 'array-bracket-newline': ['off', 'consistent'], // object option alternative: { multiline: true, minItems: 3 } + '@stylistic/js/array-bracket-newline': ['off', 'consistent'], // object option alternative: { multiline: true, minItems: 3 } // enforce line breaks between array elements - // https://eslint.org/docs/rules/array-element-newline + // https://eslint.style/rules/default/array-element-newline // TODO: enable? semver-major - 'array-element-newline': ['off', { multiline: true, minItems: 3 }], + '@stylistic/js/array-element-newline': ['off', { multiline: true, minItems: 3 }], // enforce spacing inside array brackets - 'array-bracket-spacing': ['error', 'never'], + '@stylistic/js/array-bracket-spacing': ['error', 'never'], // enforce spacing inside single-line blocks - // https://eslint.org/docs/rules/block-spacing - 'block-spacing': ['error', 'always'], + // https://eslint.style/rules/default/block-spacing + '@stylistic/js/block-spacing': ['error', 'always'], // enforce one true brace style - 'brace-style': ['error', '1tbs', { allowSingleLine: true }], + '@stylistic/js/brace-style': ['error', '1tbs', { allowSingleLine: true }], // require camel case names camelcase: ['error', { properties: 'never', ignoreDestructuring: false }], @@ -39,7 +39,7 @@ module.exports = { }], // require trailing commas in multiline object literals - 'comma-dangle': ['error', { + '@stylistic/js/comma-dangle': ['error', { arrays: 'always-multiline', objects: 'always-multiline', imports: 'always-multiline', @@ -48,10 +48,10 @@ module.exports = { }], // enforce spacing before and after comma - 'comma-spacing': ['error', { before: false, after: true }], + '@stylistic/js/comma-spacing': ['error', { before: false, after: true }], // enforce one true comma style - 'comma-style': ['error', 'last', { + '@stylistic/js/comma-style': ['error', 'last', { exceptions: { ArrayExpression: false, ArrayPattern: false, @@ -64,24 +64,24 @@ module.exports = { ObjectPattern: false, VariableDeclaration: false, NewExpression: false, - } + }, }], // disallow padding inside computed properties - 'computed-property-spacing': ['error', 'never'], + '@stylistic/js/computed-property-spacing': ['error', 'never'], // enforces consistent naming when capturing the current execution context 'consistent-this': 'off', // enforce newline at the end of file, with no multiple empty lines - 'eol-last': ['error', 'always'], + '@stylistic/js/eol-last': ['error', 'always'], - // https://eslint.org/docs/rules/function-call-argument-newline - 'function-call-argument-newline': ['error', 'consistent'], + // https://eslint.style/rules/default/function-call-argument-newline + '@stylistic/js/function-call-argument-newline': ['error', 'consistent'], // enforce spacing between functions and their invocations - // https://eslint.org/docs/rules/func-call-spacing - 'func-call-spacing': ['error', 'never'], + // https://eslint.style/rules/default/func-call-spacing + '@stylistic/js/func-call-spacing': ['error', 'never'], // requires function names to match the name of the variable or property to which they are // assigned @@ -101,8 +101,8 @@ module.exports = { 'func-style': ['off', 'expression'], // require line breaks inside function parentheses if there are line breaks between parameters - // https://eslint.org/docs/rules/function-paren-newline - 'function-paren-newline': ['error', 'multiline-arguments'], + // https://eslint.style/rules/default/function-paren-newline + '@stylistic/js/function-paren-newline': ['error', 'multiline-arguments'], // disallow specified identifiers // https://eslint.org/docs/rules/id-denylist @@ -116,26 +116,26 @@ module.exports = { 'id-match': 'off', // Enforce the location of arrow function bodies with implicit returns - // https://eslint.org/docs/rules/implicit-arrow-linebreak - 'implicit-arrow-linebreak': ['error', 'beside'], + // https://eslint.style/rules/default/implicit-arrow-linebreak + '@stylistic/js/implicit-arrow-linebreak': ['error', 'beside'], // this option sets a specific tab width for your code - // https://eslint.org/docs/rules/indent - indent: ['error', 2, { + // https://eslint.style/rules/default/indent + '@stylistic/js/indent': ['error', 2, { SwitchCase: 1, VariableDeclarator: 1, outerIIFEBody: 1, // MemberExpression: null, FunctionDeclaration: { parameters: 1, - body: 1 + body: 1, }, FunctionExpression: { parameters: 1, - body: 1 + body: 1, }, CallExpression: { - arguments: 1 + arguments: 1, }, ArrayExpression: 1, ObjectExpression: 1, @@ -143,25 +143,25 @@ module.exports = { flatTernaryExpressions: false, // list derived from https://github.com/benjamn/ast-types/blob/HEAD/def/jsx.js ignoredNodes: ['JSXElement', 'JSXElement > *', 'JSXAttribute', 'JSXIdentifier', 'JSXNamespacedName', 'JSXMemberExpression', 'JSXSpreadAttribute', 'JSXExpressionContainer', 'JSXOpeningElement', 'JSXClosingElement', 'JSXFragment', 'JSXOpeningFragment', 'JSXClosingFragment', 'JSXText', 'JSXEmptyExpression', 'JSXSpreadChild'], - ignoreComments: false + ignoreComments: false, }], // specify whether double or single quotes should be used in JSX attributes - // https://eslint.org/docs/rules/jsx-quotes - 'jsx-quotes': ['off', 'prefer-double'], + // https://eslint.style/rules/jsx/jsx-quotes + '@stylistic/js/jsx-quotes': ['off', 'prefer-double'], // enforces spacing between keys and values in object literal properties - 'key-spacing': ['error', { beforeColon: false, afterColon: true }], + '@stylistic/js/key-spacing': ['error', { beforeColon: false, afterColon: true }], // require a space before & after certain keywords - 'keyword-spacing': ['error', { + '@stylistic/js/keyword-spacing': ['error', { before: true, after: true, overrides: { return: { after: true }, throw: { after: true }, - case: { after: true } - } + case: { after: true }, + }, }], // enforce position of line comments @@ -174,12 +174,12 @@ module.exports = { }], // disallow mixed 'LF' and 'CRLF' as linebreaks - // https://eslint.org/docs/rules/linebreak-style - 'linebreak-style': ['error', 'unix'], + // https://eslint.style/rules/default/linebreak-style + '@stylistic/js/linebreak-style': ['error', 'unix'], // require or disallow an empty line between class members - // https://eslint.org/docs/rules/lines-between-class-members - 'lines-between-class-members': ['error', 'always', { exceptAfterSingleLine: false }], + // https://eslint.style/rules/default/lines-between-class-members + '@stylistic/js/lines-between-class-members': ['error', 'always', { exceptAfterSingleLine: false }], // enforces empty lines around comments 'lines-around-comment': 'off', @@ -202,8 +202,8 @@ module.exports = { 'max-depth': ['off', 4], // specify the maximum length of a line in your program - // https://eslint.org/docs/rules/max-len - 'max-len': ['error', 100, 2, { + // https://eslint.style/rules/default/max-len + '@stylistic/js/max-len': ['error', 100, 2, { ignoreUrls: true, ignoreComments: false, ignoreRegExpLiterals: true, @@ -216,7 +216,7 @@ module.exports = { 'max-lines': ['off', { max: 300, skipBlankLines: true, - skipComments: true + skipComments: true, }], // enforce a maximum function length @@ -238,17 +238,17 @@ module.exports = { 'max-statements': ['off', 10], // restrict the number of statements per line - // https://eslint.org/docs/rules/max-statements-per-line - 'max-statements-per-line': ['off', { max: 1 }], + // https://eslint.style/rules/default/max-statements-per-line + '@stylistic/js/max-statements-per-line': ['off', { max: 1 }], // enforce a particular style for multiline comments - // https://eslint.org/docs/rules/multiline-comment-style - 'multiline-comment-style': ['off', 'starred-block'], + // https://eslint.style/rules/default/multiline-comment-style + '@stylistic/js/multiline-comment-style': ['off', 'starred-block'], // require multiline ternary - // https://eslint.org/docs/rules/multiline-ternary + // https://eslint.style/rules/default/multiline-ternary // TODO: enable? - 'multiline-ternary': ['off', 'never'], + '@stylistic/js/multiline-ternary': ['off', 'never'], // require a capital letter for constructors 'new-cap': ['error', { @@ -259,19 +259,19 @@ module.exports = { }], // disallow the omission of parentheses when invoking a constructor with no arguments - // https://eslint.org/docs/rules/new-parens - 'new-parens': 'error', + // https://eslint.style/rules/default/new-parens + '@stylistic/js/new-parens': 'error', // allow/disallow an empty newline after var statement 'newline-after-var': 'off', - // https://eslint.org/docs/rules/newline-before-return + // https://eslint.style/rules/default/newline-before-return 'newline-before-return': 'off', // enforces new line after each method call in the chain to make it // more readable and easy to maintain - // https://eslint.org/docs/rules/newline-per-chained-call - 'newline-per-chained-call': ['error', { ignoreChainWithDepth: 4 }], + // https://eslint.style/rules/default/newline-per-chained-call + '@stylistic/js/newline-per-chained-call': ['error', { ignoreChainWithDepth: 4 }], // disallow use of the Array constructor 'no-array-constructor': 'error', @@ -292,8 +292,8 @@ module.exports = { 'no-lonely-if': 'error', // disallow un-paren'd mixes of different operators - // https://eslint.org/docs/rules/no-mixed-operators - 'no-mixed-operators': ['error', { + // https://eslint.style/rules/default/no-mixed-operators + '@stylistic/js/no-mixed-operators': ['error', { // the list of arithmetic groups disallows mixing `%` and `**` // with other arithmetic operators. groups: [ @@ -307,19 +307,19 @@ module.exports = { ['==', '!=', '===', '!=='], ['&&', '||'], ], - allowSamePrecedence: false + allowSamePrecedence: false, }], // disallow mixed spaces and tabs for indentation - 'no-mixed-spaces-and-tabs': 'error', + '@stylistic/js/no-mixed-spaces-and-tabs': 'error', // disallow use of chained assignment expressions // https://eslint.org/docs/rules/no-multi-assign 'no-multi-assign': ['error'], // disallow multiple empty lines, only one newline at the end, and no new lines at the beginning - // https://eslint.org/docs/rules/no-multiple-empty-lines - 'no-multiple-empty-lines': ['error', { max: 1, maxBOF: 0, maxEOF: 0 }], + // https://eslint.style/rules/default/no-multiple-empty-lines + '@stylistic/js/no-multiple-empty-lines': ['error', { max: 1, maxBOF: 0, maxEOF: 0 }], // disallow negated conditions // https://eslint.org/docs/rules/no-negated-condition @@ -362,13 +362,13 @@ module.exports = { 'no-spaced-func': 'off', // disallow tab characters entirely - 'no-tabs': 'error', + '@stylistic/js/no-tabs': 'error', // disallow the use of ternary operators 'no-ternary': 'off', // disallow trailing whitespace at the end of lines - 'no-trailing-spaces': ['error', { + '@stylistic/js/no-trailing-spaces': ['error', { skipBlankLines: false, ignoreComments: false, }], @@ -388,19 +388,19 @@ module.exports = { 'no-unneeded-ternary': ['error', { defaultAssignment: false }], // disallow whitespace before properties - // https://eslint.org/docs/rules/no-whitespace-before-property - 'no-whitespace-before-property': 'error', + // https://eslint.style/rules/default/no-whitespace-before-property + '@stylistic/js/no-whitespace-before-property': 'error', // enforce the location of single-line statements - // https://eslint.org/docs/rules/nonblock-statement-body-position - 'nonblock-statement-body-position': ['error', 'beside', { overrides: {} }], + // https://eslint.style/rules/default/nonblock-statement-body-position + '@stylistic/js/nonblock-statement-body-position': ['error', 'beside', { overrides: {} }], // require padding inside curly braces - 'object-curly-spacing': ['error', 'always'], + '@stylistic/js/object-curly-spacing': ['error', 'always'], // enforce line breaks between braces - // https://eslint.org/docs/rules/object-curly-newline - 'object-curly-newline': ['error', { + // https://eslint.style/rules/default/object-curly-newline + '@stylistic/js/object-curly-newline': ['error', { ObjectExpression: { minProperties: 4, multiline: true, consistent: true }, ObjectPattern: { minProperties: 4, multiline: true, consistent: true }, ImportDeclaration: { minProperties: 4, multiline: true, consistent: true }, @@ -408,8 +408,8 @@ module.exports = { }], // enforce "same line" or "multiple line" on object properties. - // https://eslint.org/docs/rules/object-property-newline - 'object-property-newline': ['error', { + // https://eslint.style/rules/default/object-property-newline + '@stylistic/js/object-property-newline': ['error', { allowAllPropertiesOnSameLine: true, }], @@ -417,19 +417,19 @@ module.exports = { 'one-var': ['error', 'never'], // require a newline around variable declaration - // https://eslint.org/docs/rules/one-var-declaration-per-line - 'one-var-declaration-per-line': ['error', 'always'], + // https://eslint.style/rules/default/one-var-declaration-per-line + '@stylistic/js/one-var-declaration-per-line': ['error', 'always'], // require assignment operator shorthand where possible or prohibit it entirely // https://eslint.org/docs/rules/operator-assignment 'operator-assignment': ['error', 'always'], // Requires operator at the beginning of the line in multiline statements - // https://eslint.org/docs/rules/operator-linebreak - 'operator-linebreak': ['error', 'before', { overrides: { '=': 'none' } }], + // https://eslint.style/rules/default/operator-linebreak + '@stylistic/js/operator-linebreak': ['error', 'before', { overrides: { '=': 'none' } }], // disallow padding within blocks - 'padded-blocks': ['error', { + '@stylistic/js/padded-blocks': ['error', { blocks: 'never', classes: 'never', switches: 'never', @@ -438,8 +438,8 @@ module.exports = { }], // Require or disallow padding lines between statements - // https://eslint.org/docs/rules/padding-line-between-statements - 'padding-line-between-statements': 'off', + // https://eslint.style/rules/default/padding-line-between-statements + '@stylistic/js/padding-line-between-statements': 'off', // Disallow the use of Math.pow in favor of the ** operator // https://eslint.org/docs/rules/prefer-exponentiation-operator @@ -450,25 +450,25 @@ module.exports = { 'prefer-object-spread': 'error', // require quotes around object literal property names - // https://eslint.org/docs/rules/quote-props.html - 'quote-props': ['error', 'as-needed', { keywords: false, unnecessary: true, numbers: false }], + // https://eslint.style/rules/default/quote-props + '@stylistic/js/quote-props': ['error', 'as-needed', { keywords: false, unnecessary: true, numbers: false }], // specify whether double or single quotes should be used - quotes: ['error', 'single', { avoidEscape: true }], + '@stylistic/js/quotes': ['error', 'single', { avoidEscape: true }], // do not require jsdoc // https://eslint.org/docs/rules/require-jsdoc 'require-jsdoc': 'off', // require or disallow use of semicolons instead of ASI - semi: ['error', 'always'], + '@stylistic/js/semi': ['error', 'always'], // enforce spacing before and after semicolons - 'semi-spacing': ['error', { before: false, after: true }], + '@stylistic/js/semi-spacing': ['error', { before: false, after: true }], // Enforce location of semicolons - // https://eslint.org/docs/rules/semi-style - 'semi-style': ['error', 'last'], + // https://eslint.style/rules/default/semi-style + '@stylistic/js/semi-style': ['error', 'last'], // requires object keys to be sorted 'sort-keys': ['off', 'asc', { caseSensitive: false, natural: true }], @@ -477,25 +477,25 @@ module.exports = { 'sort-vars': 'off', // require or disallow space before blocks - 'space-before-blocks': 'error', + '@stylistic/js/space-before-blocks': 'error', // require or disallow space before function opening parenthesis - // https://eslint.org/docs/rules/space-before-function-paren - 'space-before-function-paren': ['error', { + // https://eslint.style/rules/default/space-before-function-paren + '@stylistic/js/space-before-function-paren': ['error', { anonymous: 'always', named: 'never', - asyncArrow: 'always' + asyncArrow: 'always', }], // require or disallow spaces inside parentheses - 'space-in-parens': ['error', 'never'], + '@stylistic/js/space-in-parens': ['error', 'never'], // require spaces around operators - 'space-infix-ops': 'error', + '@stylistic/js/space-infix-ops': 'error', // Require or disallow spaces before/after unary operators - // https://eslint.org/docs/rules/space-unary-ops - 'space-unary-ops': ['error', { + // https://eslint.style/rules/default/space-unary-ops + '@stylistic/js/space-unary-ops': ['error', { words: true, nonwords: false, overrides: { @@ -503,8 +503,8 @@ module.exports = { }], // require or disallow a space immediately following the // or /* in a comment - // https://eslint.org/docs/rules/spaced-comment - 'spaced-comment': ['error', 'always', { + // https://eslint.style/rules/default/spaced-comment + '@stylistic/js/spaced-comment': ['error', 'always', { line: { exceptions: ['-', '+'], markers: ['=', '!', '/'], // space here to support sprockets directives, slash for TS /// comments @@ -513,22 +513,22 @@ module.exports = { exceptions: ['-', '+'], markers: ['=', '!', ':', '::'], // space here to support sprockets directives and flow comment types balanced: true, - } + }, }], // Enforce spacing around colons of switch statements - // https://eslint.org/docs/rules/switch-colon-spacing - 'switch-colon-spacing': ['error', { after: true, before: false }], + // https://eslint.style/rules/default/switch-colon-spacing + '@stylistic/js/switch-colon-spacing': ['error', { after: true, before: false }], // Require or disallow spacing between template tags and their literals - // https://eslint.org/docs/rules/template-tag-spacing - 'template-tag-spacing': ['error', 'never'], + // https://eslint.style/rules/default/template-tag-spacing + '@stylistic/js/template-tag-spacing': ['error', 'never'], // require or disallow the Unicode Byte Order Mark // https://eslint.org/docs/rules/unicode-bom 'unicode-bom': ['error', 'never'], // require regex literals to be wrapped in parentheses - 'wrap-regex': 'off' - } + '@stylistic/js/wrap-regex': 'off', + }, }; diff --git a/packages/eslint-config-airbnb-base/rules/variables.js b/packages/eslint-config-airbnb-base/rules/variables.js index 7d61989e6a..f968e1ab47 100644 --- a/packages/eslint-config-airbnb-base/rules/variables.js +++ b/packages/eslint-config-airbnb-base/rules/variables.js @@ -55,5 +55,5 @@ module.exports = { // disallow use of variables before they are defined 'no-use-before-define': ['error', { functions: true, classes: true, variables: true }], - } + }, }; diff --git a/packages/eslint-config-airbnb-base/test/test-base.js b/packages/eslint-config-airbnb-base/test/test-base.js index 4380bf5567..9f83f4b5d8 100644 --- a/packages/eslint-config-airbnb-base/test/test-base.js +++ b/packages/eslint-config-airbnb-base/test/test-base.js @@ -22,7 +22,7 @@ Object.keys(files).forEach(( // scan plugins for react and fail if it is found const hasReactPlugin = Object.prototype.hasOwnProperty.call(config, 'plugins') - && config.plugins.indexOf('react') !== -1; + && Object.prototype.hasOwnProperty.call(config.plugins, 'react'); t.notOk(hasReactPlugin, 'there is no react plugin'); // scan rules for react/ and fail if any exist diff --git a/packages/eslint-config-airbnb-base/whitespace-async.js b/packages/eslint-config-airbnb-base/whitespace-async.js index 06f4f89075..a8f9ca7074 100755 --- a/packages/eslint-config-airbnb-base/whitespace-async.js +++ b/packages/eslint-config-airbnb-base/whitespace-async.js @@ -23,7 +23,7 @@ async function onlyErrorOnRules(rulesToError, config) { const errorsOnly = { ...config }; const cli = new ESLint({ useEslintrc: false, - baseConfig: config + baseConfig: config, }); const baseRules = (await cli.calculateConfigForFile(require.resolve('./'))).rules; @@ -46,4 +46,5 @@ async function onlyErrorOnRules(rulesToError, config) { return errorsOnly; } +// eslint-disable-next-line no-console onlyErrorOnRules(whitespaceRules, baseConfig).then((config) => console.log(JSON.stringify(config))); diff --git a/packages/eslint-config-airbnb-base/whitespace.js b/packages/eslint-config-airbnb-base/whitespace.js index 01e5198671..1652772649 100644 --- a/packages/eslint-config-airbnb-base/whitespace.js +++ b/packages/eslint-config-airbnb-base/whitespace.js @@ -1,61 +1,46 @@ -/* eslint global-require: 0 */ - const { isArray } = Array; const { entries } = Object; -const { CLIEngine } = require('eslint'); - -if (CLIEngine) { - /* eslint no-inner-declarations: 0 */ - const whitespaceRules = require('./whitespaceRules'); +const { ESLint } = require('eslint'); - const baseConfig = require('.'); +const whitespaceRules = require('./whitespaceRules'); +const baseConfig = require('.'); - const severities = ['off', 'warn', 'error']; +const severities = ['off', 'warn', 'error']; - function getSeverity(ruleConfig) { - if (isArray(ruleConfig)) { - return getSeverity(ruleConfig[0]); - } - if (typeof ruleConfig === 'number') { - return severities[ruleConfig]; - } - return ruleConfig; +function getSeverity(ruleConfig) { + if (isArray(ruleConfig)) { + return getSeverity(ruleConfig[0]); } - - function onlyErrorOnRules(rulesToError, config) { - const errorsOnly = { ...config }; - const cli = new CLIEngine({ baseConfig: config, useEslintrc: false }); - const baseRules = cli.getConfigForFile(require.resolve('./')).rules; - - entries(baseRules).forEach((rule) => { - const ruleName = rule[0]; - const ruleConfig = rule[1]; - const severity = getSeverity(ruleConfig); - - if (rulesToError.indexOf(ruleName) === -1 && severity === 'error') { - if (isArray(ruleConfig)) { - errorsOnly.rules[ruleName] = ['warn'].concat(ruleConfig.slice(1)); - } else if (typeof ruleConfig === 'number') { - errorsOnly.rules[ruleName] = 1; - } else { - errorsOnly.rules[ruleName] = 'warn'; - } - } - }); - - return errorsOnly; + if (typeof ruleConfig === 'number') { + return severities[ruleConfig]; } + return ruleConfig; +} - module.exports = onlyErrorOnRules(whitespaceRules, baseConfig); -} else { - const path = require('path'); - const { execSync } = require('child_process'); - - // NOTE: ESLint adds runtime statistics to the output (so it's no longer JSON) if TIMING is set - module.exports = JSON.parse(String(execSync(path.join(__dirname, 'whitespace-async.js'), { - env: { - ...process.env, - TIMING: undefined, +async function onlyErrorOnRules(rulesToError, config) { + const errorsOnly = { ...config }; + const cli = new ESLint({ + baseConfig: config, + }); + const baseRules = (await cli.calculateConfigForFile(require.resolve('./'))).rules; + + entries(baseRules).forEach((rule) => { + const ruleName = rule[0]; + const ruleConfig = rule[1]; + const severity = getSeverity(ruleConfig); + + if (rulesToError.indexOf(ruleName) === -1 && severity === 'error') { + if (isArray(ruleConfig)) { + errorsOnly.rules[ruleName] = ['warn'].concat(ruleConfig.slice(1)); + } else if (typeof ruleConfig === 'number') { + errorsOnly.rules[ruleName] = 1; + } else { + errorsOnly.rules[ruleName] = 'warn'; + } } - }))); + }); + + return errorsOnly; } + +module.exports = onlyErrorOnRules(whitespaceRules, baseConfig); diff --git a/packages/eslint-config-airbnb-base/whitespaceRules.js b/packages/eslint-config-airbnb-base/whitespaceRules.js index 6b0d3bfec7..aa8af3dcf1 100644 --- a/packages/eslint-config-airbnb-base/whitespaceRules.js +++ b/packages/eslint-config-airbnb-base/whitespaceRules.js @@ -45,5 +45,5 @@ module.exports = [ 'spaced-comment', 'switch-colon-spacing', 'template-tag-spacing', - 'import/newline-after-import' + 'import/newline-after-import', ]; diff --git a/packages/eslint-config-airbnb/index.js b/packages/eslint-config-airbnb/index.js index 6432e10dda..922f49bf46 100644 --- a/packages/eslint-config-airbnb/index.js +++ b/packages/eslint-config-airbnb/index.js @@ -4,5 +4,6 @@ module.exports = { './rules/react', './rules/react-a11y', ].map(require.resolve), + plugins: ['@stylistic/react'], rules: {} }; diff --git a/packages/eslint-config-airbnb/package.json b/packages/eslint-config-airbnb/package.json index c36359ea7c..74e8fe867b 100644 --- a/packages/eslint-config-airbnb/package.json +++ b/packages/eslint-config-airbnb/package.json @@ -66,15 +66,15 @@ }, "homepage": "https://github.com/airbnb/javascript", "dependencies": { - "eslint-config-airbnb-base": "^15.0.0" + "eslint-config-airbnb-base": "file:../eslint-config-airbnb-base" }, "devDependencies": { "@babel/runtime": "^7.25.6", "babel-preset-airbnb": "^4.5.0", "babel-tape-runner": "^3.0.0", "eclint": "^2.8.1", - "eslint": "^7.32.0 || ^8.2.0", - "eslint-find-rules": "^4.1.0", + "eslint": "^9.8.0", + "@stylistic/eslint-plugin-jsx": "^1.7.0", "eslint-plugin-import": "^2.30.0", "eslint-plugin-jsx-a11y": "^6.10.0", "eslint-plugin-react": "^7.36.1", @@ -85,7 +85,7 @@ "tape": "^5.9.0" }, "peerDependencies": { - "eslint": "^7.32.0 || ^8.2.0", + "eslint": "^9.8.0", "eslint-plugin-import": "^2.30.0", "eslint-plugin-jsx-a11y": "^6.10.0", "eslint-plugin-react": "^7.36.1", diff --git a/packages/eslint-config-airbnb/rules/react.js b/packages/eslint-config-airbnb/rules/react.js index c4d29e0b39..63be23d7d4 100644 --- a/packages/eslint-config-airbnb/rules/react.js +++ b/packages/eslint-config-airbnb/rules/react.js @@ -22,8 +22,8 @@ module.exports = { }], // Specify whether double or single quotes should be used in JSX attributes - // https://eslint.org/docs/rules/jsx-quotes - 'jsx-quotes': ['error', 'prefer-double'], + // https://eslint.style/rules/jsx/jsx-quotes + '@stylistic/jsx/jsx-quotes': ['error', 'prefer-double'], 'class-methods-use-this': ['error', { exceptMethods: [ @@ -74,16 +74,16 @@ module.exports = { 'react/jsx-boolean-value': ['error', 'never', { always: [] }], // Validate closing bracket location in JSX - // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-closing-bracket-location.md - 'react/jsx-closing-bracket-location': ['error', 'line-aligned'], + // https://eslint.style/rules/jsx/jsx-closing-bracket-location + '@stylistic/jsx/jsx-closing-bracket-location': ['error', 'line-aligned'], // Validate closing tag location in JSX - // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-closing-tag-location.md - 'react/jsx-closing-tag-location': 'error', + // https://eslint.style/rules/jsx/jsx-closing-tag-location + '@stylistic/jsx/jsx-closing-tag-location': 'error', // Enforce or disallow spaces inside of curly braces in JSX attributes - // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-curly-spacing.md - 'react/jsx-curly-spacing': ['error', 'never', { allowMultiline: true }], + // https://eslint.style/rules/jsx/jsx-curly-spacing + '@stylistic/jsx/jsx-curly-spacing': ['error', 'never', { allowMultiline: true }], // Enforce event handler naming conventions in JSX // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-handler-names.md @@ -93,8 +93,8 @@ module.exports = { }], // Validate props indentation in JSX - // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-indent-props.md - 'react/jsx-indent-props': ['error', 2], + // https://eslint.style/rules/jsx/jsx-indent-props + '@stylistic/jsx/jsx-indent-props': ['error', 2], // Validate JSX has key prop when in array or iterator // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-key.md @@ -102,8 +102,8 @@ module.exports = { 'react/jsx-key': 'off', // Limit maximum of props on a single line in JSX - // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-max-props-per-line.md - 'react/jsx-max-props-per-line': ['error', { maximum: 1, when: 'multiline' }], + // https://eslint.style/rules/jsx/jsx-max-props-per-line + '@stylistic/jsx/jsx-max-props-per-line': ['error', { maximum: 1, when: 'multiline' }], // Prevent usage of .bind() in JSX props // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-no-bind.md @@ -241,8 +241,8 @@ module.exports = { 'react/require-render-return': 'error', // Prevent extra closing tags for components without children - // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/self-closing-comp.md - 'react/self-closing-comp': 'error', + // https://eslint.style/rules/jsx/self-closing-comp + '@stylistic/jsx/self-closing-comp': 'error', // Enforce component methods order // https://github.com/jsx-eslint/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/sort-comp.md @@ -297,8 +297,8 @@ module.exports = { }], // Prevent missing parentheses around multilines JSX - // https://github.com/jsx-eslint/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/jsx-wrap-multilines.md - 'react/jsx-wrap-multilines': ['error', { + // https://eslint.style/rules/jsx/jsx-wrap-multilines + '@stylistic/jsx/jsx-wrap-multilines': ['error', { declaration: 'parens-new-line', assignment: 'parens-new-line', return: 'parens-new-line', @@ -309,16 +309,16 @@ module.exports = { }], // Require that the first prop in a JSX element be on a new line when the element is multiline - // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-first-prop-new-line.md - 'react/jsx-first-prop-new-line': ['error', 'multiline-multiprop'], + // https://eslint.style/rules/jsx/jsx-first-prop-new-line + '@stylistic/jsx/jsx-first-prop-new-line': ['error', 'multiline-multiprop'], // Enforce spacing around jsx equals signs - // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-equals-spacing.md - 'react/jsx-equals-spacing': ['error', 'never'], + // https://eslint.style/rules/jsx/jsx-equals-spacing + '@stylistic/jsx/jsx-equals-spacing': ['error', 'never'], // Enforce JSX indentation - // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-indent.md - 'react/jsx-indent': ['error', 2], + // https://eslint.style/rules/jsx/jsx-indent + '@stylistic/jsx/jsx-indent': ['error', 2], // Disallow target="_blank" on links // https://github.com/jsx-eslint/eslint-plugin-react/blob/ac102885765be5ff37847a871f239c6703e1c7cc/docs/rules/jsx-no-target-blank.md @@ -377,8 +377,8 @@ module.exports = { 'react/no-children-prop': 'error', // Validate whitespace in and around the JSX opening and closing brackets - // https://github.com/jsx-eslint/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/jsx-tag-spacing.md - 'react/jsx-tag-spacing': ['error', { + // https://eslint.style/rules/jsx/jsx-tag-spacing + '@stylistic/jsx/jsx-tag-spacing': ['error', { closingSlash: 'never', beforeSelfClosing: 'always', afterOpening: 'never', @@ -435,12 +435,12 @@ module.exports = { 'react/no-typos': 'error', // Enforce curly braces or disallow unnecessary curly braces in JSX props and/or children - // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-curly-brace-presence.md - 'react/jsx-curly-brace-presence': ['error', { props: 'never', children: 'never' }], + // https://eslint.style/rules/jsx/jsx-curly-brace-presence + '@stylistic/jsx/jsx-curly-brace-presence': ['error', { props: 'never', children: 'never' }], // One JSX Element Per Line - // https://github.com/jsx-eslint/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/jsx-one-expression-per-line.md - 'react/jsx-one-expression-per-line': ['error', { allow: 'single-child' }], + // https://eslint.style/rules/jsx/jsx-one-expression-per-line + '@stylistic/jsx/jsx-one-expression-per-line': ['error', { allow: 'single-child' }], // Enforce consistent usage of destructuring assignment of props, state, and context // https://github.com/jsx-eslint/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/destructuring-assignment.md @@ -459,7 +459,7 @@ module.exports = { }], // Ensures inline tags are not rendered without spaces between them - 'react/jsx-child-element-spacing': 'off', + '@stylistic/jsx/jsx-child-element-spacing': 'off', // Prevent this from being used in stateless functional components // https://github.com/jsx-eslint/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/no-this-in-sfc.md @@ -470,8 +470,8 @@ module.exports = { 'react/jsx-max-depth': 'off', // Disallow multiple spaces between inline JSX props - // https://github.com/jsx-eslint/eslint-plugin-react/blob/ac102885765be5ff37847a871f239c6703e1c7cc/docs/rules/jsx-props-no-multi-spaces.md - 'react/jsx-props-no-multi-spaces': 'error', + // https://eslint.style/rules/jsx/jsx-props-no-multi-spaces + '@stylistic/jsx/jsx-props-no-multi-spaces': 'error', // Prevent usage of UNSAFE_ methods // https://github.com/jsx-eslint/eslint-plugin-react/blob/157cc932be2cfaa56b3f5b45df6f6d4322a2f660/docs/rules/no-unsafe.md @@ -482,8 +482,8 @@ module.exports = { 'react/jsx-fragments': ['error', 'syntax'], // Enforce linebreaks in curly braces in JSX attributes and expressions. - // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-curly-newline.md - 'react/jsx-curly-newline': ['error', { + // https://eslint.style/rules/jsx/jsx-curly-newline + '@stylistic/jsx/jsx-curly-newline': ['error', { multiline: 'consistent', singleline: 'consistent', }], @@ -537,8 +537,8 @@ module.exports = { }], // Enforce a new line after jsx elements and expressions - // https://github.com/jsx-eslint/eslint-plugin-react/blob/e2eaadae316f9506d163812a09424eb42698470a/docs/rules/jsx-newline.md - 'react/jsx-newline': 'off', + // https://eslint.style/rules/jsx/jsx-newline + '@stylistic/jsx/jsx-newline': 'off', // Prevent react contexts from taking non-stable values // https://github.com/jsx-eslint/eslint-plugin-react/blob/e2eaadae316f9506d163812a09424eb42698470a/docs/rules/jsx-no-constructed-context-values.md