Use source loader for email sprite icons
[ProtonMail-WebClient.git] / packages / eslint-config-proton / index.js
blobf40c7dec5b14d77ee60a56542e46652f9e0da160
1 const path = require('path');
3 module.exports = {
4     env: {
5         browser: true,
6         commonjs: true,
7         es6: true,
8         jest: true,
9         node: true,
10     },
11     extends: ['airbnb-typescript', 'prettier', 'plugin:monorepo-cop/recommended', 'plugin:jsx-a11y/recommended'],
12     parser: '@typescript-eslint/parser',
13     parserOptions: {
14         project: './tsconfig.json',
15     },
16     plugins: [
17         'react',
18         'react-hooks',
19         'import',
20         '@typescript-eslint',
21         'es',
22         'monorepo-cop',
23         'no-only-tests',
24         'jsx-a11y',
25         'custom-rules',
26         'lodash',
27     ],
28     rules: {
29         '@typescript-eslint/array-type': [
30             'error',
31             {
32                 default: 'array',
33             },
34         ],
35         '@typescript-eslint/default-param-last': 'off',
36         '@typescript-eslint/no-shadow': 'off',
37         '@typescript-eslint/no-redeclare': ['error'],
38         '@typescript-eslint/explicit-function-return-type': 'off',
39         '@typescript-eslint/indent': 'off',
40         '@typescript-eslint/no-explicit-any': 'off',
41         '@typescript-eslint/no-floating-promises': 'warn',
42         '@typescript-eslint/no-for-in-array': 'error',
43         '@typescript-eslint/no-misused-promises': ['error', { checksVoidReturn: false }],
44         '@typescript-eslint/naming-convention': [
45             'error',
46             {
47                 selector: 'variable',
48                 format: ['camelCase', 'PascalCase', 'UPPER_CASE'],
49             },
50             {
51                 selector: 'function',
52                 format: ['camelCase', 'PascalCase'],
53             },
54             {
55                 selector: 'typeLike',
56                 format: ['PascalCase', 'UPPER_CASE'],
57             },
58             {
59                 selector: 'enum',
60                 format: ['PascalCase', 'UPPER_CASE'],
61             },
62         ],
63         'arrow-body-style': 'off',
64         'consistent-return': 'off',
65         curly: ['error', 'all'],
66         'import/export': 2,
67         // Provided by TS
68         'import/named': 'off',
69         'import/default': 'off',
70         'import/namespace': 'off',
71         // Off since we use @trivago/prettier-plugin-sort-imports
72         'import/order': 'off',
73         'import/no-extraneous-dependencies': 'off',
74         'import/no-named-as-default': 'off',
75         'import/no-named-as-default-member': 'off',
76         'import/no-mutable-exports': 'off',
77         'import/no-unresolved': [
78             2,
79             {
80                 amd: true,
81                 commonjs: true,
82             },
83         ],
84         'import/prefer-default-export': 'off',
85         'no-redeclare': 'off',
86         'no-await-in-loop': 'off',
87         'no-bitwise': 'off',
88         'no-console': 'warn',
89         'no-continue': 'off',
90         'no-nested-ternary': 'warn',
91         'no-param-reassign': 'off',
92         'no-plusplus': 'off',
93         'no-restricted-imports': [
94             'error',
95             {
96                 patterns: [
97                     {
98                         group: ['pmcrypto'],
99                         message:
100                             'You should probably import from `@proton/crypto` instead: using `pmcrypto` directly is only needed for crypto-specific use cases.',
101                     },
102                 ],
103             },
104         ],
105         'no-restricted-syntax': [
106             'error',
107             {
108                 selector:
109                     'TaggedTemplateExpression > TemplateLiteral > TemplateElement.quasis[value.raw=/\\bProton\\b(?!\\s+(Account|Mail|Drive|Calendar|VPN|Verify))/i]',
110                 message: 'Use `BRAND_NAME` instead to avoid possible translation.',
111             },
112             {
113                 selector:
114                     'TaggedTemplateExpression > TemplateLiteral > TemplateElement.quasis[value.raw=/\\bProton Account\\b/i]',
115                 message: 'Use `${BRAND_NAME} Account` instead to allow translation of `Account`.',
116             },
117             {
118                 selector:
119                     'TaggedTemplateExpression > TemplateLiteral > TemplateElement.quasis[value.raw=/\\bProton Mail\\b/i]',
120                 message: 'Use `MAIL_APP_NAME` instead to avoid possible translation.',
121             },
122             {
123                 selector:
124                     'TaggedTemplateExpression > TemplateLiteral > TemplateElement.quasis[value.raw=/\\bProton Drive\\b/i]',
125                 message: 'Use `DRIVE_APP_NAME` instead to avoid possible translation.',
126             },
127             {
128                 selector:
129                     'TaggedTemplateExpression > TemplateLiteral > TemplateElement.quasis[value.raw=/\\bProton Calendar\\b/i]',
130                 message: 'Use `CALENDAR_APP_NAME` instead to avoid possible translation.',
131             },
132             {
133                 selector:
134                     'TaggedTemplateExpression > TemplateLiteral > TemplateElement.quasis[value.raw=/\\bProton VPN\\b/i]',
135                 message: 'Use `VPN_APP_NAME` instead to avoid possible translation.',
136             },
137             {
138                 selector:
139                     'TaggedTemplateExpression > TemplateLiteral > TemplateElement.quasis[value.raw=/\\bProton Verify\\b/i]',
140                 message: 'Use `VERIFY_APP_NAME` instead to avoid possible translation.',
141             },
142         ],
143         'no-shadow': 'off',
144         'no-void': [2, { allowAsStatement: true }],
145         'react-hooks/rules-of-hooks': 'error',
146         'react/display-name': 'warn',
147         'react/jsx-filename-extension': [
148             1,
149             {
150                 extensions: ['.js', '.jsx', '.tsx'],
151             },
152         ],
153         'react/jsx-props-no-spreading': 'off',
154         'react/prop-types': 'warn',
155         'react/require-default-props': 'off',
156         /*
157          * next two rules "off" because of the new JSX transform that
158          * came with React 17
159          */
160         'react/jsx-uses-react': 'off',
161         'react/react-in-jsx-scope': 'off',
162         'react/forbid-component-props': [
163             'warn',
164             {
165                 forbid: [
166                     {
167                         propName: 'data-test-id',
168                         message: 'Please use `data-testid` instead',
169                     },
170                 ],
171             },
172         ],
173         'es/no-regexp-lookbehind-assertions': 'error',
174         'no-only-tests/no-only-tests': 'error',
175         /*
176          * jsx-a11y
177          * set up some as warning only, while waiting real feedback
178          * disabled some
179          */
180         'jsx-a11y/anchor-ambiguous-text': 'warn',
181         'jsx-a11y/anchor-is-valid': 'warn',
182         'jsx-a11y/click-events-have-key-events': 'warn',
183         'jsx-a11y/control-has-associated-label': 'warn',
184         'jsx-a11y/interactive-supports-focus': 'warn',
185         'jsx-a11y/label-has-associated-control': 'warn',
186         'jsx-a11y/media-has-caption': 'warn',
187         'jsx-a11y/mouse-events-have-key-events': 'warn',
188         'jsx-a11y/no-static-element-interactions': 'warn',
189         'jsx-a11y/no-interactive-element-to-noninteractive-role': 'warn',
190         'jsx-a11y/no-noninteractive-element-interactions': 'warn',
191         'jsx-a11y/no-noninteractive-tabindex': 'warn',
192         'jsx-a11y/no-aria-hidden-on-focusable': 'warn',
193         'jsx-a11y/prefer-tag-over-role': 'warn',
194         'jsx-a11y/img-redundant-alt': 'off',
195         'jsx-a11y/label-has-for': 'off',
196         'jsx-a11y/no-autofocus': 'off',
197         'jsx-a11y/no-onchange': 'off',
198         'custom-rules/deprecate-spacing-utility-classes': 'warn',
199         'custom-rules/deprecate-responsive-utility-classes': 'warn',
200         'custom-rules/deprecate-sizing-classes': 'warn',
201         'custom-rules/deprecate-classes': 'warn',
202         'custom-rules/no-template-in-translator-context': 'error',
203         '@typescript-eslint/consistent-type-imports': 'error',
204         'lodash/import-scope': [2, 'method'],
205     },
206     settings: {
207         'import/resolver': {
208             // The built-in node resolver does not support the `exports` entrypoints.
209             // The TS one is used as a workaround, see https://github.com/import-js/eslint-plugin-import/issues/1810#issuecomment-1189510672
210             typescript: {},
212             alias: {
213                 map: [
214                     ['proton-mail', path.resolve(__dirname, '../../applications/mail/src/app')],
215                     ['tests', path.resolve(__dirname, '../../tests')],
216                     ['proton-pass-extension', path.resolve(__dirname, '../../applications/pass-extension/src')],
217                     ['proton-pass-web', path.resolve(__dirname, '../../applications/pass/src')],
218                 ],
219                 extensions: ['.ts', '.tsx'],
220             },
221         },
222         react: {
223             version: 'detect',
224         },
225     },