shawnmcknight/react-scrollbar-size

View on GitHub
.eslintrc.js

Summary

Maintainability
A
0 mins
Test Coverage
module.exports = {
    extends: [
        'airbnb',
        'airbnb-typescript',
        'plugin:react/jsx-runtime',
        'plugin:jsx-a11y/recommended',
        'plugin:jest/recommended',
        'plugin:jest/style',
        'plugin:@typescript-eslint/recommended',
        'plugin:import/typescript',
        'prettier',
    ],

    parserOptions: { tsconfigRootDir: __dirname, project: './tsconfig.eslint.json' },

    env: { es2021: true, browser: true, node: true, 'jest/globals': true },

    plugins: ['react-hooks', 'testing-library', 'jest'],

    rules: {
        // enforce curly brace usage
        curly: ['error', 'all'],

        // allow class methods which do not use this
        'class-methods-use-this': 'off',

        // Allow use of ForOfStatement - no-restricted-syntax does not allow us to turn off a rule. This block overrides the airbnb rule entirely
        // https://github.com/airbnb/javascript/blob/7152396219e290426a03e47837e53af6bcd36bbe/packages/eslint-config-airbnb-base/rules/style.js#L257-L263
        'no-restricted-syntax': [
            'error',
            {
                selector: 'ForInStatement',
                message:
                    'for..in loops iterate over the entire prototype chain, which is virtually never what you want. Use Object.{keys,values,entries}, and iterate over the resulting array.',
            },
            {
                selector: 'LabeledStatement',
                message:
                    'Labels are a form of GOTO; using them makes code confusing and hard to maintain and understand.',
            },
            {
                selector: 'WithStatement',
                message:
                    '`with` is disallowed in strict mode because it makes code impossible to predict and optimize.',
            },
        ],

        // enforce consistent sort order
        'sort-imports': ['error', { ignoreCase: true, ignoreDeclarationSort: true }],

        // enforce convention in import order
        'import/order': [
            'error',
            {
                'newlines-between': 'never',
                groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index'],
                alphabetize: { order: 'asc', caseInsensitive: true },
            },
        ],

        // ensure consistent array typings
        '@typescript-eslint/array-type': 'error',

        // ban ts-comment except with description
        '@typescript-eslint/ban-ts-comment': [
            'error',
            {
                'ts-expect-error': 'allow-with-description',
                'ts-ignore': 'allow-with-description',
                'ts-nocheck': true,
                'ts-check': false,
            },
        ],

        // prefer type imports and exports
        '@typescript-eslint/consistent-type-exports': [
            'error',
            { fixMixedExportsWithInlineTypeSpecifier: true },
        ],
        '@typescript-eslint/consistent-type-imports': ['error', { prefer: 'type-imports' }],

        // enforce consistent order of class members
        '@typescript-eslint/member-ordering': 'error',

        // disallow parameter properties in favor of explicit class declarations
        '@typescript-eslint/no-parameter-properties': 'error',

        // disable function-component-definition rule enabled by airbnb
        'react/function-component-definition': 'off',

        // tab indentation
        'react/jsx-indent': ['error', 'tab'],
        'react/jsx-indent-props': ['error', 'tab'],

        // permit spreading of props
        'react/jsx-props-no-spreading': 'off',

        // React triggers no-unused-vars rules
        'react/jsx-uses-react': 'off',

        // typescript is better at prop-types than `prop-types`
        'react/prop-types': 'off',

        // disable react-in-jsx-scope (must use @babel/preset-react option { runtime: 'automatic' })
        // see: https://reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html and https://babeljs.io/docs/en/babel-preset-react/#runtime
        'react/react-in-jsx-scope': 'off',

        // check effect dependencies
        'react-hooks/exhaustive-deps': 'warn',

        // check rules of react hooks
        'react-hooks/rules-of-hooks': 'error',
    },

    overrides: [
        {
            files: ['**/*.ts', '**/*.tsx'],
            extends: ['plugin:@typescript-eslint/recommended-requiring-type-checking'],
            rules: {
                // disable rules turned on by @typescript-eslint/recommended-requiring-type-checking which are too noisy
                // https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/src/configs/recommended-requiring-type-checking.ts
                '@typescript-eslint/no-unsafe-argument': 'off',
                '@typescript-eslint/no-unsafe-assignment': 'off',
                '@typescript-eslint/no-unsafe-call': 'off',
                '@typescript-eslint/no-unsafe-member-access': 'off',
                '@typescript-eslint/no-unsafe-return': 'off',
                '@typescript-eslint/restrict-template-expressions': 'off',
                '@typescript-eslint/unbound-method': 'off',

                // force explicit member accessibility modifiers
                '@typescript-eslint/explicit-member-accessibility': 'error',
            },
        },

        {
            files: ['*.tsx'],
            rules: {
                // no proptypes in typescript components
                'react/require-default-props': 'off',
            },
        },

        {
            files: ['**/index.ts', '**/index.tsx'],
            rules: {
                // prefer named exports for certain file types
                'import/prefer-default-export': 'off',
                'import/no-default-export': 'error',
            },
        },

        {
            files: ['**/__tests__/**/*.[jt]s?(x)', '**/?(*.)+(spec|test).[jt]s?(x)'],
            extends: ['plugin:testing-library/react'],
            rules: {
                // allow tests to create multiple classes
                'max-classes-per-file': 'off',

                // allow side effect constructors
                'no-new': 'off',

                // allow import with CommonJS export
                'import/no-import-module-exports': 'off',

                // disallow use of "it" for test blocks
                'jest/consistent-test-it': ['error', { fn: 'test', withinDescribe: 'test' }],

                // ensure all tests contain an assertion
                'jest/expect-expect': 'error',

                // no commented out tests
                'jest/no-commented-out-tests': 'error',

                // no duplicate test hooks
                'jest/no-duplicate-hooks': 'error',

                // valid titles
                'jest/valid-title': 'error',

                // no if conditionals in tests
                'jest/no-if': 'error',

                // expect statements in test blocks
                'jest/no-standalone-expect': 'error',

                // disallow returning from test
                'jest/no-test-return-statement': 'error',

                // disallow truthy and falsy in tests
                'jest/no-restricted-matchers': ['error', { toBeFalsy: null, toBeTruthy: null }],

                // prefer called with
                'jest/prefer-called-with': 'error',
            },
        },

        {
            files: ['**/__tests__/**/*.ts?(x)', '**/?(*.)+(spec|test).ts?(x)'],
            rules: {
                // allow explicit any in tests
                '@typescript-eslint/no-explicit-any': 'off',

                // allow non-null-assertions
                '@typescript-eslint/no-non-null-assertion': 'off',

                // allow empty arrow functions
                '@typescript-eslint/no-empty-function': ['error', { allow: ['arrowFunctions'] }],
            },
        },

        {
            files: [
                '**/__tests__/**/*.[jt]s?(x)',
                '**/?(*.)+(spec|test).[jt]s?(x)',
                '**/example/*.ts?(x)',
                '**/scripts/*.ts?(x)',
            ],
            rules: {
                // allow dev dependencies
                'import/no-extraneous-dependencies': [
                    'error',
                    { devDependencies: true, optionalDependencies: false, peerDependencies: false },
                ],
            },
        },
    ],
};