@will-stone/eslint-config 0.4.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,2069 @@
1
+ // src/factory.ts
2
+ import gitignore from "eslint-config-flat-gitignore";
3
+
4
+ // src/configs/astro.ts
5
+ import parserTypescript from "@typescript-eslint/parser";
6
+ import parserAstro from "astro-eslint-parser";
7
+ import pluginAstro, { configs as configsAstro } from "eslint-plugin-astro";
8
+ function astro() {
9
+ return [
10
+ {
11
+ files: ["**/*.astro"],
12
+ languageOptions: {
13
+ // @ts-expect-error -- does not confirm to type
14
+ parser: parserAstro,
15
+ parserOptions: {
16
+ extraFileExtensions: [".astro"],
17
+ parser: parserTypescript
18
+ }
19
+ },
20
+ plugins: {
21
+ // @ts-expect-error -- does not confirm to type
22
+ astro: pluginAstro
23
+ },
24
+ // @ts-expect-error -- does not confirm to type
25
+ rules: configsAstro.recommended.rules
26
+ }
27
+ ];
28
+ }
29
+
30
+ // src/configs/base.ts
31
+ import restrictedGlobals from "confusing-browser-globals";
32
+ import globals from "globals";
33
+ function base() {
34
+ return [
35
+ {
36
+ languageOptions: {
37
+ globals: {
38
+ ...globals.browser,
39
+ ...globals.es2021
40
+ }
41
+ },
42
+ rules: {
43
+ /**
44
+ * Built-in rules
45
+ */
46
+ // Off for Prettier
47
+ // https://github.com/prettier/eslint-config-prettier/blob/main/index.js
48
+ // TODO move to prettier config
49
+ "array-bracket-newline": "off",
50
+ "array-bracket-spacing": "off",
51
+ "array-element-newline": "off",
52
+ "arrow-parens": "off",
53
+ "arrow-spacing": "off",
54
+ "block-spacing": "off",
55
+ "brace-style": "off",
56
+ "comma-dangle": "off",
57
+ "comma-spacing": "off",
58
+ "comma-style": "off",
59
+ "computed-property-spacing": "off",
60
+ "curly": 0,
61
+ "dot-location": "off",
62
+ "eol-last": "off",
63
+ "func-call-spacing": "off",
64
+ "function-call-argument-newline": "off",
65
+ "function-paren-newline": "off",
66
+ "generator-star": "off",
67
+ "generator-star-spacing": "off",
68
+ "implicit-arrow-linebreak": "off",
69
+ "indent": "off",
70
+ "jsx-quotes": "off",
71
+ "key-spacing": "off",
72
+ "keyword-spacing": "off",
73
+ "linebreak-style": "off",
74
+ "lines-around-comment": 0,
75
+ "max-len": 0,
76
+ "multiline-ternary": "off",
77
+ "new-parens": "off",
78
+ "newline-per-chained-call": "off",
79
+ "no-arrow-condition": "off",
80
+ "no-comma-dangle": "off",
81
+ "no-confusing-arrow": 0,
82
+ "no-extra-parens": "off",
83
+ "no-extra-semi": "off",
84
+ "no-floating-decimal": "off",
85
+ "no-mixed-operators": 0,
86
+ "no-mixed-spaces-and-tabs": "off",
87
+ "no-multi-spaces": "off",
88
+ "no-multiple-empty-lines": "off",
89
+ "no-reserved-keys": "off",
90
+ "no-space-before-semi": "off",
91
+ "no-tabs": 0,
92
+ "no-trailing-spaces": "off",
93
+ "no-unexpected-multiline": 0,
94
+ "no-whitespace-before-property": "off",
95
+ "no-wrap-func": "off",
96
+ "nonblock-statement-body-position": "off",
97
+ "object-curly-newline": "off",
98
+ "object-curly-spacing": "off",
99
+ "object-property-newline": "off",
100
+ "one-var-declaration-per-line": "off",
101
+ "operator-linebreak": "off",
102
+ "padded-blocks": "off",
103
+ "quote-props": "off",
104
+ "quotes": 0,
105
+ "rest-spread-spacing": "off",
106
+ "semi": "off",
107
+ "semi-spacing": "off",
108
+ "semi-style": "off",
109
+ "space-after-function-name": "off",
110
+ "space-after-keywords": "off",
111
+ "space-before-blocks": "off",
112
+ "space-before-function-paren": "off",
113
+ "space-before-function-parentheses": "off",
114
+ "space-before-keywords": "off",
115
+ "space-in-brackets": "off",
116
+ "space-in-parens": "off",
117
+ "space-infix-ops": "off",
118
+ "space-return-throw-case": "off",
119
+ "space-unary-ops": "off",
120
+ "space-unary-word-ops": "off",
121
+ "switch-colon-spacing": "off",
122
+ "template-curly-spacing": "off",
123
+ "template-tag-spacing": "off",
124
+ "unicode-bom": "off",
125
+ "wrap-iife": "off",
126
+ "wrap-regex": "off",
127
+ "yield-star-spacing": "off",
128
+ // Enforces getter/setter pairs in objects and classes
129
+ "accessor-pairs": "error",
130
+ // Enforces return statements in callbacks of array's methods
131
+ "array-callback-return": [
132
+ "error",
133
+ // To be compatible with unicorn/no-useless-undefined
134
+ { allowImplicit: true }
135
+ ],
136
+ // Can cause issues when Prettier is enabled
137
+ // TODO should this move to prettier config?
138
+ "arrow-body-style": "off",
139
+ // Generates warnings when variables are used outside of the
140
+ // block in which they were defined
141
+ "block-scoped-var": "error",
142
+ // camelCase vars
143
+ "camelcase": "error",
144
+ // Write comments however you like
145
+ "capitalized-comments": "off",
146
+ // If a class method does not use this,
147
+ // it can sometimes be made into a static function
148
+ "class-methods-use-this": "error",
149
+ // Measures the number of linearly independent paths through a program's
150
+ // source code. Rubbish. Use your own judgement on complexity.
151
+ "complexity": "off",
152
+ // Do not care how return statements specify values.
153
+ // When on, this rule gets annoying when combined with Unicorn's no-useless-* rules.
154
+ "consistent-return": "off",
155
+ // Not sure if required
156
+ "consistent-this": "error",
157
+ // Constructors of derived classes must call super().
158
+ // Constructors of non derived classes must not call super()
159
+ "constructor-super": "error",
160
+ // Require Default Case in Switch Statements
161
+ "default-case": "error",
162
+ // enforce default clauses in switch statements to be last
163
+ "default-case-last": "error",
164
+ // Putting default parameter at last allows function calls
165
+ // to omit optional tail arguments.
166
+ "default-param-last": "error",
167
+ // Access properties using the dot notation.
168
+ "dot-notation": "warn",
169
+ // Use === over ==
170
+ "eqeqeq": "warn",
171
+ // Enforce "for" loop update clause moving the counter in the right direction
172
+ "for-direction": "error",
173
+ // Require function names to match the name of the variable or property to
174
+ // which they are assigned.
175
+ "func-name-matching": "error",
176
+ // Requires function expressions to have a name,
177
+ // If the name cannot be assigned automatically
178
+ "func-names": ["error", "as-needed"],
179
+ // Declaration style: function name() {}
180
+ // Except arrow functions
181
+ "func-style": ["error", "declaration", { allowArrowFunctions: true }],
182
+ // Enforces that a return statement is present in property getters
183
+ "getter-return": "error",
184
+ // If a property has a getter and a setter, the setter should be defined
185
+ // right after the getter, or vice versa.
186
+ "grouped-accessor-pairs": "error",
187
+ // This rule is aimed at preventing unexpected behavior that could arise
188
+ // from using a for in loop without filtering the results in the loop.
189
+ "guard-for-in": "error",
190
+ // Disallows specified identifiers.
191
+ // Maybe turn this on when it's obvious which identifiers do not make sense.
192
+ // Rules like unicorn/catch-error-name look after some of these, anyway.
193
+ "id-denylist": "off",
194
+ // Allow variables named with as little chars as you like
195
+ "id-length": "off",
196
+ // Requires identifiers to match a specified regular expression.
197
+ // Mainly covered by rules like "camelcase". This could probably cause more
198
+ // trouble than it's worth.
199
+ "id-match": "off",
200
+ // Initialise vairables however you like
201
+ "init-declarations": "off",
202
+ // Enforces line comments positioned above code
203
+ "line-comment-position": "error",
204
+ // Require an empty line between class members
205
+ "lines-between-class-members": "warn",
206
+ "logical-assignment-operators": ["warn", "always"],
207
+ // Organise classes how you see fit
208
+ "max-classes-per-file": "off",
209
+ // This rule enforces a maximum depth that blocks can be nested to reduce
210
+ // code complexity. Just gets in the way too much.
211
+ "max-depth": "off",
212
+ // Files can contain as many lines as you like
213
+ "max-lines": "off",
214
+ // Functions can be as complicated as you like
215
+ "max-lines-per-function": "off",
216
+ // This rule enforces a maximum depth that callbacks can be nested to
217
+ // increase code clarity. Defaults to 10.
218
+ "max-nested-callbacks": "error",
219
+ // Enforces a maximum number of parameters allowed in function definitions.
220
+ // This is usually to help readability but TS self-documents this kind of thing.
221
+ "max-params": "off",
222
+ // Statements can be as complicated as you like
223
+ "max-statements": "off",
224
+ // Enforces maximum number of statements allowed per line to 1.
225
+ "max-statements-per-line": "error",
226
+ // Allow any style of multiline comments
227
+ "multiline-comment-style": "off",
228
+ // Require constructor names to begin with a capital letter
229
+ "new-cap": "error",
230
+ // alert is often used while debugging code, which should be removed before
231
+ // deployment to production.
232
+ "no-alert": "error",
233
+ // Use of the Array constructor to construct a new array is generally
234
+ // discouraged in favor of array literal notation because of the
235
+ // single-argument pitfall and because the Array global may be redefined.
236
+ // The exception is when the Array constructor is used to intentionally
237
+ // create sparse arrays of a specified size by giving the constructor a
238
+ // single numeric argument.
239
+ "no-array-constructor": "error",
240
+ // The executor function can also be an async function.
241
+ // However, this is usually a mistake:
242
+ // https://eslint.org/docs/rules/no-async-promise-executor#top
243
+ "no-async-promise-executor": "error",
244
+ // Use Promise.all() instead
245
+ "no-await-in-loop": "error",
246
+ // Use of bitwise operators in JavaScript is very rare and often & or | is
247
+ // simply a mistyped && or ||, which will lead to unexpected behavior.
248
+ "no-bitwise": "error",
249
+ // Use the producer methods Buffer.from, Buffer.alloc,
250
+ // and Buffer.allocUnsafe instead.
251
+ "no-buffer-constructor": "error",
252
+ // arguments.caller and arguments.callee ave been deprecated in future
253
+ // versions of JavaScript and their use is forbidden in ECMAScript 5 while
254
+ // in strict mode.
255
+ "no-caller": "error",
256
+ // Disallows lexical declarations (let, const, function and class) in
257
+ // case/default clauses. To ensure that the lexical declaration only applies
258
+ // to the current case clause wrap your clauses in blocks.
259
+ "no-case-declarations": "error",
260
+ // Disallow modifying variables of class declarations
261
+ "no-class-assign": "error",
262
+ // Disallow comparing against -0
263
+ "no-compare-neg-zero": "error",
264
+ // Disallow assignment operators in conditional statements. e.g.
265
+ // if (user.jobTitle = "manager") { }
266
+ "no-cond-assign": "error",
267
+ // Disallow the use of console
268
+ "no-console": "warn",
269
+ // Disallow modifying variables that are declared using const
270
+ "no-const-assign": "error",
271
+ // This rule identifies == and === comparisons which, based on the semantics
272
+ // of the JavaScript language, will always evaluate to true or false.
273
+ "no-constant-binary-expression": "error",
274
+ // Disallow constant expressions in conditions
275
+ // if (true) {}
276
+ "no-constant-condition": "error",
277
+ // Disallows return statements in the constructor of a class
278
+ "no-constructor-return": "error",
279
+ // Disallow continue statements.
280
+ // When used incorrectly it makes code less testable, less readable and less
281
+ // maintainable. Structured control flow statements such as if should be
282
+ // used instead.
283
+ "no-continue": "error",
284
+ // Control characters are special, invisible characters in the ASCII range
285
+ // 0-31. These characters are rarely used in JavaScript strings so a regular
286
+ // expression containing these characters is most likely a mistake.
287
+ "no-control-regex": "error",
288
+ // The debugger statement is used to tell the executing JavaScript
289
+ // environment to stop execution and start up a debugger at the current
290
+ // point in the code. This has fallen out of favor as a good practice with
291
+ // the advent of modern debugging and development tools.
292
+ "no-debugger": "error",
293
+ // The purpose of the delete operator is to remove a property from an
294
+ // object. Using the delete operator on a variable might lead to unexpected
295
+ // behavior.
296
+ "no-delete-var": "error",
297
+ // Require regex literals to escape division operators.
298
+ "no-div-regex": "warn",
299
+ // function foo(a, b, a) { } // duplicate "a" arg
300
+ "no-dupe-args": "error",
301
+ // class Foo {
302
+ // bar() { console.log("hello") }
303
+ // bar() { console.log("goodbye") } // duplicate class member
304
+ // }
305
+ "no-dupe-class-members": "error",
306
+ // if (isSomething(x)) {
307
+ // foo()
308
+ // } else if (isSomething(x)) { // duplicate condition
309
+ // bar()
310
+ // }
311
+ "no-dupe-else-if": "error",
312
+ // const foo = {
313
+ // bar: "baz",
314
+ // bar: "qux" // duplicate key
315
+ // }
316
+ "no-dupe-keys": "error",
317
+ // switch (a) {
318
+ // case 1:
319
+ // break
320
+ // case 2:
321
+ // break
322
+ // case 1: // duplicate test expression
323
+ // break
324
+ // default:
325
+ // break
326
+ // }
327
+ "no-duplicate-case": "error",
328
+ // Combine named imports in single statement.
329
+ "no-duplicate-imports": "error",
330
+ // If an `if` block contains a return statement, the else block becomes
331
+ // unnecessary. Its contents can be placed outside of the block.
332
+ "no-else-return": "warn",
333
+ // Disallow empty block statements.
334
+ "no-empty": "error",
335
+ // Disallow empty character classes in regular expressions.
336
+ "no-empty-character-class": "error",
337
+ // Disallow empty functions.
338
+ "no-empty-function": "error",
339
+ // Disallow empty destructuring patterns.
340
+ "no-empty-pattern": "error",
341
+ "no-empty-static-block": "error",
342
+ // Error: if (foo == null)
343
+ // Good: if (foo === null)
344
+ "no-eq-null": "error",
345
+ // Disallow eval()
346
+ "no-eval": "error",
347
+ // Disallow reassigning exceptions in catch clauses.
348
+ "no-ex-assign": "error",
349
+ // Disallow extending of native objects.
350
+ "no-extend-native": "error",
351
+ // Disallow unnecessary function binding
352
+ "no-extra-bind": "warn",
353
+ // In contexts such as an if statement's test where the result of the
354
+ // expression will already be coerced to a Boolean, casting to a Boolean via
355
+ // double negation (!!) or a Boolean call is unnecessary.
356
+ "no-extra-boolean-cast": "warn",
357
+ // If a loop contains no nested loops or switches, labeling the loop is unnecessary.
358
+ "no-extra-label": "warn",
359
+ // Disallow case statement fallthrough.
360
+ "no-fallthrough": "error",
361
+ // Disallow reassigning function declarations.
362
+ "no-func-assign": "error",
363
+ // Disallow assignment to native objects or read-only global variables.
364
+ "no-global-assign": "error",
365
+ // Disallow the type conversion with shorter notations.
366
+ "no-implicit-coercion": "warn",
367
+ // Disallow declarations in the global scope.
368
+ "no-implicit-globals": "error",
369
+ // There are some other ways to pass a string and have it interpreted as
370
+ // JavaScript code that have similar concerns.
371
+ // e.g. setTimeout("alert('Hi!');", 100);
372
+ "no-implied-eval": "error",
373
+ // Disallow assigning to imported bindings.
374
+ "no-import-assign": "error",
375
+ // Disallow inline comments after code.
376
+ "no-inline-comments": "error",
377
+ // Disallow variable or function declarations in nested blocks.
378
+ "no-inner-declarations": "error",
379
+ // Disallow invalid regular expression strings in RegExp constructors.
380
+ "no-invalid-regexp": "error",
381
+ // Disallow this keywords outside of classes or class-like objects.
382
+ "no-invalid-this": "error",
383
+ // Invalid or irregular whitespace causes issues with ECMAScript 5 parsers
384
+ // and also makes code harder to debug in a similar nature to mixed tabs and spaces.
385
+ "no-irregular-whitespace": "error",
386
+ // The __iterator__ property was a SpiderMonkey extension to JavaScript that
387
+ // could be used to create custom iterators that are compatible with
388
+ // JavaScript's for in and for each constructs. However, this property is
389
+ // now obsolete, so it should not be used.
390
+ "no-iterator": "error",
391
+ // Disallow labels that are variables names.
392
+ "no-label-var": "error",
393
+ // While convenient in some cases, labels tend to be used only rarely and
394
+ // are frowned upon by some as a remedial form of flow control that is more
395
+ // error prone and harder to understand.
396
+ "no-labels": "error",
397
+ // Disallow unnecessary nested blocks
398
+ "no-lone-blocks": "error",
399
+ // Disallow if statements as the only statement in else blocks.
400
+ "no-lonely-if": "warn",
401
+ // Writing functions within loops tends to result in errors due to the way
402
+ // the function creates a closure around the loop.
403
+ "no-loop-func": "error",
404
+ // Disallow the use of number literals that immediately lose precision at
405
+ // runtime when converted to a JS Number due to 64-bit floating-point rounding.
406
+ "no-loss-of-precision": "error",
407
+ // Disallowing magic numbers causes all sorts of problems
408
+ "no-magic-numbers": "off",
409
+ // Disallow characters which are made with multiple code points in character class syntax.
410
+ "no-misleading-character-class": "error",
411
+ // const foo = bar = "baz"
412
+ "no-multi-assign": "error",
413
+ // var x = "Line 1 \
414
+ // Line 2"
415
+ "no-multi-str": "error",
416
+ // Negated conditions are more difficult to understand. Code can be made
417
+ // more readable by inverting the condition instead.
418
+ // This is handled by unicorn.
419
+ "no-negated-condition": "off",
420
+ // Disallow nested ternary expressions
421
+ "no-nested-ternary": "error",
422
+ // Disallows constructor calls using the new keyword that do not assign
423
+ // the resulting object to a variable.
424
+ "no-new": "error",
425
+ // ❌ Function()
426
+ // ✅ function()
427
+ "no-new-func": "error",
428
+ // ❌ new BigInt(12344555)
429
+ // ✅ BigInt(12344555)
430
+ "no-new-native-nonconstructor": "error",
431
+ // ❌ var myObject = new Object()
432
+ // ✅ var myObject = {}
433
+ "no-new-object": "error",
434
+ // Symbol is not intended to be used with the new operator, but to be called
435
+ // as a function.
436
+ "no-new-symbol": "error",
437
+ // This rule aims to eliminate the use of String, Number, and Boolean with
438
+ // the new operator. As such, it warns whenever it sees new String,
439
+ // new Number, or new Boolean.
440
+ "no-new-wrappers": "error",
441
+ // Disallow \8 and \9 escape sequences in string literals
442
+ "no-nonoctal-decimal-escape": "error",
443
+ // This rule disallows calling the Math, JSON, Reflect and Atomics objects as functions.
444
+ "no-obj-calls": "error",
445
+ // the leading zero which identifies an octal literal has been a source of
446
+ // confusion and error in JavaScript code, ECMAScript 5 deprecates the use
447
+ // of octal numeric literals.
448
+ "no-octal": "error",
449
+ // As of the ECMAScript 5 specification, octal escape sequences in string
450
+ // literals are deprecated and should not be used. Unicode escape sequences
451
+ // should be used instead.
452
+ "no-octal-escape": "error",
453
+ // Assignment to variables declared as function parameters can be misleading
454
+ // and lead to confusing behavior, as modifying function parameters will
455
+ // also mutate the arguments object.
456
+ "no-param-reassign": "error",
457
+ // Because the unary ++ and -- operators are subject to automatic semicolon
458
+ // insertion, differences in whitespace can change semantics of source code.
459
+ "no-plusplus": "error",
460
+ // Disallow returning values from Promise executor functions
461
+ "no-promise-executor-return": "error",
462
+ // __proto__ property has been deprecated as of ECMAScript 3.1 and shouldn't
463
+ // be used in the code. Use Object.getPrototypeOf and Object.setPrototypeOf instead.
464
+ "no-proto": "error",
465
+ // Disallow use of Object.prototypes builtins directly.
466
+ "no-prototype-builtins": "error",
467
+ // Disallow variable redeclaration.
468
+ "no-redeclare": "error",
469
+ // Disallow multiple spaces in regular expression literals.
470
+ "no-regex-spaces": "warn",
471
+ // No export names are restricted
472
+ "no-restricted-exports": "off",
473
+ // Global variable names that are dangerous to use by mistake
474
+ "no-restricted-globals": ["error", ...restrictedGlobals],
475
+ // No imports are restricted
476
+ "no-restricted-imports": "off",
477
+ // No properties are restricted
478
+ "no-restricted-properties": "off",
479
+ // No syntax is restricted
480
+ "no-restricted-syntax": "off",
481
+ // Disallow assignment in return statement
482
+ "no-return-assign": "error",
483
+ // Disallows unnecessary return await
484
+ "no-return-await": "error",
485
+ // ❌ location.href = "javascript:void(0)"
486
+ "no-script-url": "error",
487
+ // Self assignments have no effect.
488
+ // ❌ foo = foo
489
+ "no-self-assign": "error",
490
+ // Comparing a variable against itself is usually an error, either a typo or
491
+ // refactoring error.
492
+ "no-self-compare": "error",
493
+ // Disallow use of the comma operator.
494
+ "no-sequences": "error",
495
+ // Disallow returning values from setters.
496
+ "no-setter-return": "error",
497
+ // Disallow variable declarations from shadowing variables declared in the outer scope.
498
+ "no-shadow": "error",
499
+ // ES5 Value Properties of the Global Object (NaN, Infinity, undefined) as
500
+ // well as strict mode restricted identifiers eval and arguments are considered
501
+ // to be restricted names in JavaScript. Defining them to mean something
502
+ // else can have unintended consequences and confuse others reading the code.
503
+ "no-shadow-restricted-names": "error",
504
+ // This rule disallows sparse array literals which have "holes" where commas
505
+ // are not preceded by elements. It does not apply to a trailing comma
506
+ // following the last element. Use ignored values instead.
507
+ "no-sparse-arrays": "error",
508
+ // Disallow template literal placeholder syntax in regular strings.
509
+ "no-template-curly-in-string": "error",
510
+ // Simple ternaries are okay
511
+ "no-ternary": "off",
512
+ // Disallow use of this/super before calling super() in constructors.
513
+ "no-this-before-super": "error",
514
+ // Maintain consistency when throwing exception by disallowing to throw
515
+ // literals and other expressions which cannot possibly be an Error object.
516
+ "no-throw-literal": "error",
517
+ // Disallow undeclared variables.
518
+ "no-undef": "error",
519
+ // Disallow initializing to undefined.
520
+ "no-undef-init": "warn",
521
+ // Allow undefined. Use no-global-assign and no-shadow-restricted-names
522
+ // rules to prevent undefined from being shadowed or assigned a different value.
523
+ "no-undefined": "off",
524
+ // Allow dangling underscores in identifiers.
525
+ "no-underscore-dangle": "off",
526
+ // Disallow unmodified conditions of loops
527
+ "no-unmodified-loop-condition": "error",
528
+ // Disallow ternary operators when simpler alternatives exist.
529
+ "no-unneeded-ternary": "warn",
530
+ // Disallow unreachable code after return, throw, continue, and break statements.
531
+ "no-unreachable": "error",
532
+ // Disallow loops with a body that allows only one iteration
533
+ "no-unreachable-loop": "error",
534
+ // Disallow control flow statements in finally blocks.
535
+ "no-unsafe-finally": "error",
536
+ // Disallow negating the left operand of relational operators.
537
+ "no-unsafe-negation": "error",
538
+ // Disallow use of optional chaining in contexts where the `undefined` value is not allowed
539
+ "no-unsafe-optional-chaining": "error",
540
+ // An unused expression which has no effect on the state of the program
541
+ // indicates a logic error.
542
+ "no-unused-expressions": "error",
543
+ // Labels that are declared and not used anywhere in the code are most
544
+ // likely an error due to incomplete refactoring.
545
+ "no-unused-labels": "warn",
546
+ "no-unused-private-class-members": "error",
547
+ // Variables must be used unless name starts with "ignored"
548
+ "no-unused-vars": [
549
+ "error",
550
+ {
551
+ // Useful for extracting args from props and ignoring them:
552
+ // { style: _style, ...restProps }
553
+ argsIgnorePattern: "^_",
554
+ varsIgnorePattern: "[iI]gnored"
555
+ }
556
+ ],
557
+ // It's possible to use identifiers before their formal declarations in code.
558
+ // This can be confusing and some believe it is best to always declare
559
+ // variables and functions before using them.
560
+ "no-use-before-define": "error",
561
+ // Do I need this? https://eslint.org/docs/rules/no-useless-backreference
562
+ "no-useless-backreference": "off",
563
+ // Function.prototype.call() and Function.prototype.apply() are slower than
564
+ // the normal function invocation.
565
+ "no-useless-call": "error",
566
+ // A catch clause that only rethrows the original error is redundant, and
567
+ // has no effect on the runtime behavior of the program.
568
+ "no-useless-catch": "error",
569
+ // ❌ var foo = {['a']: 'b'}
570
+ // ✅ var foo = {a: 'b'}
571
+ "no-useless-computed-key": "error",
572
+ // ❌ var foo = 'a' + 'b'
573
+ // ✅ var foo = 'ab'
574
+ "no-useless-concat": "error",
575
+ // ES2015 provides a default class constructor if one is not specified. As
576
+ // such, it isunnecessary to provide an empty constructor or one that simply
577
+ // delegates into its parent class.
578
+ "no-useless-constructor": "error",
579
+ // Escaping non-special characters in strings, template literals, and
580
+ // regular expressions doesn't have any effect.
581
+ "no-useless-escape": "error",
582
+ // Disallow renaming import, export, and destructured assignments to the same name.
583
+ "no-useless-rename": "warn",
584
+ // A return; statement with nothing after it is redundant, and has no effect
585
+ // on the runtime behavior of a function. This can be confusing, so it's
586
+ // better to disallow these redundant statements.
587
+ "no-useless-return": "warn",
588
+ // Require let or const instead of var.
589
+ "no-var": "warn",
590
+ // Disallow use of the void operator.
591
+ "no-void": "error",
592
+ // Allow TODOs and FIXMEs
593
+ "no-warning-comments": "off",
594
+ // The with statement is potentially problematic because it adds members of
595
+ // an object to the current scope, making it impossible to tell what a
596
+ // variable inside the block actually refers to.
597
+ "no-with": "error",
598
+ // Functions declared in object keys must conform to a certain style
599
+ // Capitalised functions are exempt as they are probably constructor functions
600
+ "object-shorthand": ["warn", "always", { ignoreConstructors: true }],
601
+ // Prevent combined variable declarations
602
+ "one-var": ["warn", "never"],
603
+ // Disallow assignment operator shorthand where possible.
604
+ "operator-assignment": ["warn", "never"],
605
+ "padding-line-between-statements": [
606
+ "warn",
607
+ { blankLine: "always", next: "*", prev: "multiline-block-like" },
608
+ { blankLine: "always", next: "multiline-block-like", prev: "*" },
609
+ { blankLine: "always", next: "*", prev: "multiline-const" },
610
+ { blankLine: "always", next: "multiline-const", prev: "*" },
611
+ { blankLine: "always", next: "*", prev: "multiline-let" },
612
+ { blankLine: "always", next: "multiline-let", prev: "*" },
613
+ { blankLine: "always", next: "*", prev: "multiline-var" },
614
+ { blankLine: "always", next: "multiline-var", prev: "*" }
615
+ ],
616
+ // Can cause issues when Prettier is enabled
617
+ "prefer-arrow-callback": "off",
618
+ // If a variable is never reassigned, using the const declaration is better.
619
+ "prefer-const": "warn",
620
+ // Make compatible with Unicorn's no-unreadable-array-destructuring
621
+ "prefer-destructuring": ["warn", { array: false, object: true }],
622
+ // Introduced in ES2016, the infix exponentiation operator ** is an
623
+ // alternative for the standard Math.pow function. Infix notation is
624
+ // considered to be more readable and thus more preferable than the function notation.
625
+ "prefer-exponentiation-operator": "warn",
626
+ // Allow regex to be left as-is
627
+ "prefer-named-capture-group": "off",
628
+ // This rule disallows calls to parseInt() or Number.parseInt() if called
629
+ // with two arguments: a string; and a radix option of 2 (binary), 8 (octal),
630
+ // or 16 (hexadecimal).
631
+ "prefer-numeric-literals": "warn",
632
+ // Not supported by Typescript yet
633
+ "prefer-object-has-own": "off",
634
+ // Prefer use of an object spread over Object.assign()
635
+ "prefer-object-spread": "warn",
636
+ // It is considered good practice to only pass instances of the built-in
637
+ // Error object to the reject() function for user-defined errors in Promises.
638
+ // Error objects automatically store a stack trace, which can be used to
639
+ // debug an error by determining where it came from. If a Promise is rejected
640
+ // with a non-Error value, it can be difficult to determine where the rejection occurred.
641
+ "prefer-promise-reject-errors": "error",
642
+ // Disallow use of the RegExp constructor in favor of regular expression literals.
643
+ "prefer-regex-literals": "error",
644
+ // Suggest using the rest parameters instead of `arguments`.
645
+ "prefer-rest-params": "error",
646
+ // Suggest using spread syntax instead of `.apply()`.
647
+ "prefer-spread": "error",
648
+ // Suggest using template literals instead of string concatenation.
649
+ "prefer-template": "warn",
650
+ // When using the parseInt() function it is common to omit the second argument,
651
+ // the radix, and let the function try to determine from the first argument
652
+ // what type of number it is. By default, parseInt() will autodetect decimal
653
+ // and hexadecimal (via 0x prefix). Prior to ECMAScript 5, parseInt() also
654
+ // autodetected octal literals, which caused problems because many developers
655
+ // assumed a leading 0 would be ignored.
656
+ "radix": "error",
657
+ // Disallow assignments that can lead to race conditions due to usage of await or yield.
658
+ "require-atomic-updates": "error",
659
+ // Disallow async functions which have no await expression.
660
+ "require-await": "error",
661
+ // Enforce the use of 'u' flag on RegExp.
662
+ "require-unicode-regexp": "error",
663
+ // Disallow generator functions that do not have yield.
664
+ "require-yield": "error",
665
+ // Sorting imports is handled by simple-import-sort
666
+ "sort-imports": "off",
667
+ "sort-keys": [
668
+ "error",
669
+ "asc",
670
+ {
671
+ allowLineSeparatedGroups: true,
672
+ caseSensitive: false,
673
+ natural: true
674
+ }
675
+ ],
676
+ // Not required as one-var rule is set to 'error' and so there will never be vars to sort.
677
+ "sort-vars": "off",
678
+ // All comments must have a space after the //
679
+ // This also allows /// reference comments
680
+ "spaced-comment": ["warn", "always", { markers: ["/"] }],
681
+ // Generally gets in the way as it's difficult to know when this may be required.
682
+ "strict": "off",
683
+ // Using description promotes easier debugging.
684
+ // ✅ var foo = Symbol("some description")
685
+ "symbol-description": "error",
686
+ // Require calls to isNaN() when checking for NaN.
687
+ "use-isnan": "error",
688
+ // Enforce comparing typeof expressions against valid strings.
689
+ "valid-typeof": ["error", { requireStringLiterals: true }],
690
+ // By default variable declarations are always moved (“hoisted”) invisibly
691
+ // to the top of their containing scope by the JavaScript interpreter.
692
+ // This rule forces the programmer to represent that behavior by manually
693
+ // moving the variable declaration to the top of its containing scope.
694
+ "vars-on-top": "error",
695
+ // ❌ if ('red' === color) {}
696
+ // ✅ if (color === 'red') {}
697
+ "yoda": "warn"
698
+ }
699
+ }
700
+ ];
701
+ }
702
+
703
+ // src/globs.ts
704
+ var GLOB_EXCLUDE = [
705
+ "**/node_modules",
706
+ "**/dist",
707
+ "**/package-lock.json",
708
+ "**/yarn.lock",
709
+ "**/pnpm-lock.yaml",
710
+ "**/bun.lockb",
711
+ "**/output",
712
+ "**/coverage",
713
+ "**/temp",
714
+ "**/.vitepress/cache",
715
+ "**/.nuxt",
716
+ "**/.vercel",
717
+ "**/.changeset",
718
+ "**/.idea",
719
+ "**/.cache",
720
+ "**/.output",
721
+ "**/.vite-inspect",
722
+ "**/CHANGELOG*.md",
723
+ "**/*.min.*",
724
+ "**/LICENSE*",
725
+ "**/__snapshots__",
726
+ "**/auto-import?(s).d.ts",
727
+ "**/components.d.ts"
728
+ ];
729
+
730
+ // src/configs/ignores.ts
731
+ function ignores() {
732
+ return [
733
+ {
734
+ ignores: GLOB_EXCLUDE
735
+ }
736
+ ];
737
+ }
738
+
739
+ // src/configs/imports.ts
740
+ import pluginImport from "eslint-plugin-i";
741
+ import pluginSimpleImport from "eslint-plugin-simple-import-sort";
742
+ function imports() {
743
+ return [
744
+ {
745
+ plugins: {
746
+ "import": pluginImport,
747
+ "simple-import-sort": pluginSimpleImport
748
+ },
749
+ rules: {
750
+ // Prefer inline types
751
+ "import/consistent-type-specifier-style": ["warn", "prefer-top-level"],
752
+ // Reports funny business with exports,
753
+ // like repeated exports of names or defaults
754
+ "import/export": "error",
755
+ // Stating exports at the end of the file can make refactoring a two-step process
756
+ "import/exports-last": "off",
757
+ // Same as import/exports-last
758
+ "import/group-exports": "off",
759
+ // There must be a line's space between imports and code
760
+ "import/newline-after-import": "warn",
761
+ // ❌ import {} from 'mod'
762
+ "import/no-empty-named-blocks": "warn",
763
+ // When there is only a single export from a module,
764
+ // this _would_ prefer using default export over named export, but it
765
+ // causes too many issues and it soon becomes tiresome with some tools
766
+ // requiring defaults and others forbidding them or requiring a certain
767
+ // named export.
768
+ "import/prefer-default-export": "off",
769
+ // Sort all the imports!
770
+ "simple-import-sort/exports": "warn",
771
+ "simple-import-sort/imports": "warn",
772
+ // The rest of the rules, off until required
773
+ "import/default": "off",
774
+ "import/dynamic-import-chunkname": "off",
775
+ "import/extensions": "off",
776
+ "import/first": "off",
777
+ "import/max-dependencies": "off",
778
+ "import/named": "off",
779
+ "import/namespace": "off",
780
+ "import/no-absolute-path": "off",
781
+ "import/no-amd": "off",
782
+ "import/no-anonymous-default-export": "off",
783
+ "import/no-commonjs": "off",
784
+ "import/no-cycle": "off",
785
+ "import/no-default-export": "off",
786
+ "import/no-deprecated": "off",
787
+ "import/no-duplicates": "off",
788
+ "import/no-dynamic-require": "off",
789
+ "import/no-extraneous-dependencies": "off",
790
+ "import/no-import-module-exports": "off",
791
+ "import/no-internal-modules": "off",
792
+ "import/no-mutable-exports": "off",
793
+ "import/no-named-as-default": "off",
794
+ "import/no-named-as-default-member": "off",
795
+ "import/no-named-default": "off",
796
+ "import/no-named-export": "off",
797
+ "import/no-namespace": "off",
798
+ "import/no-nodejs-modules": "off",
799
+ "import/no-relative-packages": "off",
800
+ "import/no-relative-parent-imports": "off",
801
+ "import/no-restricted-paths": "off",
802
+ "import/no-self-import": "off",
803
+ "import/no-unassigned-import": "off",
804
+ "import/no-unresolved": "off",
805
+ "import/no-unused-modules": "off",
806
+ "import/no-useless-path-segments": "off",
807
+ "import/no-webpack-loader-syntax": "off",
808
+ "import/order": "off",
809
+ "import/unambiguous": "off"
810
+ }
811
+ }
812
+ ];
813
+ }
814
+
815
+ // src/configs/jest.ts
816
+ import pluginJest from "eslint-plugin-jest";
817
+ import globals2 from "globals";
818
+ function jest() {
819
+ return [
820
+ {
821
+ files: ["**/__mocks__/**/*", "**/*.{spec,test}.{js,cjs,mjs,jsx,ts,tsx}"],
822
+ languageOptions: {
823
+ globals: globals2.jest
824
+ }
825
+ },
826
+ {
827
+ files: ["**/*.{spec,test}.{js,cjs,mjs,jsx,ts,tsx}"],
828
+ plugins: {
829
+ jest: pluginJest
830
+ },
831
+ rules: {
832
+ // Consistent test function names
833
+ // test
834
+ // describe -> it
835
+ "jest/consistent-test-it": [
836
+ "error",
837
+ { fn: "test", withinDescribe: "it" }
838
+ ],
839
+ // Enforce assertion to be made in a test body
840
+ "jest/expect-expect": "error",
841
+ // Have as many expects as you like
842
+ "jest/max-expects": "off",
843
+ "jest/max-nested-describe": "off",
844
+ // Consistent expect methods
845
+ "jest/no-alias-methods": "error",
846
+ "jest/no-commented-out-tests": "error",
847
+ // Prevent calling expect conditionally
848
+ "jest/no-conditional-expect": "error",
849
+ "jest/no-conditional-in-test": "error",
850
+ "jest/no-deprecated-functions": "warn",
851
+ "jest/no-disabled-tests": "warn",
852
+ // Avoid using a callback in asynchronous tests and hooks
853
+ "jest/no-done-callback": "error",
854
+ // Do not allow multiple beforeEach, for example
855
+ "jest/no-duplicate-hooks": "error",
856
+ // Disallow using exports in files containing tests
857
+ "jest/no-export": "error",
858
+ "jest/no-focused-tests": "error",
859
+ "jest/no-hooks": "off",
860
+ "jest/no-identical-title": "error",
861
+ // Conditional logic in tests is usually an indication that a test is attempting to cover too much
862
+ "jest/no-if": "error",
863
+ // Disallow string interpolation inside snapshots
864
+ "jest/no-interpolation-in-snapshots": "error",
865
+ "jest/no-jasmine-globals": "warn",
866
+ "jest/no-large-snapshots": "off",
867
+ // Disallow manually importing from __mocks__
868
+ "jest/no-mocks-import": "error",
869
+ // No methods that need restricting
870
+ "jest/no-restricted-jest-methods": "off",
871
+ "jest/no-restricted-matchers": "off",
872
+ // No standalone expect in a describe block
873
+ "jest/no-standalone-expect": "error",
874
+ // Use .only and .skip over f and x
875
+ "jest/no-test-prefixes": "warn",
876
+ // Tests shouldn't return anything
877
+ "jest/no-test-return-statement": "error",
878
+ "jest/prefer-called-with": "off",
879
+ // https://github.com/jest-community/eslint-plugin-jest/blob/main/docs/rules/prefer-comparison-matcher.md
880
+ "jest/prefer-comparison-matcher": "warn",
881
+ "jest/prefer-each": "error",
882
+ // https://github.com/jest-community/eslint-plugin-jest/blob/main/docs/rules/prefer-equality-matcher.md
883
+ "jest/prefer-equality-matcher": "error",
884
+ "jest/prefer-expect-assertions": "off",
885
+ "jest/prefer-expect-resolves": "warn",
886
+ // Put lifecycle hooks in particular order
887
+ "jest/prefer-hooks-in-order": "error",
888
+ // beforeEach, beforeAll, afterEach etc. should be at top of test block
889
+ "jest/prefer-hooks-on-top": "error",
890
+ // Allow any case in test names
891
+ "jest/prefer-lowercase-title": "off",
892
+ // When working with mocks of functions that return promises, Jest provides
893
+ // some API sugar functions to reduce the amount of boilerplate you have to write.
894
+ "jest/prefer-mock-promise-shorthand": "warn",
895
+ "jest/prefer-snapshot-hint": "error",
896
+ // By overwriting a property with `jest.fn()` you have to manually restore
897
+ // the original implementation when cleaning up. When using jest.spyOn()
898
+ // Jest keeps track of changes, and they can be restored.
899
+ "jest/prefer-spy-on": "error",
900
+ "jest/prefer-strict-equal": "error",
901
+ "jest/prefer-to-be": "warn",
902
+ // expect(a.includes(b)).toBe(true) -> expect(a).toContain(b)
903
+ "jest/prefer-to-contain": "error",
904
+ // expect(files.length).toBe(1) -> expect(files).toHaveLength(1)
905
+ "jest/prefer-to-have-length": "error",
906
+ // When test cases are empty then it is better to mark them as test.todo
907
+ // as it will be highlighted in the summary output
908
+ "jest/prefer-todo": "error",
909
+ // Require setup and tear down code to be within lifecycle hooks
910
+ "jest/require-hook": "error",
911
+ // Requiring a message ensures that the intended error is thrown
912
+ "jest/require-to-throw-message": "error",
913
+ "jest/require-top-level-describe": "off",
914
+ "jest/unbound-method": "off",
915
+ "jest/valid-describe-callback": "error",
916
+ "jest/valid-expect": "error",
917
+ "jest/valid-expect-in-promise": "error",
918
+ // Titles are...
919
+ // - not empty
920
+ // - is a string
921
+ // - not prefixed with their block name
922
+ // - have no leading or trailing spaces
923
+ "jest/valid-title": "error"
924
+ }
925
+ },
926
+ {
927
+ files: ["**/*.{spec,test}.{ts,tsx}"],
928
+ rules: {
929
+ "jest/no-untyped-mock-factory": "warn"
930
+ }
931
+ }
932
+ ];
933
+ }
934
+
935
+ // src/configs/node.ts
936
+ import pluginNode from "eslint-plugin-n";
937
+ import globals3 from "globals";
938
+ function node() {
939
+ return [
940
+ {
941
+ languageOptions: {
942
+ globals: globals3.node
943
+ },
944
+ plugins: {
945
+ n: pluginNode
946
+ },
947
+ rules: {
948
+ // Enforces return statements in callbacks of array's methods
949
+ "n/callback-return": "error",
950
+ // require() should be called only in the top level of a module to make it
951
+ // easier to identify dependencies.
952
+ "n/global-require": "error",
953
+ // This rule expects that when you're using the callback pattern in Node.js
954
+ // you'll handle the error.
955
+ "n/handle-callback-err": "error",
956
+ // Disallow require calls to be mixed with regular variable declarations.
957
+ "n/no-mixed-requires": "error",
958
+ // ❌ var appHeader = new require('app-header')
959
+ // ✅ var AppHeader = require('app-header')
960
+ // var appHeader = new AppHeader()
961
+ "n/no-new-require": "error",
962
+ // Disallow string concatenation when using __dirname and __filename.
963
+ // Use path.join() instead.
964
+ "n/no-path-concat": "error",
965
+ // Allow env vars in code
966
+ "n/no-process-env": "off",
967
+ // Handled by Unicorn
968
+ "n/no-process-exit": "off",
969
+ // No modules are restricted
970
+ "n/no-restricted-require": "off",
971
+ // I like synchronous functions
972
+ "n/no-sync": "off",
973
+ // Not sure I need this...?
974
+ // TODO check others' configs to see how they use this.
975
+ "n/shebang": "off",
976
+ // Turn these off until I work out if I need them
977
+ "n/exports-style": "off",
978
+ "n/file-extension-in-import": "off",
979
+ "n/no-callback-literal": "off",
980
+ "n/no-deprecated-api": "off",
981
+ "n/no-exports-assign": "off",
982
+ "n/no-extraneous-import": "off",
983
+ "n/no-extraneous-require": "off",
984
+ "n/no-missing-import": "off",
985
+ "n/no-missing-require": "off",
986
+ "n/no-restricted-import": "off",
987
+ "n/no-unpublished-bin": "off",
988
+ "n/no-unpublished-import": "off",
989
+ "n/no-unpublished-require": "off",
990
+ "n/no-unsupported-features/es-builtins": "off",
991
+ "n/no-unsupported-features/es-syntax": "off",
992
+ "n/no-unsupported-features/node-builtins": "off",
993
+ "n/prefer-global/buffer": "off",
994
+ "n/prefer-global/console": "off",
995
+ "n/prefer-global/process": "off",
996
+ "n/prefer-global/text-decoder": "off",
997
+ "n/prefer-global/text-encoder": "off",
998
+ "n/prefer-global/url": "off",
999
+ "n/prefer-global/url-search-params": "off",
1000
+ "n/prefer-promises/dns": "off",
1001
+ "n/prefer-promises/fs": "off",
1002
+ "n/process-exit-as-throw": "off"
1003
+ }
1004
+ }
1005
+ ];
1006
+ }
1007
+
1008
+ // src/configs/prettier.ts
1009
+ import pluginPrettier from "eslint-plugin-prettier";
1010
+ function prettier() {
1011
+ return [
1012
+ {
1013
+ plugins: {
1014
+ prettier: pluginPrettier
1015
+ },
1016
+ rules: {
1017
+ "prettier/prettier": "warn"
1018
+ }
1019
+ }
1020
+ ];
1021
+ }
1022
+
1023
+ // src/configs/react.ts
1024
+ import pluginJsxA11y from "eslint-plugin-jsx-a11y";
1025
+ import pluginReact from "eslint-plugin-react";
1026
+ import pluginReactHooks from "eslint-plugin-react-hooks";
1027
+ import globals4 from "globals";
1028
+ function react() {
1029
+ return [
1030
+ {
1031
+ files: ["**/*.{jsx,tsx}"],
1032
+ languageOptions: {
1033
+ globals: globals4.browser,
1034
+ parserOptions: {
1035
+ ecmaFeatures: {
1036
+ jsx: true
1037
+ }
1038
+ }
1039
+ },
1040
+ plugins: {
1041
+ "jsx-a11y": pluginJsxA11y,
1042
+ "react": pluginReact,
1043
+ "react-hooks": pluginReactHooks
1044
+ },
1045
+ rules: {
1046
+ "jsx-a11y/alt-text": "error",
1047
+ "jsx-a11y/anchor-ambiguous-text": "error",
1048
+ "jsx-a11y/anchor-has-content": "error",
1049
+ "jsx-a11y/anchor-is-valid": "error",
1050
+ "jsx-a11y/aria-activedescendant-has-tabindex": "error",
1051
+ "jsx-a11y/aria-props": "error",
1052
+ "jsx-a11y/aria-proptypes": "error",
1053
+ "jsx-a11y/aria-role": "error",
1054
+ "jsx-a11y/aria-unsupported-elements": "error",
1055
+ "jsx-a11y/autocomplete-valid": "error",
1056
+ "jsx-a11y/click-events-have-key-events": "error",
1057
+ "jsx-a11y/control-has-associated-label": [
1058
+ "off",
1059
+ {
1060
+ ignoreElements: [
1061
+ "audio",
1062
+ "canvas",
1063
+ "embed",
1064
+ "input",
1065
+ "textarea",
1066
+ "tr",
1067
+ "video"
1068
+ ],
1069
+ ignoreRoles: [
1070
+ "grid",
1071
+ "listbox",
1072
+ "menu",
1073
+ "menubar",
1074
+ "radiogroup",
1075
+ "row",
1076
+ "tablist",
1077
+ "toolbar",
1078
+ "tree",
1079
+ "treegrid"
1080
+ ],
1081
+ includeRoles: ["alert", "dialog"]
1082
+ }
1083
+ ],
1084
+ "jsx-a11y/heading-has-content": "error",
1085
+ "jsx-a11y/html-has-lang": "error",
1086
+ "jsx-a11y/iframe-has-title": "error",
1087
+ "jsx-a11y/img-redundant-alt": "error",
1088
+ "jsx-a11y/interactive-supports-focus": [
1089
+ "error",
1090
+ {
1091
+ tabbable: [
1092
+ "button",
1093
+ "checkbox",
1094
+ "link",
1095
+ "searchbox",
1096
+ "spinbutton",
1097
+ "switch",
1098
+ "textbox"
1099
+ ]
1100
+ }
1101
+ ],
1102
+ "jsx-a11y/label-has-associated-control": "error",
1103
+ "jsx-a11y/label-has-for": "off",
1104
+ "jsx-a11y/lang": "error",
1105
+ "jsx-a11y/media-has-caption": "error",
1106
+ "jsx-a11y/mouse-events-have-key-events": "error",
1107
+ "jsx-a11y/no-access-key": "error",
1108
+ "jsx-a11y/no-aria-hidden-on-focusable": "error",
1109
+ "jsx-a11y/no-autofocus": "error",
1110
+ "jsx-a11y/no-distracting-elements": "error",
1111
+ "jsx-a11y/no-interactive-element-to-noninteractive-role": [
1112
+ "error",
1113
+ {
1114
+ canvas: ["img"],
1115
+ tr: ["none", "presentation"]
1116
+ }
1117
+ ],
1118
+ "jsx-a11y/no-noninteractive-element-interactions": [
1119
+ "error",
1120
+ {
1121
+ alert: ["onKeyUp", "onKeyDown", "onKeyPress"],
1122
+ body: ["onError", "onLoad"],
1123
+ dialog: ["onKeyUp", "onKeyDown", "onKeyPress"],
1124
+ handlers: [
1125
+ "onClick",
1126
+ "onError",
1127
+ "onLoad",
1128
+ "onMouseDown",
1129
+ "onMouseUp",
1130
+ "onKeyPress",
1131
+ "onKeyDown",
1132
+ "onKeyUp"
1133
+ ],
1134
+ iframe: ["onError", "onLoad"],
1135
+ img: ["onError", "onLoad"]
1136
+ }
1137
+ ],
1138
+ "jsx-a11y/no-noninteractive-element-to-interactive-role": [
1139
+ "error",
1140
+ {
1141
+ fieldset: ["radiogroup", "presentation"],
1142
+ li: ["menuitem", "option", "row", "tab", "treeitem"],
1143
+ ol: [
1144
+ "listbox",
1145
+ "menu",
1146
+ "menubar",
1147
+ "radiogroup",
1148
+ "tablist",
1149
+ "tree",
1150
+ "treegrid"
1151
+ ],
1152
+ table: ["grid"],
1153
+ td: ["gridcell"],
1154
+ ul: [
1155
+ "listbox",
1156
+ "menu",
1157
+ "menubar",
1158
+ "radiogroup",
1159
+ "tablist",
1160
+ "tree",
1161
+ "treegrid"
1162
+ ]
1163
+ }
1164
+ ],
1165
+ "jsx-a11y/no-noninteractive-tabindex": [
1166
+ "error",
1167
+ {
1168
+ allowExpressionValues: true,
1169
+ roles: ["tabpanel"],
1170
+ tags: []
1171
+ }
1172
+ ],
1173
+ "jsx-a11y/no-redundant-roles": "error",
1174
+ "jsx-a11y/no-static-element-interactions": [
1175
+ "error",
1176
+ {
1177
+ allowExpressionValues: true,
1178
+ handlers: [
1179
+ "onClick",
1180
+ "onMouseDown",
1181
+ "onMouseUp",
1182
+ "onKeyPress",
1183
+ "onKeyDown",
1184
+ "onKeyUp"
1185
+ ]
1186
+ }
1187
+ ],
1188
+ "jsx-a11y/prefer-tag-over-role": "error",
1189
+ "jsx-a11y/role-has-required-aria-props": "error",
1190
+ "jsx-a11y/role-supports-aria-props": "error",
1191
+ "jsx-a11y/scope": "error",
1192
+ "jsx-a11y/tabindex-no-positive": "error",
1193
+ /**
1194
+ * Off for Prettier
1195
+ * https://github.com/prettier/eslint-config-prettier/blob/main/index.js
1196
+ */
1197
+ "react/jsx-child-element-spacing": "off",
1198
+ "react/jsx-closing-bracket-location": "off",
1199
+ "react/jsx-closing-tag-location": "off",
1200
+ "react/jsx-curly-newline": "off",
1201
+ "react/jsx-curly-spacing": "off",
1202
+ "react/jsx-equals-spacing": "off",
1203
+ "react/jsx-first-prop-new-line": "off",
1204
+ "react/jsx-indent": "off",
1205
+ "react/jsx-indent-props": "off",
1206
+ "react/jsx-max-props-per-line": "off",
1207
+ "react/jsx-newline": "off",
1208
+ "react/jsx-one-expression-per-line": "off",
1209
+ "react/jsx-props-no-multi-spaces": "off",
1210
+ "react/jsx-tag-spacing": "off",
1211
+ "react/jsx-wrap-multilines": "off",
1212
+ // It is common to use these lifecycle methods without using "this".
1213
+ "class-methods-use-this": [
1214
+ "error",
1215
+ {
1216
+ exceptMethods: [
1217
+ "render",
1218
+ "getInitialState",
1219
+ "getDefaultProps",
1220
+ "getChildContext",
1221
+ "componentWillMount",
1222
+ "componentDidMount",
1223
+ "componentWillReceiveProps",
1224
+ "shouldComponentUpdate",
1225
+ "componentWillUpdate",
1226
+ "componentDidUpdate",
1227
+ "componentWillUnmount",
1228
+ "componentDidCatch"
1229
+ ]
1230
+ }
1231
+ ],
1232
+ "react/boolean-prop-naming": "error",
1233
+ "react/button-has-type": "error",
1234
+ "react/default-props-match-prop-types": "error",
1235
+ "react/destructuring-assignment": "error",
1236
+ "react/display-name": "error",
1237
+ // Components can use any props.
1238
+ "react/forbid-component-props": "off",
1239
+ "react/forbid-dom-props": "error",
1240
+ "react/forbid-elements": "error",
1241
+ "react/forbid-foreign-prop-types": "error",
1242
+ "react/forbid-prop-types": "error",
1243
+ // Functional components can use any style.
1244
+ "react/function-component-definition": "off",
1245
+ "react/hook-use-state": "error",
1246
+ "react/iframe-missing-sandbox": "error",
1247
+ // ❌ <Hello personal={true} />
1248
+ // ✅ <Hello personal />
1249
+ "react/jsx-boolean-value": "warn",
1250
+ // disallow unnecessary curly braces in JSX props and/or children.
1251
+ "react/jsx-curly-brace-presence": "warn",
1252
+ // Allow JSX in any files
1253
+ "react/jsx-filename-extension": "off",
1254
+ // Enforce shorthand for React fragments.
1255
+ "react/jsx-fragments": "warn",
1256
+ "react/jsx-handler-names": "error",
1257
+ "react/jsx-key": "error",
1258
+ // Unlimited JSX nesting.
1259
+ "react/jsx-max-depth": "off",
1260
+ // I haven't found any modern benchmarks for disallowing inline arrow
1261
+ // functions, and quite frankly it feels like this "optimisation" is just
1262
+ // people repeating sentiments from old blog posts.
1263
+ "react/jsx-no-bind": [
1264
+ "error",
1265
+ {
1266
+ allowArrowFunctions: true
1267
+ }
1268
+ ],
1269
+ "react/jsx-no-comment-textnodes": "error",
1270
+ "react/jsx-no-constructed-context-values": "error",
1271
+ "react/jsx-no-duplicate-props": "error",
1272
+ // In React, you might end up rendering unexpected values like 0 or NaN.
1273
+ // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-no-leaked-render.md
1274
+ "react/jsx-no-leaked-render": "warn",
1275
+ // ✅ <div>test</div>
1276
+ // ✅ <div>{'test'}</div>
1277
+ "react/jsx-no-literals": "off",
1278
+ "react/jsx-no-script-url": "error",
1279
+ "react/jsx-no-target-blank": "error",
1280
+ "react/jsx-no-undef": "error",
1281
+ "react/jsx-no-useless-fragment": "warn",
1282
+ "react/jsx-pascal-case": "error",
1283
+ // Allow prop spreading, you know the dangers!
1284
+ "react/jsx-props-no-spreading": "off",
1285
+ // Alphabetical sorting of props
1286
+ // TODO there's other options in this one that could be useful.
1287
+ "react/jsx-sort-props": ["warn", { reservedFirst: true }],
1288
+ "react/jsx-uses-react": "error",
1289
+ "react/jsx-uses-vars": "error",
1290
+ "react/no-access-state-in-setstate": "error",
1291
+ "react/no-adjacent-inline-elements": "error",
1292
+ "react/no-array-index-key": "error",
1293
+ "react/no-arrow-function-lifecycle": "error",
1294
+ "react/no-children-prop": "error",
1295
+ "react/no-danger": "error",
1296
+ "react/no-danger-with-children": "error",
1297
+ "react/no-deprecated": "error",
1298
+ "react/no-did-mount-set-state": "error",
1299
+ "react/no-did-update-set-state": "error",
1300
+ "react/no-direct-mutation-state": "error",
1301
+ "react/no-find-dom-node": "error",
1302
+ "react/no-invalid-html-attribute": "error",
1303
+ "react/no-is-mounted": "error",
1304
+ // Allow as many components per file as you like
1305
+ "react/no-multi-comp": "off",
1306
+ "react/no-namespace": "error",
1307
+ // Prevent potential unnecessary rerenders, and performance regressions
1308
+ "react/no-object-type-as-default-prop": "error",
1309
+ "react/no-redundant-should-component-update": "error",
1310
+ "react/no-render-return-value": "error",
1311
+ "react/no-set-state": "error",
1312
+ "react/no-string-refs": "error",
1313
+ "react/no-this-in-sfc": "error",
1314
+ "react/no-typos": "error",
1315
+ "react/no-unescaped-entities": "error",
1316
+ // ❌ <div class="hello">Hello World</div>
1317
+ // ✅ <div className="hello">Hello World</div>
1318
+ "react/no-unknown-property": "warn",
1319
+ "react/no-unsafe": "error",
1320
+ "react/no-unstable-nested-components": "error",
1321
+ "react/no-unused-class-component-methods": "error",
1322
+ "react/no-unused-prop-types": "error",
1323
+ "react/no-unused-state": "error",
1324
+ "react/no-will-update-set-state": "error",
1325
+ "react/prefer-es6-class": "error",
1326
+ "react/prefer-exact-props": "error",
1327
+ "react/prefer-read-only-props": "error",
1328
+ "react/prefer-stateless-function": "error",
1329
+ "react/prop-types": "off",
1330
+ // React is no longer required to be imported to use JSX
1331
+ "react/react-in-jsx-scope": "off",
1332
+ // Enforce a defaultProps definition for every prop that is not a required prop
1333
+ // TODO turn this back on and create a react-typescript rule set for disabling thing like this.
1334
+ "react/require-default-props": "off",
1335
+ // Do not enforce React components to have a shouldComponentUpdate method.
1336
+ "react/require-optimization": "off",
1337
+ "react/require-render-return": "error",
1338
+ // Prevent extra closing tags for components without children.
1339
+ "react/self-closing-comp": "warn",
1340
+ "react/sort-comp": "error",
1341
+ "react/sort-default-props": "error",
1342
+ "react/sort-prop-types": "error",
1343
+ "react/state-in-constructor": "error",
1344
+ "react/static-property-placement": "error",
1345
+ "react/style-prop-object": "error",
1346
+ "react/void-dom-elements-no-children": "error",
1347
+ // Checks effect dependencies
1348
+ "react-hooks/exhaustive-deps": "warn",
1349
+ // Checks rules of Hooks
1350
+ "react-hooks/rules-of-hooks": "error"
1351
+ },
1352
+ settings: {
1353
+ react: {
1354
+ version: "detect"
1355
+ }
1356
+ }
1357
+ }
1358
+ ];
1359
+ }
1360
+
1361
+ // src/configs/switch-case.ts
1362
+ import pluginSwitchCase from "eslint-plugin-switch-case";
1363
+ function switchCase() {
1364
+ return [
1365
+ {
1366
+ plugins: {
1367
+ "switch-case": pluginSwitchCase
1368
+ },
1369
+ rules: {
1370
+ // Switches must have new lines between case groups
1371
+ "switch-case/newline-between-switch-case": [
1372
+ "warn",
1373
+ "always",
1374
+ { fallthrough: "never" }
1375
+ ],
1376
+ // It can be useful for switch cases to have their own scope.
1377
+ "switch-case/no-case-curly": "off"
1378
+ }
1379
+ }
1380
+ ];
1381
+ }
1382
+
1383
+ // src/configs/typescript.ts
1384
+ import pluginTypescript from "@typescript-eslint/eslint-plugin";
1385
+ import parserTypescript2 from "@typescript-eslint/parser";
1386
+ function typescript() {
1387
+ return [
1388
+ {
1389
+ files: ["**/*.{ts,tsx,astro}"],
1390
+ languageOptions: {
1391
+ // @ts-expect-error -- does not confirm to type
1392
+ parser: parserTypescript2
1393
+ },
1394
+ plugins: {
1395
+ // @ts-expect-error -- does not confirm to type
1396
+ "@typescript-eslint": pluginTypescript
1397
+ },
1398
+ rules: {
1399
+ /**
1400
+ * Recommended to turn off these eslint built-in rules
1401
+ * https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/src/configs/eslint-recommended.ts
1402
+ */
1403
+ // ts(2335) & ts(2377)
1404
+ "constructor-super": "off",
1405
+ // ts(2378)
1406
+ "getter-return": "off",
1407
+ // ts(2588)
1408
+ "no-const-assign": "off",
1409
+ // ts(2300)
1410
+ "no-dupe-args": "off",
1411
+ // ts(2393) & ts(2300)
1412
+ "no-dupe-class-members": "off",
1413
+ // ts(1117)
1414
+ "no-dupe-keys": "off",
1415
+ // ts(2539)
1416
+ "no-func-assign": "off",
1417
+ // ts(2539) & ts(2540)
1418
+ "no-import-assign": "off",
1419
+ // ts(2588)
1420
+ "no-new-symbol": "off",
1421
+ // ts(2349)
1422
+ "no-obj-calls": "off",
1423
+ // ts(2408)
1424
+ "no-setter-return": "off",
1425
+ // ts(2376)
1426
+ "no-this-before-super": "off",
1427
+ // ts(2304)
1428
+ "no-undef": "off",
1429
+ // ts(7027)
1430
+ "no-unreachable": "off",
1431
+ // ts(2365) & ts(2360) & ts(2358)
1432
+ "no-unsafe-negation": "off",
1433
+ // ts transpiles let/const to var, so no need for vars any more
1434
+ "no-var": "error",
1435
+ // ts provides better types with const
1436
+ "prefer-const": "warn",
1437
+ // ts provides better types with rest args over arguments
1438
+ "prefer-rest-params": "error",
1439
+ // ts transpiles spread to apply, so no need for manual apply
1440
+ "prefer-spread": "error",
1441
+ // ts(2367)
1442
+ "valid-typeof": "off",
1443
+ /**
1444
+ * TS Recommended
1445
+ * https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/src/configs/recommended.ts
1446
+ */
1447
+ "@typescript-eslint/adjacent-overload-signatures": "error",
1448
+ "@typescript-eslint/ban-ts-comment": "error",
1449
+ "@typescript-eslint/ban-types": "error",
1450
+ "@typescript-eslint/explicit-module-boundary-types": "warn",
1451
+ "@typescript-eslint/no-array-constructor": "error",
1452
+ "@typescript-eslint/no-empty-function": "error",
1453
+ "@typescript-eslint/no-empty-interface": "error",
1454
+ "@typescript-eslint/no-explicit-any": "warn",
1455
+ "@typescript-eslint/no-inferrable-types": "error",
1456
+ "@typescript-eslint/no-misused-new": "error",
1457
+ "@typescript-eslint/no-namespace": "error",
1458
+ "@typescript-eslint/no-non-null-asserted-optional-chain": "error",
1459
+ "@typescript-eslint/no-non-null-assertion": "warn",
1460
+ "@typescript-eslint/no-this-alias": "error",
1461
+ "@typescript-eslint/no-var-requires": "error",
1462
+ "@typescript-eslint/prefer-as-const": "error",
1463
+ "@typescript-eslint/prefer-namespace-keyword": "error",
1464
+ "@typescript-eslint/triple-slash-reference": "error",
1465
+ "no-array-constructor": "off",
1466
+ "no-empty-function": "off",
1467
+ "no-extra-semi": "off",
1468
+ /**
1469
+ * These are for type checking which I don't use eslint for
1470
+ */
1471
+ "@typescript-eslint/await-thenable": "off",
1472
+ "@typescript-eslint/consistent-type-exports": "off",
1473
+ "@typescript-eslint/dot-notation": "off",
1474
+ "@typescript-eslint/naming-convention": "off",
1475
+ "@typescript-eslint/no-base-to-string": "off",
1476
+ "@typescript-eslint/no-confusing-void-expression": "off",
1477
+ "@typescript-eslint/no-duplicate-type-constituents": "off",
1478
+ "@typescript-eslint/no-floating-promises": "off",
1479
+ "@typescript-eslint/no-for-in-array": "off",
1480
+ "@typescript-eslint/no-implied-eval": "off",
1481
+ "@typescript-eslint/no-meaningless-void-operator": "off",
1482
+ "@typescript-eslint/no-misused-promises": "off",
1483
+ "@typescript-eslint/no-mixed-enums": "off",
1484
+ "@typescript-eslint/no-redundant-type-constituents": "off",
1485
+ "@typescript-eslint/no-throw-literal": "off",
1486
+ "@typescript-eslint/no-unnecessary-boolean-literal-compare": "off",
1487
+ "@typescript-eslint/no-unnecessary-condition": "off",
1488
+ "@typescript-eslint/no-unnecessary-qualifier": "off",
1489
+ "@typescript-eslint/no-unnecessary-type-arguments": "off",
1490
+ "@typescript-eslint/no-unnecessary-type-assertion": "off",
1491
+ "@typescript-eslint/no-unsafe-argument": "off",
1492
+ "@typescript-eslint/no-unsafe-assignment": "off",
1493
+ "@typescript-eslint/no-unsafe-call": "off",
1494
+ "@typescript-eslint/no-unsafe-enum-comparison": "off",
1495
+ "@typescript-eslint/no-unsafe-member-access": "off",
1496
+ "@typescript-eslint/no-unsafe-return": "off",
1497
+ "@typescript-eslint/non-nullable-type-assertion-style": "off",
1498
+ "@typescript-eslint/prefer-includes": "off",
1499
+ "@typescript-eslint/prefer-nullish-coalescing": "off",
1500
+ "@typescript-eslint/prefer-optional-chain": "off",
1501
+ "@typescript-eslint/prefer-readonly": "off",
1502
+ "@typescript-eslint/prefer-readonly-parameter-types": "off",
1503
+ "@typescript-eslint/prefer-reduce-type-parameter": "off",
1504
+ "@typescript-eslint/prefer-regexp-exec": "off",
1505
+ "@typescript-eslint/prefer-return-this-type": "off",
1506
+ "@typescript-eslint/prefer-string-starts-ends-with": "off",
1507
+ "@typescript-eslint/promise-function-async": "off",
1508
+ "@typescript-eslint/require-array-sort-compare": "off",
1509
+ "@typescript-eslint/require-await": "off",
1510
+ "@typescript-eslint/restrict-plus-operands": "off",
1511
+ "@typescript-eslint/restrict-template-expressions": "off",
1512
+ "@typescript-eslint/return-await": "off",
1513
+ "@typescript-eslint/strict-boolean-expressions": "off",
1514
+ "@typescript-eslint/switch-exhaustiveness-check": "off",
1515
+ "@typescript-eslint/unbound-method": "off",
1516
+ /**
1517
+ * Off for Prettier
1518
+ * https://github.com/prettier/eslint-config-prettier/blob/main/index.js
1519
+ */
1520
+ "@typescript-eslint/block-spacing": "off",
1521
+ "@typescript-eslint/brace-style": "off",
1522
+ "@typescript-eslint/comma-dangle": "off",
1523
+ "@typescript-eslint/comma-spacing": "off",
1524
+ "@typescript-eslint/func-call-spacing": "off",
1525
+ "@typescript-eslint/indent": "off",
1526
+ "@typescript-eslint/key-spacing": "off",
1527
+ "@typescript-eslint/keyword-spacing": "off",
1528
+ "@typescript-eslint/lines-around-comment": "off",
1529
+ "@typescript-eslint/member-delimiter-style": "off",
1530
+ "@typescript-eslint/no-extra-parens": "off",
1531
+ "@typescript-eslint/no-extra-semi": "off",
1532
+ "@typescript-eslint/object-curly-spacing": "off",
1533
+ "@typescript-eslint/quotes": "off",
1534
+ "@typescript-eslint/semi": "off",
1535
+ "@typescript-eslint/space-before-blocks": "off",
1536
+ "@typescript-eslint/space-before-function-paren": "off",
1537
+ "@typescript-eslint/space-infix-ops": "off",
1538
+ "@typescript-eslint/type-annotation-spacing": "off",
1539
+ /**
1540
+ * Superseded by TS rules below
1541
+ */
1542
+ "default-param-last": "off",
1543
+ "lines-between-class-members": "off",
1544
+ "no-duplicate-imports": "off",
1545
+ "no-invalid-this": "off",
1546
+ "no-loop-func": "off",
1547
+ "no-loss-of-precision": "off",
1548
+ "no-redeclare": "off",
1549
+ "no-restricted-imports": "off",
1550
+ "no-shadow": "off",
1551
+ "no-unused-expressions": "off",
1552
+ "no-unused-vars": "off",
1553
+ "no-use-before-define": "off",
1554
+ "no-useless-constructor": "off",
1555
+ "padding-line-between-statements": "off",
1556
+ /**
1557
+ * The rest
1558
+ */
1559
+ // Requires using T[] over Array<T> for arrays
1560
+ "@typescript-eslint/array-type": ["warn", { default: "array" }],
1561
+ // Bans // tslint:<rule-flag> comments from being used
1562
+ "@typescript-eslint/ban-tslint-comment": "warn",
1563
+ // Ensures that literals on classes are exposed in a consistent style
1564
+ "@typescript-eslint/class-literal-property-style": "warn",
1565
+ // https://typescript-eslint.io/rules/consistent-generic-constructors/
1566
+ "@typescript-eslint/consistent-generic-constructors": "warn",
1567
+ // Enforce the use of the record type
1568
+ "@typescript-eslint/consistent-indexed-object-style": "warn",
1569
+ // Enforces consistent usage of type assertions
1570
+ "@typescript-eslint/consistent-type-assertions": "error",
1571
+ // Enforce using types for object type definitions
1572
+ "@typescript-eslint/consistent-type-definitions": ["warn", "type"],
1573
+ // Enforces consistent usage of type imports
1574
+ "@typescript-eslint/consistent-type-imports": [
1575
+ "warn",
1576
+ {
1577
+ fixStyle: "separate-type-imports",
1578
+ prefer: "type-imports"
1579
+ }
1580
+ ],
1581
+ // Enforce default parameters to be last
1582
+ "@typescript-eslint/default-param-last": ["error"],
1583
+ // Don't mind if functions do not have return types.
1584
+ "@typescript-eslint/explicit-function-return-type": "off",
1585
+ // Require explicit accessibility modifiers ("public") on class properties and methods
1586
+ "@typescript-eslint/explicit-member-accessibility": "warn",
1587
+ // Initialise vairables however you like
1588
+ "@typescript-eslint/init-declarations": "off",
1589
+ "@typescript-eslint/lines-between-class-members": [
1590
+ "warn",
1591
+ "always",
1592
+ { exceptAfterOverload: true }
1593
+ ],
1594
+ // Require a consistent member declaration order
1595
+ "@typescript-eslint/member-ordering": "error",
1596
+ // ❌
1597
+ // interface T1 {
1598
+ // func(arg: string): number;
1599
+ // }
1600
+ // ✅
1601
+ // interface T1 {
1602
+ // func: (arg: string) => number;
1603
+ // }
1604
+ "@typescript-eslint/method-signature-style": "warn",
1605
+ // Disallow non-null assertion in locations that may be confusing
1606
+ "@typescript-eslint/no-confusing-non-null-assertion": "warn",
1607
+ // Disallow duplicate class members
1608
+ "@typescript-eslint/no-dupe-class-members": "error",
1609
+ // ❌
1610
+ // enum E {
1611
+ // A = 0,
1612
+ // B = 0,
1613
+ // }
1614
+ // ✅
1615
+ // enum E {
1616
+ // A = 0,
1617
+ // B = 1,
1618
+ // }
1619
+ "@typescript-eslint/no-duplicate-enum-values": "error",
1620
+ // Deleting missing key/value is safe
1621
+ "@typescript-eslint/no-dynamic-delete": "off",
1622
+ // ❌ const bar = foo!!!.bar
1623
+ // ✅ const bar = foo!.bar
1624
+ "@typescript-eslint/no-extra-non-null-assertion": "warn",
1625
+ // Warns when a class is accidentally used as a namespace
1626
+ "@typescript-eslint/no-extraneous-class": "error",
1627
+ "@typescript-eslint/no-import-type-side-effects": "warn",
1628
+ // Disallow this keywords outside of classes or class-like objects
1629
+ "@typescript-eslint/no-invalid-this": "error",
1630
+ // Disallows usage of void type outside of generic or return types
1631
+ "@typescript-eslint/no-invalid-void-type": "error",
1632
+ // Disallow function declarations that contain unsafe references inside loop statements
1633
+ "@typescript-eslint/no-loop-func": "error",
1634
+ // Disallow literal numbers that lose precision
1635
+ "@typescript-eslint/no-loss-of-precision": ["error"],
1636
+ // Disallowing magic numbers causes all sorts of problems
1637
+ "@typescript-eslint/no-magic-numbers": "off",
1638
+ "@typescript-eslint/no-non-null-asserted-nullish-coalescing": "error",
1639
+ "@typescript-eslint/no-redeclare": "error",
1640
+ "@typescript-eslint/no-require-imports": "error",
1641
+ "@typescript-eslint/no-restricted-imports": "off",
1642
+ // Disallow variable declarations from shadowing variables declared in the outer scope
1643
+ "@typescript-eslint/no-shadow": ["error"],
1644
+ // Aliasing can be useful
1645
+ "@typescript-eslint/no-type-alias": "off",
1646
+ // Disallows unnecessary constraints on generic types
1647
+ "@typescript-eslint/no-unnecessary-type-constraint": "warn",
1648
+ "@typescript-eslint/no-unsafe-declaration-merging": "error",
1649
+ // Aims to eliminate unused expressions which have no effect on the state of the program.
1650
+ "@typescript-eslint/no-unused-expressions": ["error"],
1651
+ // Variables must be used unless name ends with "ignored"
1652
+ "@typescript-eslint/no-unused-vars": [
1653
+ "error",
1654
+ {
1655
+ // Useful for extracting args from props and ignoring them:
1656
+ // { style: _style, ...restProps }
1657
+ argsIgnorePattern: "^_",
1658
+ varsIgnorePattern: "[iI]gnored"
1659
+ }
1660
+ ],
1661
+ "@typescript-eslint/no-use-before-define": "error",
1662
+ "@typescript-eslint/no-useless-constructor": "error",
1663
+ // Disallow empty exports that don't change anything in a module file
1664
+ "@typescript-eslint/no-useless-empty-export": "warn",
1665
+ "@typescript-eslint/padding-line-between-statements": [
1666
+ "error",
1667
+ { blankLine: "always", next: "*", prev: "multiline-block-like" },
1668
+ { blankLine: "always", next: "multiline-block-like", prev: "*" },
1669
+ { blankLine: "always", next: "*", prev: "multiline-const" },
1670
+ { blankLine: "always", next: "multiline-const", prev: "*" },
1671
+ { blankLine: "always", next: "*", prev: "multiline-let" },
1672
+ { blankLine: "always", next: "multiline-let", prev: "*" },
1673
+ { blankLine: "always", next: "*", prev: "multiline-var" },
1674
+ { blankLine: "always", next: "multiline-var", prev: "*" }
1675
+ ],
1676
+ // Not sure I need this, how many classes do I write?!
1677
+ // https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/docs/rules/parameter-properties.md
1678
+ "@typescript-eslint/parameter-properties": "off",
1679
+ "@typescript-eslint/prefer-enum-initializers": "error",
1680
+ // Unicorn does this better by providing a fixer
1681
+ "@typescript-eslint/prefer-for-of": "off",
1682
+ "@typescript-eslint/prefer-function-type": "warn",
1683
+ // Require that all enum members be literal values to prevent unintended enum member name shadow issues.
1684
+ "@typescript-eslint/prefer-literal-enum-member": "error",
1685
+ // Recommends using // @ts-expect-error over // @ts-ignore
1686
+ "@typescript-eslint/prefer-ts-expect-error": "warn",
1687
+ "@typescript-eslint/sort-type-constituents": "warn",
1688
+ // Not sure if required yet. Might be too strict and produce noist code.
1689
+ "@typescript-eslint/typedef": "off",
1690
+ "@typescript-eslint/unified-signatures": "error"
1691
+ }
1692
+ }
1693
+ ];
1694
+ }
1695
+
1696
+ // src/configs/unicorn.ts
1697
+ import pluginUnicorn from "eslint-plugin-unicorn";
1698
+ function unicorn() {
1699
+ return [
1700
+ {
1701
+ plugins: {
1702
+ unicorn: pluginUnicorn
1703
+ },
1704
+ rules: {
1705
+ // This rule is superseded by the unicorn version below
1706
+ "no-nested-ternary": "off",
1707
+ // Improve regexes by making them shorter, consistent, and safer
1708
+ "unicorn/better-regex": "warn",
1709
+ // Catch error argument name should be "error"
1710
+ "unicorn/catch-error-name": "error",
1711
+ // Use destructured variables over properties
1712
+ "unicorn/consistent-destructuring": "warn",
1713
+ // Move function definitions to the highest possible scope
1714
+ "unicorn/consistent-function-scoping": [
1715
+ "error",
1716
+ { checkArrowFunctions: false }
1717
+ ],
1718
+ // Custom Error classes must conform to standard
1719
+ "unicorn/custom-error-definition": "warn",
1720
+ // Enforce no spaces between braces
1721
+ "unicorn/empty-brace-spaces": "warn",
1722
+ // Enforces a message value to be passed in when throwing built-in Error
1723
+ "unicorn/error-message": "error",
1724
+ // Enforces defining escape sequence values with uppercase characters rather
1725
+ // than lowercase ones. This promotes readability by making the escaped
1726
+ // value more distinguishable from the identifier.
1727
+ "unicorn/escape-case": "warn",
1728
+ // Allows todo/fixme to be given expiry conditions and will error when met
1729
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/expiring-todo-comments.md
1730
+ "unicorn/expiring-todo-comments": "error",
1731
+ // Don't care how if(blah.length) is checked
1732
+ "unicorn/explicit-length-check": "off",
1733
+ // Kebab-case only
1734
+ "unicorn/filename-case": "error",
1735
+ // Enforces requiring index file with . instead of ./, ./index or ./index.js
1736
+ // Turned off for imports where this can mess with ESM.
1737
+ "unicorn/import-index": ["warn", { ignoreImports: true }],
1738
+ // Not sure if this is useful yet
1739
+ "unicorn/import-style": "off",
1740
+ // Enforce the use of new for all builtins, except String, Number and Boolean
1741
+ "unicorn/new-for-builtins": "warn",
1742
+ // Enforce specifying rules to disable in eslint-disable comments
1743
+ "unicorn/no-abusive-eslint-disable": "error",
1744
+ // Allow passing a function reference directly to iterator methods
1745
+ "unicorn/no-array-callback-reference": "off",
1746
+ // Prefer for…of over Array#forEach(…)
1747
+ "unicorn/no-array-for-each": "warn",
1748
+ // Disallow using the this argument in array methods
1749
+ "unicorn/no-array-method-this-argument": "warn",
1750
+ // Enforce combining multiple Array#push() into one call
1751
+ "unicorn/no-array-push-push": "warn",
1752
+ // for..of is much easier to read
1753
+ "unicorn/no-array-reduce": "error",
1754
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-await-expression-member.md
1755
+ "unicorn/no-await-expression-member": "warn",
1756
+ // Do not use leading/trailing space between console.log parameters
1757
+ "unicorn/no-console-spaces": "warn",
1758
+ // Do not use document.cookie directly
1759
+ "unicorn/no-document-cookie": "error",
1760
+ // Disallow empty files
1761
+ // TODO turn back on when it can exclude files. As this warns about the
1762
+ // auto-generated next-env.d.ts file.
1763
+ "unicorn/no-empty-file": "off",
1764
+ // Do not use a for loop that can be replaced with a for-of loop
1765
+ "unicorn/no-for-loop": "warn",
1766
+ // Enforce the use of Unicode escapes instead of hexadecimal escapes
1767
+ "unicorn/no-hex-escape": "warn",
1768
+ // Require Array.isArray() instead of instanceof Array
1769
+ "unicorn/no-instanceof-array": "warn",
1770
+ // The removeEventListener function must be called with a reference to the same
1771
+ // function that was passed to addEventListener.
1772
+ "unicorn/no-invalid-remove-event-listener": "error",
1773
+ // Disallow identifiers (var names) starting with new.
1774
+ // Do not check properties and allow "class" so that "className" is allowed.
1775
+ "unicorn/no-keyword-prefix": [
1776
+ "error",
1777
+ { checkProperties: false, disallowedPrefixes: ["new"] }
1778
+ ],
1779
+ // This rule adds onto the built-in no-lonely-if rule, which only forbids if
1780
+ // statements in else, not in if.
1781
+ "unicorn/no-lonely-if": "warn",
1782
+ // This is an improved version of the no-negated-condition ESLint rule that
1783
+ // makes it automatically fixable. ESLint did not want to make it fixable.
1784
+ "unicorn/no-negated-condition": "warn",
1785
+ // Improved version of the no-nested-ternary ESLint rule, which allows cases
1786
+ // where the nested ternary is only one level and wrapped in parens.
1787
+ "unicorn/no-nested-ternary": "warn",
1788
+ // Disallow new Array()
1789
+ "unicorn/no-new-array": "warn",
1790
+ // Enforce the use of Buffer.from() and Buffer.alloc() instead of the
1791
+ // deprecated new Buffer()
1792
+ "unicorn/no-new-buffer": "warn",
1793
+ // Allow the use of the null literal, it useful for React components and empty JSON values.
1794
+ "unicorn/no-null": "off",
1795
+ // Disallow the use of objects as default parameters
1796
+ "unicorn/no-object-as-default-parameter": "error",
1797
+ // Extension to ESLint's no-process-exit rule, that allows process.exit() to
1798
+ // be called in files that start with a hashbang → #!/usr/bin/env node
1799
+ "unicorn/no-process-exit": "error",
1800
+ // A class with only static members could just be an object instead
1801
+ "unicorn/no-static-only-class": "error",
1802
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-thenable.md
1803
+ "unicorn/no-thenable": "error",
1804
+ // Disallow assigning this to a variable
1805
+ "unicorn/no-this-assignment": "error",
1806
+ // Checking if a value is undefined by using typeof value === 'undefined' is needlessly verbose.
1807
+ "unicorn/no-typeof-undefined": "warn",
1808
+ // Disallow awaiting non-promise values
1809
+ "unicorn/no-unnecessary-await": "warn",
1810
+ // Disallow [,, foo], use ignored vars instead
1811
+ "unicorn/no-unreadable-array-destructuring": "error",
1812
+ // IIFE with parenthesized arrow function body is considered unreadable
1813
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-unreadable-iife.md
1814
+ "unicorn/no-unreadable-iife": "error",
1815
+ // Uses safe-regex to disallow potentially catastrophic exponential-time regular expressions.
1816
+ // Turned off for now, even Sindre doesn't like it: https://github.com/sindresorhus/eslint-plugin-unicorn/issues/153
1817
+ "unicorn/no-unsafe-regex": "off",
1818
+ // Recommended config turned this off so I will too
1819
+ "unicorn/no-unused-properties": "off",
1820
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-useless-fallback-in-spread.md
1821
+ "unicorn/no-useless-fallback-in-spread": "warn",
1822
+ // Disallow useless array length check
1823
+ "unicorn/no-useless-length-check": "warn",
1824
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-useless-promise-resolve-reject.md
1825
+ "unicorn/no-useless-promise-resolve-reject": "warn",
1826
+ // Disallow useless spread
1827
+ "unicorn/no-useless-spread": "warn",
1828
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-useless-switch-case.md
1829
+ "unicorn/no-useless-switch-case": "error",
1830
+ // ❌ let foo = undefined;
1831
+ // ✅ let foo;
1832
+ "unicorn/no-useless-undefined": "warn",
1833
+ // Disallow number literals with zero fractions or dangling dots
1834
+ "unicorn/no-zero-fractions": "warn",
1835
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/number-literal-case.md
1836
+ "unicorn/number-literal-case": "warn",
1837
+ // Enforce the style of numeric separators by correctly grouping digits
1838
+ "unicorn/numeric-separators-style": "warn",
1839
+ // Prefer .addEventListener() and .removeEventListener() over on-functions
1840
+ "unicorn/prefer-add-event-listener": "warn",
1841
+ // Prefer .find(…) over the first element from .filter(…)
1842
+ "unicorn/prefer-array-find": "warn",
1843
+ // Prefer Array#flat() over legacy techniques to flatten arrays
1844
+ "unicorn/prefer-array-flat": "warn",
1845
+ // Prefer .flatMap(…) over .map(…).flat()
1846
+ "unicorn/prefer-array-flat-map": "warn",
1847
+ // Prefer Array#indexOf() over Array#findIndex() when looking for the index of an item
1848
+ "unicorn/prefer-array-index-of": "warn",
1849
+ // Prefer using Array#some over Array#find when ensuring at least one element
1850
+ // in the array passes a given check.
1851
+ "unicorn/prefer-array-some": "error",
1852
+ // Prefer .at() method for index access and String#charAt()
1853
+ "unicorn/prefer-at": "warn",
1854
+ // Prefer Blob#arrayBuffer() over FileReader#readAsArrayBuffer(…) and Blob#text() over FileReader#readAsText(…)
1855
+ "unicorn/prefer-blob-reading-methods": "error",
1856
+ // Prefer String#codePointAt(…) over String#charCodeAt(…)
1857
+ // and String.fromCodePoint(…) over String.fromCharCode(…)
1858
+ "unicorn/prefer-code-point": "error",
1859
+ // Prefer Date.now() to get the number of milliseconds since the Unix Epoch
1860
+ "unicorn/prefer-date-now": "warn",
1861
+ // Prefer default parameters over reassignment
1862
+ "unicorn/prefer-default-parameters": "warn",
1863
+ // Prefer Node#append() over Node#appendChild()
1864
+ "unicorn/prefer-dom-node-append": "warn",
1865
+ // Prefer using .dataset on DOM elements over .setAttribute(…)
1866
+ "unicorn/prefer-dom-node-dataset": "warn",
1867
+ // Prefer node.remove() over parentNode.removeChild(node) and parentElement.removeChild(node)
1868
+ "unicorn/prefer-dom-node-remove": "warn",
1869
+ // Prefer .textContent over .innerText
1870
+ "unicorn/prefer-dom-node-text-content": "warn",
1871
+ // Prefer EventTarget over EventEmitter.
1872
+ "unicorn/prefer-event-target": "error",
1873
+ // Prefer `export…from` when re-exporting
1874
+ "unicorn/prefer-export-from": "warn",
1875
+ // Prefer .includes() over .indexOf() when checking for existence or non-existence
1876
+ "unicorn/prefer-includes": "warn",
1877
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-json-parse-buffer.md
1878
+ "unicorn/prefer-json-parse-buffer": "warn",
1879
+ // Prefer KeyboardEvent#key over KeyboardEvent#keyCode
1880
+ "unicorn/prefer-keyboard-event-key": "warn",
1881
+ // Disallow ternary operators when simpler logical operator alternatives exist.
1882
+ "unicorn/prefer-logical-operator-over-ternary": "warn",
1883
+ // Enforce the use of Math.trunc instead of bitwise operators
1884
+ "unicorn/prefer-math-trunc": "warn",
1885
+ // e.g. foo.insertBefore(baz, bar) -> foo.before(bar, 'baz')
1886
+ "unicorn/prefer-modern-dom-apis": "warn",
1887
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-modern-math-apis.md
1888
+ "unicorn/prefer-modern-math-apis": "warn",
1889
+ // Not ready yet for ESM modules
1890
+ // https://github.com/microsoft/TypeScript/issues/33079
1891
+ "unicorn/prefer-module": "off",
1892
+ // If a function is equivalent to String, Number, BigInt, Boolean, or Symbol,
1893
+ // you should use the built-in one directly. Wrapping the built-in in a function is moot.
1894
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-native-coercion-functions.md
1895
+ "unicorn/prefer-native-coercion-functions": "warn",
1896
+ // Prefer negative index over .length - index
1897
+ // for {String,Array,TypedArray}#slice() and Array#splice()
1898
+ "unicorn/prefer-negative-index": "warn",
1899
+ // Prefer using the node: protocol when importing Node.js builtin modules
1900
+ // TODO seems like this is not well supported by webpack yet
1901
+ "unicorn/prefer-node-protocol": "off",
1902
+ // Prefer Number static properties over global ones
1903
+ "unicorn/prefer-number-properties": "warn",
1904
+ // Prefer using Object.fromEntries(…) to transform a list of key-value pairs into an object
1905
+ "unicorn/prefer-object-from-entries": "warn",
1906
+ // Prefer Object.hasOwn(…) over Object.prototype.hasOwnProperty.call(…)
1907
+ "unicorn/prefer-object-has-own": "warn",
1908
+ // Prefer omitting the catch binding parameter
1909
+ "unicorn/prefer-optional-catch-binding": "warn",
1910
+ // Prefer borrowing methods from the prototype instead of methods from an instance
1911
+ "unicorn/prefer-prototype-methods": "warn",
1912
+ // Prefer .querySelector() over .getElementById(),
1913
+ // .querySelectorAll() over .getElementsByClassName() and .getElementsByTagName()
1914
+ "unicorn/prefer-query-selector": "warn",
1915
+ // Prefer Reflect.apply() over Function#apply()
1916
+ "unicorn/prefer-reflect-apply": "warn",
1917
+ // Prefer RegExp#test() over String#match() and RegExp#exec()
1918
+ "unicorn/prefer-regexp-test": "warn",
1919
+ // Prefer Set#has() over Array#includes() when checking for existence or non-existence
1920
+ // Set#has() is faster than Array#includes().
1921
+ "unicorn/prefer-set-has": "warn",
1922
+ // Prefer using Set#size instead of Array#length
1923
+ "unicorn/prefer-set-size": "warn",
1924
+ // Prefer the spread operator over Array.from()
1925
+ "unicorn/prefer-spread": "warn",
1926
+ // Prefer String#replaceAll() over regex searches with the global flag
1927
+ "unicorn/prefer-string-replace-all": "warn",
1928
+ // Prefer String#slice() over String#substr() and String#substring()
1929
+ "unicorn/prefer-string-slice": "warn",
1930
+ // Prefer String#startsWith() & String#endsWith() over more complex alternatives
1931
+ "unicorn/prefer-string-starts-ends-with": "error",
1932
+ // Prefer String#trimStart() / String#trimEnd() over String#trimLeft() / String#trimRight()
1933
+ "unicorn/prefer-string-trim-start-end": "warn",
1934
+ // Use whatever feels correct in the moment
1935
+ "unicorn/prefer-switch": "off",
1936
+ // Prefer ternary expressions over simple if-else statements
1937
+ "unicorn/prefer-ternary": ["warn", "only-single-line"],
1938
+ // Prefer top-level await over top-level promises and async function calls
1939
+ "unicorn/prefer-top-level-await": "error",
1940
+ // Enforce throwing TypeError in type checking conditions
1941
+ "unicorn/prefer-type-error": "warn",
1942
+ // Using complete words results in more readable code. Not everyone knows all your abbreviations.
1943
+ // Code is written only once, but read many times.
1944
+ "unicorn/prevent-abbreviations": [
1945
+ "warn",
1946
+ {
1947
+ allowList: {
1948
+ "next-env.d": true,
1949
+ "react-app-env.d": true
1950
+ },
1951
+ replacements: {
1952
+ props: false,
1953
+ ref: false,
1954
+ refs: false
1955
+ }
1956
+ }
1957
+ ],
1958
+ // Enforce the use of regex shorthands to improve readability
1959
+ "unicorn/regex-shorthand": "warn",
1960
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/relative-url-style.md
1961
+ "unicorn/relative-url-style": "warn",
1962
+ // Enforce using the separator argument with Array#join()
1963
+ "unicorn/require-array-join-separator": "warn",
1964
+ // Enforce using the digits argument with Number#toFixed()
1965
+ "unicorn/require-number-to-fixed-digits-argument": "warn",
1966
+ // Enforce using the targetOrigin argument with window.postMessage()
1967
+ "unicorn/require-post-message-target-origin": "error",
1968
+ // No swaps needed yet
1969
+ "unicorn/string-content": "off",
1970
+ // Only allow braces when there are variable declaration or function
1971
+ // declaration which requires a scope.
1972
+ "unicorn/switch-case-braces": ["warn", "avoid"],
1973
+ // Fix whitespace-insensitive template indentation
1974
+ "unicorn/template-indent": [
1975
+ "warn",
1976
+ {
1977
+ indent: 2
1978
+ }
1979
+ ],
1980
+ "unicorn/text-encoding-identifier-case": "error",
1981
+ // Require new when throwing an error
1982
+ "unicorn/throw-new-error": "warn"
1983
+ }
1984
+ }
1985
+ ];
1986
+ }
1987
+
1988
+ // src/utils.ts
1989
+ import { existsSync } from "fs";
1990
+ import { globbySync } from "globby";
1991
+ import { loadJsonFileSync } from "load-json-file";
1992
+ function checkEnvironment() {
1993
+ const isGitIgnore = existsSync(".gitignore");
1994
+ let isNodeEngine = false;
1995
+ let isPrettier = false;
1996
+ let isTailwind = false;
1997
+ let testingFramework = null;
1998
+ const allPackageJsonPaths = globbySync([
1999
+ "**/package.json",
2000
+ // Could use the `gitIgnore` option but the negative pattern is about 8 times faster.
2001
+ // https://github.com/sindresorhus/globby/issues/50
2002
+ "!**/node_modules"
2003
+ ]);
2004
+ for (const packageJsonPath of allPackageJsonPaths) {
2005
+ const packageJson = loadJsonFileSync(packageJsonPath);
2006
+ if (!testingFramework && Boolean(
2007
+ packageJson.dependencies?.jest || packageJson.devDependencies?.jest
2008
+ )) {
2009
+ testingFramework = "jest";
2010
+ }
2011
+ if (!isNodeEngine && Boolean(packageJson.engines?.node)) {
2012
+ isNodeEngine = true;
2013
+ }
2014
+ if (!isPrettier && Boolean(
2015
+ packageJson.dependencies?.prettier || packageJson.devDependencies?.prettier
2016
+ )) {
2017
+ isPrettier = true;
2018
+ }
2019
+ if (!isTailwind && Boolean(
2020
+ packageJson.dependencies?.tailwindcss || packageJson.devDependencies?.tailwindcss
2021
+ )) {
2022
+ isTailwind = true;
2023
+ }
2024
+ }
2025
+ const isNode = isNodeEngine || existsSync(".nvmrc") || existsSync(".node-version");
2026
+ return {
2027
+ isGitIgnore,
2028
+ isNode,
2029
+ isPrettier,
2030
+ isTailwind,
2031
+ testingFramework
2032
+ };
2033
+ }
2034
+
2035
+ // src/factory.ts
2036
+ function factory() {
2037
+ const { isGitIgnore, isNode, isPrettier, isTailwind, testingFramework } = checkEnvironment();
2038
+ const configs = [];
2039
+ if (isGitIgnore) {
2040
+ configs.push([gitignore()]);
2041
+ }
2042
+ configs.push(
2043
+ ignores(),
2044
+ base(),
2045
+ imports(),
2046
+ switchCase(),
2047
+ unicorn(),
2048
+ typescript(),
2049
+ astro(),
2050
+ react()
2051
+ );
2052
+ if (isNode) {
2053
+ configs.push(node());
2054
+ }
2055
+ if (isTailwind) {
2056
+ configs.push(node());
2057
+ }
2058
+ if (testingFramework === "jest") {
2059
+ configs.push(jest());
2060
+ }
2061
+ if (isPrettier) {
2062
+ configs.push(prettier());
2063
+ }
2064
+ const merged = configs.flat();
2065
+ return merged;
2066
+ }
2067
+ export {
2068
+ factory as default
2069
+ };