React.AddLinterAndPrettier

1-eslint.js

module.exports = {
    /*
     * Отступы = 4 пробела.
     * Код должен быть опрятным и не сливаться в кучу.
     * https://eslint.org/docs/rules/indent
     */
    indent: ['error', 4, { SwitchCase: 1 }],

    /*
     * Запрещается использовать 'магические' числа.
     * Все числа должны быть указаны в виде констант.
     * https://eslint.org/docs/rules/no-magic-numbers
     */
    'no-magic-numbers': ['error', { ignore: [0, 1], detectObjects: false, enforceConst: true }],

    /*
     * Перевод строки после фигурной скобки в объектах.
     * Фигурные скобки должны быть согласованы между собой и переноситься синхронизованно.
     * https://eslint.org/docs/rules/object-curly-newline
     */
    'object-curly-newline': ['error', { consistent: true }],

    /*
     * Разрешается использование только одинарных кавычек.
     * https://eslint.org/docs/rules/quotes
     */
    quotes: ['error', 'single'],

    /*
     * В JSX-элементах разрешается использование только двойных кавычек.
     * https://eslint.org/docs/rules/jsx-quotes
     */
    'jsx-quotes': ['error', 'prefer-double'],

    /*
     * Разрешается использовать сущности до их объявления. TODO: Включить после поднятия версии реакта!
     * Сейчас существует баг с версией React https://stackoverflow.com/questions/63818415/react-was-used-before-it-was-defined
     * Поэтому вместо этого правила, сейчас включено @typescript-eslint/no-use-before-define.
     * https://eslint.org/docs/rules/no-use-before-define
     */
    'no-use-before-define': 'off',

    /*
     * Разрешается использовать имена переменных, как и в родительской области видимости.
     * https://eslint.org/docs/rules/no-shadow
     */
    'no-shadow': 'off',

    /*
     * Семантика стрелочных функций не регламентируется.
     * Возвращать значение сразу или явно указывать return - это непринципиальный кейс.
     * https://eslint.org/docs/rules/arrow-body-style
     */
    'arrow-body-style': 'off',

    /*
     * Максимальное количество символов в строке.
     * В .editorconfig поставляется аналогичное значение.
     * https://eslint.org/docs/rules/max-len
     */
    'max-len': ['error', { code: 120 }],

    /*
     * Максимальное кол-во строк в файле = 1000. TODO: Уменьшить до 500!
     * Файлы должны быть максимально компактными и легко читаемыми.
     * https://eslint.org/docs/rules/max-lines
     */
    'max-lines': ['error', 1000],

    /*
     * Запрещается использование класса console.
     * Единственное исключение = console.error().
     * https://eslint.org/docs/rules/no-console
     */
    'no-console': ['error', { allow: ['warn', 'error'] }],

    /*
     * Разрешается оставлять неиспользованные переменные.
     * Правило включается посредством '@typescript-eslint/no-unused-vars'.
     * Потому что только TS умеет работать с переменными в типизации.
     * https://eslint.org/docs/rules/no-unused-vars
     */
    'no-unused-vars': 'off',

    /*
     * Все файлы должны заканчиваться пустой строкой.
     * Это просто правило хорошего тона.
     * https://eslint.org/docs/rules/eol-last
     */
    'eol-last': ['error', 'always'],

    /*
     * Запрещается использовать стрелки там, где они могут быть спутаны со знаком сравнения.
     * https://eslint.org/docs/rules/no-confusing-arrow
     */
    'no-confusing-arrow': 'error',

    /*
     * Аргументы стрелочной функции всегда должны быть в скобках.
     * Оставление 'висячих' аргументов выглядит неаккуратно в большой массе кода.
     * https://eslint.org/docs/rules/arrow-parens
     */
    'arrow-parens': ['error', 'always'],

    /*
     * Запрещено изменять аргументы функции.
     * Это может привести к неявному изменению значения.
     * https://eslint.org/docs/rules/no-param-reassign
     */
    'no-param-reassign': 'off',

    /*
     * Разрешается использовать и шаблоны и конкатенацию.
     * Конкатенация зачастую выглядит аккуратней.
     * https://eslint.org/docs/rules/prefer-template
     */
    'prefer-template': 'off',

    /*
     * Запрещается javascript:void(0) и подобное.
     * https://eslint.org/docs/rules/no-script-url
     */
    'no-script-url': 'error',

    /*
     * Разрешается любой тип ошибки в 'catch' промиса.
     * https://eslint.org/docs/rules/prefer-promise-reject-errors
     */
    'prefer-promise-reject-errors': 'off',

    /*
     * Правила пустых строк после или до указанных команд.
     * Все правила сводятся к аккуратности итогового кода.
     * https://eslint.org/docs/rules/padding-line-between-statements
     */
    'padding-line-between-statements': [
        'error',
        // Пустая строка после импортов.
        { blankLine: 'always', prev: 'import', next: '*' },
        { blankLine: 'any', prev: 'import', next: 'import' },

        // Пустая строка перед return.
        { blankLine: 'always', prev: '*', next: 'return' },

        // Пустая строка после объявления переменных.
        { blankLine: 'always', prev: ['const', 'let', 'var'], next: '*' },
        {
            blankLine: 'any',
            prev: ['const', 'let', 'var'],
            next: ['const', 'let', 'var'],
        },
    ],

    /*
     * Управление стилем комментариев.
     * https://eslint.org/docs/rules/multiline-comment-style
     */
    'multiline-comment-style': 'off',

    /*
     * Разрешается не использовать 'default' конструкцию в 'switch'.
     * https://eslint.org/docs/rules/default-case
     */
    'default-case': 'off',

    /*
     * Деструктуризация в массивах и объектах необязательна.
     * Мы часто обращаемся к элементу массива по его индексу, а данное правило этому противоречит.
     * https://eslint.org/docs/rules/prefer-destructuring
     */
    'prefer-destructuring': 'off',

    /*
     * Запрещается отделять спред-оператор с переменной пробелом.
     * https://eslint.org/docs/rules/rest-spread-spacing
     */
    'rest-spread-spacing': ['error', 'never'],

    /*
     * Правила переноса скобок массива.
     * Скобки должны быть согласованы между собой и переноситься синхронизовано.
     * https://eslint.org/docs/rules/array-bracket-newline
     */
    'array-bracket-newline': ['error', 'consistent'],

    /*
     * Разрешаются неиспользуемые выражения.
     * Необходимо для выражений типа 'a && c || b()'.
     * https://eslint.org/docs/rules/no-unused-expressions
     */
    'no-unused-expressions': 'off',
};

2-import.js

module.exports = {
    /*
     * Разрешается не указывать расширения файлов для указанных типов.
     * https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/extensions.md
     */
    'import/extensions': [2, 'ignorePackages', { js: 'never', jsx: 'never', ts: 'never', tsx: 'never' }],

    /*
     * Разрешается использовать именованные экспорты (кроме асинхронных компонентов).
     * https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/prefer-default-export.md
     */
    'import/prefer-default-export': 0,

    /*
     * Запрещены 'overhead' импорты, например, при обращении к 'index'.
     * https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-useless-path-segments.md
     */
    'import/no-useless-path-segments': [2, { noUselessIndex: true }],

    /*
     * Проверка резолва происходит за счет сборщика, а не линта.
     * https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-unresolved.md
     */
    'import/no-unresolved': 0,

    /*
     * Сортировка импортов по группам, а внутри них по алфавиту.
     * https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/order.md
     */
    'import/order': [2, { alphabetize: { order: 'asc', caseInsensitive: true } }],

    /*
     * Отключение наблюдение за импортами зависимостей
     * https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-extraneous-dependencies.md
     */
    'import/no-extraneous-dependencies': 'off',
};

3-react.js

module.exports = {
    /*
     * Деструктуризация в 'props', 'state', 'context' необязательна.
     * https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/destructuring-assignment.md
     */
    'react/destructuring-assignment': 0,

    /*
     * Поле 'displayName' у компонента необязателен.
     * https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/display-name.md
     */
    'react/display-name': 0,

    /*
     * Запрещается обращаться к 'this.state' внутри 'setState'.
     * Это может привести к ошибкам, связанным с потерей актуального состояния стейта, когда в очереди несколько
     * вызовов 'setState'. Для получения текущего стейта используйте колбэк.
     * https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-access-state-in-setstate.md
     */
    'react/no-access-state-in-setstate': 2,

    /*
     * Между компонентами, написанными в строку должны быть пробелы.
     * Компоненты не выглядят слипнувшимися и это добавляет аккуратности.
     * https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-adjacent-inline-elements.md
     */
    'react/no-adjacent-inline-elements': 2,

    /*
     * Запрещается использовать индексы массивов для 'key' в React-компонентах.
     * TODO: Включить! Потому что это правило добавляет safety в проект.
     * https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-array-index-key.md
     */
    'react/no-array-index-key': 1,

    /*
     * Запрещается использование 'опасных' пропсов.
     * https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-danger.md
     */
    'react/no-danger': 2,

    /*
     * Запрещается мутировать стейт напрямую (кроме конструктора класса).
     * https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-direct-mutation-state.md
     */
    'react/no-direct-mutation-state': 2,

    /*
     * Предпочитать 'SFC', нежели классы.
     * https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/prefer-stateless-function.md
     */
    'react/prefer-stateless-function': 1,

    /*
     * Стейт создается только в теле класса (не в конструкторе).
     * https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/state-in-constructor.md
     */
    'react/state-in-constructor': [2, 'never'],

    /*
     * Статичные поля описываются только в теле ES6 класса.
     * https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/static-property-placement.md
     */
    'react/static-property-placement': 'off',

    /*
     * Мы не используем prop-types, у нас typescript
     */
    'react/require-default-props': 'off',
    'react/prop-types': 'off',
    'react/function-component-definition': [1, {
        namedComponents: "arrow-function",
        unnamedComponents: "arrow-function"
    }]
};

4-react-jsx.js

module.exports = {
    /*
     * Перенос фигурных скобок в JSX-элементах не регламентируется.
     * https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-curly-newline.md
     */
    'react/jsx-curly-newline': 0,

    /*
     * JSX доступен только в данных файлах.
     * https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-filename-extension.md
     */
    'react/jsx-filename-extension': [2, { extensions: ['.jsx', '.tsx'] }],

    /*
     * Если переносится хотябы одна пропса, то первая тоже должна перенести.
     * https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-first-prop-new-line.md
     */
    'react/jsx-first-prop-new-line': [2, 'multiline'],

    /*
     * Обязательны корректные префиксы для хендлеров.
     * https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-handler-names.md
     */
    'react/jsx-handler-names': 2,

    /*
     * В 'JSX' тэгах отступ ревен 4 пробелам.
     * https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-indent.md
     */
    'react/jsx-indent': [2, 4],

    /*
     * В пропсах отступ ревен 4 пробелам.
     * https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-indent-props.md
     */
    'react/jsx-indent-props': [2, 4],

    /*
     * Свойство 'key' обязательно если оно требуется.
     * https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-key.md
     */
    'react/jsx-key': 2,

    /*
     * Максимальная вложенность элементов = 10.
     * https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-max-depth.md
     */
    'react/jsx-max-depth': [2, { max: 10 }],

    /*
     * Между 'JSX-элементами' необязательна пустая строка. (потому что есть JSX комменты для JSX элементов).
     * https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-newline.md
     */
    'react/jsx-newline': 0,

    /*
     * Запрещены биндинги и стрелочные функции в пропсах.
     * https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-bind.md
     */
    'react/jsx-no-bind': 2,

    /*
     * Запрещается в контекст провайдера помещать нестабильные пропсы.
     * https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-constructed-context-values.md
     */
    'react/jsx-no-constructed-context-values': 2,

    /*
     * Запрещены опасные js-ссылки (<a href="javascript:void(0)"></a>).
     * https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-script-url.md
     */
    'react/jsx-no-script-url': 2,

    /*
     * Безопасное открытие ссылок не регламентируется.
     * https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-target-blank.md
     */
    'react/jsx-no-target-blank': 0,

    /*
     * Запрещены избыточные фрагменты.
     * https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-useless-fragment.md
     */
    'react/jsx-no-useless-fragment': 2,

    /*
     * Спред-пропсы разрешены.
     * https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-props-no-spreading.md
     */
    'react/jsx-props-no-spreading': 0,

    /*
     * Необходимо поддерживать алфавитный порядок в пропсах.
     * https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-sort-props.md
     */
    'react/jsx-sort-props': [2, { ignoreCase: true, shorthandLast: true }],
};

5-lodash.js

module.exports = {
    /*
     * Разрешаются только точечные импорты из библиотеки lodash.
     * Потому что только так сокращается размер данной библиотеки.
     * https://github.com/wix/eslint-plugin-lodash/blob/master/docs/rules/import-scope.md
     */
    'lodash/import-scope': [2, 'method'],
    /*
     * Есть функции, для которых это правило не подходит, например shouldComponentUpdate.
     * https://github.com/wix/eslint-plugin-lodash/blob/v7.2.0/docs/rules/import-scope.md
     */
    'lodash/prefer-constant': 'off',
    /*
     * Нам далеко не всегда нужно импортировать lodash.
     * https://github.com/wix/eslint-plugin-lodash/blob/v7.2.0/docs/rules/prefer-lodash-method.md
     */
    'lodash/prefer-lodash-method': 'off',
};

6-typescript.js

module.exports = {
    /*
     * Отступы = 4 пробела.
     * Дублирующее правило 'indent' из eslint, создано для перестраховки.
     * https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/indent.md
     */
    '@typescript-eslint/indent': [2, 4],

    /*
     * У функций бывают очень длинные возвращаемые типы, поэтому это не всегда целесообразно для соблюдения чистоты кода.
     * https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/explicit-function-return-type.md
     */
    '@typescript-eslint/explicit-function-return-type': 0,

    /*
     * Правила разделителей в интерфейсах (точка с запятой).
     * https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/member-delimiter-style.md
     */
    '@typescript-eslint/member-delimiter-style': 2,

    /*
     * Запрещаются неиспользованные переменные.
     * Кроме переменных в типизации и спред-операторов.
     * https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-unused-vars.md
     */
    '@typescript-eslint/no-unused-vars': [
        2,
        {
            vars: 'all',
            args: 'after-used',
            ignoreRestSiblings: true,
        },
    ],

    /*
     * Типизировать граничные функции необязательно. TODO: Пересмотреть правило!
     * Сейчас достаточно использования '@typescript-eslint/explicit-function-return-type'.
     * https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/explicit-module-boundary-types.md
     */
    '@typescript-eslint/explicit-module-boundary-types': 0,

    /*
     * Модификаторы доступа необязательны.
     * https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/explicit-member-accessibility.md
     */
    '@typescript-eslint/explicit-member-accessibility': 0,

    /*
     * Запрещается использовать сущности до их объявления. TODO: Включить полностью!
     * https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-use-before-define.md
     */
    '@typescript-eslint/no-use-before-define': 1,

    /*
     * Разрешаются к использованию всевозможные типы.
     * В будущем тут можно явно ограничивать использование типов.
     * https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/ban-types.md
     */
    '@typescript-eslint/ban-types': 0,

    /*
     * Разрешается импорт через require.
     * https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-var-requires.md
     */
    '@typescript-eslint/no-var-requires': 0,
};

7-jsx-a11y.js

module.exports = {
    /*
     * Данные правила (jsx-a11y) пришли из стайлгайда airbnb.
     * https://github.com/jsx-eslint/eslint-plugin-jsx-a11y
     */

    /*
     * Видимые элементы должны иметь заполненный атрибут alt
     * https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/alt-text.md
     */
    'jsx-a11y/alt-text': ['error', { elements: ['img', 'object', 'area', 'input[type="image"]'] }],

    /*
     * Видимые элементы должны иметь заполненный атрибут alt
     * https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/anchor-has-content.md
     */
    'jsx-a11y/anchor-has-content': 'warn',

    /*
     * Для композитных элементов, внутренний фокус должен быть равен нулю или быть положительным
     * https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/aria-activedescendant-has-tabindex.md
     */
    'jsx-a11y/aria-activedescendant-has-tabindex': 'warn',

    /*
     * Корректные названия для aria-* атрибутов
     * https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/aria-props.md
     */
    'jsx-a11y/aria-props': 'warn',

    /*
     * Валидные значения для aria элементов
     * https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/aria-proptypes.md
     */
    'jsx-a11y/aria-proptypes': 'warn',

    /*
     * Валидные значения для aria ролей
     * https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/aria-role.md
     * Список ролей https://www.w3.org/TR/wai-aria/#role_definitions
     */
    'jsx-a11y/aria-role': 'warn',

    /*
     * Не использовать элементы, не поддерживаемые aria
     * https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/aria-unsupported-elements.md
     */
    'jsx-a11y/aria-unsupported-elements': 'warn',

    /*
     * Дублирование кликов мыши событиями на клавиатуре
     * https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/click-events-have-key-events.md
     */
    'jsx-a11y/click-events-have-key-events': 'warn',

    /*
     * Заголовок дожен иметь контент и он не должен быть спрятан
     * https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/heading-has-content.md
     */
    'jsx-a11y/heading-has-content': 'warn',

    /*
     * Атрибут html должен иметь тег lang
     * https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/html-has-lang.md
     */
    'jsx-a11y/html-has-lang': 'warn',

    /*
     * Элементы <iframe> должны иметь уникальное имя
     * https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/iframe-has-title.md
     */
    'jsx-a11y/iframe-has-title': 'warn',

    /*
     * Избыточное описание для тега img, скринридеры уже объявляют img элементы картинками
     * https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/img-redundant-alt.md
     */
    'jsx-a11y/img-redundant-alt': ['warn', { elements: ['img'], words: ['Иконка', 'Картинка'] }],

    /*
     * Все активные элементы должны уметь получать фокус
     * https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/interactive-supports-focus.md
     */
    'jsx-a11y/interactive-supports-focus': 'warn',

    /*
     * Медиа-теги audio, video и др. должны иметь специальный атрибут название для скринридера
     * https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/media-has-caption.md
     */
    'jsx-a11y/media-has-caption': 'warn',

    /*
     * Дублирование событий мыши событиями на клавиатуре для пользователей только клавиатуры
     * https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/mouse-events-have-key-events.md
     */
    'jsx-a11y/mouse-events-have-key-events': 'warn',

    /*
     * Запрет атрибута accessKey, чтобы не создавать путаницу скринридерам
     * https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-access-key.md
     */
    'jsx-a11y/no-access-key': 'warn',

    /*
     * Запрет на использование тега autoFocus
     * https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-autofocus.md
     */
    'jsx-a11y/no-autofocus': ['warn', { ignoreNonDOM: true }],

    /*
     * Запрет на использование элементов <marquee> и <blink>
     * https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-distracting-elements.md
     */
    'jsx-a11y/no-distracting-elements': 'warn',

    /*
     * Не интерактивные aria роли не должны использоваться с интерактивными элементами, кроме <tr>
     * https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-interactive-element-to-noninteractive-role.md
     */
    'jsx-a11y/no-interactive-element-to-noninteractive-role': ['warn', { tr: ['none', 'presentation'] }],

    /*
     * Не использовать обработчики в неинтерактивных элементах
     * https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-noninteractive-element-interactions.md
     */
    'jsx-a11y/no-noninteractive-element-interactions': [
        'warn',
        {
            handlers: ['onClick', 'onMouseDown', 'onMouseUp', 'onKeyPress', 'onKeyDown', 'onKeyUp'],
        },
    ],

    /*
     * Не интерактивные элементы не должны использоваться с интерактивными ролями
     * https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-static-element-interactions.md
     */
    'jsx-a11y/no-noninteractive-element-to-interactive-role': [
        'warn',
        {
            ul: ['listbox', 'menu', 'menubar', 'radiogroup', 'tablist', 'tree', 'treegrid'],
            ol: ['listbox', 'menu', 'menubar', 'radiogroup', 'tablist', 'tree', 'treegrid'],
            li: ['menuitem', 'option', 'row', 'tab', 'treeitem'],
            table: ['grid'],
            td: ['gridcell'],
        },
    ],

    /*
     * Предупреждать об элементах, которые не взаимодействуют с пользователем и
     * на них установлен tabindex
     * https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-noninteractive-tabindex.md
     */
    'jsx-a11y/no-noninteractive-tabindex': [
        'warn',
        {
            tags: [],
            roles: ['tabpanel'],
        },
    ],

    /*
     * Избыточное описание ролей, для элементов, которые и так
     * семантически понятны, например <img role="img"> (.etc)
     * https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-redundant-roles.md
     */
    'jsx-a11y/no-redundant-roles': 'warn',

    /*
     * Присваивание роли для статических элементов
     * https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-static-element-interactions.md
     */
    'jsx-a11y/no-static-element-interactions': [
        'warn',
        {
            handlers: ['onClick', 'onMouseDown', 'onMouseUp', 'onKeyPress', 'onKeyDown', 'onKeyUp'],
        },
    ],

    /*
     * Соответствие aria атрибутов aria ролям
     * https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/role-has-required-aria-props.md
     */
    'jsx-a11y/role-has-required-aria-props': 'warn',

    /*
     * Соответствие aria атрибутов aria ролям
     * https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/role-supports-aria-props.md
     */
    'jsx-a11y/role-supports-aria-props': 'warn',

    /*
     * Атрибут scope должен использоваться только на элементе <th>
     * https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/scope.md
     */
    'jsx-a11y/scope': 'warn',

    /*
     * Таб-индекс элементов равен 0 либо меньше 0, чтобы не нарушать скролл табом по странице
     * https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/tabindex-no-positive.md
     */
    'jsx-a11y/tabindex-no-positive': 'warn',
};

eslint.rc

const eslintRules = require('./tools/eslint/rules/1-eslint');
const importRules = require('./tools/eslint/rules/2-import');
const reactRules = require('./tools/eslint/rules/3-react');
const reactJSXRules = require('./tools/eslint/rules/4-react-jsx');
const lodashRules = require('./tools/eslint/rules/5-lodash');
const typescriptRules = require('./tools/eslint/rules/6-typescript');
const a11yRules = require('./tools/eslint/rules/7-jsx-a11y');

module.exports = {
    root: true,
    env: { browser: true, es6: true, jest: true },

    extends: [
        'eslint:recommended',
        'plugin:import/recommended',
        'plugin:react/recommended',
        'plugin:lodash/recommended',
        'plugin:@typescript-eslint/eslint-recommended',
        'plugin:@typescript-eslint/recommended',
        'airbnb',
        'airbnb/hooks',
        'plugin:@sbbol/web-library-guard/recommended',
        'plugin:jest-dom/recommended',
        'plugin:testing-library/react',
        'prettier',
    ],

    globals: {
        Atomics: 'readonly',
        SharedArrayBuffer: 'readonly',
        JSX: 'readonly',
        page: 'readonly',
        reporter: 'readonly',
        BUILD_VERSION: 'readonly',
        LATEST_COMMIT_HASH: 'readonly',
    },

    parser: '@typescript-eslint/parser',

    parserOptions: {
        ecmaFeatures: { jsx: true },
        ecmaVersion: 2020,
        sourceType: 'module',
    },

    settings: {
        'import/resolver': {
            node: { extensions: ['.js', '.jsx', '.ts', '.tsx'] },
        },
    },

    plugins: ['react', 'lodash', '@typescript-eslint', 'testing-library', 'jest-dom', 'jsx-a11y'],

    rules: {
        // убираем ругань на CRLF под виндой
        'linebreak-style': ['error', process.platform === 'win32' ? 'windows' : 'unix'],

        // Убираем проверку типов react/prop-types, эти функции выполняет TS
        'react/prop-types': 0,

        // Отключаем правила для пустого конструктора
        'no-useless-constructor': 'off',

        // Правила на пустые функции, они необходимы для задания начального значения в контексте, что бы не использовать null
        'lodash/prefer-noop': 'off',
        'no-empty-function': 'off',
        '@typescript-eslint/no-empty-function': 'off',

        // Правила ESLint.
        ...eslintRules,

        // Правила импортов.
        ...importRules,

        // Правила React.
        ...reactRules,

        // Правила React JSX.
        ...reactJSXRules,

        // Правила Lodash.
        ...lodashRules,

        // Правила TypeScript.
        ...typescriptRules,

        // Правила JSX a11y.
        ...a11yRules,
    },
    ignorePatterns: ['.eslintrc.js', 'tools/eslint/rules', 'node_modules', 'out'],
};

.gitignore

...
!.eslintrc.js
!.gitignore
!.npmrc
!.prettierignore
!.prettierrc.js
!.stylelintrc.js
...

prettierrc.js

module.exports = {
    tabWidth: 4,
    printWidth: 120,
    useTabs: false,
    semi: true,
    singleQuote: true,
    quoteProps: 'as-needed',
    jsxSingleQuote: false,
    trailingComma: 'all',
    bracketSpacing: true,
    jsxBracketSameLine: false,
    arrowParens: 'always',
    endOfLine: 'auto',
};

prettierrc.ignore

# Add files here to ignore them from prettier formatting
/out
/node_modules
package-lock.json
/src/assets

lint-staged.config.js

module.exports = {
    /** Синтакс функции позволяет запустить tsc с tsconfig.json. */
    '*.{ts,tsx}': [() => 'tsc --noEmit'],
    '*.{ts,tsx,less}': ['npm run prettier:pre-commit'],
    'src/**/*.less': ['npm run stylelint:pre-commit'],
    '{src,__mocks__,__tests__}/**/*.{ts,tsx}': ['npm run eslint:pre-commit'],
};

Package.json

...
devDependencies
        "electron-to-chromium": "1.4.118",
        "eslint-config-airbnb": "19.0.4",
        "eslint-config-prettier": "8.5.0",
        "eslint-plugin-import": "2.26.0",
        "eslint-plugin-jest-dom": "4.0.1",
        "eslint-plugin-jsx-a11y": "6.6.1",
        "eslint-plugin-lodash": "7.4.0",
        "eslint-plugin-prettier": "4.2.1",
        "eslint-plugin-react": "7.29.4",
        "eslint-plugin-react-hooks": "4.6.0",
        "eslint-plugin-testing-library": "5.6.0",
...
scripts
        "eslint": "eslint",
        "eslint:fix": "eslint \"src/**/*.{ts,tsx}\" --fix",
        "eslint:pre-commit": "eslint \"src/**/*.{ts,tsx}\" --fix --color --max-warnings=0",
        "eslint:src": "eslint \"src/**/*.{ts,tsx}\"",
        "stylelint": "stylelint \"**/*.less\"",
        "stylelint:fix": "stylelint \"**/*.less\" --fix",
        "stylelint:pre-commit": "stylelint \"**/*.less\" --fix --color --max-warnings=0",
        "prettier:pre-commit": "prettier --write \"src/**/*.{js,ts,tsx,less}\"",

123

    "husky": {
        "hooks": {
            "pre-commit": "lint-staged"
        }
    }
This entry was posted in Без рубрики. Bookmark the permalink.