eslint.config.mjs 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. import { fixupConfigRules, fixupPluginRules } from "@eslint/compat";
  2. import js from "@eslint/js";
  3. import { FlatCompat } from "@eslint/eslintrc";
  4. import { configs as tsConfigs } from "typescript-eslint";
  5. import path from "node:path";
  6. import { fileURLToPath } from "node:url";
  7. import globals from "globals";
  8. import nextPlugin from "@next/eslint-plugin-next";
  9. import reactHooks from "eslint-plugin-react-hooks";
  10. import reactPlugin from "eslint-plugin-react";
  11. import importPlugin from "eslint-plugin-import";
  12. import unusedImportsPlugin from "eslint-plugin-unused-imports";
  13. import tsParser from "@typescript-eslint/parser";
  14. const __filename = fileURLToPath(import.meta.url);
  15. const __dirname = path.dirname(__filename);
  16. const compat = new FlatCompat({
  17. baseDirectory: __dirname,
  18. recommendedConfig: js.configs.recommended,
  19. });
  20. const config = [
  21. js.configs.recommended,
  22. ...tsConfigs.recommended,
  23. ...fixupConfigRules(
  24. compat.extends(
  25. "plugin:react/recommended",
  26. "plugin:react/jsx-runtime",
  27. "plugin:react-hooks/recommended",
  28. "plugin:prettier/recommended",
  29. "plugin:import/recommended",
  30. "plugin:import/typescript",
  31. "next/core-web-vitals",
  32. ),
  33. ),
  34. {
  35. files: ["**/*.{js,jsx,ts,tsx}"],
  36. ignores: [
  37. "**/node_modules/**",
  38. "**/.next/**",
  39. "**/out/**",
  40. "**/coverage/**",
  41. "**/build/**",
  42. "**/dist/**",
  43. "**/package.json",
  44. "**/package-lock.json",
  45. "**/eslint.config.mjs",
  46. "**/next.config.js",
  47. "src/utils/attempt2.js",
  48. "src/utils/inapp.js",
  49. "src/utils/externalLinkOpener.js",
  50. "src/utils/browserEscape.js",
  51. ],
  52. plugins: {
  53. "react-hooks": fixupPluginRules(reactHooks),
  54. react: fixupPluginRules(reactPlugin),
  55. import: fixupPluginRules(importPlugin),
  56. "unused-imports": fixupPluginRules(unusedImportsPlugin),
  57. next: nextPlugin,
  58. },
  59. languageOptions: {
  60. globals: {
  61. ...globals.browser,
  62. ...globals.node,
  63. },
  64. ecmaVersion: 2018,
  65. sourceType: "module",
  66. parser: tsParser,
  67. parserOptions: {
  68. project: "./tsconfig.json",
  69. ecmaFeatures: {
  70. jsx: true,
  71. },
  72. },
  73. },
  74. settings: {
  75. "import/resolver": {
  76. node: {
  77. paths: ["src"],
  78. extensions: [".js", ".jsx", ".ts", ".tsx"],
  79. },
  80. },
  81. react: {
  82. version: "detect",
  83. },
  84. },
  85. rules: {
  86. "prettier/prettier": ["off", { singleQuote: true }],
  87. "no-use-before-define": ["off", { functions: false, classes: false }],
  88. "@typescript-eslint/naming-convention": [
  89. "error",
  90. {
  91. selector: "parameter",
  92. format: ["camelCase", "PascalCase"],
  93. leadingUnderscore: "allow",
  94. },
  95. {
  96. selector: "variable",
  97. format: ["camelCase", "UPPER_CASE", "PascalCase"],
  98. leadingUnderscore: "allow",
  99. },
  100. ],
  101. "import/no-extraneous-dependencies": [
  102. "error",
  103. {
  104. devDependencies: true,
  105. optionalDependencies: false,
  106. peerDependencies: false,
  107. },
  108. ],
  109. "@typescript-eslint/default-param-last": "off",
  110. "@typescript-eslint/no-use-before-define": "off",
  111. "comma-dangle": "off",
  112. "@typescript-eslint/comma-dangle": "off",
  113. "import/prefer-default-export": "off",
  114. "unused-imports/no-unused-imports": "warn",
  115. "max-len": ["warn", { code: 140, ignorePattern: "^import .*", ignoreStrings: true }],
  116. "import/order": [
  117. "error",
  118. {
  119. groups: ["builtin", "external", "internal", ["sibling", "parent"], "index", "type"],
  120. alphabetize: { order: "desc", caseInsensitive: true },
  121. pathGroups: [
  122. { pattern: "components", group: "internal" },
  123. { pattern: "components/**", group: "internal" },
  124. { pattern: "constants/**", group: "internal" },
  125. { pattern: "common", group: "internal" },
  126. { pattern: "error/**", group: "internal" },
  127. { pattern: "hooks/**", group: "internal" },
  128. { pattern: "locale/**", group: "internal" },
  129. { pattern: "routes/**", group: "internal" },
  130. { pattern: "selectors", group: "internal" },
  131. { pattern: "store", group: "internal" },
  132. ],
  133. "newlines-between": "always",
  134. },
  135. ],
  136. "@typescript-eslint/no-explicit-any": "off",
  137. "react/prop-types": "off",
  138. "react/require-default-props": "off",
  139. "import/no-unresolved": "off",
  140. "import/no-cycle": ["off", { maxDepth: "∞" }],
  141. "@typescript-eslint/no-shadow": "off",
  142. "no-shadow": "off",
  143. "no-console": "off",
  144. "no-plusplus": "off",
  145. "react-hooks/exhaustive-deps": "off",
  146. "react/jsx-filename-extension": "off",
  147. "react/jsx-props-no-spreading": "off",
  148. "class-methods-use-this": "off",
  149. "@typescript-eslint/explicit-module-boundary-types": "off",
  150. "@typescript-eslint/no-unused-vars": ["warn", { argsIgnorePattern: "^_", varsIgnorePattern: "^_" }],
  151. "@typescript-eslint/no-empty-object-type": "off",
  152. "react/jsx-sort-props": [
  153. "error",
  154. {
  155. callbacksLast: false,
  156. shorthandFirst: false,
  157. shorthandLast: false,
  158. ignoreCase: true,
  159. noSortAlphabetically: false,
  160. reservedFirst: false,
  161. },
  162. ],
  163. quotes: ["error", "double", { avoidEscape: false, allowTemplateLiterals: false }],
  164. },
  165. },
  166. ];
  167. export default config;