about summary refs log tree commit diff
path: root/.eslintrc.js
diff options
context:
space:
mode:
Diffstat (limited to '.eslintrc.js')
-rw-r--r--.eslintrc.js166
1 files changed, 110 insertions, 56 deletions
diff --git a/.eslintrc.js b/.eslintrc.js
index 03af2975b..bbdfa7de2 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -3,44 +3,49 @@ module.exports = {
 
   extends: [
     'eslint:recommended',
+    'plugin:react/recommended',
+    'plugin:jsx-a11y/recommended',
+    'plugin:import/recommended',
+    'plugin:promise/recommended',
   ],
 
   env: {
     browser: true,
     node: true,
     es6: true,
-    jest: true,
   },
 
   globals: {
     ATTACHMENT_HOST: false,
   },
 
-  parser: '@babel/eslint-parser',
+  parser: '@typescript-eslint/parser',
 
   plugins: [
     'react',
     'jsx-a11y',
     'import',
     'promise',
+    '@typescript-eslint',
   ],
 
   parserOptions: {
     sourceType: 'module',
     ecmaFeatures: {
-      experimentalObjectRestSpread: true,
       jsx: true,
     },
     ecmaVersion: 2021,
+    requireConfigFile: false,
+    babelOptions: {
+      configFile: false,
+      presets: ['@babel/react', '@babel/env'],
+    },
   },
 
   settings: {
     react: {
       version: 'detect',
     },
-    'import/extensions': [
-      '.js',
-    ],
     'import/ignore': [
       'node_modules',
       '\\.(css|scss|json)$',
@@ -48,6 +53,7 @@ module.exports = {
     'import/resolver': {
       node: {
         paths: ['app/javascript'],
+        extensions: ['.js', '.jsx', '.ts', '.tsx'],
       },
     },
   },
@@ -80,8 +86,6 @@ module.exports = {
       },
     ],
     'no-empty': 'off',
-    'no-nested-ternary': 'warn',
-    'no-prototype-builtins': 'off',
     'no-restricted-properties': [
       'error',
       { property: 'substring', message: 'Use .slice instead of .substring.' },
@@ -90,7 +94,8 @@ module.exports = {
     'no-self-assign': 'off',
     'no-trailing-spaces': 'warn',
     'no-unused-expressions': 'error',
-    'no-unused-vars': [
+    'no-unused-vars': 'off',
+    '@typescript-eslint/no-unused-vars': [
       'error',
       {
         vars: 'all',
@@ -98,7 +103,6 @@ module.exports = {
         ignoreRestSiblings: true,
       },
     ],
-    'no-useless-escape': 'off',
     'object-curly-spacing': ['error', 'always'],
     'padded-blocks': [
       'error',
@@ -110,58 +114,46 @@ module.exports = {
     semi: 'error',
     'valid-typeof': 'error',
 
+    'react/jsx-filename-extension': ['error', { extensions: ['.jsx', 'tsx'] }],
     'react/jsx-boolean-value': 'error',
     'react/jsx-closing-bracket-location': ['error', 'line-aligned'],
     'react/jsx-curly-spacing': 'error',
+    'react/display-name': 'off',
     'react/jsx-equals-spacing': 'error',
     'react/jsx-first-prop-new-line': ['error', 'multiline-multiprop'],
     'react/jsx-indent': ['error', 2],
     'react/jsx-no-bind': 'error',
-    'react/jsx-no-duplicate-props': 'error',
-    'react/jsx-no-undef': 'error',
+    'react/jsx-no-target-blank': 'off',
     'react/jsx-tag-spacing': 'error',
-    'react/jsx-uses-react': 'error',
-    'react/jsx-uses-vars': 'error',
     'react/jsx-wrap-multilines': 'error',
-    'react/no-multi-comp': 'off',
-    'react/no-string-refs': 'error',
-    'react/prop-types': 'error',
+    'react/no-deprecated': 'off',
+    'react/no-unknown-property': 'off',
     'react/self-closing-comp': 'error',
 
+    // recommended values found in https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/src/index.js
     'jsx-a11y/accessible-emoji': 'warn',
-    'jsx-a11y/alt-text': 'warn',
-    'jsx-a11y/anchor-has-content': 'warn',
-    'jsx-a11y/anchor-is-valid': [
-      'warn',
-      {
-        components: [
-          'Link',
-          'NavLink',
-        ],
-        specialLink: [
-          'to',
-        ],
-        aspect: [
-          'noHref',
-          'invalidHref',
-          'preferButton',
-        ],
-      },
-    ],
-    'jsx-a11y/aria-activedescendant-has-tabindex': 'warn',
-    'jsx-a11y/aria-props': 'warn',
-    'jsx-a11y/aria-proptypes': 'warn',
-    'jsx-a11y/aria-role': 'warn',
-    'jsx-a11y/aria-unsupported-elements': 'warn',
-    'jsx-a11y/heading-has-content': 'warn',
-    'jsx-a11y/html-has-lang': 'warn',
-    'jsx-a11y/iframe-has-title': 'warn',
-    'jsx-a11y/img-redundant-alt': 'warn',
-    'jsx-a11y/interactive-supports-focus': 'warn',
-    'jsx-a11y/label-has-for': 'off',
-    'jsx-a11y/mouse-events-have-key-events': 'warn',
-    'jsx-a11y/no-access-key': 'warn',
-    'jsx-a11y/no-distracting-elements': 'warn',
+    'jsx-a11y/click-events-have-key-events': 'off',
+    'jsx-a11y/label-has-associated-control': 'off',
+    'jsx-a11y/media-has-caption': 'off',
+    'jsx-a11y/no-autofocus': 'off',
+    // recommended rule is:
+    // 'jsx-a11y/no-interactive-element-to-noninteractive-role': [
+    //   'error',
+    //   {
+    //     tr: ['none', 'presentation'],
+    //     canvas: ['img'],
+    //   },
+    // ],
+    'jsx-a11y/no-interactive-element-to-noninteractive-role': 'off',
+    // recommended rule is:
+    // 'jsx-a11y/no-noninteractive-element-interactions': [
+    //   'error',
+    //   {
+    //     body: ['onError', 'onLoad'],
+    //     iframe: ['onError', 'onLoad'],
+    //     img: ['onError', 'onLoad'],
+    //   },
+    // ],
     'jsx-a11y/no-noninteractive-element-interactions': [
       'warn',
       {
@@ -170,8 +162,18 @@ module.exports = {
         ],
       },
     ],
+    // recommended rule is:
+    // 'jsx-a11y/no-noninteractive-tabindex': [
+    //   'error',
+    //   {
+    //     tags: [],
+    //     roles: ['tabpanel'],
+    //     allowExpressionValues: true,
+    //   },
+    // ],
+    'jsx-a11y/no-noninteractive-tabindex': 'off',
     'jsx-a11y/no-onchange': 'warn',
-    'jsx-a11y/no-redundant-roles': 'warn',
+    // recommended is full 'error'
     'jsx-a11y/no-static-element-interactions': [
       'warn',
       {
@@ -180,16 +182,16 @@ module.exports = {
         ],
       },
     ],
-    'jsx-a11y/role-has-required-aria-props': 'warn',
-    'jsx-a11y/role-supports-aria-props': 'off',
-    'jsx-a11y/scope': 'warn',
-    'jsx-a11y/tabindex-no-positive': 'warn',
 
+    // See https://github.com/import-js/eslint-plugin-import/blob/main/config/recommended.js
     'import/extensions': [
       'error',
       'always',
       {
         js: 'never',
+        jsx: 'never',
+        ts: 'never',
+        tsx: 'never',
       },
     ],
     'import/newline-after-import': 'error',
@@ -198,19 +200,71 @@ module.exports = {
       {
         devDependencies: [
           'config/webpack/**',
+          'app/javascript/mastodon/performance.js',
           'app/javascript/mastodon/test_setup.js',
           'app/javascript/**/__tests__/**',
         ],
       },
     ],
-    'import/no-unresolved': 'error',
     'import/no-webpack-loader-syntax': 'error',
 
+    'promise/always-return': 'off',
     'promise/catch-or-return': [
       'error',
       {
         allowFinally: true,
       },
     ],
+    'promise/no-callback-in-promise': 'off',
+    'promise/no-nesting': 'off',
+    'promise/no-promise-in-callback': 'off',
   },
+
+  overrides: [
+    {
+      files: [
+        '*.config.js',
+        '.*rc.js',
+        'ide-helper.js',
+      ],
+
+      env: {
+        commonjs: true,
+      },
+
+      parserOptions: {
+        sourceType: 'script',
+      },
+    },
+    {
+      files: [
+        '**/*.ts',
+        '**/*.tsx',
+      ],
+
+      extends: [
+        'eslint:recommended',
+        'plugin:@typescript-eslint/recommended',
+        'plugin:react/recommended',
+        'plugin:jsx-a11y/recommended',
+        'plugin:import/recommended',
+        'plugin:import/typescript',
+        'plugin:promise/recommended',
+      ],
+
+      rules: {
+        '@typescript-eslint/no-explicit-any': 'off',
+      },
+    },
+    {
+      files: [
+        '**/__tests__/*.js',
+        '**/__tests__/*.jsx',
+      ],
+
+      env: {
+        jest: true,
+      },
+    },
+  ],
 };