eslint.config.js 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. import js from '@eslint/js';
  2. import stylistic from '@stylistic/eslint-plugin';
  3. import prettier from 'eslint-config-prettier/flat';
  4. import importPlugin from 'eslint-plugin-import';
  5. import react from 'eslint-plugin-react';
  6. import reactHooks from 'eslint-plugin-react-hooks';
  7. import globals from 'globals';
  8. import typescript from 'typescript-eslint';
  9. const controlStatements = [
  10. 'if',
  11. 'return',
  12. 'for',
  13. 'while',
  14. 'do',
  15. 'switch',
  16. 'try',
  17. 'throw',
  18. ];
  19. const paddingAroundControl = [
  20. ...controlStatements.flatMap((stmt) => [
  21. { blankLine: 'always', prev: '*', next: stmt },
  22. { blankLine: 'always', prev: stmt, next: '*' },
  23. ]),
  24. ];
  25. /** @type {import('eslint').Linter.Config[]} */
  26. export default [
  27. js.configs.recommended,
  28. reactHooks.configs.flat['recommended-latest'],
  29. ...typescript.configs.recommended,
  30. {
  31. ...react.configs.flat.recommended,
  32. ...react.configs.flat['jsx-runtime'], // Required for React 17+
  33. languageOptions: {
  34. globals: {
  35. ...globals.browser,
  36. },
  37. },
  38. rules: {
  39. 'react/react-in-jsx-scope': 'off',
  40. 'react/prop-types': 'off',
  41. 'react/no-unescaped-entities': 'off',
  42. },
  43. settings: {
  44. react: {
  45. version: 'detect',
  46. },
  47. },
  48. },
  49. {
  50. plugins: {
  51. import: importPlugin,
  52. },
  53. settings: {
  54. 'import/resolver': {
  55. typescript: {
  56. alwaysTryTypes: true,
  57. project: './tsconfig.json',
  58. },
  59. node: true,
  60. },
  61. },
  62. rules: {
  63. '@typescript-eslint/no-explicit-any': 'off',
  64. '@typescript-eslint/consistent-type-imports': [
  65. 'error',
  66. {
  67. prefer: 'type-imports',
  68. fixStyle: 'separate-type-imports',
  69. },
  70. ],
  71. 'import/order': [
  72. 'error',
  73. {
  74. groups: [
  75. 'builtin',
  76. 'external',
  77. 'internal',
  78. 'parent',
  79. 'sibling',
  80. 'index',
  81. ],
  82. alphabetize: {
  83. order: 'asc',
  84. caseInsensitive: true,
  85. },
  86. },
  87. ],
  88. 'import/consistent-type-specifier-style': [
  89. 'error',
  90. 'prefer-top-level',
  91. ],
  92. },
  93. },
  94. {
  95. plugins: {
  96. '@stylistic': stylistic,
  97. },
  98. rules: {
  99. '@stylistic/brace-style': ['error', '1tbs', { allowSingleLine: false }],
  100. '@stylistic/padding-line-between-statements': [
  101. 'error',
  102. ...paddingAroundControl,
  103. ],
  104. },
  105. },
  106. {
  107. ignores: [
  108. 'vendor',
  109. 'node_modules',
  110. 'public',
  111. 'bootstrap/ssr',
  112. 'tailwind.config.js',
  113. 'vite.config.ts',
  114. 'resources/js/actions/**',
  115. 'resources/js/components/ui/*',
  116. 'resources/js/routes/**',
  117. 'resources/js/wayfinder/**',
  118. ],
  119. },
  120. prettier, // Turn off all rules that might conflict with Prettier
  121. {
  122. plugins: {
  123. '@stylistic': stylistic,
  124. },
  125. rules: {
  126. curly: ['error', 'all'],
  127. '@stylistic/brace-style': ['error', '1tbs', { allowSingleLine: false }],
  128. },
  129. },
  130. ];