go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/milo/ui/.eslintrc.js (about) 1 // Copyright 2023 The LUCI Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // eslint-disable-next-line no-undef 16 module.exports = { 17 env: { 18 browser: true, 19 es2021: true, 20 }, 21 plugins: ['react', '@typescript-eslint', 'prettier', 'jsx-a11y', 'import'], 22 extends: [ 23 'eslint:recommended', 24 'plugin:react/recommended', 25 'plugin:react/jsx-runtime', 26 'plugin:react-hooks/recommended', 27 'google', 28 'plugin:@typescript-eslint/recommended', 29 'plugin:import/recommended', 30 'plugin:import/typescript', 31 'plugin:jsx-a11y/recommended', 32 // "plugin:prettier/recommended" needs to be added last because it needs to 33 // disable rules that are incompatible with the prettier. 34 'plugin:prettier/recommended', 35 ], 36 settings: { 37 react: { 38 version: 'detect', 39 }, 40 'import/parsers': { 41 '@typescript-eslint/parser': ['.ts', '.tsx'], 42 }, 43 'import/resolver': { 44 typescript: {}, 45 }, 46 }, 47 parser: '@typescript-eslint/parser', 48 parserOptions: { 49 ecmaFeatures: { 50 jsx: true, 51 }, 52 ecmaVersion: 'latest', 53 sourceType: 'module', 54 }, 55 rules: { 56 '@typescript-eslint/no-unused-vars': [ 57 'error', 58 { 59 // Use cases: 60 // - declare a function property with a default value 61 // - ignore some function parameters when writing a callback function 62 // See http://b/182855639. 63 argsIgnorePattern: '^_', 64 // Use cases: 65 // - explicitly ignore some elements from a destructed array 66 // - explicitly ignore some inferred type parameters 67 // See http://b/182855639. 68 varsIgnorePattern: '^_', 69 }, 70 ], 71 72 // Code generated from protobuf may contain '_' in the identifier name, 73 // (e.g. `BuilderMask_BuilderMaskType`) and therefore triggering the error. 74 // `"ignoreImports": true` doesn't fix the issue because checks are still 75 // applied where the imported symbol is used. 76 // 77 // Since this rule doesn't add a lot of value (it only checks whether there 78 // are '_' in non-leading/trailing positions), disable it to reduce noise. 79 // 80 // Note that we should still generally use camelcase. 81 camelcase: 0, 82 83 // `==` may perform type conversion in some cases and is unintuitive. 84 eqeqeq: ['error', 'always'], 85 86 // We need to import Lit component definition file separately as a 87 // side-effect (e.g. `import './a_component'`) because type-only imports 88 // (e.g. `import { AComponent } from './a_component'`) may get optimized 89 // away by the bundler. 90 'import/no-duplicates': 0, 91 92 // See https://vitejs.dev/guide/api-plugin.html#virtual-modules-convention. 93 'import/no-unresolved': ['error', { ignore: ['^virtual:'] }], 94 95 // Group internal dependencies together. 96 'import/order': [ 97 'error', 98 { 99 pathGroups: [ 100 { 101 pattern: '@root/**', 102 group: 'external', 103 position: 'after', 104 }, 105 { 106 pattern: '@/**', 107 group: 'external', 108 position: 'after', 109 }, 110 ], 111 alphabetize: { 112 order: 'asc', 113 orderImportKind: 'asc', 114 }, 115 'newlines-between': 'always', 116 }, 117 ], 118 119 'no-restricted-imports': [ 120 'error', 121 { 122 patterns: [ 123 { 124 group: ['lodash-es'], 125 importNames: ['chain'], 126 message: '`chain` from `lodash-es` does not work with tree-shaking', 127 }, 128 { 129 group: ['lodash-es/chain'], 130 importNames: ['default'], 131 message: '`chain` from `lodash-es` does not work with tree-shaking', 132 }, 133 // Ban the use of `useSearchParams` because it may accidentally 134 // override search params when updater pattern is used. 135 { 136 group: ['react-router-dom'], 137 importNames: ['useSearchParams'], 138 message: 'use `useSyncedSearchParams` instead', 139 }, 140 ], 141 }, 142 ], 143 144 // Generated protobuf types could be very long (e.g. 145 // `ClusterResponse_ClusteredTestResult_ClusterEntry`). Set a high max-len 146 // so we don't need to disable this rule whenever those long types are used. 147 // 148 // Note that the prettier will still try to reformat the code into 80 cols 149 // when appropriate. And we should generally fit our code in 80 cols too. 150 'max-len': [ 151 'error', 152 { code: 140, ignoreUrls: true, ignoreRegExpLiterals: true }, 153 ], 154 155 // Ban `console.log` to encourage displaying message via DOM and prevent 156 // debugging statements from being accidentally left in the codebase. 157 // `console.error/warn` is still useful for error reporting from our users 158 // (most of them know how to work with the browser dev console). But they 159 // should be accessed via `@/common/tools/logging`. 160 'no-console': ['error'], 161 162 // Modify the prettier config to make it match the eslint rule from other 163 // presets better. 164 'prettier/prettier': [ 165 'error', 166 { 167 singleQuote: true, 168 }, 169 ], 170 171 // Ban the usage of `dangerouslySetInnerHTML`. 172 // 173 // Note that this rule does not catch the usage of `dangerouslySetInnerHTML` 174 // in non-native components [1]. 175 // [1]: https://github.com/jsx-eslint/eslint-plugin-react/issues/3434 176 'react/no-danger': ['error'], 177 178 // See https://emotion.sh/docs/eslint-plugin-react. 179 'react/no-unknown-property': ['error', { ignore: ['css'] }], 180 181 // JSDoc related rules are deprecated [1]. 182 // Also with TypeScript, a lot of the JSDoc are unnecessary. 183 // [1]: https://eslint.org/blog/2018/11/jsdoc-end-of-life/ 184 'require-jsdoc': 0, 185 'valid-jsdoc': 0, 186 }, 187 overrides: [ 188 { 189 files: ['src/**/*.test.ts', 'src/**/*.test.tsx'], 190 plugins: ['jest'], 191 extends: ['plugin:jest/recommended'], 192 }, 193 { 194 files: ['src/**/*.test.ts', 'src/**/*.test.tsx', '**/testing_tools/**'], 195 rules: { 196 // Allow assertion to make it easier to write test cases. 197 // All incorrect assertion will be caught during test execution anyway. 198 '@typescript-eslint/no-non-null-assertion': 0, 199 200 // It's very common to use an empty mock implementation in tests. 201 '@typescript-eslint/no-empty-function': 0, 202 203 // Don't need to restrict imports in test files. 204 'no-restricted-imports': 0, 205 }, 206 }, 207 ], 208 };