@favorodera/eslint-config 0.0.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.
package/dist/index.mjs ADDED
@@ -0,0 +1,663 @@
1
+ import { FlatConfigComposer } from "eslint-flat-config-utils";
2
+ import { defu } from "defu";
3
+ import { mergeProcessors, processorPassThrough } from "eslint-merge-processors";
4
+ import globals from "globals";
5
+ //#region src/utils.ts
6
+ /**
7
+ * Return the default export from a module-like object.
8
+ * If the module has no default export, return the original resolved value.
9
+ *
10
+ * @param module - module or promise resolving to a module
11
+ * @returns resolved module default or original module
12
+ */
13
+ async function getModuleDefault(module) {
14
+ const resolvedModule = await module;
15
+ return resolvedModule.default || resolvedModule;
16
+ }
17
+ /**
18
+ * Normalize boolean or options value into merged options or null.
19
+ * Returns null when the input is false or undefined.
20
+ *
21
+ * @param value - boolean, options object, or undefined
22
+ * @param defaults - defaults to merge with
23
+ * @returns merged options or false
24
+ */
25
+ function resolveOptions(value, defaults) {
26
+ if (!value) return false;
27
+ return defu(value === true ? {} : value, defaults);
28
+ }
29
+ /**
30
+ * Rename rules by replacing configured plugin prefixes.
31
+ *
32
+ * @param rules - rules object to rename
33
+ * @param map - prefix map used for renaming
34
+ * @returns renamed rules object
35
+ */
36
+ function renameRules(rules, map) {
37
+ return Object.fromEntries(Object.entries(rules).map(([key, value]) => {
38
+ for (const [from, to] of Object.entries(map)) if (key.startsWith(`${from}/`)) return [to + key.slice(from.length), value];
39
+ return [key, value];
40
+ }));
41
+ }
42
+ //#endregion
43
+ //#region src/globs.ts
44
+ /** Glob pattern for JavaScript linting */
45
+ const jsGlob = "**/*.?([cm])js";
46
+ /** Glob pattern for TypeScript linting */
47
+ const tsGlob = "**/*.?([cm])ts";
48
+ /** Glob pattern for Vue linting */
49
+ const vueGlob = "**/*.vue";
50
+ /** Glob pattern for Markdown linting */
51
+ const mdGlob = "**/*.md";
52
+ /**
53
+ * Default glob patterns for files and directories to ignore
54
+ * Includes common build outputs, dependencies, caches, and temporary files
55
+ */
56
+ const ignoresGlob = [
57
+ "**/node_modules",
58
+ "**/dist",
59
+ "**/package-lock.json",
60
+ "**/yarn.lock",
61
+ "**/pnpm-lock.yaml",
62
+ "**/bun.lockb",
63
+ "**/output",
64
+ "**/coverage",
65
+ "**/temp",
66
+ "**/.temp",
67
+ "**/tmp",
68
+ "**/.tmp",
69
+ "**/.history",
70
+ "**/.vitepress/cache",
71
+ "**/.nuxt",
72
+ "**/.next",
73
+ "**/.svelte-kit",
74
+ "**/.vercel",
75
+ "**/.changeset",
76
+ "**/.idea",
77
+ "**/.cache",
78
+ "**/.output",
79
+ "**/.vite-inspect",
80
+ "**/.yarn",
81
+ "**/CHANGELOG*.md",
82
+ "**/LICENSE*",
83
+ "**/*.min.*",
84
+ "**/__snapshots__",
85
+ "**/vite.config.*.timestamp-*",
86
+ "**/auto-import?(s).d.ts",
87
+ "**/components.d.ts",
88
+ "**/.context",
89
+ "**/.claude",
90
+ "**/.agents",
91
+ "**/.*/skills"
92
+ ];
93
+ //#endregion
94
+ //#region src/configs/vue.ts
95
+ const sfcBlocksDefaults = { blocks: {
96
+ styles: true,
97
+ customBlocks: true,
98
+ template: false
99
+ } };
100
+ const vueDefaults = {
101
+ files: [vueGlob],
102
+ sfcBlocks: sfcBlocksDefaults
103
+ };
104
+ /**
105
+ * Vue SFC linting via `vue-eslint-parser`, `eslint-plugin-vue`, `typescript-eslint(parser)`.
106
+ * @param options - Vue configuration options
107
+ * @returns Promise resolving to Vue ESLint config items
108
+ */
109
+ async function vue(options) {
110
+ const resolved = defu(options, vueDefaults);
111
+ const sfcBlocks = resolveOptions(resolved.sfcBlocks, sfcBlocksDefaults);
112
+ const [vuePlugin, vueParser, tsEsLint, vueBlocksProcessor] = await Promise.all([
113
+ getModuleDefault(import("eslint-plugin-vue")),
114
+ getModuleDefault(import("vue-eslint-parser")),
115
+ getModuleDefault(import("typescript-eslint")),
116
+ getModuleDefault(import("eslint-processor-vue-blocks"))
117
+ ]);
118
+ return [{
119
+ name: "favorodera/vue/rules",
120
+ plugins: { vue: vuePlugin },
121
+ files: resolved.files,
122
+ languageOptions: {
123
+ globals: {
124
+ computed: "readonly",
125
+ defineEmits: "readonly",
126
+ defineExpose: "readonly",
127
+ defineProps: "readonly",
128
+ onMounted: "readonly",
129
+ onUnmounted: "readonly",
130
+ reactive: "readonly",
131
+ ref: "readonly",
132
+ shallowReactive: "readonly",
133
+ shallowRef: "readonly",
134
+ toRef: "readonly",
135
+ toRefs: "readonly",
136
+ watch: "readonly",
137
+ watchEffect: "readonly"
138
+ },
139
+ parser: vueParser,
140
+ parserOptions: {
141
+ parser: tsEsLint.parser,
142
+ extraFileExtensions: [".vue"],
143
+ sourceType: "module"
144
+ }
145
+ },
146
+ processor: sfcBlocks === false ? vuePlugin.processors[".vue"] : mergeProcessors([vuePlugin.processors[".vue"], vueBlocksProcessor(sfcBlocks)]),
147
+ rules: {
148
+ ...vuePlugin.configs.base.rules,
149
+ ...vuePlugin.configs["flat/essential"].map((config) => config.rules).reduce((accumulator, currentConfig) => ({
150
+ ...accumulator,
151
+ ...currentConfig
152
+ }), {}),
153
+ ...vuePlugin.configs["flat/strongly-recommended"].map((config) => config.rules).reduce((accumulator, currentConfig) => ({
154
+ ...accumulator,
155
+ ...currentConfig
156
+ }), {}),
157
+ ...vuePlugin.configs["flat/recommended"].map((config) => config.rules).reduce((accumulator, currentConfig) => ({
158
+ ...accumulator,
159
+ ...currentConfig
160
+ }), {}),
161
+ "vue/block-order": ["error", { order: [
162
+ "script",
163
+ "template",
164
+ "style"
165
+ ] }],
166
+ "vue/component-name-in-template-casing": ["error", "PascalCase"],
167
+ "vue/component-options-name-casing": ["error", "PascalCase"],
168
+ "vue/multi-word-component-names": "off",
169
+ "vue/block-tag-newline": ["error", {
170
+ multiline: "ignore",
171
+ singleline: "ignore"
172
+ }],
173
+ "vue/multiline-html-element-content-newline": ["error", {
174
+ allowEmptyLines: true,
175
+ ignores: ["pre", "textarea"]
176
+ }],
177
+ ...resolved.overrides
178
+ }
179
+ }];
180
+ }
181
+ //#endregion
182
+ //#region src/configs/typescript.ts
183
+ const typescriptDefaults = { files: [tsGlob] };
184
+ /**
185
+ * Extract and merge rules from a compatible config array.
186
+ * @param configs - Array of compatible ESLint configs
187
+ * @returns Merged rules object from all configs
188
+ */
189
+ function extractRules(configs) {
190
+ return Object.assign({}, ...configs.map((config) => config.rules || {}));
191
+ }
192
+ /**
193
+ * Typescript linting via `typescript-eslint`.
194
+ * @param options - TypeScript configuration options
195
+ * @returns Promise resolving to TypeScript ESLint config items
196
+ */
197
+ async function typescript(options) {
198
+ const resolved = defu(options, typescriptDefaults);
199
+ const tsEsLint = await getModuleDefault(import("typescript-eslint"));
200
+ return [{
201
+ name: "favorodera/typescript/rules",
202
+ files: resolved.files,
203
+ plugins: { ts: tsEsLint.plugin },
204
+ languageOptions: {
205
+ parser: tsEsLint.parser,
206
+ parserOptions: { sourceType: "module" }
207
+ },
208
+ rules: {
209
+ ...renameRules(extractRules(tsEsLint.configs.strict), { "@typescript-eslint": "ts" }),
210
+ ...renameRules(extractRules(tsEsLint.configs.stylistic), { "@typescript-eslint": "ts" }),
211
+ "ts/consistent-type-imports": ["error", { prefer: "type-imports" }],
212
+ "ts/no-empty-object-type": ["error", { allowInterfaces: "with-single-extends" }],
213
+ "ts/array-type": ["error", { default: "array" }],
214
+ ...resolved.overrides
215
+ }
216
+ }];
217
+ }
218
+ //#endregion
219
+ //#region src/configs/ignores.ts
220
+ const defaultPatterns = ignoresGlob;
221
+ /**
222
+ * Globs for ignoring files and directories from ESLint scanning.
223
+ * @param patterns - Additional ignore patterns or a function to modify the defaults.
224
+ * @returns An array containing the ignore flat config item.
225
+ */
226
+ function ignores(patterns = []) {
227
+ return [{
228
+ name: "favorodera/ignores",
229
+ ignores: typeof patterns === "function" ? patterns(defaultPatterns) : [...defaultPatterns, ...patterns]
230
+ }];
231
+ }
232
+ //#endregion
233
+ //#region src/configs/stylistic.ts
234
+ const stylisticDefaults = {
235
+ indent: 2,
236
+ experimental: false,
237
+ quotes: "single",
238
+ semi: false,
239
+ jsx: false
240
+ };
241
+ /**
242
+ * Code style via `@stylistic/eslint-plugin`.
243
+ * @param options - Stylistic configuration options
244
+ * @returns Promise resolving to stylistic ESLint config items
245
+ */
246
+ async function stylistic(options) {
247
+ const resolved = defu(options, stylisticDefaults);
248
+ const stylePlugin = await getModuleDefault(import("@stylistic/eslint-plugin"));
249
+ const customizedStyleConfig = stylePlugin.configs.customize({
250
+ pluginName: "style",
251
+ ...resolved
252
+ });
253
+ return [{
254
+ name: "favorodera/stylistic/rules",
255
+ plugins: { style: stylePlugin },
256
+ rules: {
257
+ ...customizedStyleConfig.rules,
258
+ "style/quotes": [
259
+ "error",
260
+ "single",
261
+ { avoidEscape: true }
262
+ ],
263
+ "style/no-multiple-empty-lines": ["error", {
264
+ max: 2,
265
+ maxEOF: 2,
266
+ maxBOF: 0
267
+ }],
268
+ "style/padded-blocks": "off",
269
+ "style/no-trailing-spaces": ["error", { skipBlankLines: true }],
270
+ "style/brace-style": "off",
271
+ "style/generator-star-spacing": ["error", {
272
+ after: true,
273
+ before: false
274
+ }],
275
+ "style/yield-star-spacing": ["error", {
276
+ after: true,
277
+ before: false
278
+ }],
279
+ ...resolved.overrides
280
+ }
281
+ }];
282
+ }
283
+ //#endregion
284
+ //#region src/configs/tailwind.ts
285
+ const tailwindDefaults = {
286
+ files: [
287
+ jsGlob,
288
+ tsGlob,
289
+ vueGlob
290
+ ],
291
+ settings: { detectComponentClasses: true }
292
+ };
293
+ /**
294
+ * Tailwind linting via `eslint-plugin-better-tailwindcss`.
295
+ * @param options - Tailwind configuration options
296
+ * @returns Promise resolving to Tailwind ESLint config items
297
+ */
298
+ async function tailwind(options) {
299
+ const resolved = defu(options, tailwindDefaults);
300
+ const tailwindPlugin = await getModuleDefault(import("eslint-plugin-better-tailwindcss"));
301
+ return [{
302
+ name: "favorodera/tailwind/rules",
303
+ plugins: { tailwind: tailwindPlugin },
304
+ files: resolved.files,
305
+ settings: { tailwindcss: resolved.settings },
306
+ rules: {
307
+ ...renameRules(tailwindPlugin.configs["recommended-error"].rules, { "better-tailwindcss": "tailwind" }),
308
+ ...renameRules(tailwindPlugin.configs["stylistic-error"].rules, { "better-tailwindcss": "tailwind" }),
309
+ "tailwind/no-unregistered-classes": "off",
310
+ "tailwind/enforce-consistent-line-wrapping": ["error", { group: "emptyLine" }],
311
+ ...resolved.overrides
312
+ }
313
+ }];
314
+ }
315
+ //#endregion
316
+ //#region src/configs/comments.ts
317
+ const commentsDefaults = { files: [
318
+ jsGlob,
319
+ tsGlob,
320
+ vueGlob
321
+ ] };
322
+ /**
323
+ * Comments linting via `@eslint-community/eslint-plugin-eslint-comments`
324
+ * @param options - Comments configuration options
325
+ * @returns Promise resolving to comments ESLint config items
326
+ */
327
+ async function comments(options) {
328
+ const resolved = defu(options, commentsDefaults);
329
+ const commentsPlugin = await getModuleDefault(import("@eslint-community/eslint-plugin-eslint-comments"));
330
+ return [{
331
+ name: "favorodera/comments/rules",
332
+ files: resolved.files,
333
+ plugins: { comments: commentsPlugin },
334
+ rules: {
335
+ ...renameRules(commentsPlugin.configs.recommended?.rules || {}, { "@eslint-community/eslint-comments": "comments" }),
336
+ "comments/no-aggregating-enable": "error",
337
+ "comments/no-duplicate-disable": "error",
338
+ "comments/no-unlimited-disable": "error",
339
+ "comments/no-unused-enable": "error",
340
+ ...resolved.overrides
341
+ }
342
+ }];
343
+ }
344
+ //#endregion
345
+ //#region src/configs/imports.ts
346
+ const importsDefaults = { files: [
347
+ jsGlob,
348
+ tsGlob,
349
+ vueGlob
350
+ ] };
351
+ /**
352
+ * Imports & unused imports linting via `eslint-plugin-import-lite` and `eslint-plugin-unused-imports`.
353
+ * @param options - Imports & unused imports configuration options
354
+ * @returns Promise resolving to imports & unused imports ESLint config items
355
+ */
356
+ async function imports(options) {
357
+ const resolved = defu(options, importsDefaults);
358
+ const [importPlugin, unusedImportsPlugin] = await Promise.all([getModuleDefault(import("eslint-plugin-import-lite")), getModuleDefault(import("eslint-plugin-unused-imports"))]);
359
+ return [{
360
+ name: "favorodera/imports/rules",
361
+ files: resolved.files,
362
+ plugins: {
363
+ "import": importPlugin,
364
+ "unused-imports": unusedImportsPlugin
365
+ },
366
+ rules: {
367
+ ...renameRules(importPlugin.configs.recommended?.rules || {}, { "import-lite": "import" }),
368
+ "import/consistent-type-specifier-style": ["error", "top-level"],
369
+ "import/first": "error",
370
+ "import/no-duplicates": "error",
371
+ "import/no-mutable-exports": "error",
372
+ "import/no-named-default": "error",
373
+ "import/newline-after-import": ["error", { count: 1 }],
374
+ "unused-imports/no-unused-imports": "error",
375
+ "unused-imports/no-unused-vars": ["error", {
376
+ args: "after-used",
377
+ argsIgnorePattern: "^_",
378
+ ignoreRestSiblings: true,
379
+ vars: "all",
380
+ varsIgnorePattern: "^_"
381
+ }],
382
+ ...resolved.overrides
383
+ }
384
+ }];
385
+ }
386
+ //#endregion
387
+ //#region src/configs/markdown.ts
388
+ const markdownDefaults = {
389
+ files: [mdGlob],
390
+ gfm: true
391
+ };
392
+ /**
393
+ * Markdown linting via `@eslint/markdown`.
394
+ * @param options - Markdown configuration options
395
+ * @returns Promise resolving to Markdown ESLint config items
396
+ */
397
+ async function markdown(options) {
398
+ const resolved = defu(options, markdownDefaults);
399
+ const markdownPlugin = await getModuleDefault(import("@eslint/markdown"));
400
+ return [{
401
+ name: "favorodera/markdown/rules",
402
+ files: resolved.files,
403
+ plugins: { md: markdownPlugin },
404
+ processor: mergeProcessors([markdownPlugin.processors?.markdown, processorPassThrough]),
405
+ language: resolved.gfm ? "md/gfm" : "md/commonmark",
406
+ rules: {
407
+ ...renameRules(markdownPlugin.configs.recommended[0]?.rules || {}, { markdown: "md" }),
408
+ "md/fenced-code-language": "off",
409
+ "md/no-missing-label-refs": "off",
410
+ ...resolved.overrides
411
+ }
412
+ }];
413
+ }
414
+ //#endregion
415
+ //#region src/configs/javascript.ts
416
+ const javascriptDefaults = { files: [
417
+ jsGlob,
418
+ tsGlob,
419
+ vueGlob
420
+ ] };
421
+ /**
422
+ * Javascript linting via `eslint`
423
+ * @param options - Javascript configuration options
424
+ * @returns Promise resolving to javascript ESLint config items
425
+ */
426
+ async function javascript(options) {
427
+ const resolved = defu(options, javascriptDefaults);
428
+ const jsPlugin = await getModuleDefault(import("@eslint/js"));
429
+ return [{
430
+ name: "favorodera/javascript/rules",
431
+ files: resolved.files,
432
+ languageOptions: {
433
+ ecmaVersion: "latest",
434
+ sourceType: "module",
435
+ globals: {
436
+ ...globals.browser,
437
+ ...globals.es2021,
438
+ ...globals.node,
439
+ document: "readonly",
440
+ navigator: "readonly",
441
+ window: "readonly"
442
+ }
443
+ },
444
+ linterOptions: { reportUnusedDisableDirectives: true },
445
+ plugins: { js: jsPlugin },
446
+ rules: {
447
+ ...jsPlugin.configs.recommended.rules,
448
+ "accessor-pairs": ["error", {
449
+ enforceForClassMembers: true,
450
+ setWithoutGet: true
451
+ }],
452
+ "array-callback-return": "error",
453
+ "block-scoped-var": "error",
454
+ "constructor-super": "error",
455
+ "default-case-last": "error",
456
+ "dot-notation": ["error", { allowKeywords: true }],
457
+ "eqeqeq": ["error", "smart"],
458
+ "new-cap": ["error", {
459
+ capIsNew: false,
460
+ newIsCap: true,
461
+ properties: true
462
+ }],
463
+ "no-alert": "error",
464
+ "no-array-constructor": "error",
465
+ "no-async-promise-executor": "error",
466
+ "no-caller": "error",
467
+ "no-case-declarations": "error",
468
+ "no-class-assign": "error",
469
+ "no-compare-neg-zero": "error",
470
+ "no-cond-assign": ["error", "always"],
471
+ "no-console": ["error", { allow: ["warn", "error"] }],
472
+ "no-const-assign": "error",
473
+ "no-control-regex": "error",
474
+ "no-debugger": "error",
475
+ "no-delete-var": "error",
476
+ "no-dupe-args": "error",
477
+ "no-dupe-class-members": "error",
478
+ "no-dupe-keys": "error",
479
+ "no-duplicate-case": "error",
480
+ "no-empty": ["error", { allowEmptyCatch: true }],
481
+ "no-empty-character-class": "error",
482
+ "no-empty-pattern": "error",
483
+ "no-eval": "error",
484
+ "no-ex-assign": "error",
485
+ "no-extend-native": "error",
486
+ "no-extra-bind": "error",
487
+ "no-extra-boolean-cast": "error",
488
+ "no-fallthrough": "error",
489
+ "no-func-assign": "error",
490
+ "no-global-assign": "error",
491
+ "no-implied-eval": "error",
492
+ "no-import-assign": "error",
493
+ "no-invalid-regexp": "error",
494
+ "no-irregular-whitespace": "error",
495
+ "no-iterator": "error",
496
+ "no-labels": ["error", {
497
+ allowLoop: false,
498
+ allowSwitch: false
499
+ }],
500
+ "no-lone-blocks": "error",
501
+ "no-loss-of-precision": "error",
502
+ "no-misleading-character-class": "error",
503
+ "no-multi-str": "error",
504
+ "no-new": "error",
505
+ "no-new-func": "error",
506
+ "no-new-native-nonconstructor": "error",
507
+ "no-new-wrappers": "error",
508
+ "no-obj-calls": "error",
509
+ "no-octal": "error",
510
+ "no-octal-escape": "error",
511
+ "no-proto": "error",
512
+ "no-prototype-builtins": "error",
513
+ "no-redeclare": ["error", { builtinGlobals: false }],
514
+ "no-regex-spaces": "error",
515
+ "no-restricted-globals": [
516
+ "error",
517
+ {
518
+ message: "Use `globalThis` instead.",
519
+ name: "global"
520
+ },
521
+ {
522
+ message: "Use `globalThis` instead.",
523
+ name: "self"
524
+ }
525
+ ],
526
+ "no-restricted-properties": [
527
+ "error",
528
+ {
529
+ message: "Use `Object.getPrototypeOf` or `Object.setPrototypeOf` instead.",
530
+ property: "__proto__"
531
+ },
532
+ {
533
+ message: "Use `Object.defineProperty` instead.",
534
+ property: "__defineGetter__"
535
+ },
536
+ {
537
+ message: "Use `Object.defineProperty` instead.",
538
+ property: "__defineSetter__"
539
+ },
540
+ {
541
+ message: "Use `Object.getOwnPropertyDescriptor` instead.",
542
+ property: "__lookupGetter__"
543
+ },
544
+ {
545
+ message: "Use `Object.getOwnPropertyDescriptor` instead.",
546
+ property: "__lookupSetter__"
547
+ }
548
+ ],
549
+ "no-restricted-syntax": [
550
+ "error",
551
+ "TSEnumDeclaration[const=true]",
552
+ "TSExportAssignment"
553
+ ],
554
+ "no-self-assign": ["error", { props: true }],
555
+ "no-self-compare": "error",
556
+ "no-sequences": "error",
557
+ "no-shadow-restricted-names": "error",
558
+ "no-sparse-arrays": "error",
559
+ "no-template-curly-in-string": "error",
560
+ "no-this-before-super": "error",
561
+ "no-throw-literal": "error",
562
+ "no-undef": "error",
563
+ "no-undef-init": "error",
564
+ "no-unexpected-multiline": "error",
565
+ "no-unmodified-loop-condition": "error",
566
+ "no-unneeded-ternary": ["error", { defaultAssignment: false }],
567
+ "no-unreachable": "error",
568
+ "no-unreachable-loop": "error",
569
+ "no-unsafe-finally": "error",
570
+ "no-unsafe-negation": "error",
571
+ "no-unused-expressions": ["error", {
572
+ allowShortCircuit: true,
573
+ allowTaggedTemplates: true,
574
+ allowTernary: true
575
+ }],
576
+ "no-unused-vars": ["error", {
577
+ args: "none",
578
+ caughtErrors: "none",
579
+ ignoreRestSiblings: true,
580
+ vars: "all"
581
+ }],
582
+ "no-use-before-define": ["error", {
583
+ classes: false,
584
+ functions: false,
585
+ variables: true
586
+ }],
587
+ "no-useless-backreference": "error",
588
+ "no-useless-call": "error",
589
+ "no-useless-catch": "error",
590
+ "no-useless-computed-key": "error",
591
+ "no-useless-constructor": "error",
592
+ "no-useless-rename": "error",
593
+ "no-useless-return": "error",
594
+ "no-var": "error",
595
+ "no-with": "error",
596
+ "object-shorthand": [
597
+ "error",
598
+ "always",
599
+ {
600
+ avoidQuotes: true,
601
+ ignoreConstructors: false
602
+ }
603
+ ],
604
+ "one-var": ["error", { initialized: "never" }],
605
+ "prefer-arrow-callback": ["error", {
606
+ allowNamedFunctions: false,
607
+ allowUnboundThis: true
608
+ }],
609
+ "prefer-const": ["error", {
610
+ destructuring: "all",
611
+ ignoreReadBeforeAssign: true
612
+ }],
613
+ "prefer-exponentiation-operator": "error",
614
+ "prefer-promise-reject-errors": "error",
615
+ "prefer-regex-literals": ["error", { disallowRedundantWrapping: true }],
616
+ "prefer-rest-params": "error",
617
+ "prefer-spread": "error",
618
+ "prefer-template": "error",
619
+ "symbol-description": "error",
620
+ "unicode-bom": ["error", "never"],
621
+ "use-isnan": ["error", {
622
+ enforceForIndexOf: true,
623
+ enforceForSwitchCase: true
624
+ }],
625
+ "valid-typeof": ["error", { requireStringLiterals: true }],
626
+ "vars-on-top": "error",
627
+ "yoda": ["error", "never"],
628
+ ...resolved.overrides
629
+ }
630
+ }];
631
+ }
632
+ //#endregion
633
+ //#region src/factory.ts
634
+ /**
635
+ * Factory to create a flat ESLint config
636
+ * @param options - Configuration options for the ESLint config
637
+ * @returns Flat ESLint config composer
638
+ */
639
+ function factory(options = {}) {
640
+ const configs = [];
641
+ configs.push(ignores(options.ignores));
642
+ const vueOptions = resolveOptions(options.vue, {});
643
+ const typescriptOptions = resolveOptions(options.typescript, {});
644
+ const stylisticOptions = resolveOptions(options.stylistic, {});
645
+ const tailwindOptions = resolveOptions(options.tailwind, {});
646
+ const commentsOptions = resolveOptions(options.comments, {});
647
+ const importsOptions = resolveOptions(options.imports, {});
648
+ const markdownOptions = resolveOptions(options.markdown, {});
649
+ const javascriptOptions = resolveOptions(options.javascript, {});
650
+ if (vueOptions) configs.push(vue(vueOptions));
651
+ if (typescriptOptions) configs.push(typescript(typescriptOptions));
652
+ if (stylisticOptions) configs.push(stylistic(stylisticOptions));
653
+ if (tailwindOptions) configs.push(tailwind(tailwindOptions));
654
+ if (commentsOptions) configs.push(comments(commentsOptions));
655
+ if (importsOptions) configs.push(imports(importsOptions));
656
+ if (markdownOptions) configs.push(markdown(markdownOptions));
657
+ if (javascriptOptions) configs.push(javascript(javascriptOptions));
658
+ let composer = new FlatConfigComposer();
659
+ composer = composer.append(...configs);
660
+ return composer;
661
+ }
662
+ //#endregion
663
+ export { factory, getModuleDefault, renameRules };