Skip to content
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
13 changes: 13 additions & 0 deletions packages/eslint-config-airbnb-base/eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
const base = require('./flat');

module.exports = [
...base,
{ rules: { 'comma-dangle': 'off', 'max-len': 'off' } },
{
files: ['test/**'],
rules: {
'no-shadow': 'off',
'id-length': ['error', { min: 2, properties: 'never', exceptions: ['t'] }],
},
},
];
44 changes: 44 additions & 0 deletions packages/eslint-config-airbnb-base/flat.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
const globals = require('globals');
const importPlugin = require('eslint-plugin-import');

const bestPractices = require('./rules/best-practices');
const errors = require('./rules/errors');
const es6 = require('./rules/es6');
const imports = require('./rules/imports');
const node = require('./rules/node');
const strict = require('./rules/strict');
const style = require('./rules/style');
const variables = require('./rules/variables');

module.exports = [
{
languageOptions: {
ecmaVersion: 2018,
sourceType: 'module',
globals: {
...globals.es2015,
...globals.node,
},
parserOptions: {
ecmaFeatures: {
generators: false,
objectLiteralDuplicateProperties: false,
},
},
},
plugins: {
import: importPlugin,
},
settings: imports.settings,
rules: {
...bestPractices.rules,
...errors.rules,
...node.rules,
...style.rules,
...variables.rules,
...es6.rules,
...imports.rules,
...strict.rules,
},
},
];
10 changes: 6 additions & 4 deletions packages/eslint-config-airbnb-base/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"./rules/imports": "./rules/imports.js",
"./rules/strict": "./rules/strict.js",
"./rules/variables": "./rules/variables.js",
"./flat": "./flat.js",
"./package.json": "./package.json"
},
"scripts": {
Expand Down Expand Up @@ -72,21 +73,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": "^7.32.0 || ^8.2.0 || ^9.0.0",
"eslint-find-rules": "^5.0.0",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

eslint-find-rules v5 doesn't support eslint 7, so this will have to be ^4.1.0 || ^5.0.0

"eslint-plugin-import": "^2.30.0",
"in-publish": "^2.0.1",
"safe-publish-latest": "^2.0.0",
"tape": "^5.9.0"
},
"peerDependencies": {
"eslint": "^7.32.0 || ^8.2.0",
"eslint": "^7.32.0 || ^8.2.0 || ^9.0.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.14.0"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is globals needed? eslint ships with that package and we should be using the same version it uses.

}
}
1 change: 1 addition & 0 deletions packages/eslint-config-airbnb-base/test/requires.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ test('all entry points parse', (t) => {
t.doesNotThrow(() => require('..'), 'index does not throw');
t.doesNotThrow(() => require('../legacy'), 'legacy does not throw');
t.doesNotThrow(() => require('../whitespace'), 'whitespace does not throw');
t.doesNotThrow(() => require('../flat'), 'flat does not throw');

t.end();
});
54 changes: 54 additions & 0 deletions packages/eslint-config-airbnb-base/test/test-flat-parity.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import test from 'tape';

import flatConfig from '../flat';

import bestPractices from '../rules/best-practices';
import errors from '../rules/errors';
import es6 from '../rules/es6';
import imports from '../rules/imports';
import node from '../rules/node';
import strict from '../rules/strict';
import style from '../rules/style';
import variables from '../rules/variables';

test('flat config includes all rules from rule files', (t) => {
// The flat config is an array with one config object
t.ok(Array.isArray(flatConfig), 'flat config is an array');
t.equal(flatConfig.length, 1, 'flat config has one element');

const flatRules = flatConfig[0].rules;

// Merge rules in the same order as flat.js
const expectedRules = {
...bestPractices.rules,
...errors.rules,
...node.rules,
...style.rules,
...variables.rules,
...es6.rules,
...imports.rules,
...strict.rules,
};

const flatKeys = Object.keys(flatRules).sort();
const expectedKeys = Object.keys(expectedRules).sort();

t.deepEqual(flatKeys, expectedKeys, 'flat config has the same rule keys as combined rule files');

expectedKeys.forEach((key) => {
t.deepEqual(flatRules[key], expectedRules[key], `rule "${key}" has matching config`);
});

t.end();
});

test('flat config has required plugins and settings', (t) => {
const config = flatConfig[0];

t.ok(config.plugins.import, 'import plugin is present');
t.ok(config.settings, 'settings are present');
t.ok(config.languageOptions, 'languageOptions are present');
t.equal(config.languageOptions.sourceType, 'module', 'sourceType is module');

t.end();
});
13 changes: 7 additions & 6 deletions packages/eslint-config-airbnb-base/whitespace-async.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ const { isArray } = Array;
const { entries } = Object;
const { ESLint } = require('eslint');

const baseConfig = require('.');
// ESLint 9 transition-period API; will be moot once eslintrc is fully removed in ESLint 10+
const isFlat = ESLint.configType === 'flat';
const baseConfig = isFlat ? require('./flat') : require('.');
const whitespaceRules = require('./whitespaceRules');

const severities = ['off', 'warn', 'error'];
Expand All @@ -20,11 +22,10 @@ function getSeverity(ruleConfig) {
}

async function onlyErrorOnRules(rulesToError, config) {
const errorsOnly = { ...config };
const cli = new ESLint({
useEslintrc: false,
baseConfig: config
});
const errorsOnly = isFlat ? { rules: {} } : { ...config };
const cli = isFlat
? new ESLint({ overrideConfigFile: true, overrideConfig: config })
: new ESLint({ useEslintrc: false, baseConfig: config });
const baseRules = (await cli.calculateConfigForFile(require.resolve('./'))).rules;

entries(baseRules).forEach((rule) => {
Expand Down
18 changes: 17 additions & 1 deletion packages/eslint-config-airbnb-base/whitespace.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,28 @@ if (CLIEngine) {
} else {
const path = require('path');
const { execSync } = require('child_process');
const { ESLint } = require('eslint');

// 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'), {
const ruleOverrides = JSON.parse(String(execSync(path.join(__dirname, 'whitespace-async.js'), {
env: {
...process.env,
TIMING: undefined,
}
})));

// ESLint 9 transition-period API; will be moot once eslintrc is fully removed in ESLint 10+
if (ESLint.configType === 'flat') {
// In flat mode, whitespace-async.js outputs only { rules: {} } since plugins
// are not JSON-serializable. Merge the rule overrides with the full flat config
// so consumers get a complete config with plugins, settings, and languageOptions.
const flatConfig = require('./flat');
const lastConfig = flatConfig[flatConfig.length - 1];
module.exports = [
...flatConfig.slice(0, -1),
{ ...lastConfig, rules: { ...lastConfig.rules, ...ruleOverrides.rules } },
];
} else {
module.exports = ruleOverrides;
}
}
13 changes: 13 additions & 0 deletions packages/eslint-config-airbnb/eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
const airbnb = require('./flat');

module.exports = [
...airbnb,
{ rules: { 'comma-dangle': 'off' } },
{
files: ['test/**'],
rules: {
'no-shadow': 'off',
'id-length': ['error', { min: 2, properties: 'never', exceptions: ['t'] }],
},
},
];
1 change: 1 addition & 0 deletions packages/eslint-config-airbnb/flat-base.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require('eslint-config-airbnb-base/flat');
20 changes: 20 additions & 0 deletions packages/eslint-config-airbnb/flat-hooks.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
const reactHooksPlugin = require('eslint-plugin-react-hooks');

const reactHooks = require('./rules/react-hooks');

module.exports = [
{
files: ['**/*.{js,jsx,mjs,cjs}'],
plugins: {
'react-hooks': reactHooksPlugin,
},
languageOptions: {
parserOptions: {
ecmaFeatures: {
jsx: true,
},
},
},
rules: reactHooks.rules,
},
];
30 changes: 30 additions & 0 deletions packages/eslint-config-airbnb/flat.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
const reactPlugin = require('eslint-plugin-react');
const jsxA11yPlugin = require('eslint-plugin-jsx-a11y');

const baseFlatConfig = require('eslint-config-airbnb-base/flat');

const react = require('./rules/react');
const reactA11y = require('./rules/react-a11y');

module.exports = [
...baseFlatConfig,
{
files: ['**/*.{js,jsx,mjs,cjs}'],
plugins: {
react: reactPlugin,
'jsx-a11y': jsxA11yPlugin,
},
languageOptions: {
parserOptions: {
ecmaFeatures: {
jsx: true,
},
},
},
settings: react.settings,
rules: {
...react.rules,
...reactA11y.rules,
},
},
];
9 changes: 6 additions & 3 deletions packages/eslint-config-airbnb/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
"./rules/react": "./rules/react.js",
"./rules/react-a11y": "./rules/react-a11y.js",
"./rules/react-hooks": "./rules/react-hooks.js",
"./flat": "./flat.js",
"./flat-base": "./flat-base.js",
"./flat-hooks": "./flat-hooks.js",
"./package.json": "./package.json"
},
"scripts": {
Expand Down Expand Up @@ -73,8 +76,8 @@
"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": "^7.32.0 || ^8.2.0 || ^9.0.0",
"eslint-find-rules": "^5.0.0",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here

"eslint-plugin-import": "^2.30.0",
"eslint-plugin-jsx-a11y": "^6.10.0",
"eslint-plugin-react": "^7.36.1",
Expand All @@ -85,7 +88,7 @@
"tape": "^5.9.0"
},
"peerDependencies": {
"eslint": "^7.32.0 || ^8.2.0",
"eslint": "^7.32.0 || ^8.2.0 || ^9.0.0",
"eslint-plugin-import": "^2.30.0",
"eslint-plugin-jsx-a11y": "^6.10.0",
"eslint-plugin-react": "^7.36.1",
Expand Down
3 changes: 3 additions & 0 deletions packages/eslint-config-airbnb/test/requires.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ test('all entry points parse', (t) => {
t.doesNotThrow(() => require('../legacy'), 'legacy does not throw');
t.doesNotThrow(() => require('../whitespace'), 'whitespace does not throw');
t.doesNotThrow(() => require('../hooks'), 'hooks does not throw');
t.doesNotThrow(() => require('../flat'), 'flat does not throw');
t.doesNotThrow(() => require('../flat-base'), 'flat-base does not throw');
t.doesNotThrow(() => require('../flat-hooks'), 'flat-hooks does not throw');

t.end();
});
Loading