.eslintrc.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. module.exports = {
  2. root: true,
  3. env: {
  4. browser: true,
  5. node: true,
  6. es6: true,
  7. jest: true,
  8. },
  9. globals: {
  10. ATTACHMENT_HOST: false,
  11. },
  12. parser: '@babel/eslint-parser',
  13. plugins: [
  14. 'react',
  15. 'jsx-a11y',
  16. 'import',
  17. 'promise',
  18. ],
  19. parserOptions: {
  20. sourceType: 'module',
  21. ecmaFeatures: {
  22. experimentalObjectRestSpread: true,
  23. jsx: true,
  24. },
  25. ecmaVersion: 2021,
  26. },
  27. settings: {
  28. react: {
  29. version: 'detect',
  30. },
  31. 'import/extensions': [
  32. '.js',
  33. ],
  34. 'import/ignore': [
  35. 'node_modules',
  36. '\\.(css|scss|json)$',
  37. ],
  38. 'import/resolver': {
  39. node: {
  40. paths: ['app/javascript'],
  41. },
  42. },
  43. },
  44. rules: {
  45. 'brace-style': 'warn',
  46. 'comma-dangle': ['error', 'always-multiline'],
  47. 'comma-spacing': [
  48. 'warn',
  49. {
  50. before: false,
  51. after: true,
  52. },
  53. ],
  54. 'comma-style': ['warn', 'last'],
  55. 'consistent-return': 'error',
  56. 'dot-notation': 'error',
  57. eqeqeq: 'error',
  58. indent: ['warn', 2],
  59. 'jsx-quotes': ['error', 'prefer-single'],
  60. 'no-catch-shadow': 'error',
  61. 'no-cond-assign': 'error',
  62. 'no-console': [
  63. 'warn',
  64. {
  65. allow: [
  66. 'error',
  67. 'warn',
  68. ],
  69. },
  70. ],
  71. 'no-fallthrough': 'error',
  72. 'no-irregular-whitespace': 'error',
  73. 'no-mixed-spaces-and-tabs': 'warn',
  74. 'no-nested-ternary': 'warn',
  75. 'no-restricted-properties': [
  76. 'error',
  77. { property: 'substring', message: 'Use .slice instead of .substring.' },
  78. { property: 'substr', message: 'Use .slice instead of .substr.' },
  79. ],
  80. 'no-trailing-spaces': 'warn',
  81. 'no-undef': 'error',
  82. 'no-unreachable': 'error',
  83. 'no-unused-expressions': 'error',
  84. 'no-unused-vars': [
  85. 'error',
  86. {
  87. vars: 'all',
  88. args: 'after-used',
  89. ignoreRestSiblings: true,
  90. },
  91. ],
  92. 'object-curly-spacing': ['error', 'always'],
  93. 'padded-blocks': [
  94. 'error',
  95. {
  96. classes: 'always',
  97. },
  98. ],
  99. quotes: ['error', 'single'],
  100. semi: 'error',
  101. strict: 'off',
  102. 'valid-typeof': 'error',
  103. 'react/jsx-boolean-value': 'error',
  104. 'react/jsx-closing-bracket-location': ['error', 'line-aligned'],
  105. 'react/jsx-curly-spacing': 'error',
  106. 'react/jsx-equals-spacing': 'error',
  107. 'react/jsx-first-prop-new-line': ['error', 'multiline-multiprop'],
  108. 'react/jsx-indent': ['error', 2],
  109. 'react/jsx-no-bind': 'error',
  110. 'react/jsx-no-duplicate-props': 'error',
  111. 'react/jsx-no-undef': 'error',
  112. 'react/jsx-tag-spacing': 'error',
  113. 'react/jsx-uses-react': 'error',
  114. 'react/jsx-uses-vars': 'error',
  115. 'react/jsx-wrap-multilines': 'error',
  116. 'react/no-multi-comp': 'off',
  117. 'react/no-string-refs': 'error',
  118. 'react/prop-types': 'error',
  119. 'react/self-closing-comp': 'error',
  120. 'jsx-a11y/accessible-emoji': 'warn',
  121. 'jsx-a11y/alt-text': 'warn',
  122. 'jsx-a11y/anchor-has-content': 'warn',
  123. 'jsx-a11y/anchor-is-valid': [
  124. 'warn',
  125. {
  126. components: [
  127. 'Link',
  128. 'NavLink',
  129. ],
  130. specialLink: [
  131. 'to',
  132. ],
  133. aspect: [
  134. 'noHref',
  135. 'invalidHref',
  136. 'preferButton',
  137. ],
  138. },
  139. ],
  140. 'jsx-a11y/aria-activedescendant-has-tabindex': 'warn',
  141. 'jsx-a11y/aria-props': 'warn',
  142. 'jsx-a11y/aria-proptypes': 'warn',
  143. 'jsx-a11y/aria-role': 'warn',
  144. 'jsx-a11y/aria-unsupported-elements': 'warn',
  145. 'jsx-a11y/heading-has-content': 'warn',
  146. 'jsx-a11y/html-has-lang': 'warn',
  147. 'jsx-a11y/iframe-has-title': 'warn',
  148. 'jsx-a11y/img-redundant-alt': 'warn',
  149. 'jsx-a11y/interactive-supports-focus': 'warn',
  150. 'jsx-a11y/label-has-for': 'off',
  151. 'jsx-a11y/mouse-events-have-key-events': 'warn',
  152. 'jsx-a11y/no-access-key': 'warn',
  153. 'jsx-a11y/no-distracting-elements': 'warn',
  154. 'jsx-a11y/no-noninteractive-element-interactions': [
  155. 'warn',
  156. {
  157. handlers: [
  158. 'onClick',
  159. ],
  160. },
  161. ],
  162. 'jsx-a11y/no-onchange': 'warn',
  163. 'jsx-a11y/no-redundant-roles': 'warn',
  164. 'jsx-a11y/no-static-element-interactions': [
  165. 'warn',
  166. {
  167. handlers: [
  168. 'onClick',
  169. ],
  170. },
  171. ],
  172. 'jsx-a11y/role-has-required-aria-props': 'warn',
  173. 'jsx-a11y/role-supports-aria-props': 'off',
  174. 'jsx-a11y/scope': 'warn',
  175. 'jsx-a11y/tabindex-no-positive': 'warn',
  176. 'import/extensions': [
  177. 'error',
  178. 'always',
  179. {
  180. js: 'never',
  181. },
  182. ],
  183. 'import/newline-after-import': 'error',
  184. 'import/no-extraneous-dependencies': [
  185. 'error',
  186. {
  187. devDependencies: [
  188. 'config/webpack/**',
  189. 'app/javascript/mastodon/test_setup.js',
  190. 'app/javascript/**/__tests__/**',
  191. ],
  192. },
  193. ],
  194. 'import/no-unresolved': 'error',
  195. 'import/no-webpack-loader-syntax': 'error',
  196. 'promise/catch-or-return': [
  197. 'error',
  198. {
  199. allowFinally: true,
  200. },
  201. ],
  202. },
  203. };