@cfx-dev/eslint-config-ui
Version:
cfx-dev's ESLint config, following our styleguide
236 lines (228 loc) • 7.65 kB
JavaScript
import { FlatCompat } from '@eslint/eslintrc';
import stylistic from '@stylistic/eslint-plugin';
import globals from 'globals';
import noRelativeImportPaths from 'eslint-plugin-no-relative-import-paths';
import reactCompiler from 'eslint-plugin-react-compiler';
import reactHooks from 'eslint-plugin-react-hooks';
import react from 'eslint-plugin-react';
import jsxA11y from 'eslint-plugin-jsx-a11y';
import eslint from '@eslint/js';
import tseslint from 'typescript-eslint';
import path from 'path';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const compat = new FlatCompat({
baseDirectory: __dirname, // optional; default: process.cwd()
resolvePluginsRelativeTo: __dirname, // optional
recommendedConfig: eslint.configs.recommended, // optional unless you're using 'eslint:recommended'
allConfig: eslint.configs.all, // optional unless you're using 'eslint:all'
});
export default tseslint.config([
eslint.configs.recommended,
tseslint.configs.recommended,
// Unused because we use airbnb config
// importPlagin.flatConfigs.recommended,
...compat.extends(
'airbnb',
'airbnb/hooks',
),
stylistic.configs.customize({
indent: 2,
quotes: 'single',
semi: true,
jsx: true,
arrowParens: true,
}),
{
files: ['src/**/*.{ts,tsx}', 'lib/**/*.{ts,tsx}'],
...react.configs.flat.recommended,
...jsxA11y.flatConfigs.recommended,
languageOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
...react.configs.flat.recommended.languageOptions,
...jsxA11y.flatConfigs.recommended.languageOptions,
globals: {
...globals.serviceworker,
...globals.browser,
},
},
plugins: {
react,
'react-hooks': reactHooks,
'jsx-a11y': jsxA11y,
'@stylistic': stylistic,
'no-relative-import-paths': noRelativeImportPaths,
},
settings: {
react: {
version: 'detect',
},
'import/parsers': {
'@typescript-eslint/parser': ['.ts', '.tsx'],
},
'import/resolver': {
typescript: { project: './' },
},
},
rules: {
// Start - Disable rules that are not needed or conflict with stylistic rules
'quote-props': 'off',
'space-before-function-paren': 'off',
'react/jsx-indent': 'off',
'indent': 'off',
// End
'react-hooks/rules-of-hooks': 'error',
'react-hooks/exhaustive-deps': 'error',
'jsx-a11y/alt-text': 'error',
'jsx-a11y/label-has-associated-control': [ 'error', {
'labelComponents': [
'Label',
],
'controlComponents': [
'Input',
'Input*',
'*Input',
'Select',
'Textarea',
'Checkbox',
'Radio',
'DropdownSelect',
'Switch',
'ToggleGroup',
],
'depth': 3,
}],
// stylistic rules start
'@stylistic/jsx-wrap-multilines': ['error', {
declaration: 'parens',
assignment: 'parens',
return: 'parens',
arrow: 'parens',
condition: 'parens',
logical: 'parens',
prop: 'parens',
propertyValue: 'parens',
}],
'@stylistic/jsx-one-expression-per-line': 'off',
'@stylistic/quote-props': ['error', 'as-needed', { numbers: true }],
'max-len': 'off',
'@stylistic/max-len': ['error', { code: 120, ignoreComments: true }],
'@stylistic/multiline-ternary': ['error', 'always'],
'brace-style': 'off',
'@stylistic/brace-style': ['error', '1tbs'],
'@stylistic/object-curly-newline': ['error', {
ObjectExpression: { consistent: true },
ObjectPattern: 'always',
ImportDeclaration: { consistent: true },
ExportDeclaration: { multiline: true, minProperties: 3 },
}],
'@stylistic/object-property-newline': 'error',
// stylistic rules end
'prefer-arrow-callback': 'off',
'linebreak-style': ['error', 'unix'],
'consistent-return': 'off',
'class-methods-use-this': 'off',
'grouped-accessor-pairs': 'error',
'padding-line-between-statements': [
'error',
{ blankLine: 'always', prev: '*', next: 'try' },
{ blankLine: 'always', prev: '*', next: 'if' },
{ blankLine: 'always', prev: '*', next: 'for' },
{ blankLine: 'always', prev: '*', next: 'return' },
{ blankLine: 'always', prev: '*', next: 'switch' },
{ blankLine: 'always', prev: '*', next: 'while' },
],
// Enforce consistent brace style
curly: ['error', 'all'],
'import/prefer-default-export': 'off',
// Will allow devDependencies import in test files
'import/no-extraneous-dependencies': [
'error',
{
devDependencies: ['**/*{.,_}{test,spec,stories}.{ts,tsx}'],
},
],
// Allow spreding in props like: { prop1, ...restProps }
'react/jsx-props-no-spreading': 'off',
'no-shadow': 'off',
'@typescript-eslint/no-shadow': ['error'],
// Very useful exemption when you need to omit some props
'no-unused-vars': 'off',
'@typescript-eslint/no-unused-vars': [
'error',
{
ignoreRestSiblings: true,
destructuredArrayIgnorePattern: '^_',
argsIgnorePattern: '^_',
},
],
// Turn off default react rule that don't useful in ts
'react/require-default-props': 'off',
// We don't need to import React in each jsx file
'react/react-in-jsx-scope': 'off',
'import/no-unresolved': 'error',
// Ignore specific extensions
'import/extensions': [
'error',
'ignorePackages',
{
js: 'never',
jsx: 'never',
ts: 'never',
tsx: 'never',
},
],
'react/jsx-filename-extension': [
1,
{
extensions: ['.tsx'],
},
],
// more options for import/order can be found in documentation
// https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/order.md
'import/order': [
'error',
{
// add new line between groups
'newlines-between': 'always', // ['ignore', 'always', 'always-and-inside-groups', 'never']
// main grouping pattern for imports
groups: [
'builtin', // node 'builtin' modules
'external', // 'external' modules
'internal', // 'internal' modules
'type', // 'type' imports
'object', // 'object'-imports (only available in TypeScript)
'unknown', // special group for unknowns
['sibling', 'parent'], // modules from a 'parent' directory or from the same or a sibling's directory
'index', // 'index' of the current directory
],
// add new line fore pathGroups
distinctGroup: true,
// group imports by pattern
pathGroups: [
{
pattern: './*.module.scss',
group: 'index',
position: 'after',
},
],
// sorting options for imports inside of the group
alphabetize: {
order: 'asc',
caseInsensitive: true,
},
},
],
'no-relative-import-paths/no-relative-import-paths': [
'error',
{
allowSameFolder: true,
allowedDepth: 1,
},
],
},
},
reactCompiler.configs.recommended,
]);