Files
gsap-carousel/eslint.config.mjs

266 lines
8.6 KiB
JavaScript
Raw Normal View History

/**
* Конфигурация ESLint 9 (Flat Config)
*
* ESLint - это инструмент для статического анализа JavaScript/TypeScript кода,
* который помогает находить и исправлять проблемы в коде.
*
* Используется новый формат конфигурации (Flat Config) для ESLint 9+
*
* Подключенные плагины:
* - @eslint/js: базовые правила JavaScript
* - typescript-eslint: правила для TypeScript
* - eslint-plugin-react: правила для React
* - eslint-plugin-react-hooks: правила для React Hooks
* - eslint-plugin-jsx-a11y: правила доступности для JSX
* - eslint-plugin-import: правила для импортов
* - eslint-plugin-jest: правила для тестов Jest
* - eslint-plugin-prettier: интеграция с Prettier
*
* Глобальные переменные:
* - __IS_DEV__: флаг режима разработки
* - __API__: URL API
* - __PROJECT__: тип проекта
*
* @example
* // Запуск проверки:
* pnpm lint
*
* // Автоматическое исправление:
* pnpm lint --fix
*/
import js from '@eslint/js'
import prettierConfig from 'eslint-config-prettier'
import importPlugin from 'eslint-plugin-import'
import jestPlugin from 'eslint-plugin-jest'
import jsxA11yPlugin from 'eslint-plugin-jsx-a11y'
import prettierPlugin from 'eslint-plugin-prettier'
import reactPlugin from 'eslint-plugin-react'
import reactHooksPlugin from 'eslint-plugin-react-hooks'
import globals from 'globals'
import tseslint from 'typescript-eslint'
export default [
/**
* Базовые конфигурации
*/
js.configs.recommended,
...tseslint.configs.recommended,
prettierConfig,
/**
* Глобальные исключения (не проверяются линтером)
*/
{
ignores: [
'dist/**',
'node_modules/**',
'.fttemplates/**',
'*.config.js',
'*.config.mjs',
'*.config.ts',
],
},
/**
* Основная конфигурация для всех файлов
*/
{
files: ['**/*.{js,mjs,cjs,ts,tsx}'],
plugins: {
react: reactPlugin,
'react-hooks': reactHooksPlugin,
'jsx-a11y': jsxA11yPlugin,
import: importPlugin,
jest: jestPlugin,
prettier: prettierPlugin,
},
languageOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
parser: tseslint.parser,
parserOptions: {
ecmaFeatures: {
jsx: true,
},
},
globals: {
...globals.browser,
...globals.es2021,
...globals.jest,
__IS_DEV__: 'readonly',
__API__: 'readonly',
__PROJECT__: 'readonly',
},
},
settings: {
react: {
version: 'detect',
},
'import/resolver': {
typescript: true,
node: true,
},
},
rules: {
/**
* Правила для импортов
*/
/** Упорядочивание импортов по группам с алфавитной сортировкой */
'import/order': [
'error',
{
groups: [
['external', 'builtin'],
'internal',
['sibling', 'parent'],
'index',
'type',
],
pathGroups: [
{
pattern: '@react',
group: 'external',
position: 'before',
},
{
pattern: '@/**',
group: 'internal',
},
],
pathGroupsExcludedImportTypes: ['type'],
'newlines-between': 'always',
distinctGroup: false,
alphabetize: {
order: 'asc',
caseInsensitive: true,
},
},
],
'import/no-unresolved': 'off',
'import/no-extraneous-dependencies': 'off',
'import/extensions': 'off',
'import/prefer-default-export': 'off',
'import/no-import-module-exports': 'off',
/**
* Правила для React
*/
/** Определение компонентов через стрелочные функции или function declaration */
'react/function-component-definition': [
2,
{
namedComponents: ['arrow-function', 'function-declaration'],
unnamedComponents: ['arrow-function', 'function-expression'],
},
],
'react/jsx-filename-extension': [
2,
{ extensions: ['.tsx', '.jsx', '.js'] },
],
'react/require-default-props': 'off',
'react/jsx-props-no-spreading': 'warn',
'react/display-name': 'off',
'react/jsx-no-useless-fragment': [2, { allowExpressions: true }],
/** Не нужен с новым JSX transform */
'react/react-in-jsx-scope': 'off',
/**
* Правила для React Hooks
*/
/** Проверка правил хуков */
'react-hooks/rules-of-hooks': 'error',
/** Проверка зависимостей эффектов */
'react-hooks/exhaustive-deps': 'error',
/**
* Правила доступности (A11y)
*/
'jsx-a11y/click-events-have-key-events': 'warn',
'jsx-a11y/no-static-element-interactions': 'warn',
/**
* Правила для TypeScript
*/
'@typescript-eslint/no-shadow': 'warn',
'@typescript-eslint/no-unused-vars': 'warn',
'@typescript-eslint/no-var-requires': 'warn',
'@typescript-eslint/no-use-before-define': ['error', { enums: false }],
'@typescript-eslint/naming-convention': [
'warn',
{
selector: 'function',
format: ['camelCase', 'PascalCase'],
},
{
selector: 'variable',
format: ['camelCase', 'UPPER_CASE', 'PascalCase'],
},
],
'@typescript-eslint/ban-ts-comment': 'warn',
/**
* Общие правила JavaScript/TypeScript
*/
/** Точки с запятой контролируются Prettier */
semi: 'off',
'jsx-quotes': ['error', 'prefer-single'],
'no-shadow': 'off',
'no-unused-vars': 'off',
'no-underscore-dangle': 'off',
'no-use-before-define': 'off',
'no-param-reassign': ['warn', { props: false }],
'max-len': [
2,
{
ignoreComments: true,
ignoreUrls: true,
code: 140,
ignorePattern: '^(import\\s.+\\sfrom\\s.+|\\} from)',
},
],
/**
* Правила форматирования (Prettier)
*/
'prettier/prettier': [
'error',
{
semi: false,
singleQuote: true,
jsxSingleQuote: true,
trailingComma: 'es5',
},
],
},
},
/**
* Переопределение правил для JavaScript файлов
*/
{
files: ['**/*.js'],
rules: {
'consistent-return': 'off',
'@typescript-eslint/no-var-requires': 'off',
},
},
/**
* Переопределение правил для тестов и сторибуков
*/
{
files: ['**/src/**/*.{test,stories}.{ts,tsx}'],
rules: {
'max-len': 'off',
},
},
]