UNPKG

6.26 kBJavaScriptView Raw
1const prettierOptions = require('./.prettierrc')
2
3const RULES = {
4 OFF: 0,
5 WARNING: 1,
6 ERROR: 2
7}
8
9const ACCESIBILITY_RULES = {
10 'jsx-a11y/accessible-emoji': RULES.WARNING,
11 'jsx-a11y/alt-text': RULES.WARNING,
12 'jsx-a11y/anchor-has-content': RULES.WARNING,
13 'jsx-a11y/anchor-is-valid': RULES.WARNING,
14 'jsx-a11y/aria-activedescendant-has-tabindex': RULES.WARNING,
15 'jsx-a11y/aria-props': RULES.WARNING,
16 'jsx-a11y/aria-proptypes': RULES.WARNING,
17 'jsx-a11y/aria-role': RULES.WARNING,
18 'jsx-a11y/aria-unsupported-elements': RULES.WARNING,
19 // 'jsx-a11y/autocomplete-valid': RULES.WARNING, // we need to update eslint for this
20 'jsx-a11y/click-events-have-key-events': RULES.WARNING,
21 'jsx-a11y/control-has-associated-label': [
22 'off',
23 {
24 ignoreElements: [
25 'audio',
26 'canvas',
27 'embed',
28 'input',
29 'textarea',
30 'tr',
31 'video'
32 ],
33 ignoreRoles: [
34 'grid',
35 'listbox',
36 'menu',
37 'menubar',
38 'radiogroup',
39 'row',
40 'tablist',
41 'toolbar',
42 'tree',
43 'treegrid'
44 ],
45 includeRoles: ['alert', 'dialog']
46 }
47 ],
48 'jsx-a11y/heading-has-content': RULES.WARNING,
49 'jsx-a11y/html-has-lang': RULES.WARNING,
50 'jsx-a11y/iframe-has-title': RULES.WARNING,
51 'jsx-a11y/img-redundant-alt': RULES.WARNING,
52 'jsx-a11y/interactive-supports-focus': [
53 RULES.WARNING,
54 {
55 tabbable: [
56 'button',
57 'checkbox',
58 'link',
59 'searchbox',
60 'spinbutton',
61 'switch',
62 'textbox'
63 ]
64 }
65 ],
66 'jsx-a11y/label-has-associated-control': RULES.WARNING,
67 'jsx-a11y/label-has-for': 'off',
68 'jsx-a11y/media-has-caption': RULES.WARNING,
69 'jsx-a11y/mouse-events-have-key-events': RULES.WARNING,
70 'jsx-a11y/no-access-key': RULES.WARNING,
71 'jsx-a11y/no-autofocus': RULES.WARNING,
72 'jsx-a11y/no-distracting-elements': RULES.WARNING,
73 'jsx-a11y/no-interactive-element-to-noninteractive-role': [
74 RULES.WARNING,
75 {
76 tr: ['none', 'presentation']
77 }
78 ],
79 'jsx-a11y/no-noninteractive-element-interactions': [
80 RULES.WARNING,
81 {
82 handlers: [
83 'onClick',
84 'onError',
85 'onLoad',
86 'onMouseDown',
87 'onMouseUp',
88 'onKeyPress',
89 'onKeyDown',
90 'onKeyUp'
91 ],
92 alert: ['onKeyUp', 'onKeyDown', 'onKeyPress'],
93 body: ['onError', 'onLoad'],
94 dialog: ['onKeyUp', 'onKeyDown', 'onKeyPress'],
95 iframe: ['onError', 'onLoad'],
96 img: ['onError', 'onLoad']
97 }
98 ],
99 'jsx-a11y/no-noninteractive-element-to-interactive-role': [
100 RULES.WARNING,
101 {
102 ul: [
103 'listbox',
104 'menu',
105 'menubar',
106 'radiogroup',
107 'tablist',
108 'tree',
109 'treegrid'
110 ],
111 ol: [
112 'listbox',
113 'menu',
114 'menubar',
115 'radiogroup',
116 'tablist',
117 'tree',
118 'treegrid'
119 ],
120 li: ['menuitem', 'option', 'row', 'tab', 'treeitem'],
121 table: ['grid'],
122 td: ['gridcell']
123 }
124 ],
125 'jsx-a11y/no-noninteractive-tabindex': [
126 RULES.WARNING,
127 {
128 tags: [],
129 roles: ['tabpanel'],
130 allowExpressionValues: true
131 }
132 ],
133 'jsx-a11y/no-onchange': RULES.WARNING,
134 'jsx-a11y/no-redundant-roles': RULES.WARNING,
135 'jsx-a11y/no-static-element-interactions': [
136 RULES.WARNING,
137 {
138 allowExpressionValues: true,
139 handlers: [
140 'onClick',
141 'onMouseDown',
142 'onMouseUp',
143 'onKeyPress',
144 'onKeyDown',
145 'onKeyUp'
146 ]
147 }
148 ],
149 'jsx-a11y/role-has-required-aria-props': RULES.WARNING,
150 'jsx-a11y/role-supports-aria-props': RULES.WARNING,
151 'jsx-a11y/scope': RULES.WARNING,
152 'jsx-a11y/tabindex-no-positive': RULES.WARNING
153}
154
155const REACT_RULES = {
156 'react-hooks/exhaustive-deps': RULES.WARNING, // Checks effect dependencies
157 'react-hooks/rules-of-hooks': RULES.ERROR, // Checks rules of Hooks
158 'react/default-props-match-prop-types': RULES.WARNING,
159 'react/jsx-handler-names': RULES.WARNING,
160 'react/jsx-no-duplicate-props': [RULES.WARNING, {ignoreCase: true}],
161 'react/jsx-no-undef': RULES.WARNING,
162 'react/jsx-pascal-case': [
163 RULES.WARNING,
164 {
165 allowAllCaps: true,
166 ignore: []
167 }
168 ],
169 'react/jsx-uses-react': RULES.OFF,
170 'react/jsx-uses-vars': RULES.WARNING,
171 'react/no-deprecated': RULES.WARNING,
172 'react/no-direct-mutation-state': RULES.ERROR,
173 'react/no-is-mounted': RULES.WARNING,
174 'react/no-multi-comp': [RULES.WARNING, {ignoreStateless: true}],
175 'react/no-unused-prop-types': RULES.WARNING,
176 'react/react-in-jsx-scope': RULES.OFF,
177 'react/require-render-return': RULES.WARNING
178}
179
180const TESTING_RULES = {
181 'chai-friendly/no-unused-expressions': [
182 RULES.ERROR,
183 {allowShortCircuit: true, allowTernary: true}
184 ],
185 'no-only-tests/no-only-tests': RULES.ERROR
186}
187
188let resolvedBabelPresetSui = false
189try {
190 require.resolve('babel-preset-sui')
191 resolvedBabelPresetSui = true
192} catch {}
193
194const parser = resolvedBabelPresetSui ? '@babel/eslint-parser' : undefined
195
196module.exports = {
197 env: {
198 es6: true,
199 mocha: true
200 },
201 globals: {
202 'cypress/globals': true,
203 preval: 'readonly'
204 },
205 parser,
206 parserOptions: {
207 ecmaFeatures: {
208 jsx: true
209 },
210 ecmaVersion: 12,
211 babelOptions: {
212 configFile: resolvedBabelPresetSui
213 }
214 },
215 extends: [
216 'standard',
217 'standard-react',
218 'prettier',
219 'plugin:cypress/recommended',
220 'prettier/standard',
221 'prettier/react'
222 ],
223 plugins: [
224 '@babel',
225 'chai-friendly',
226 'jsx-a11y',
227 'no-only-tests',
228 'prettier',
229 'react-hooks'
230 ],
231 rules: {
232 ...ACCESIBILITY_RULES,
233 ...REACT_RULES,
234 ...TESTING_RULES,
235 'accessor-pairs': RULES.OFF,
236 '@babel/no-unused-expressions': RULES.OFF,
237 'no-console': RULES.WARNING,
238 'no-debugger': RULES.ERROR,
239 'no-nested-ternary': RULES.WARNING,
240 'no-prototype-builtins': RULES.OFF,
241 'no-return-await': RULES.WARNING,
242 'no-unused-expressions': RULES.OFF,
243 'no-unused-vars': [
244 RULES.ERROR,
245 {args: 'none', ignoreRestSiblings: true, varsIgnorePattern: 'React'}
246 ],
247 'no-var': RULES.WARNING,
248 strict: RULES.OFF,
249 'prettier/prettier': [RULES.ERROR, prettierOptions]
250 }
251}