@ofk/eslint-config 0.0.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.mjs ADDED
@@ -0,0 +1,1156 @@
1
+ // src/base.ts
2
+ import pluginTs13 from "typescript-eslint";
3
+
4
+ // src/configs/eslint-comments.ts
5
+ import pluginEslintComments from "@eslint-community/eslint-plugin-eslint-comments/configs";
6
+ import pluginTs from "typescript-eslint";
7
+ var eslintCommentsStrict = pluginTs.config(pluginEslintComments.recommended, {
8
+ rules: {
9
+ "@eslint-community/eslint-comments/disable-enable-pair": ["error", { allowWholeFile: true }]
10
+ }
11
+ });
12
+
13
+ // src/configs/imports.ts
14
+ import pluginImport from "eslint-plugin-import";
15
+ import pluginTs2 from "typescript-eslint";
16
+ var importsStrict = pluginTs2.config(
17
+ pluginImport.flatConfigs.recommended,
18
+ // https://github.com/import-js/eslint-plugin-import?tab=readme-ov-file#helpful-warnings
19
+ {
20
+ rules: {
21
+ "import/no-deprecated": "off",
22
+ // discarded
23
+ "import/no-empty-named-blocks": "error",
24
+ // cf. https://github.com/airbnb/javascript/blob/eslint-config-airbnb-v19.0.4/packages/eslint-config-airbnb-base/rules/imports.js#L71
25
+ "import/no-extraneous-dependencies": [
26
+ "error",
27
+ {
28
+ devDependencies: [
29
+ "test/**",
30
+ "tests/**",
31
+ "spec/**",
32
+ "**/__tests__/**",
33
+ "**/__mocks__/**",
34
+ "**/*{.,_}{test,spec}.*",
35
+ "test.*",
36
+ "test-*.*",
37
+ "*.{config,setup,conf}.{js,ts,mjs,mts,cjs,cts}",
38
+ "*.{config,setup,conf}.*.{js,ts,mjs,mts,cjs,cts}",
39
+ ".*rc.{js,ts,mjs,mts,cjs,cts}"
40
+ ],
41
+ optionalDependencies: false
42
+ }
43
+ ],
44
+ "import/no-mutable-exports": "error",
45
+ "import/no-unused-modules": "error"
46
+ }
47
+ },
48
+ // https://github.com/import-js/eslint-plugin-import?tab=readme-ov-file#module-systems
49
+ {
50
+ rules: {
51
+ "import/no-amd": "error",
52
+ "import/no-commonjs": "off",
53
+ // disabled for use in esm
54
+ "import/no-import-module-exports": "error",
55
+ "import/no-nodejs-modules": "error",
56
+ "import/unambiguous": "off"
57
+ }
58
+ },
59
+ // https://github.com/import-js/eslint-plugin-import?tab=readme-ov-file#static-analysis
60
+ {
61
+ rules: {
62
+ "import/enforce-node-protocol-usage": "off",
63
+ // for node.js
64
+ "import/no-absolute-path": "error",
65
+ "import/no-cycle": "error",
66
+ "import/no-dynamic-require": "error",
67
+ "import/no-internal-modules": "off",
68
+ // discarded
69
+ "import/no-relative-packages": "error",
70
+ "import/no-relative-parent-imports": "off",
71
+ // discarded
72
+ "import/no-restricted-paths": "off",
73
+ // discarded
74
+ "import/no-self-import": "error",
75
+ "import/no-useless-path-segments": "error",
76
+ "import/no-webpack-loader-syntax": "error"
77
+ }
78
+ },
79
+ // https://github.com/import-js/eslint-plugin-import?tab=readme-ov-file#style-guide
80
+ {
81
+ rules: {
82
+ "import/consistent-type-specifier-style": ["error", "prefer-top-level"],
83
+ "import/dynamic-import-chunkname": "off",
84
+ // don't use webpack
85
+ "import/exports-last": "error",
86
+ "import/extensions": [
87
+ "error",
88
+ "ignorePackages",
89
+ { cjs: "never", js: "never", jsx: "never", mjs: "never" }
90
+ ],
91
+ "import/first": "error",
92
+ "import/group-exports": "off",
93
+ // discarded
94
+ "import/max-dependencies": "off",
95
+ // disabled style rules
96
+ "import/newline-after-import": "error",
97
+ "import/no-anonymous-default-export": [
98
+ "error",
99
+ {
100
+ allowArray: true,
101
+ allowCallExpression: true,
102
+ allowLiteral: true,
103
+ allowNew: true,
104
+ allowObject: true
105
+ }
106
+ ],
107
+ "import/no-default-export": "error",
108
+ // disallow default export
109
+ "import/no-duplicates": "error",
110
+ "import/no-named-default": "error",
111
+ "import/no-named-export": "off",
112
+ // disallow default export
113
+ "import/no-namespace": "error",
114
+ "import/no-unassigned-import": "off",
115
+ // allow to use side-effects module
116
+ "import/order": ["error", { groups: [["builtin", "external", "internal"]] }],
117
+ "import/prefer-default-export": "off",
118
+ // discarded
119
+ "no-duplicate-imports": "off"
120
+ }
121
+ },
122
+ // disable slow rules due to bugs
123
+ // https://github.com/import-js/eslint-plugin-import/issues/3148
124
+ {
125
+ rules: {
126
+ "import/namespace": "off",
127
+ "import/no-cycle": "off",
128
+ "import/no-deprecated": "off"
129
+ }
130
+ }
131
+ );
132
+ function imports({
133
+ defaultExportFiles = false,
134
+ node = false,
135
+ typescript = false,
136
+ ...config
137
+ }) {
138
+ return pluginTs2.config(
139
+ importsStrict,
140
+ config,
141
+ // allow default export in config files
142
+ {
143
+ files: [
144
+ "*.{config,setup,conf}.{js,ts,mjs,mts,cjs,cts}",
145
+ "*.{config,setup,conf}.*.{js,ts,mjs,mts,cjs,cts}",
146
+ ".*rc.{js,ts,mjs,mts,cjs,cts}",
147
+ ...defaultExportFiles || []
148
+ ],
149
+ rules: {
150
+ "import/no-default-export": "off"
151
+ }
152
+ },
153
+ node ? {
154
+ rules: {
155
+ "import/enforce-node-protocol-usage": ["error", "always"],
156
+ "import/no-nodejs-modules": "off"
157
+ }
158
+ } : {},
159
+ typescript ? {
160
+ extends: [
161
+ pluginImport.flatConfigs.typescript,
162
+ {
163
+ rules: {
164
+ "import/extensions": [
165
+ "error",
166
+ "ignorePackages",
167
+ {
168
+ cjs: "never",
169
+ cts: "never",
170
+ js: "never",
171
+ jsx: "never",
172
+ mjs: "never",
173
+ mts: "never",
174
+ ts: "never",
175
+ tsx: "never"
176
+ }
177
+ ]
178
+ }
179
+ },
180
+ // see https://github.com/iamturns/eslint-config-airbnb-typescript/blob/v18.0.0/lib/shared.js#L285-L290
181
+ {
182
+ rules: {
183
+ "import/default": "off",
184
+ "import/named": "off",
185
+ "import/namespace": "off",
186
+ "import/no-named-as-default-member": "off",
187
+ "import/no-unresolved": "off"
188
+ }
189
+ }
190
+ ],
191
+ files: ["**/*.{ts,tsx,mts,cts}"]
192
+ } : {}
193
+ );
194
+ }
195
+
196
+ // src/configs/js.ts
197
+ import pluginJs from "@eslint/js";
198
+ import confusingBrowserGlobals from "confusing-browser-globals";
199
+ import globalVariables from "globals";
200
+ import pluginTs3 from "typescript-eslint";
201
+ var jsStrict = pluginTs3.config(
202
+ pluginJs.configs.recommended,
203
+ {
204
+ rules: {
205
+ "no-empty": "warn",
206
+ // override recommended in suggestions
207
+ "no-empty-static-block": "warn",
208
+ // override recommended in suggestions
209
+ "no-misleading-character-class": ["error", { allowEscape: true }],
210
+ // override recommended in possible-problems
211
+ "no-unsafe-optional-chaining": ["error", { disallowArithmeticOperators: true }],
212
+ // override recommended in possible-problems
213
+ "no-unused-vars": [
214
+ "warn",
215
+ {
216
+ argsIgnorePattern: "^_",
217
+ caughtErrorsIgnorePattern: "^_",
218
+ ignoreRestSiblings: true,
219
+ varsIgnorePattern: "^_"
220
+ }
221
+ ],
222
+ // override recommended in possible-problems
223
+ "valid-typeof": ["error", { requireStringLiterals: true }]
224
+ // override recommended in possible-problems
225
+ }
226
+ },
227
+ // https://eslint.org/docs/latest/rules/#possible-problems
228
+ {
229
+ rules: {
230
+ "array-callback-return": "error",
231
+ "no-await-in-loop": "error",
232
+ "no-cond-assign": "error",
233
+ "no-constructor-return": "error",
234
+ "no-duplicate-imports": "error",
235
+ "no-inner-declarations": "error",
236
+ "no-promise-executor-return": "error",
237
+ "no-self-compare": "error",
238
+ "no-template-curly-in-string": "error",
239
+ "no-unmodified-loop-condition": "error",
240
+ "no-unreachable-loop": "error",
241
+ "no-use-before-define": "error",
242
+ "no-useless-assignment": "error",
243
+ "require-atomic-updates": "error"
244
+ }
245
+ },
246
+ // https://eslint.org/docs/latest/rules/#suggestions
247
+ {
248
+ rules: {
249
+ "accessor-pairs": "error",
250
+ "arrow-body-style": "error",
251
+ "block-scoped-var": "error",
252
+ camelcase: ["error", { ignoreDestructuring: false, properties: "never" }],
253
+ "capitalized-comments": "off",
254
+ // disabled style rules
255
+ "class-methods-use-this": "error",
256
+ complexity: "off",
257
+ // disabled metrics rules
258
+ "consistent-return": "error",
259
+ "consistent-this": "error",
260
+ curly: ["error", "multi-line"],
261
+ "default-case": ["error", { commentPattern: "^no default$" }],
262
+ "default-case-last": "error",
263
+ "default-param-last": "error",
264
+ "dot-notation": "error",
265
+ eqeqeq: ["error", "always", { null: "ignore" }],
266
+ "func-name-matching": "error",
267
+ "func-names": ["error", "as-needed"],
268
+ "func-style": ["error", "declaration", { allowArrowFunctions: true }],
269
+ "grouped-accessor-pairs": ["error", "getBeforeSet"],
270
+ "guard-for-in": "error",
271
+ "id-denylist": "off",
272
+ // disabled style rules
273
+ "id-length": "off",
274
+ // disabled style rules
275
+ "id-match": "off",
276
+ // disabled style rules
277
+ "init-declarations": "error",
278
+ "logical-assignment-operators": ["error", "always", { enforceForIfStatements: true }],
279
+ "max-classes-per-file": "error",
280
+ "max-depth": "off",
281
+ // disabled style rules
282
+ "max-lines": "off",
283
+ // disabled style rules
284
+ "max-lines-per-function": "off",
285
+ // disabled style rules
286
+ "max-nested-callbacks": "off",
287
+ // disabled style rules
288
+ "max-params": "off",
289
+ // disabled style rules
290
+ "max-statements": "off",
291
+ // disabled style rules
292
+ "new-cap": "error",
293
+ "no-alert": "error",
294
+ "no-array-constructor": "error",
295
+ "no-bitwise": "error",
296
+ "no-caller": "error",
297
+ "no-console": ["warn", { allow: ["warn", "error", "assert"] }],
298
+ "no-continue": "error",
299
+ "no-div-regex": "error",
300
+ "no-else-return": ["error", { allowElseIf: false }],
301
+ "no-empty-function": "warn",
302
+ "no-eq-null": "off",
303
+ // allow null equals
304
+ "no-eval": "error",
305
+ "no-extend-native": "error",
306
+ "no-extra-bind": "error",
307
+ "no-extra-label": "error",
308
+ "no-implicit-coercion": "error",
309
+ "no-implicit-globals": "off",
310
+ // disabled for use in esm
311
+ "no-implied-eval": "error",
312
+ "no-inline-comments": "off",
313
+ // allow inline comments
314
+ "no-invalid-this": "error",
315
+ "no-iterator": "error",
316
+ "no-label-var": "error",
317
+ "no-labels": "error",
318
+ "no-lone-blocks": "error",
319
+ "no-lonely-if": "error",
320
+ "no-loop-func": "error",
321
+ "no-magic-numbers": "off",
322
+ // allow magic numbers
323
+ "no-multi-assign": "error",
324
+ "no-multi-str": "error",
325
+ "no-negated-condition": "error",
326
+ "no-nested-ternary": "error",
327
+ "no-new": "error",
328
+ "no-new-func": "error",
329
+ "no-new-wrappers": "error",
330
+ "no-object-constructor": "error",
331
+ "no-octal-escape": "error",
332
+ "no-param-reassign": "error",
333
+ "no-plusplus": ["error", { allowForLoopAfterthoughts: true }],
334
+ "no-proto": "error",
335
+ // see https://github.com/airbnb/javascript/blob/eslint-config-airbnb-v19.0.4/packages/eslint-config-airbnb-base/rules/es6.js#L65
336
+ "no-restricted-exports": ["error", { restrictedNamedExports: ["default", "then"] }],
337
+ // see https://github.com/airbnb/javascript/blob/eslint-config-airbnb-v19.0.4/packages/eslint-config-airbnb-base/rules/variables.js#L19
338
+ "no-restricted-globals": ["error", ...confusingBrowserGlobals],
339
+ "no-restricted-imports": "off",
340
+ // allow all imports
341
+ "no-restricted-properties": "off",
342
+ // allow all properties
343
+ // see https://github.com/airbnb/javascript/blob/eslint-config-airbnb-v19.0.4/packages/eslint-config-airbnb-base/rules/style.js#L333
344
+ "no-restricted-syntax": [
345
+ "error",
346
+ {
347
+ message: "for..in loops iterate over the entire prototype chain, which is virtually never what you want. Use Object.{keys,values,entries}, and iterate over the resulting array.",
348
+ selector: "ForInStatement"
349
+ },
350
+ {
351
+ message: "iterators/generators require regenerator-runtime, which is too heavyweight for this guide to allow them. Separately, loops should be avoided in favor of array iterations.",
352
+ selector: "ForOfStatement"
353
+ },
354
+ {
355
+ message: "Labels are a form of GOTO; using them makes code confusing and hard to maintain and understand.",
356
+ selector: "LabeledStatement"
357
+ },
358
+ {
359
+ message: "`with` is disallowed in strict mode because it makes code impossible to predict and optimize.",
360
+ selector: "WithStatement"
361
+ }
362
+ ],
363
+ "no-return-assign": ["error", "always"],
364
+ "no-script-url": "error",
365
+ "no-sequences": "error",
366
+ "no-shadow": "error",
367
+ "no-ternary": "off",
368
+ // allow ternary operators
369
+ "no-throw-literal": "error",
370
+ "no-undef-init": "error",
371
+ "no-undefined": "off",
372
+ // allow undefined as a value
373
+ "no-underscore-dangle": "off",
374
+ // allow variable names containing underscores
375
+ "no-unneeded-ternary": ["error", { defaultAssignment: false }],
376
+ "no-unused-expressions": "error",
377
+ "no-useless-call": "error",
378
+ "no-useless-computed-key": "error",
379
+ "no-useless-concat": "error",
380
+ "no-useless-constructor": "error",
381
+ "no-useless-rename": "error",
382
+ "no-useless-return": "error",
383
+ "no-var": "error",
384
+ "no-void": ["error", { allowAsStatement: true }],
385
+ "no-warning-comments": "off",
386
+ // disabled style rules
387
+ "object-shorthand": ["error", "always", { avoidQuotes: true, ignoreConstructors: false }],
388
+ "one-var": ["error", "never"],
389
+ "operator-assignment": "error",
390
+ "prefer-arrow-callback": "error",
391
+ "prefer-const": ["error", { ignoreReadBeforeAssign: true }],
392
+ // see https://github.com/airbnb/javascript/blob/eslint-config-airbnb-v19.0.4/packages/eslint-config-airbnb-base/rules/es6.js#L123
393
+ "prefer-destructuring": [
394
+ "error",
395
+ {
396
+ AssignmentExpression: { array: true, object: false },
397
+ VariableDeclarator: { array: false, object: true }
398
+ },
399
+ { enforceForRenamedProperties: false }
400
+ ],
401
+ "prefer-exponentiation-operator": "error",
402
+ "prefer-named-capture-group": "off",
403
+ // don't enable new regexp features
404
+ "prefer-numeric-literals": "error",
405
+ "prefer-object-has-own": "error",
406
+ "prefer-object-spread": "error",
407
+ "prefer-promise-reject-errors": ["error", { allowEmptyReject: true }],
408
+ "prefer-regex-literals": ["error", { disallowRedundantWrapping: true }],
409
+ "prefer-rest-params": "error",
410
+ "prefer-spread": "error",
411
+ "prefer-template": "error",
412
+ radix: "error",
413
+ "require-await": "error",
414
+ "require-unicode-regexp": "off",
415
+ // don't enable new regexp features
416
+ "sort-imports": "off",
417
+ // disabled style rules
418
+ "sort-keys": "off",
419
+ // disabled style rules
420
+ "sort-vars": "off",
421
+ // disabled style rules
422
+ strict: ["error", "never"],
423
+ "symbol-description": "error",
424
+ "vars-on-top": "error",
425
+ yoda: "error"
426
+ }
427
+ },
428
+ // https://eslint.org/docs/latest/rules/#layout--formatting
429
+ {
430
+ rules: {
431
+ "unicode-bom": "error"
432
+ }
433
+ }
434
+ );
435
+ function jsGlobals({
436
+ browser = true,
437
+ es2024 = true,
438
+ node = true
439
+ }) {
440
+ return pluginTs3.config({
441
+ languageOptions: {
442
+ globals: {
443
+ ...es2024 ? globalVariables.es2024 : {},
444
+ ...browser ? globalVariables.browser : {},
445
+ ...node ? globalVariables.node : {}
446
+ }
447
+ }
448
+ });
449
+ }
450
+ function js({
451
+ globals = {},
452
+ ...config
453
+ }) {
454
+ return pluginTs3.config(globals ? jsGlobals(globals) : {}, jsStrict, config);
455
+ }
456
+
457
+ // src/configs/jsx-a11y.ts
458
+ import pluginJsxA11y from "eslint-plugin-jsx-a11y";
459
+ import pluginTs4 from "typescript-eslint";
460
+ var jsxA11yStrict = pluginTs4.config(pluginJsxA11y.flatConfigs.recommended, {
461
+ rules: {
462
+ "jsx-a11y/accessible-emoji": "off",
463
+ // deprecated
464
+ "jsx-a11y/lang": "error",
465
+ "jsx-a11y/no-aria-hidden-on-focusable": "off",
466
+ "jsx-a11y/no-onchange": "off",
467
+ // deprecated
468
+ "jsx-a11y/prefer-tag-over-role": "off"
469
+ }
470
+ });
471
+
472
+ // src/configs/perfectionist.ts
473
+ import pluginPerfectionist from "eslint-plugin-perfectionist";
474
+ import pluginTs5 from "typescript-eslint";
475
+ function mergeRuleOptions(rule, options) {
476
+ if (Array.isArray(rule)) {
477
+ return [rule[0], { ...rule[1], ...options }];
478
+ }
479
+ return rule;
480
+ }
481
+ function mergeConfig(config, options) {
482
+ return {
483
+ ...config,
484
+ rules: config.rules ? Object.fromEntries(
485
+ Object.entries(config.rules).map(([name, rule]) => [
486
+ name,
487
+ mergeRuleOptions(rule, options)
488
+ ])
489
+ ) : void 0
490
+ };
491
+ }
492
+ var perfectionistRecommended = mergeConfig(pluginPerfectionist.configs["recommended-natural"], {
493
+ ignoreCase: false
494
+ });
495
+ var perfectionistStrict = pluginTs5.config(
496
+ perfectionistRecommended,
497
+ {
498
+ rules: {
499
+ // see https://perfectionist.dev/rules/sort-imports
500
+ "perfectionist/sort-imports": mergeRuleOptions(
501
+ perfectionistRecommended.rules["perfectionist/sort-imports"],
502
+ {
503
+ groups: [
504
+ "type",
505
+ ["builtin", "external"],
506
+ "internal-type",
507
+ "internal",
508
+ ["parent-type", "sibling-type", "index-type"],
509
+ ["parent", "sibling", "index"],
510
+ "object",
511
+ "side-effect",
512
+ "style",
513
+ "unknown"
514
+ ],
515
+ internalPattern: [
516
+ "^[@~]/.*"
517
+ // next.js/remix default pattern
518
+ ]
519
+ }
520
+ ),
521
+ // see https://perfectionist.dev/rules/sort-jsx-props
522
+ "perfectionist/sort-jsx-props": mergeRuleOptions(
523
+ perfectionistRecommended.rules["perfectionist/sort-jsx-props"],
524
+ {
525
+ customGroups: {
526
+ reserved: "^(?:key|ref)$"
527
+ },
528
+ groups: ["reserved", "unknown"]
529
+ }
530
+ ),
531
+ // see https://perfectionist.dev/rules/sort-union-types
532
+ "perfectionist/sort-union-types": mergeRuleOptions(
533
+ perfectionistRecommended.rules["perfectionist/sort-union-types"],
534
+ {
535
+ groups: ["unknown", "nullish"]
536
+ }
537
+ )
538
+ }
539
+ },
540
+ {
541
+ rules: {
542
+ // disable sorting of method definitions that conflict with no-use-before-define
543
+ "perfectionist/sort-classes": "off",
544
+ "perfectionist/sort-modules": "off"
545
+ }
546
+ },
547
+ {
548
+ rules: {
549
+ // conflict with https://perfectionist.dev/rules/sort-interfaces
550
+ // https://perfectionist.dev/rules/sort-object-types
551
+ "@typescript-eslint/adjacent-overload-signatures": "off",
552
+ // conflict with https://perfectionist.dev/rules/sort-classes
553
+ "@typescript-eslint/member-ordering": "off",
554
+ // conflict with https://perfectionist.dev/rules/sort-intersection-types
555
+ // https://perfectionist.dev/rules/sort-union-types
556
+ "@typescript-eslint/sort-type-constituents": "off",
557
+ // conflict with https://perfectionist.dev/rules/sort-imports
558
+ // https://perfectionist.dev/rules/sort-named-imports
559
+ "import/order": "off",
560
+ // conflict with https://perfectionist.dev/rules/sort-jsx-props
561
+ "react/jsx-sort-props": "off",
562
+ // conflict with https://perfectionist.dev/rules/sort-classes
563
+ "react/sort-comp": "off",
564
+ // conflict with https://perfectionist.dev/rules/sort-objects
565
+ "react/sort-default-props": "off",
566
+ "react/sort-prop-types": "off",
567
+ // conflict with https://perfectionist.dev/rules/sort-imports
568
+ // https://perfectionist.dev/rules/sort-named-imports
569
+ "sort-imports": "off",
570
+ // conflict with https://perfectionist.dev/rules/sort-objects
571
+ "sort-keys": "off"
572
+ }
573
+ }
574
+ );
575
+
576
+ // src/configs/react.ts
577
+ import pluginReact from "eslint-plugin-react";
578
+ import pluginTs6 from "typescript-eslint";
579
+ var reactStrict = pluginTs6.config(pluginReact.configs.flat.recommended, {
580
+ rules: {
581
+ "react/boolean-prop-naming": "off",
582
+ "react/button-has-type": ["error", { button: true, reset: false, submit: true }],
583
+ "react/checked-requires-onchange-or-readonly": "off",
584
+ "react/default-props-match-prop-types": "off",
585
+ "react/destructuring-assignment": ["error", "always"],
586
+ "react/forbid-component-props": "off",
587
+ "react/forbid-dom-props": "off",
588
+ "react/forbid-elements": "off",
589
+ "react/forbid-foreign-prop-types": ["warn", { allowInPropTypes: true }],
590
+ "react/forbid-prop-types": [
591
+ "error",
592
+ {
593
+ checkChildContextTypes: true,
594
+ checkContextTypes: true,
595
+ forbid: ["any", "array", "object"]
596
+ }
597
+ ],
598
+ "react/forward-ref-uses-ref": "error",
599
+ "react/function-component-definition": [
600
+ "error",
601
+ { namedComponents: "function-declaration", unnamedComponents: "function-expression" }
602
+ ],
603
+ "react/hook-use-state": "error",
604
+ "react/iframe-missing-sandbox": "error",
605
+ "react/jsx-boolean-value": ["error", "never"],
606
+ "react/jsx-child-element-spacing": "off",
607
+ "react/jsx-closing-bracket-location": ["error", "line-aligned"],
608
+ "react/jsx-closing-tag-location": "error",
609
+ "react/jsx-curly-brace-presence": ["error", { children: "never", props: "never" }],
610
+ "react/jsx-curly-newline": ["error", { multiline: "consistent", singleline: "consistent" }],
611
+ "react/jsx-curly-spacing": ["error", "never", { allowMultiline: true }],
612
+ "react/jsx-equals-spacing": ["error", "never"],
613
+ "react/jsx-filename-extension": ["error", { extensions: [".jsx", ".tsx"] }],
614
+ "react/jsx-first-prop-new-line": ["error", "multiline-multiprop"],
615
+ "react/jsx-fragments": ["error", "syntax"],
616
+ "react/jsx-handler-names": "off",
617
+ "react/jsx-indent": ["error", 2],
618
+ "react/jsx-indent-props": ["error", 2],
619
+ "react/jsx-max-depth": "off",
620
+ "react/jsx-max-props-per-line": ["error", { maximum: 1, when: "multiline" }],
621
+ "react/jsx-newline": "off",
622
+ "react/jsx-no-bind": [
623
+ "error",
624
+ {
625
+ allowArrowFunctions: true,
626
+ allowBind: false,
627
+ allowFunctions: false,
628
+ ignoreDOMComponents: true,
629
+ ignoreRefs: true
630
+ }
631
+ ],
632
+ "react/jsx-no-constructed-context-values": "error",
633
+ "react/jsx-no-leaked-render": ["error", { validStrategies: ["ternary"] }],
634
+ "react/jsx-no-literals": "off",
635
+ "react/jsx-no-script-url": ["error", [{ name: "Link", props: ["to"] }]],
636
+ "react/jsx-no-useless-fragment": "error",
637
+ "react/jsx-one-expression-per-line": ["error", { allow: "single-child" }],
638
+ "react/jsx-pascal-case": ["error", { allowAllCaps: true }],
639
+ "react/jsx-props-no-multi-spaces": "error",
640
+ "react/jsx-props-no-spread-multi": "error",
641
+ "react/jsx-props-no-spreading": "off",
642
+ "react/jsx-sort-props": "off",
643
+ "react/jsx-tag-spacing": [
644
+ "error",
645
+ {
646
+ afterOpening: "never",
647
+ beforeClosing: "never",
648
+ beforeSelfClosing: "always",
649
+ closingSlash: "never"
650
+ }
651
+ ],
652
+ "react/jsx-wrap-multilines": [
653
+ "error",
654
+ {
655
+ arrow: "parens-new-line",
656
+ assignment: "parens-new-line",
657
+ condition: "parens-new-line",
658
+ declaration: "parens-new-line",
659
+ logical: "parens-new-line",
660
+ prop: "parens-new-line",
661
+ return: "parens-new-line"
662
+ }
663
+ ],
664
+ "react/no-access-state-in-setstate": "error",
665
+ "react/no-adjacent-inline-elements": "off",
666
+ "react/no-array-index-key": "error",
667
+ "react/no-arrow-function-lifecycle": "error",
668
+ "react/no-danger": "warn",
669
+ "react/no-did-mount-set-state": "off",
670
+ "react/no-did-update-set-state": "error",
671
+ "react/no-invalid-html-attribute": "error",
672
+ "react/no-multi-comp": "off",
673
+ "react/no-namespace": "error",
674
+ "react/no-object-type-as-default-prop": "error",
675
+ "react/no-redundant-should-component-update": "error",
676
+ "react/no-set-state": "off",
677
+ "react/no-this-in-sfc": "error",
678
+ "react/no-typos": "error",
679
+ "react/no-unstable-nested-components": "error",
680
+ "react/no-unused-class-component-methods": "error",
681
+ "react/no-unused-prop-types": "error",
682
+ "react/no-unused-state": "error",
683
+ "react/no-will-update-set-state": "error",
684
+ "react/prefer-es6-class": ["error", "always"],
685
+ "react/prefer-exact-props": "error",
686
+ "react/prefer-read-only-props": "off",
687
+ // too strict
688
+ "react/prefer-stateless-function": ["error", { ignorePureComponents: true }],
689
+ "react/require-default-props": "off",
690
+ // disallow defaultProps
691
+ "react/require-optimization": "off",
692
+ "react/self-closing-comp": "error",
693
+ "react/sort-comp": "error",
694
+ "react/sort-default-props": "error",
695
+ "react/sort-prop-types": "error",
696
+ "react/state-in-constructor": ["error", "never"],
697
+ "react/static-property-placement": ["error", "property assignment"],
698
+ "react/style-prop-object": "error",
699
+ "react/void-dom-elements-no-children": "error"
700
+ }
701
+ });
702
+ function react(config) {
703
+ return pluginTs6.config(
704
+ {
705
+ settings: {
706
+ react: {
707
+ version: "detect"
708
+ }
709
+ }
710
+ },
711
+ {
712
+ ...config,
713
+ extends: [reactStrict, ...config.extends ?? []],
714
+ files: ["**/*.{jsx,tsx}"]
715
+ }
716
+ );
717
+ }
718
+
719
+ // src/configs/react-hooks.ts
720
+ import pluginReactHooks from "eslint-plugin-react-hooks";
721
+ import pluginTs7 from "typescript-eslint";
722
+ var reactHooksStrict = pluginTs7.config(
723
+ // Flat Config version has not been released yet.
724
+ {
725
+ plugins: { "react-hooks": pluginReactHooks },
726
+ rules: pluginReactHooks.configs.recommended.rules
727
+ }
728
+ );
729
+
730
+ // src/configs/react-refresh.ts
731
+ import pluginReactRefresh from "eslint-plugin-react-refresh";
732
+ import pluginTs8 from "typescript-eslint";
733
+ var reactRefreshStrict = pluginTs8.config(pluginReactRefresh.configs.recommended);
734
+
735
+ // src/configs/ts.ts
736
+ import pluginTs9 from "typescript-eslint";
737
+ var tsRecommendedOverride = pluginTs9.config(
738
+ // override rules in recommended
739
+ {
740
+ rules: {
741
+ // override no-empty-object-type in recommended
742
+ "@typescript-eslint/no-empty-object-type": [
743
+ "error",
744
+ { allowInterfaces: "with-single-extends" }
745
+ ],
746
+ // override no-unused-vars in recommended
747
+ "@typescript-eslint/no-unused-vars": [
748
+ "warn",
749
+ {
750
+ argsIgnorePattern: "^_",
751
+ caughtErrorsIgnorePattern: "^_",
752
+ ignoreRestSiblings: true,
753
+ varsIgnorePattern: "^_"
754
+ }
755
+ ]
756
+ }
757
+ },
758
+ // best practices
759
+ {
760
+ rules: {
761
+ "@typescript-eslint/consistent-type-exports": "error",
762
+ "@typescript-eslint/consistent-type-imports": "error",
763
+ "no-duplicate-imports": "off"
764
+ // confilict with @typescript-eslint/consistent-type-imports
765
+ }
766
+ }
767
+ );
768
+ var tsRecommended = pluginTs9.config(pluginTs9.configs.recommended, tsRecommendedOverride);
769
+ var tsStrict = pluginTs9.config(
770
+ pluginTs9.configs.strictTypeChecked,
771
+ pluginTs9.configs.stylisticTypeChecked,
772
+ tsRecommendedOverride,
773
+ {
774
+ rules: {
775
+ // override no-empty-function in stylistic
776
+ "@typescript-eslint/no-empty-function": "warn",
777
+ // override no-unnecessary-condition in strict
778
+ "@typescript-eslint/no-unnecessary-condition": [
779
+ "error",
780
+ { allowConstantLoopConditions: true }
781
+ ],
782
+ // override prefer-for-of in stylistic
783
+ "@typescript-eslint/prefer-for-of": "off"
784
+ // disallow for-of
785
+ }
786
+ },
787
+ {
788
+ rules: {
789
+ "@typescript-eslint/class-methods-use-this": "error",
790
+ "@typescript-eslint/consistent-return": "off",
791
+ // disabled because tsc checks
792
+ "@typescript-eslint/default-param-last": "error",
793
+ "@typescript-eslint/explicit-function-return-type": "error",
794
+ "@typescript-eslint/explicit-member-accessibility": ["error", { accessibility: "no-public" }],
795
+ "@typescript-eslint/explicit-module-boundary-types": "off",
796
+ // typescript-eslint/explicit-function-return-type is enabled
797
+ "@typescript-eslint/init-declarations": "error",
798
+ "@typescript-eslint/max-params": "off",
799
+ // disabled like js
800
+ "@typescript-eslint/member-ordering": "off",
801
+ // disabled style rules
802
+ "@typescript-eslint/method-signature-style": "error",
803
+ "@typescript-eslint/naming-convention": "off",
804
+ // disabled style rules
805
+ "@typescript-eslint/no-dupe-class-members": "off",
806
+ // disabled because tsc checks
807
+ "@typescript-eslint/no-import-type-side-effects": "error",
808
+ "@typescript-eslint/no-invalid-this": "off",
809
+ // disabled because tsc checks
810
+ "@typescript-eslint/no-loop-func": "error",
811
+ "@typescript-eslint/no-magic-numbers": "off",
812
+ // disabled like js
813
+ "@typescript-eslint/no-redeclare": "error",
814
+ "@typescript-eslint/no-restricted-imports": "off",
815
+ // disabled like js
816
+ "@typescript-eslint/no-restricted-types": "off",
817
+ // allow all types
818
+ "@typescript-eslint/no-shadow": "error",
819
+ "@typescript-eslint/no-unnecessary-parameter-property-assignment": "error",
820
+ "@typescript-eslint/no-unnecessary-qualifier": "error",
821
+ "@typescript-eslint/no-unsafe-type-assertion": "off",
822
+ // too strict
823
+ "@typescript-eslint/no-use-before-define": "error",
824
+ "@typescript-eslint/no-useless-empty-export": "error",
825
+ "@typescript-eslint/parameter-properties": ["error", { prefer: "parameter-property" }],
826
+ "@typescript-eslint/prefer-destructuring": [
827
+ "error",
828
+ {
829
+ AssignmentExpression: { array: true, object: false },
830
+ VariableDeclarator: { array: false, object: true }
831
+ },
832
+ { enforceForRenamedProperties: false }
833
+ ],
834
+ "@typescript-eslint/prefer-enum-initializers": "error",
835
+ "@typescript-eslint/prefer-readonly": "error",
836
+ "@typescript-eslint/prefer-readonly-parameter-types": "off",
837
+ // too strict
838
+ "@typescript-eslint/promise-function-async": "error",
839
+ "@typescript-eslint/require-array-sort-compare": "error",
840
+ "@typescript-eslint/strict-boolean-expressions": "off",
841
+ // too strict
842
+ "@typescript-eslint/switch-exhaustiveness-check": "error",
843
+ "@typescript-eslint/typedef": "off",
844
+ // disabled for use strict tsc
845
+ "class-methods-use-this": "off",
846
+ "default-param-last": "off",
847
+ "init-declarations": "off",
848
+ "max-params": "off",
849
+ "no-dupe-class-members": "off",
850
+ "no-invalid-this": "off",
851
+ "no-loop-func": "off",
852
+ "no-magic-numbers": "off",
853
+ "no-redeclare": "off",
854
+ "no-restricted-imports": "off",
855
+ "no-shadow": "off",
856
+ "no-use-before-define": "off",
857
+ "prefer-destructuring": "off"
858
+ }
859
+ }
860
+ );
861
+ function ts({
862
+ disableTypeChecked = false,
863
+ parserOptions = {},
864
+ strict = true,
865
+ ...config
866
+ }) {
867
+ return pluginTs9.config(
868
+ parserOptions ? {
869
+ languageOptions: {
870
+ parserOptions: {
871
+ projectService: true,
872
+ ...parserOptions
873
+ }
874
+ }
875
+ } : {},
876
+ strict ? tsStrict : tsRecommended,
877
+ config,
878
+ disableTypeChecked ? {
879
+ extends: [
880
+ pluginTs9.configs.disableTypeChecked,
881
+ // disabled unsafe rules for js files
882
+ {
883
+ rules: {
884
+ "@typescript-eslint/no-unsafe-argument": "off",
885
+ "@typescript-eslint/no-unsafe-assignment": "off",
886
+ "@typescript-eslint/no-unsafe-call": "off",
887
+ "@typescript-eslint/no-unsafe-declaration-merging": "off",
888
+ "@typescript-eslint/no-unsafe-enum-comparison": "off",
889
+ "@typescript-eslint/no-unsafe-function-type": "off",
890
+ "@typescript-eslint/no-unsafe-member-access": "off",
891
+ "@typescript-eslint/no-unsafe-return": "off",
892
+ "@typescript-eslint/no-unsafe-type-assertion": "off",
893
+ "@typescript-eslint/no-unsafe-unary-minus": "off"
894
+ }
895
+ }
896
+ ],
897
+ files: ["**/*.{js,jsx,mjs,cjs}"]
898
+ } : {}
899
+ );
900
+ }
901
+
902
+ // src/configs/unused-imports.ts
903
+ import pluginUnusedImports from "eslint-plugin-unused-imports";
904
+ import pluginTs10 from "typescript-eslint";
905
+ var unusedImportsStrict = pluginTs10.config({
906
+ plugins: {
907
+ "unused-imports": pluginUnusedImports
908
+ },
909
+ rules: {
910
+ "@typescript-eslint/no-unused-vars": "off",
911
+ "no-unused-vars": "off",
912
+ "unused-imports/no-unused-imports": "error",
913
+ "unused-imports/no-unused-vars": [
914
+ "warn",
915
+ {
916
+ argsIgnorePattern: "^_",
917
+ caughtErrorsIgnorePattern: "^_",
918
+ ignoreRestSiblings: true,
919
+ varsIgnorePattern: "^_"
920
+ }
921
+ ]
922
+ }
923
+ });
924
+
925
+ // src/configs/vitest.ts
926
+ import pluginVitest from "@vitest/eslint-plugin";
927
+ import pluginTs11 from "typescript-eslint";
928
+ var vitestStrict = pluginTs11.config(pluginVitest.configs.recommended, {
929
+ rules: {
930
+ "vitest/consistent-test-filename": "off",
931
+ "vitest/consistent-test-it": "error",
932
+ "vitest/max-expects": "off",
933
+ "vitest/max-nested-describe": "off",
934
+ "vitest/no-alias-methods": "error",
935
+ "vitest/no-conditional-expect": "error",
936
+ "vitest/no-conditional-in-test": "error",
937
+ "vitest/no-conditional-tests": "error",
938
+ "vitest/no-disabled-tests": "off",
939
+ "vitest/no-done-callback": "off",
940
+ // deprecated
941
+ "vitest/no-duplicate-hooks": "error",
942
+ "vitest/no-focused-tests": "off",
943
+ "vitest/no-hooks": "off",
944
+ "vitest/no-interpolation-in-snapshots": "error",
945
+ "vitest/no-large-snapshots": "off",
946
+ "vitest/no-mocks-import": "off",
947
+ "vitest/no-restricted-matchers": "off",
948
+ "vitest/no-restricted-vi-methods": "off",
949
+ "vitest/no-standalone-expect": "error",
950
+ "vitest/no-test-prefixes": "off",
951
+ "vitest/no-test-return-statement": "error",
952
+ "vitest/padding-around-after-all-blocks": "error",
953
+ "vitest/padding-around-after-each-blocks": "error",
954
+ "vitest/padding-around-all": "error",
955
+ "vitest/padding-around-before-all-blocks": "error",
956
+ "vitest/padding-around-before-each-blocks": "error",
957
+ "vitest/padding-around-describe-blocks": "error",
958
+ "vitest/padding-around-expect-groups": "error",
959
+ "vitest/padding-around-test-blocks": "error",
960
+ "vitest/prefer-called-with": "error",
961
+ "vitest/prefer-comparison-matcher": "error",
962
+ "vitest/prefer-each": "error",
963
+ "vitest/prefer-equality-matcher": "error",
964
+ "vitest/prefer-expect-assertions": "error",
965
+ "vitest/prefer-expect-resolves": "error",
966
+ "vitest/prefer-hooks-in-order": "error",
967
+ "vitest/prefer-hooks-on-top": "error",
968
+ "vitest/prefer-lowercase-title": "error",
969
+ "vitest/prefer-mock-promise-shorthand": "error",
970
+ "vitest/prefer-snapshot-hint": "error",
971
+ "vitest/prefer-spy-on": "error",
972
+ "vitest/prefer-strict-equal": "error",
973
+ "vitest/prefer-to-be": "error",
974
+ "vitest/prefer-to-be-falsy": "error",
975
+ "vitest/prefer-to-be-object": "error",
976
+ "vitest/prefer-to-be-truthy": "error",
977
+ "vitest/prefer-to-contain": "error",
978
+ "vitest/prefer-to-have-length": "error",
979
+ "vitest/prefer-todo": "error",
980
+ "vitest/prefer-vi-mocked": "error",
981
+ "vitest/require-hook": "error",
982
+ "vitest/require-to-throw-message": "error",
983
+ "vitest/require-top-level-describe": "error",
984
+ "vitest/valid-expect-in-promise": "error"
985
+ }
986
+ });
987
+ function vitest(config) {
988
+ return pluginTs11.config({
989
+ extends: [vitestStrict, config],
990
+ files: ["tests/**", "*.test.*"]
991
+ });
992
+ }
993
+
994
+ // src/configs/unicorn.ts
995
+ import pluginUnicorn from "eslint-plugin-unicorn";
996
+ import pluginTs12 from "typescript-eslint";
997
+ var unicornRecommended = pluginTs12.config(
998
+ {
999
+ ...pluginUnicorn.configs["flat/recommended"],
1000
+ rules: Object.fromEntries(
1001
+ Object.entries(pluginUnicorn.configs["flat/recommended"].rules ?? {}).filter(
1002
+ ([_key, value]) => value !== "off"
1003
+ )
1004
+ )
1005
+ },
1006
+ {
1007
+ rules: {
1008
+ "no-negated-condition": "off",
1009
+ "no-nested-ternary": "off",
1010
+ "unicorn/better-regex": "off",
1011
+ // not recommended
1012
+ "unicorn/catch-error-name": "off",
1013
+ // overcorrection
1014
+ "unicorn/consistent-destructuring": "off",
1015
+ "unicorn/custom-error-definition": "off",
1016
+ "unicorn/expiring-todo-comments": "off",
1017
+ // discarded
1018
+ "unicorn/filename-case": "off",
1019
+ // discarded
1020
+ "unicorn/no-abusive-eslint-disable": "off",
1021
+ // disabled for use eslint-comments/no-unlimited-disable
1022
+ "unicorn/no-anonymous-default-export": "off",
1023
+ // disabled for use import/no-anonymous-default-export
1024
+ "unicorn/no-array-for-each": "off",
1025
+ // disallow for-of
1026
+ "unicorn/no-array-reduce": "off",
1027
+ // allow array reduce
1028
+ "unicorn/no-console-spaces": "off",
1029
+ // discarded
1030
+ "unicorn/no-for-loop": "off",
1031
+ // disallow for-of
1032
+ "unicorn/no-keyword-prefix": "error",
1033
+ "unicorn/no-magic-array-flat-depth": "off",
1034
+ // allow magic numbers
1035
+ "unicorn/no-null": "off",
1036
+ // allow null
1037
+ "unicorn/no-typeof-undefined": "off",
1038
+ // discarded
1039
+ "unicorn/no-unnecessary-polyfills": "off",
1040
+ // skip validate polyfills
1041
+ "unicorn/no-unused-properties": "off",
1042
+ // not recommended
1043
+ "unicorn/numeric-separators-style": "off",
1044
+ // disabled style rules
1045
+ "unicorn/prefer-global-this": "off",
1046
+ // discarded
1047
+ "unicorn/prefer-json-parse-buffer": "off",
1048
+ // not recommended
1049
+ "unicorn/prefer-keyboard-event-key": "off",
1050
+ // allow keyCode
1051
+ "unicorn/prefer-node-protocol": "off",
1052
+ // disabled for use import/enforce-node-protocol-usage
1053
+ "unicorn/prefer-string-raw": "off",
1054
+ // disallow String.raw
1055
+ "unicorn/prefer-structured-clone": "off",
1056
+ // disallow structuredClone
1057
+ "unicorn/prefer-switch": "off",
1058
+ // discarded
1059
+ "unicorn/prefer-ternary": "off",
1060
+ // discarded
1061
+ "unicorn/prefer-top-level-await": "off",
1062
+ // discarded
1063
+ "unicorn/prefer-type-error": "off",
1064
+ // discarded
1065
+ "unicorn/prevent-abbreviations": "off",
1066
+ // disabled style rules
1067
+ "unicorn/relative-url-style": ["error", "always"],
1068
+ "unicorn/require-post-message-target-origin": "off",
1069
+ // not recommended
1070
+ "unicorn/string-content": "off",
1071
+ // not recommended
1072
+ "unicorn/switch-case-braces": ["error", "avoid"]
1073
+ }
1074
+ }
1075
+ );
1076
+
1077
+ // src/base.ts
1078
+ function defineBaseConfig({
1079
+ eslintComments: eslintCommentsOptions = {},
1080
+ ignores,
1081
+ imports: importsOptions = {},
1082
+ js: jsOptions = {},
1083
+ perfectionist: perfectionistOptions = {},
1084
+ settings,
1085
+ ts: tsOptions = {},
1086
+ unicorn: unicornOptions = {},
1087
+ unusedImports: unusedImportsOptions = {},
1088
+ vitest: vitestOptions = {},
1089
+ ...config
1090
+ } = {}) {
1091
+ return pluginTs13.config(
1092
+ settings ? { settings } : {},
1093
+ ignores ? { ignores } : {},
1094
+ jsOptions ? js(jsOptions) : {},
1095
+ tsOptions ? ts(tsOptions) : {},
1096
+ importsOptions ? imports({ typescript: Boolean(tsOptions), ...importsOptions }) : {},
1097
+ unusedImportsOptions ? unusedImportsStrict : {},
1098
+ eslintCommentsOptions ? eslintCommentsStrict : {},
1099
+ vitestOptions ? vitest(vitestOptions) : {},
1100
+ perfectionistOptions ? perfectionistStrict : {},
1101
+ unicornOptions ? unicornRecommended : {},
1102
+ config
1103
+ );
1104
+ }
1105
+
1106
+ // src/react.ts
1107
+ import pluginReact2 from "eslint-plugin-react";
1108
+ import pluginTs14 from "typescript-eslint";
1109
+ function defineReactConfig({
1110
+ jsxA11y: enabledJsxA11y = true,
1111
+ jsxRuntime: enabledJsxRuntime = true,
1112
+ reactHooks: enabledReactHooks = true,
1113
+ reactRefresh: enabledReactRefresh = true,
1114
+ ...reactOptions
1115
+ } = {}) {
1116
+ return pluginTs14.config(
1117
+ react({
1118
+ ...reactOptions,
1119
+ extends: [
1120
+ enabledJsxRuntime ? pluginReact2.configs.flat["jsx-runtime"] : {},
1121
+ enabledReactHooks ? reactHooksStrict : {},
1122
+ enabledReactRefresh ? reactRefreshStrict : {},
1123
+ enabledJsxA11y ? jsxA11yStrict : {},
1124
+ ...reactOptions.extends ?? []
1125
+ ]
1126
+ })
1127
+ );
1128
+ }
1129
+
1130
+ // src/index.ts
1131
+ function defineConfig({
1132
+ eslintComments: eslintCommentsOptions,
1133
+ imports: importsOptions,
1134
+ js: jsOptions,
1135
+ perfectionist: perfectionistOptions,
1136
+ react: reactOptions = {},
1137
+ ts: tsOptions,
1138
+ unusedImports: unusedImportsOptions,
1139
+ vitest: vitestOptions,
1140
+ ...config
1141
+ } = {}) {
1142
+ return defineBaseConfig({
1143
+ ...config,
1144
+ eslintComments: eslintCommentsOptions,
1145
+ extends: [reactOptions ? defineReactConfig(reactOptions) : {}, ...config.extends ?? []],
1146
+ imports: importsOptions,
1147
+ js: jsOptions,
1148
+ perfectionist: perfectionistOptions,
1149
+ ts: tsOptions,
1150
+ unusedImports: unusedImportsOptions,
1151
+ vitest: vitestOptions
1152
+ });
1153
+ }
1154
+ export {
1155
+ defineConfig as default
1156
+ };