@leyman/eslint-config 0.0.0-stage → 0.1.0

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.
@@ -0,0 +1,1170 @@
1
+ import Path from 'node:path';
2
+ import { fileURLToPath } from 'node:url';
3
+ import typescriptPlugin from "@typescript-eslint/eslint-plugin";
4
+ import typescriptParser from "@typescript-eslint/parser";
5
+ import globals from 'globals';
6
+ import { getInternalRegex } from './lib/internal-regex.js';
7
+ import { nodeFloorRules } from './lib/node-floor.js';
8
+ import { assertIsPackageJson } from './lib/package-json-schema.js';
9
+ import { packagePluginConfig } from './lib/package-plugins.js';
10
+ import { commentsPlugin, eslintConfig, importPlugin, jsDocPlugin, jsxA11yPlugin, nodePlugin, prettierConfig, reactHooksPlugin, reactPlugin, regexpPlugin, sonarPlugin, unicornPlugin } from './lib/plugins.js';
11
+ const isForJavaScript = (rule)=>{
12
+ const languages = rule.meta?.languages;
13
+ return !languages || languages.includes('*') || languages.includes('js/js');
14
+ };
15
+ export const nonDeprecatedRules = (name, plugin)=>{
16
+ const rules = {};
17
+ for (const [ruleName, rule] of Object.entries(plugin.rules)){
18
+ if (typeof rule === 'object' && (rule.meta?.deprecated ?? false) === false && isForJavaScript(rule)) {
19
+ rules[`${name}/${ruleName}`] = 'error';
20
+ }
21
+ }
22
+ return rules;
23
+ };
24
+ const disableReplacedTypeRules = ()=>{
25
+ const rules = {};
26
+ for (const [ruleName, rule] of Object.entries(typescriptPlugin.rules)){
27
+ const { extendsBaseRule } = rule.meta.docs;
28
+ if (typeof extendsBaseRule === 'string') {
29
+ rules[extendsBaseRule] = 'off';
30
+ } else if (extendsBaseRule === true) {
31
+ rules[ruleName] = 'off';
32
+ }
33
+ }
34
+ return rules;
35
+ };
36
+ export const baseNamingConvention = [
37
+ {
38
+ selector: 'default',
39
+ format: [
40
+ 'camelCase'
41
+ ],
42
+ leadingUnderscore: 'forbid',
43
+ trailingUnderscore: 'forbid'
44
+ },
45
+ {
46
+ selector: 'enum',
47
+ format: [
48
+ 'PascalCase'
49
+ ]
50
+ },
51
+ {
52
+ selector: 'enumMember',
53
+ format: [
54
+ 'UPPER_CASE'
55
+ ]
56
+ },
57
+ {
58
+ selector: 'property',
59
+ modifiers: [
60
+ 'public'
61
+ ],
62
+ format: null
63
+ },
64
+ {
65
+ selector: 'typeProperty',
66
+ modifiers: [
67
+ 'public'
68
+ ],
69
+ format: [
70
+ 'camelCase',
71
+ 'snake_case'
72
+ ]
73
+ },
74
+ {
75
+ selector: 'typeProperty',
76
+ modifiers: [
77
+ 'public'
78
+ ],
79
+ format: [
80
+ 'PascalCase'
81
+ ]
82
+ },
83
+ {
84
+ selector: 'property',
85
+ modifiers: [
86
+ 'static',
87
+ 'readonly'
88
+ ],
89
+ format: [
90
+ 'camelCase'
91
+ ]
92
+ },
93
+ {
94
+ selector: 'memberLike',
95
+ modifiers: [
96
+ 'private'
97
+ ],
98
+ format: [
99
+ 'camelCase'
100
+ ],
101
+ leadingUnderscore: 'require'
102
+ },
103
+ {
104
+ selector: 'class',
105
+ format: [
106
+ 'PascalCase'
107
+ ]
108
+ },
109
+ {
110
+ selector: 'interface',
111
+ format: [
112
+ 'PascalCase'
113
+ ]
114
+ },
115
+ {
116
+ selector: 'typeAlias',
117
+ format: [
118
+ 'PascalCase'
119
+ ]
120
+ },
121
+ {
122
+ selector: 'typeParameter',
123
+ format: [
124
+ 'PascalCase'
125
+ ]
126
+ },
127
+ {
128
+ selector: 'parameter',
129
+ modifiers: [
130
+ 'unused'
131
+ ],
132
+ format: [
133
+ 'camelCase'
134
+ ],
135
+ leadingUnderscore: 'require'
136
+ },
137
+ {
138
+ selector: 'import',
139
+ modifiers: [
140
+ 'default'
141
+ ],
142
+ format: [
143
+ 'camelCase',
144
+ 'PascalCase'
145
+ ]
146
+ },
147
+ {
148
+ selector: 'import',
149
+ modifiers: [
150
+ 'namespace'
151
+ ],
152
+ format: [
153
+ 'camelCase',
154
+ 'PascalCase'
155
+ ]
156
+ },
157
+ {
158
+ selector: 'variable',
159
+ modifiers: [
160
+ 'const',
161
+ 'global'
162
+ ],
163
+ format: [
164
+ 'camelCase',
165
+ 'UPPER_CASE'
166
+ ]
167
+ }
168
+ ];
169
+ export const reactComponentNamingConvention = [
170
+ {
171
+ selector: 'function',
172
+ format: [
173
+ 'camelCase',
174
+ 'PascalCase'
175
+ ]
176
+ },
177
+ {
178
+ selector: 'variable',
179
+ modifiers: [
180
+ 'const'
181
+ ],
182
+ types: [
183
+ 'function'
184
+ ],
185
+ format: [
186
+ 'camelCase',
187
+ 'PascalCase'
188
+ ]
189
+ },
190
+ {
191
+ selector: 'variable',
192
+ modifiers: [
193
+ 'const',
194
+ 'global'
195
+ ],
196
+ types: [
197
+ 'function'
198
+ ],
199
+ format: [
200
+ 'camelCase',
201
+ 'PascalCase',
202
+ 'UPPER_CASE'
203
+ ]
204
+ }
205
+ ];
206
+ export default function makeEslintConfigForPackage({ configUrl, node = false, packageJson, plugins = [] }) {
207
+ assertIsPackageJson(packageJson);
208
+ const projectUrl = Path.dirname(fileURLToPath(configUrl));
209
+ const sourceFiles = [
210
+ '**/*.{c,m,}ts{x,}',
211
+ '**/*.{c,m,}js'
212
+ ];
213
+ const extraneousDependencies = {
214
+ includeInternal: true,
215
+ whitelist: [
216
+ packageJson.name
217
+ ]
218
+ };
219
+ const hasReact = [
220
+ packageJson.dependencies,
221
+ packageJson.devDependencies,
222
+ packageJson.optionalDependencies,
223
+ packageJson.peerDependencies
224
+ ].some((dependencies)=>dependencies !== undefined && 'react' in dependencies);
225
+ return [
226
+ {
227
+ ignores: [
228
+ 'coverage',
229
+ 'dist',
230
+ 'dist-test',
231
+ 'node_modules',
232
+ 'out',
233
+ '.eslintcache'
234
+ ].map((directory)=>`${directory}/**`)
235
+ },
236
+ {
237
+ files: [
238
+ ...sourceFiles
239
+ ],
240
+ languageOptions: {
241
+ ecmaVersion: 'latest',
242
+ parser: typescriptParser,
243
+ parserOptions: {
244
+ ecmaVersion: 'latest',
245
+ projectService: {
246
+ allowDefaultProject: [
247
+ '*.{c,m,}js'
248
+ ]
249
+ },
250
+ tsconfigRootDir: projectUrl
251
+ },
252
+ globals: node ? globals.nodeBuiltin : globals['shared-node-browser']
253
+ },
254
+ linterOptions: {
255
+ reportUnusedDisableDirectives: true
256
+ },
257
+ plugins: {
258
+ '@eslint-community/eslint-comments': commentsPlugin,
259
+ "@typescript-eslint": typescriptPlugin,
260
+ 'import-x': importPlugin,
261
+ jsdoc: jsDocPlugin,
262
+ 'jsx-a11y': jsxA11yPlugin,
263
+ n: nodePlugin,
264
+ react: reactPlugin,
265
+ 'react-hooks': reactHooksPlugin,
266
+ regexp: regexpPlugin,
267
+ sonarjs: sonarPlugin,
268
+ unicorn: unicornPlugin
269
+ },
270
+ settings: {
271
+ 'import-x/internal-regex': getInternalRegex(packageJson),
272
+ react: {
273
+ version: hasReact ? 'detect' : '999.999.999'
274
+ }
275
+ },
276
+ rules: {
277
+ ...eslintConfig.configs.all.rules,
278
+ 'arrow-body-style': 'error',
279
+ camelcase: 'off',
280
+ 'capitalized-comments': [
281
+ 'error',
282
+ 'always',
283
+ {
284
+ ignoreConsecutiveComments: true,
285
+ ignoreInlineComments: true,
286
+ ignorePattern: String.raw`\w+:|^ biome-ignore (?:format|lint):`
287
+ }
288
+ ],
289
+ 'class-methods-use-this': 'off',
290
+ complexity: 'off',
291
+ 'consistent-this': [
292
+ 'error',
293
+ 'self'
294
+ ],
295
+ 'func-names': [
296
+ 'error',
297
+ 'never'
298
+ ],
299
+ 'func-style': [
300
+ 'error',
301
+ 'expression',
302
+ {
303
+ allowArrowFunctions: true
304
+ }
305
+ ],
306
+ 'id-blacklist': 'off',
307
+ 'id-length': 'off',
308
+ 'id-match': 'off',
309
+ 'line-comment-position': 'off',
310
+ 'max-classes-per-file': 'off',
311
+ 'max-depth': 'off',
312
+ 'max-lines': 'off',
313
+ 'max-lines-per-function': 'off',
314
+ 'max-statements': 'off',
315
+ 'multiline-comment-style': [
316
+ 'error',
317
+ 'separate-lines'
318
+ ],
319
+ 'new-cap': [
320
+ 'error',
321
+ {
322
+ capIsNew: false
323
+ }
324
+ ],
325
+ 'no-await-in-loop': 'off',
326
+ 'no-constant-condition': [
327
+ 'error',
328
+ {
329
+ checkLoops: false
330
+ }
331
+ ],
332
+ 'no-continue': 'off',
333
+ 'no-empty': 'error',
334
+ 'no-duplicate-imports': [
335
+ 'error',
336
+ {
337
+ allowSeparateTypeImports: true
338
+ }
339
+ ],
340
+ 'no-implicit-coercion': [
341
+ 'error',
342
+ {
343
+ allow: [
344
+ '!!'
345
+ ]
346
+ }
347
+ ],
348
+ 'no-inline-comments': 'off',
349
+ 'no-plusplus': 'off',
350
+ 'no-restricted-imports': 'off',
351
+ 'no-restricted-modules': 'off',
352
+ 'no-restricted-properties': 'off',
353
+ 'no-restricted-syntax': [
354
+ 'error',
355
+ {
356
+ selector: 'ExportNamedDeclaration > TSEnumDeclaration[const=true]',
357
+ message: "Don't export const enums; consumers using isolatedModules can't read them. Use a regular enum"
358
+ },
359
+ {
360
+ selector: 'LabeledStatement',
361
+ message: 'Labels are a form of GOTO; using them makes code ' + 'confusing and hard to maintain and understand.'
362
+ }
363
+ ],
364
+ 'no-ternary': 'off',
365
+ 'no-undefined': 'off',
366
+ 'no-void': [
367
+ 'error',
368
+ {
369
+ allowAsStatement: true
370
+ }
371
+ ],
372
+ 'no-warning-comments': 'off',
373
+ 'one-var': [
374
+ 'error',
375
+ 'never'
376
+ ],
377
+ 'prefer-const': [
378
+ 'error',
379
+ {
380
+ destructuring: 'all',
381
+ ignoreReadBeforeAssign: true
382
+ }
383
+ ],
384
+ 'prefer-destructuring': 'off',
385
+ 'sort-imports': [
386
+ 'error',
387
+ {
388
+ ignoreCase: true,
389
+ ignoreDeclarationSort: true
390
+ }
391
+ ],
392
+ 'sort-keys': 'off',
393
+ 'spaced-comment': [
394
+ 'error',
395
+ 'always',
396
+ {
397
+ exceptions: [
398
+ '*'
399
+ ],
400
+ markers: [
401
+ '!'
402
+ ]
403
+ }
404
+ ],
405
+ 'vars-on-top': 'off',
406
+ ...disableReplacedTypeRules(),
407
+ ...nonDeprecatedRules("@typescript-eslint", typescriptPlugin),
408
+ "@typescript-eslint/ban-ts-comment": [
409
+ 'error',
410
+ {
411
+ 'ts-expect-error': "allow-with-description",
412
+ 'ts-check': true
413
+ }
414
+ ],
415
+ "@typescript-eslint/consistent-type-assertions": 'error',
416
+ "@typescript-eslint/consistent-type-imports": 'error',
417
+ "@typescript-eslint/class-methods-use-this": [
418
+ 'error',
419
+ {
420
+ ignoreOverrideMethods: true,
421
+ ignoreClassesThatImplementAnInterface: 'public-fields'
422
+ }
423
+ ],
424
+ "@typescript-eslint/explicit-function-return-type": [
425
+ 'error',
426
+ {
427
+ allowExpressions: true
428
+ }
429
+ ],
430
+ "@typescript-eslint/explicit-module-boundary-types": 'error',
431
+ "@typescript-eslint/max-params": 'off',
432
+ "@typescript-eslint/member-ordering": [
433
+ 'error',
434
+ {
435
+ default: [
436
+ 'signature',
437
+ 'static-field',
438
+ 'instance-field',
439
+ 'field',
440
+ 'constructor',
441
+ 'public-method',
442
+ 'protected-method',
443
+ 'private-method',
444
+ 'method'
445
+ ]
446
+ }
447
+ ],
448
+ "@typescript-eslint/naming-convention": [
449
+ 'error',
450
+ ...baseNamingConvention
451
+ ],
452
+ "@typescript-eslint/no-explicit-any": 'off',
453
+ "@typescript-eslint/no-extraneous-class": 'error',
454
+ "@typescript-eslint/no-floating-promises": [
455
+ 'error',
456
+ {
457
+ checkThenables: true
458
+ }
459
+ ],
460
+ "@typescript-eslint/no-invalid-void-type": 'off',
461
+ "@typescript-eslint/no-misused-promises": 'error',
462
+ "@typescript-eslint/no-namespace": [
463
+ 'error',
464
+ {
465
+ allowDefinitionFiles: false
466
+ }
467
+ ],
468
+ "@typescript-eslint/no-type-alias": 'off',
469
+ "@typescript-eslint/no-non-null-assertion": 'off',
470
+ "@typescript-eslint/no-unnecessary-condition": [
471
+ 'error',
472
+ {
473
+ allowConstantLoopConditions: true
474
+ }
475
+ ],
476
+ "@typescript-eslint/parameter-properties": [
477
+ 'error',
478
+ {
479
+ allow: [
480
+ 'private readonly'
481
+ ]
482
+ }
483
+ ],
484
+ "@typescript-eslint/prefer-destructuring": [
485
+ 'error',
486
+ {
487
+ AssignmentExpression: {
488
+ array: false,
489
+ object: true
490
+ }
491
+ }
492
+ ],
493
+ "@typescript-eslint/prefer-nullish-coalescing": 'error',
494
+ "@typescript-eslint/prefer-readonly-parameter-types": 'off',
495
+ "@typescript-eslint/restrict-template-expressions": [
496
+ 'error',
497
+ {
498
+ allowAny: false,
499
+ allowNullish: false
500
+ }
501
+ ],
502
+ "@typescript-eslint/sort-type-constituents": [
503
+ 'error',
504
+ {
505
+ groupOrder: [
506
+ 'literal',
507
+ 'keyword',
508
+ 'named',
509
+ 'operator',
510
+ 'import',
511
+ 'object',
512
+ 'tuple',
513
+ 'function',
514
+ 'conditional',
515
+ 'intersection',
516
+ 'union',
517
+ 'nullish'
518
+ ]
519
+ }
520
+ ],
521
+ "@typescript-eslint/strict-boolean-expressions": 'error',
522
+ "@typescript-eslint/strict-void-return": 'off',
523
+ "@typescript-eslint/switch-exhaustiveness-check": 'error',
524
+ "@typescript-eslint/triple-slash-reference": [
525
+ 'error',
526
+ {
527
+ types: 'never',
528
+ lib: 'never'
529
+ }
530
+ ],
531
+ "@typescript-eslint/typedef": 'off',
532
+ "@typescript-eslint/no-empty-function": 'off',
533
+ "@typescript-eslint/no-magic-numbers": [
534
+ 'error',
535
+ {
536
+ detectObjects: true,
537
+ enforceConst: true,
538
+ ignore: [
539
+ -1,
540
+ 0,
541
+ '0n',
542
+ 1,
543
+ '1n',
544
+ 2,
545
+ '2n',
546
+ 10
547
+ ],
548
+ ignoreArrayIndexes: true,
549
+ ignoreTypeIndexes: true,
550
+ ignoreReadonlyClassProperties: true,
551
+ ignoreEnums: true
552
+ }
553
+ ],
554
+ "@typescript-eslint/no-unsafe-type-assertion": 'off',
555
+ "@typescript-eslint/no-unused-expressions": 'error',
556
+ "@typescript-eslint/no-unused-vars": [
557
+ 'error',
558
+ {
559
+ ignoreRestSiblings: true
560
+ }
561
+ ],
562
+ "@typescript-eslint/no-use-before-define": 'error',
563
+ "@typescript-eslint/require-await": 'off',
564
+ ...nonDeprecatedRules('import-x', importPlugin),
565
+ 'import-x/consistent-type-specifier-style': [
566
+ 'error',
567
+ 'prefer-top-level'
568
+ ],
569
+ 'import-x/dynamic-import-chunkname': 'off',
570
+ 'import-x/exports-last': 'off',
571
+ 'import-x/extensions': 'off',
572
+ 'import-x/group-exports': 'off',
573
+ 'import-x/max-dependencies': 'off',
574
+ 'import-x/named': 'off',
575
+ 'import-x/namespace': 'off',
576
+ 'import-x/newline-after-import': [
577
+ 'error',
578
+ {
579
+ count: 1
580
+ }
581
+ ],
582
+ 'import-x/no-anonymous-default-export': 'off',
583
+ 'import-x/no-default-export': 'off',
584
+ 'import-x/no-extraneous-dependencies': [
585
+ 'error',
586
+ extraneousDependencies
587
+ ],
588
+ 'import-x/no-internal-modules': 'off',
589
+ 'import-x/no-named-export': 'off',
590
+ 'import-x/no-namespace': 'off',
591
+ 'import-x/no-nodejs-modules': 'off',
592
+ 'import-x/no-relative-parent-imports': [
593
+ 'error',
594
+ {
595
+ ignore: [
596
+ '^[^.]'
597
+ ]
598
+ }
599
+ ],
600
+ 'import-x/no-rename-default': 'off',
601
+ 'import-x/no-unassigned-import': [
602
+ 'error',
603
+ {
604
+ allow: [
605
+ '**/*.css'
606
+ ]
607
+ }
608
+ ],
609
+ 'import-x/no-unresolved': 'off',
610
+ 'import-x/no-unused-modules': 'off',
611
+ 'import-x/no-useless-path-segments': [
612
+ 'error',
613
+ {
614
+ commonjs: true
615
+ }
616
+ ],
617
+ 'import-x/order': [
618
+ 'error',
619
+ {
620
+ alphabetize: {
621
+ caseInsensitive: true,
622
+ order: 'asc'
623
+ },
624
+ groups: [
625
+ 'type',
626
+ 'builtin',
627
+ 'external',
628
+ 'internal',
629
+ 'index',
630
+ 'parent',
631
+ 'sibling',
632
+ [
633
+ 'object',
634
+ 'unknown'
635
+ ]
636
+ ],
637
+ 'newlines-between-types': 'never',
638
+ 'newlines-between': 'never',
639
+ pathGroups: [
640
+ {
641
+ pattern: String.raw`\#*{,/**}`,
642
+ group: 'internal',
643
+ position: 'after'
644
+ }
645
+ ],
646
+ sortTypesGroup: true,
647
+ warnOnUnassignedImports: true
648
+ }
649
+ ],
650
+ 'import-x/prefer-default-export': 'off',
651
+ ...nonDeprecatedRules('jsdoc', jsDocPlugin),
652
+ 'jsdoc/check-examples': 'off',
653
+ 'jsdoc/check-tag-names': [
654
+ 'error',
655
+ {
656
+ definedTags: [
657
+ 'rejects'
658
+ ]
659
+ }
660
+ ],
661
+ 'jsdoc/check-indentation': [
662
+ 'error',
663
+ {
664
+ allowIndentedSections: true
665
+ }
666
+ ],
667
+ 'jsdoc/check-param-names': [
668
+ 'error',
669
+ {
670
+ checkDestructured: false,
671
+ disableMissingParamChecks: true
672
+ }
673
+ ],
674
+ 'jsdoc/imports-as-dependencies': 'off',
675
+ 'jsdoc/lines-before-block': 'off',
676
+ 'jsdoc/convert-to-jsdoc-comments': 'off',
677
+ 'jsdoc/match-name': 'off',
678
+ 'jsdoc/no-missing-syntax': 'off',
679
+ 'jsdoc/no-multi-asterisks': 'error',
680
+ 'jsdoc/no-restricted-syntax': 'off',
681
+ "jsdoc/require-description-complete-sentence": 'off',
682
+ "jsdoc/require-description": [
683
+ 'error',
684
+ {
685
+ checkConstructors: false
686
+ }
687
+ ],
688
+ 'jsdoc/require-example': 'off',
689
+ 'jsdoc/require-file-overview': 'off',
690
+ 'jsdoc/require-jsdoc': [
691
+ 'error',
692
+ {
693
+ checkConstructors: false,
694
+ publicOnly: true,
695
+ require: {
696
+ ArrowFunctionExpression: false,
697
+ ClassDeclaration: true,
698
+ ClassExpression: true,
699
+ FunctionDeclaration: false,
700
+ FunctionExpression: false,
701
+ MethodDefinition: false
702
+ },
703
+ contexts: [
704
+ 'ExportDefaultDeclaration > ArrowFunctionExpression',
705
+ 'ExportNamedDeclaration > ArrowFunctionExpression',
706
+ 'ExportDefaultDeclaration > FunctionExpression',
707
+ 'ExportNamedDeclaration > FunctionExpression',
708
+ 'TSDeclareFunction:not(TSDeclareFunction + TSDeclareFunction)',
709
+ 'FunctionDeclaration:not(TSDeclareFunction + FunctionDeclaration)',
710
+ 'MethodDefinition:not(MethodDefinition + MethodDefinition)'
711
+ ]
712
+ }
713
+ ],
714
+ 'jsdoc/require-param': [
715
+ 'error',
716
+ {
717
+ checkDestructured: false
718
+ }
719
+ ],
720
+ 'jsdoc/require-param-type': 'off',
721
+ 'jsdoc/require-returns-type': 'off',
722
+ 'jsdoc/require-tags': 'off',
723
+ 'jsdoc/sort-tags': 'off',
724
+ 'jsdoc/tag-lines': [
725
+ 'error',
726
+ 'never',
727
+ {
728
+ applyToEndTag: false,
729
+ startLines: 1,
730
+ tags: {
731
+ example: {
732
+ lines: 'always'
733
+ },
734
+ see: {
735
+ lines: 'always'
736
+ }
737
+ }
738
+ }
739
+ ],
740
+ 'jsdoc/text-escaping': 'off',
741
+ 'jsdoc/ts-ban-ts-comment': 'off',
742
+ ...nonDeprecatedRules('jsx-a11y', jsxA11yPlugin),
743
+ 'jsx-a11y/anchor-is-valid': [
744
+ 'error',
745
+ {
746
+ components: [
747
+ 'Link'
748
+ ],
749
+ aspects: [
750
+ 'invalidHref',
751
+ 'preferButton'
752
+ ]
753
+ }
754
+ ],
755
+ ...nonDeprecatedRules('n', nodePlugin),
756
+ 'n/callback-return': [
757
+ 'error',
758
+ [
759
+ 'callback',
760
+ 'cb',
761
+ 'next',
762
+ 'done'
763
+ ]
764
+ ],
765
+ 'n/no-missing-import': 'off',
766
+ 'n/no-missing-require': 'off',
767
+ 'n/no-sync': [
768
+ 'error',
769
+ {
770
+ allowAtRootLevel: true
771
+ }
772
+ ],
773
+ 'n/no-unsupported-features/node-builtins': [
774
+ 'error',
775
+ {
776
+ allowExperimental: true
777
+ }
778
+ ],
779
+ ...nonDeprecatedRules('react', reactPlugin),
780
+ 'react/boolean-prop-naming': [
781
+ 'error',
782
+ {
783
+ validateNested: true
784
+ }
785
+ ],
786
+ 'react/forbid-dom-props': 'off',
787
+ 'react/forbid-elements': 'off',
788
+ 'react/function-component-definition': [
789
+ 'error',
790
+ {
791
+ namedComponents: 'arrow-function',
792
+ unnamedComponents: 'arrow-function'
793
+ }
794
+ ],
795
+ 'react/jsx-filename-extension': [
796
+ 'error',
797
+ {
798
+ extensions: [
799
+ '.tsx'
800
+ ]
801
+ }
802
+ ],
803
+ 'react/jsx-key': [
804
+ 'error',
805
+ {
806
+ checkFragmentShorthand: true
807
+ }
808
+ ],
809
+ 'react/jsx-no-literals': 'off',
810
+ 'react/jsx-no-target-blank': [
811
+ 'error',
812
+ {
813
+ allowReferrer: false,
814
+ enforceDynamicLinks: 'always'
815
+ }
816
+ ],
817
+ 'react/jsx-props-no-spreading': [
818
+ 'error',
819
+ {
820
+ exceptions: [
821
+ 'App',
822
+ 'Component'
823
+ ]
824
+ }
825
+ ],
826
+ 'react/jsx-sort-props': [
827
+ 'error',
828
+ {
829
+ callbacksLast: true,
830
+ ignoreCase: true,
831
+ noSortAlphabetically: false,
832
+ reservedFirst: true,
833
+ shorthandFirst: true
834
+ }
835
+ ],
836
+ 'react/no-multi-comp': [
837
+ 'error',
838
+ {
839
+ ignoreStateless: true
840
+ }
841
+ ],
842
+ 'react/no-unescaped-entities': [
843
+ 'error',
844
+ {
845
+ forbid: [
846
+ {
847
+ char: '<',
848
+ alternatives: [
849
+ '&lt;'
850
+ ]
851
+ },
852
+ {
853
+ char: '>',
854
+ alternatives: [
855
+ '&gt;'
856
+ ]
857
+ },
858
+ {
859
+ char: "'",
860
+ alternatives: [
861
+ '&apos;',
862
+ '&lsquo;',
863
+ '&rsquo;'
864
+ ]
865
+ },
866
+ {
867
+ char: '‘',
868
+ alternatives: [
869
+ '&lsquo;'
870
+ ]
871
+ },
872
+ {
873
+ char: '’',
874
+ alternatives: [
875
+ '&rsquo;'
876
+ ]
877
+ },
878
+ {
879
+ char: '"',
880
+ alternatives: [
881
+ '&quot;',
882
+ '&ldquo;',
883
+ '&rdquo;'
884
+ ]
885
+ },
886
+ {
887
+ char: '“',
888
+ alternatives: [
889
+ '&ldquo;'
890
+ ]
891
+ },
892
+ {
893
+ char: '”',
894
+ alternatives: [
895
+ '&rdquo;'
896
+ ]
897
+ },
898
+ {
899
+ char: '{',
900
+ alternatives: [
901
+ '&#123;'
902
+ ]
903
+ },
904
+ {
905
+ char: '}',
906
+ alternatives: [
907
+ '&#125;'
908
+ ]
909
+ }
910
+ ]
911
+ }
912
+ ],
913
+ 'react/no-unsafe': [
914
+ 'error',
915
+ {
916
+ checkAliases: true
917
+ }
918
+ ],
919
+ 'react/no-will-update-set-state': [
920
+ 'error',
921
+ 'disallow-in-func'
922
+ ],
923
+ 'react/react-in-jsx-scope': 'off',
924
+ 'react/static-property-placement': [
925
+ 'error',
926
+ 'static public field'
927
+ ],
928
+ ...nonDeprecatedRules('react-hooks', reactHooksPlugin),
929
+ ...nonDeprecatedRules('regexp', regexpPlugin),
930
+ 'regexp/hexadecimal-escape': [
931
+ 'error',
932
+ 'never'
933
+ ],
934
+ 'regexp/letter-case': [
935
+ 'error',
936
+ {
937
+ hexadecimalEscape: 'uppercase',
938
+ unicodeEscape: 'uppercase'
939
+ }
940
+ ],
941
+ ...nonDeprecatedRules('sonarjs', sonarPlugin),
942
+ 'sonarjs/cognitive-complexity': 'off',
943
+ 'sonarjs/cyclomatic-complexity': 'off',
944
+ 'sonarjs/different-types-comparison': 'off',
945
+ 'sonarjs/elseif-without-else': 'off',
946
+ 'sonarjs/expression-complexity': 'off',
947
+ 'sonarjs/file-header': 'off',
948
+ 'sonarjs/max-lines': 'off',
949
+ 'sonarjs/max-lines-per-function': 'off',
950
+ 'sonarjs/max-union-size': 'off',
951
+ 'sonarjs/nested-control-flow': 'off',
952
+ 'sonarjs/no-duplicate-string': 'off',
953
+ 'sonarjs/no-empty-test-file': 'off',
954
+ 'sonarjs/no-wildcard-import': 'off',
955
+ 'sonarjs/prefer-specific-assertions': 'off',
956
+ 'sonarjs/todo-tag': 'off',
957
+ "@eslint-community/eslint-comments/require-description": [
958
+ 'error',
959
+ {
960
+ ignore: [
961
+ 'eslint-enable'
962
+ ]
963
+ }
964
+ ],
965
+ ...nonDeprecatedRules('unicorn', unicornPlugin),
966
+ 'unicorn/catch-error-name': [
967
+ 'error',
968
+ {
969
+ ignore: [
970
+ /^error$/v
971
+ ],
972
+ name: 'err'
973
+ }
974
+ ],
975
+ 'unicorn/consistent-arrow-return-style': 'off',
976
+ 'unicorn/consistent-boolean-name': [
977
+ 'error',
978
+ {
979
+ ignore: [
980
+ /(?:^validate\d*|[Vv]alidator)$/v
981
+ ]
982
+ }
983
+ ],
984
+ 'unicorn/consistent-class-member-order': 'off',
985
+ 'unicorn/name-replacements': 'off',
986
+ 'unicorn/no-asterisk-prefix-in-documentation-comments': 'off',
987
+ 'unicorn/no-barrel-files': 'off',
988
+ "unicorn/no-exports-in-scripts": 'off',
989
+ 'unicorn/no-keyword-prefix': 'off',
990
+ 'unicorn/no-manually-wrapped-comments': 'off',
991
+ 'unicorn/no-null': 'off',
992
+ 'unicorn/no-this-outside-of-class': 'off',
993
+ 'unicorn/no-top-level-side-effects': 'off',
994
+ 'unicorn/no-useless-undefined': 'error',
995
+ 'unicorn/numeric-separators-style': [
996
+ 'error',
997
+ {
998
+ hexadecimal: {
999
+ groupLength: 8
1000
+ }
1001
+ }
1002
+ ],
1003
+ 'unicorn/prefer-export-from': [
1004
+ 'error',
1005
+ {
1006
+ checkUsedVariables: false
1007
+ }
1008
+ ],
1009
+ 'unicorn/prefer-global-number-constants': 'off',
1010
+ 'unicorn/prefer-ternary': [
1011
+ 'error',
1012
+ 'only-single-line'
1013
+ ],
1014
+ 'unicorn/prefer-type-literal-last': 'off',
1015
+ 'unicorn/prevent-abbreviations': 'off',
1016
+ 'unicorn/template-indent': [
1017
+ 'error',
1018
+ {
1019
+ indent: 4
1020
+ }
1021
+ ],
1022
+ 'unicorn/try-complexity': 'off',
1023
+ ...nodeFloorRules(packageJson)
1024
+ }
1025
+ },
1026
+ {
1027
+ files: [
1028
+ '**/*.{c,m,}js'
1029
+ ],
1030
+ rules: (()=>{
1031
+ const rules = {};
1032
+ for (const [ruleName, ruleSettings] of Object.entries(typescriptPlugin.rules)){
1033
+ if (ruleSettings.meta.docs.requiresTypeChecking !== true) {
1034
+ continue;
1035
+ }
1036
+ rules[`@typescript-eslint/${ruleName}`] = 'off';
1037
+ const { extendsBaseRule } = ruleSettings.meta.docs;
1038
+ if (typeof extendsBaseRule === 'string') {
1039
+ rules[extendsBaseRule] = 'error';
1040
+ } else if (extendsBaseRule === true) {
1041
+ rules[ruleName] = 'error';
1042
+ }
1043
+ }
1044
+ return rules;
1045
+ })()
1046
+ },
1047
+ {
1048
+ files: [
1049
+ '**/*.c{j,t}s{x,}'
1050
+ ],
1051
+ rules: {
1052
+ "@typescript-eslint/no-require-imports": 'off',
1053
+ "@typescript-eslint/no-var-requires": 'off',
1054
+ 'unicorn/prefer-top-level-await': 'off'
1055
+ }
1056
+ },
1057
+ {
1058
+ files: [
1059
+ '**/*.{c,m,}tsx'
1060
+ ],
1061
+ rules: {
1062
+ "@typescript-eslint/naming-convention": [
1063
+ 'error',
1064
+ ...baseNamingConvention,
1065
+ ...reactComponentNamingConvention
1066
+ ]
1067
+ }
1068
+ },
1069
+ {
1070
+ files: [
1071
+ '**/*.{c,m,}ts'
1072
+ ],
1073
+ rules: (()=>{
1074
+ const rules = {};
1075
+ for (const ruleName of [
1076
+ ...Object.keys(jsxA11yPlugin.rules).map((rule)=>`jsx-a11y/${rule}`),
1077
+ ...Object.keys(reactPlugin.rules).map((rule)=>`react/${rule}`),
1078
+ ...Object.keys(reactHooksPlugin.rules).map((rule)=>`react-hooks/${rule}`)
1079
+ ]){
1080
+ rules[ruleName] = 'off';
1081
+ }
1082
+ return rules;
1083
+ })()
1084
+ },
1085
+ {
1086
+ files: [
1087
+ '**/eslint/**/*.{c,m,}ts'
1088
+ ],
1089
+ rules: {
1090
+ "@typescript-eslint/naming-convention": [
1091
+ 'error',
1092
+ ...baseNamingConvention,
1093
+ {
1094
+ selector: 'objectLiteralMethod',
1095
+ format: [
1096
+ 'camelCase',
1097
+ 'PascalCase'
1098
+ ]
1099
+ },
1100
+ {
1101
+ selector: [
1102
+ 'objectLiteralMethod',
1103
+ 'objectLiteralProperty',
1104
+ 'typeProperty'
1105
+ ],
1106
+ modifiers: [
1107
+ 'requiresQuotes'
1108
+ ],
1109
+ format: null
1110
+ }
1111
+ ],
1112
+ 'sonarjs/function-name': 'off'
1113
+ }
1114
+ },
1115
+ {
1116
+ files: sourceFiles.map((glob)=>`src/${glob}`),
1117
+ rules: {
1118
+ 'import-x/no-extraneous-dependencies': [
1119
+ 'error',
1120
+ {
1121
+ ...extraneousDependencies,
1122
+ devDependencies: false,
1123
+ includeTypes: true
1124
+ }
1125
+ ]
1126
+ }
1127
+ },
1128
+ {
1129
+ files: [
1130
+ 'src/cli.{c,m,}ts',
1131
+ 'src/commands/**/*.{c,m,}ts'
1132
+ ],
1133
+ rules: {
1134
+ 'no-console': 'off'
1135
+ }
1136
+ },
1137
+ {
1138
+ files: [
1139
+ 'test/**/*.{c,m,}ts{x,}'
1140
+ ],
1141
+ languageOptions: {
1142
+ globals: globals.nodeBuiltin
1143
+ },
1144
+ rules: {
1145
+ 'no-magic-numbers': 'off',
1146
+ "@typescript-eslint/explicit-function-return-type": 'off',
1147
+ "@typescript-eslint/no-magic-numbers": 'off',
1148
+ "@typescript-eslint/only-throw-error": 'off',
1149
+ 'sonarjs/pseudo-random': 'off',
1150
+ 'sonarjs/no-undefined-assignment': 'off',
1151
+ 'sonarjs/use-type-alias': 'off',
1152
+ 'unicorn/consistent-function-scoping': 'off',
1153
+ 'unicorn/max-nested-calls': 'off',
1154
+ "@typescript-eslint/ban-ts-comment": [
1155
+ 'error',
1156
+ {
1157
+ 'ts-expect-error': false,
1158
+ 'ts-check': true
1159
+ }
1160
+ ]
1161
+ }
1162
+ },
1163
+ ...plugins.map((plugin)=>packagePluginConfig(plugin, sourceFiles, [
1164
+ 'test/**'
1165
+ ])),
1166
+ prettierConfig
1167
+ ];
1168
+ }
1169
+
1170
+ //# sourceMappingURL=eslint-config.js.map