import { FlatCompat } from "@eslint/eslintrc"; import eslintPluginImport from "eslint-plugin-import"; import eslintPluginReact from "eslint-plugin-react"; import eslintPluginReactHooks from "eslint-plugin-react-hooks"; import eslintPluginSort from "eslint-plugin-simple-import-sort"; import eslintPluginUnused from "eslint-plugin-unused-imports"; import { dirname } from "path"; import { fileURLToPath } from "url"; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); const compat = new FlatCompat({ baseDirectory: __dirname, }); const eslintConfig = [ ...compat.extends("next/core-web-vitals", "next/typescript"), { plugins: { import: eslintPluginImport, "unused-imports": eslintPluginUnused, "simple-import-sort": eslintPluginSort, react: eslintPluginReact, "react-hooks": eslintPluginReactHooks, }, rules: { /* неиспользуемые переменные и импорты */ "@typescript-eslint/no-unused-vars": [ "warn", { argsIgnorePattern: "^_", varsIgnorePattern: "^_" }, ], "unused-imports/no-unused-imports": "error", "unused-imports/no-unused-vars": [ "warn", { vars: "all", varsIgnorePattern: "^_", args: "after-used", argsIgnorePattern: "^_", }, ], /* порядок импортов: стили .module.(s)css внизу */ "simple-import-sort/imports": [ "error", { groups: [ ["^\\u0000"], // side-effects ["^react", "^next", "^@?\\w"], // пакеты ["^@/"], // алиасы проекта ["^\\.\\.?(?:/|$)"], // относительные импорты (включая "..") ["^.+\\.module\\.(css|scss)$"], // модули стилей ], }, ], "simple-import-sort/exports": "error", /* React правила */ "react/jsx-uses-react": "off", // не нужно в React 17+ "react/react-in-jsx-scope": "off", // не нужно в React 17+ "react/prop-types": "off", // используем TypeScript "react/display-name": "warn", "react/jsx-key": "error", "react/jsx-no-duplicate-props": "error", "react/jsx-no-undef": "error", // "react/no-array-index-key": "warn", "react/no-danger": "warn", "react/no-deprecated": "error", "react/no-direct-mutation-state": "error", "react/no-find-dom-node": "error", "react/no-is-mounted": "error", "react/no-render-return-value": "error", "react/no-string-refs": "error", "react/no-unescaped-entities": "warn", "react/no-unknown-property": "error", "react/no-unsafe": "warn", "react/self-closing-comp": "error", /* React Hooks правила */ "react-hooks/rules-of-hooks": "error", "react-hooks/exhaustive-deps": "warn", /* TypeScript правила */ "@typescript-eslint/no-explicit-any": "warn", "@typescript-eslint/no-non-null-assertion": "warn", "@typescript-eslint/no-var-requires": "error", "@typescript-eslint/explicit-function-return-type": "off", "@typescript-eslint/explicit-module-boundary-types": "off", "@typescript-eslint/no-empty-function": "warn", "@typescript-eslint/no-inferrable-types": "error", /* Общие правила */ "no-console": "warn", "no-debugger": "error", "no-alert": "warn", "no-var": "error", "prefer-const": "error", "no-unused-expressions": "error", "no-duplicate-imports": "error", "no-multiple-empty-lines": ["error", { max: 2 }], "eol-last": "error", "no-trailing-spaces": "error", /* Запрет SVG импортов как компонентов */ "no-restricted-imports": [ "error", { patterns: [ { group: ["*.svg"], message: "❌ SVG imports as components break in production. Use inline SVG or next/image.", }, ], }, ], }, }, { ignores: [ "node_modules/**", ".next/**", "out/**", "build/**", "next-env.d.ts", "public/metrics-scripts/**" ] }]; export default eslintConfig;