@favorodera/eslint-config 0.0.2 → 0.0.4

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.cjs CHANGED
@@ -29,17 +29,31 @@ eslint_processor_vue_blocks = __toESM(eslint_processor_vue_blocks, 1);
29
29
  let globals = require("globals");
30
30
  globals = __toESM(globals, 1);
31
31
  //#region src/globs.ts
32
- /** Glob pattern for JavaScript linting */
32
+ /** Glob pattern for matching JavaScript files */
33
33
  const jsGlob = "**/*.{js,cjs,mjs}";
34
- /** Glob pattern for TypeScript linting */
34
+ /** Glob pattern for matching TypeScript files */
35
35
  const tsGlob = "**/*.{ts,cts,mts}";
36
- /** Glob pattern for Vue linting */
36
+ /** Glob pattern for matching Vue single-file components */
37
37
  const vueGlob = "**/*.vue";
38
- /** Glob pattern for Markdown linting */
38
+ /** Glob pattern for matching Markdown files */
39
39
  const mdGlob = "**/*.md";
40
+ /** Glob pattern for matching virtual files extracted from Markdown */
41
+ const mdInMdGlob = "**/*.md/*.md";
42
+ /** Glob pattern for matching code blocks embedded in Markdown files */
43
+ const codeInMdGlob = "**/*.md/**/*.{js,cjs,mjs,ts,cts,mts,vue}";
44
+ /** Glob pattern for matching JSON files */
45
+ const jsonGlob = "**/*.json";
46
+ /** Glob pattern for matching JSON5 files */
47
+ const json5Glob = "**/*.json5";
48
+ /** Glob pattern for matching JSON with Comments files */
49
+ const jsoncGlob = "**/*.jsonc";
50
+ /** Glob patterns for matching TypeScript configuration files */
51
+ const tsConfigGlob = ["**/tsconfig.json", "**/tsconfig.*.json"];
52
+ /** Glob pattern for matching package.json files */
53
+ const packageJsonGlob = "**/package.json";
40
54
  /**
41
- * Default glob patterns for files and directories to ignore
42
- * Includes common build outputs, dependencies, caches, and temporary files
55
+ * Common glob patterns for files and directories that should be ignored by ESLint.
56
+ * Includes node_modules, build outputs, lock files, temporary files, and tool-specific caches.
43
57
  */
44
58
  const ignoresGlob = [
45
59
  "**/node_modules/**",
@@ -86,9 +100,9 @@ const ignoresGlob = [
86
100
  *
87
101
  * Handles both ESM modules (which wrap exports under `.default`) and
88
102
  * CJS / plain-object modules uniformly.
89
- *
90
- * @param module - A module or a promise that resolves to one
91
- * @returns The `.default` export if it exists, otherwise the module itself
103
+ * @template TModule The type of the module being imported.
104
+ * @param module A module or a promise that resolves to one.
105
+ * @returns The `.default` export if it exists, otherwise the module itself.
92
106
  */
93
107
  async function importModule(module) {
94
108
  const resolved = await module;
@@ -98,15 +112,23 @@ async function importModule(module) {
98
112
  /**
99
113
  * Normalize boolean or options value into merged options or null.
100
114
  * Returns null when the input is false or undefined.
101
- *
102
- * @param value - boolean, options object, or undefined
103
- * @param defaults - defaults to merge with
104
- * @returns merged options or false
115
+ * @template TOptions The type of the options object.
116
+ * @param value The configuration value, which can be a boolean, an options object, or undefined.
117
+ * @param defaults The default options to merge with if `value` is true or an object.
118
+ * @returns The merged options object, or false if the feature is disabled.
105
119
  */
106
120
  function resolveOptions(value, defaults) {
107
121
  if (!value) return false;
108
122
  return (0, defu.defu)(value === true ? {} : value, defaults);
109
123
  }
124
+ /**
125
+ * Extracts and merges the rules from multiple ESLint configuration arrays.
126
+ * @param configArrays Rest parameter representing multiple arrays of ESLint flat config items.
127
+ * @returns A single object containing all the merged rules from the provided configurations.
128
+ */
129
+ function extractRules(...configArrays) {
130
+ return Object.assign({}, ...configArrays.flat().map((config) => config?.rules || {}));
131
+ }
110
132
  //#endregion
111
133
  //#region src/configs/vue.ts
112
134
  const sfcBlocksDefaults = { blocks: {
@@ -118,6 +140,12 @@ const vueDefaults = {
118
140
  files: [vueGlob],
119
141
  sfcBlocks: sfcBlocksDefaults
120
142
  };
143
+ /**
144
+ * Constructs the flat config items for Vue linting, setting up the custom template parser,
145
+ * Vue block processors, and rules to enforce recommended component syntax.
146
+ * @param options Vue configuration options.
147
+ * @returns Promise resolving to Vue ESLint config items.
148
+ */
121
149
  async function vue(options) {
122
150
  const resolved = (0, defu.defu)(options, vueDefaults);
123
151
  const sfcBlocks = resolveOptions(resolved.sfcBlocks, sfcBlocksDefaults);
@@ -126,32 +154,31 @@ async function vue(options) {
126
154
  importModule(import("vue-eslint-parser")),
127
155
  importModule(import("typescript-eslint"))
128
156
  ]);
129
- const inheritedRules = Object.assign({}, ...[
130
- ...vuePlugin.configs["flat/essential"],
131
- ...vuePlugin.configs["flat/strongly-recommended"],
132
- ...vuePlugin.configs["flat/recommended"]
133
- ].map((config) => config?.rules || {}));
157
+ const baseRules = extractRules(vuePlugin.configs["flat/essential"], vuePlugin.configs["flat/strongly-recommended"], vuePlugin.configs["flat/recommended"]);
158
+ const processor = sfcBlocks === false ? vuePlugin.processors[".vue"] : (0, eslint_merge_processors.mergeProcessors)([vuePlugin.processors[".vue"], (0, eslint_processor_vue_blocks.default)(sfcBlocks)]);
134
159
  return [{
135
- name: "favorodera/vue",
160
+ name: "favorodera/vue/setup",
136
161
  plugins: { vue: vuePlugin },
162
+ languageOptions: { globals: {
163
+ computed: "readonly",
164
+ defineEmits: "readonly",
165
+ defineExpose: "readonly",
166
+ defineProps: "readonly",
167
+ onMounted: "readonly",
168
+ onUnmounted: "readonly",
169
+ reactive: "readonly",
170
+ ref: "readonly",
171
+ shallowReactive: "readonly",
172
+ shallowRef: "readonly",
173
+ toRef: "readonly",
174
+ toRefs: "readonly",
175
+ watch: "readonly",
176
+ watchEffect: "readonly"
177
+ } }
178
+ }, {
179
+ name: "favorodera/vue/rules",
137
180
  files: resolved.files,
138
181
  languageOptions: {
139
- globals: {
140
- computed: "readonly",
141
- defineEmits: "readonly",
142
- defineExpose: "readonly",
143
- defineProps: "readonly",
144
- onMounted: "readonly",
145
- onUnmounted: "readonly",
146
- reactive: "readonly",
147
- ref: "readonly",
148
- shallowReactive: "readonly",
149
- shallowRef: "readonly",
150
- toRef: "readonly",
151
- toRefs: "readonly",
152
- watch: "readonly",
153
- watchEffect: "readonly"
154
- },
155
182
  parser: vueParser,
156
183
  parserOptions: {
157
184
  parser: tsEsLint.parser,
@@ -159,9 +186,9 @@ async function vue(options) {
159
186
  sourceType: "module"
160
187
  }
161
188
  },
162
- processor: sfcBlocks === false ? vuePlugin.processors[".vue"] : (0, eslint_merge_processors.mergeProcessors)([vuePlugin.processors[".vue"], (0, eslint_processor_vue_blocks.default)(sfcBlocks)]),
189
+ processor,
163
190
  rules: {
164
- ...inheritedRules,
191
+ ...baseRules,
165
192
  "vue/block-order": ["error", { order: [
166
193
  "script",
167
194
  "template",
@@ -187,7 +214,7 @@ async function vue(options) {
187
214
  const defaultPatterns = ignoresGlob;
188
215
  /**
189
216
  * Globs for ignoring files and directories from ESLint scanning.
190
- * @param patterns - Additional ignore patterns or a function to modify the defaults.
217
+ * @param patterns Additional ignore patterns or a function to modify the defaults.
191
218
  * @returns An array containing the ignore flat config item.
192
219
  */
193
220
  function ignores(patterns = []) {
@@ -203,19 +230,27 @@ const importsDefaults = { files: [
203
230
  tsGlob,
204
231
  vueGlob
205
232
  ] };
233
+ /**
234
+ * Constructs the flat config items for imports linting, providing plugin setup and
235
+ * specific rules to enforce consistent import ordering and unused variable checks.
236
+ * @param options Configuration options for imports linting.
237
+ * @returns Promise resolving to imports ESLint config items.
238
+ */
206
239
  async function imports(options) {
207
240
  const resolved = (0, defu.defu)(options, importsDefaults);
208
241
  const [importPlugin, unusedImportsPlugin] = await Promise.all([importModule(import("eslint-plugin-import-lite")), importModule(import("eslint-plugin-unused-imports"))]);
209
- const inheritedRules = importPlugin.configs.recommended?.rules || {};
242
+ const baseRules = importPlugin.configs.recommended?.rules || {};
210
243
  return [{
211
- name: "favorodera/imports",
212
- files: resolved.files,
244
+ name: "favorodera/imports/setup",
213
245
  plugins: {
214
246
  "import": importPlugin,
215
247
  "unused-imports": unusedImportsPlugin
216
- },
248
+ }
249
+ }, {
250
+ name: "favorodera/imports/rules",
251
+ files: resolved.files,
217
252
  rules: {
218
- ...(0, eslint_flat_config_utils.renamePluginsInRules)(inheritedRules, { "import-lite": "import" }),
253
+ ...(0, eslint_flat_config_utils.renamePluginsInRules)(baseRules, { "import-lite": "import" }),
219
254
  "import/consistent-type-specifier-style": ["error", "top-level"],
220
255
  "import/first": "error",
221
256
  "import/no-duplicates": "error",
@@ -242,16 +277,16 @@ const javascriptDefaults = { files: [
242
277
  vueGlob
243
278
  ] };
244
279
  /**
245
- * Javascript linting via `eslint`
246
- * @param options - Javascript configuration options
247
- * @returns Promise resolving to javascript ESLint config items
280
+ * Constructs the flat config items for core JavaScript linting, setting up the required
281
+ * language options, globals, and recommended baseline rules.
282
+ * @param options Javascript configuration options.
283
+ * @returns Promise resolving to javascript ESLint config items.
248
284
  */
249
285
  async function javascript(options) {
250
286
  const resolved = (0, defu.defu)(options, javascriptDefaults);
251
- const inheritedRules = (await importModule(import("@eslint/js"))).configs.recommended.rules;
287
+ const baseRules = (await importModule(import("@eslint/js"))).configs.recommended.rules;
252
288
  return [{
253
- name: "favorodera/javascript",
254
- files: resolved.files,
289
+ name: "favorodera/javascript/setup",
255
290
  languageOptions: {
256
291
  ecmaVersion: "latest",
257
292
  sourceType: "module",
@@ -264,9 +299,12 @@ async function javascript(options) {
264
299
  window: "readonly"
265
300
  }
266
301
  },
267
- linterOptions: { reportUnusedDisableDirectives: true },
302
+ linterOptions: { reportUnusedDisableDirectives: true }
303
+ }, {
304
+ name: "favorodera/javascript/rules",
305
+ files: resolved.files,
268
306
  rules: {
269
- ...inheritedRules,
307
+ ...baseRules,
270
308
  "accessor-pairs": ["error", {
271
309
  enforceForClassMembers: true,
272
310
  setWithoutGet: true
@@ -283,23 +321,66 @@ const markdownDefaults = {
283
321
  files: [mdGlob],
284
322
  gfm: true
285
323
  };
324
+ /**
325
+ * Constructs the flat config items for Markdown linting, extracting and linting
326
+ * embedded code blocks within the document according to specified rules.
327
+ * @param options Markdown configuration options.
328
+ * @returns Promise resolving to Markdown ESLint config items.
329
+ */
286
330
  async function markdown(options) {
287
331
  const resolved = (0, defu.defu)(options, markdownDefaults);
288
332
  const markdownPlugin = await importModule(import("@eslint/markdown"));
289
- const inheritedRules = Object.assign({}, ...[...markdownPlugin.configs.recommended].map((config) => config?.rules || {}));
290
- return [{
291
- name: "favorodera/markdown",
292
- files: resolved.files,
293
- plugins: { md: markdownPlugin },
294
- processor: (0, eslint_merge_processors.mergeProcessors)([markdownPlugin.processors?.markdown, eslint_merge_processors.processorPassThrough]),
295
- language: resolved.gfm ? "md/gfm" : "md/commonmark",
296
- rules: {
297
- ...(0, eslint_flat_config_utils.renamePluginsInRules)(inheritedRules, { markdown: "md" }),
298
- "md/fenced-code-language": "off",
299
- "md/no-missing-label-refs": "off",
300
- ...resolved.overrides
333
+ const baseRules = extractRules(markdownPlugin.configs.recommended);
334
+ return [
335
+ {
336
+ name: "favorodera/markdown/setup",
337
+ plugins: { md: markdownPlugin }
338
+ },
339
+ {
340
+ name: "favorodera/markdown/rules",
341
+ files: resolved.files,
342
+ language: resolved.gfm ? "md/gfm" : "md/commonmark",
343
+ ignores: [mdInMdGlob],
344
+ processor: (0, eslint_merge_processors.mergeProcessors)([markdownPlugin.processors?.markdown, eslint_merge_processors.processorPassThrough]),
345
+ rules: {
346
+ ...(0, eslint_flat_config_utils.renamePluginsInRules)(baseRules, { markdown: "md" }),
347
+ "md/fenced-code-language": "off",
348
+ "md/no-missing-label-refs": "off",
349
+ ...resolved.overrides
350
+ }
351
+ },
352
+ {
353
+ name: "favorodera/markdown/disables/code",
354
+ files: [codeInMdGlob],
355
+ languageOptions: { parserOptions: { ecmaFeatures: { impliedStrict: true } } },
356
+ rules: {
357
+ "no-alert": "off",
358
+ "no-console": "off",
359
+ "no-labels": "off",
360
+ "no-lone-blocks": "off",
361
+ "no-restricted-syntax": "off",
362
+ "no-undef": "off",
363
+ "no-unused-expressions": "off",
364
+ "no-unused-labels": "off",
365
+ "no-unused-vars": "off",
366
+ "node/prefer-global/process": "off",
367
+ "style/comma-dangle": "off",
368
+ "style/eol-last": "off",
369
+ "style/padding-line-between-statements": "off",
370
+ "ts/consistent-type-imports": "off",
371
+ "ts/explicit-function-return-type": "off",
372
+ "ts/no-namespace": "off",
373
+ "ts/no-redeclare": "off",
374
+ "ts/no-require-imports": "off",
375
+ "ts/no-unused-expressions": "off",
376
+ "ts/no-unused-vars": "off",
377
+ "ts/no-use-before-define": "off",
378
+ "unicode-bom": "off",
379
+ "unused-imports/no-unused-imports": "off",
380
+ "unused-imports/no-unused-vars": "off"
381
+ }
301
382
  }
302
- }];
383
+ ];
303
384
  }
304
385
  //#endregion
305
386
  //#region src/configs/stylistic.ts
@@ -317,19 +398,27 @@ const stylisticDefaults = {
317
398
  vueGlob
318
399
  ]
319
400
  };
401
+ /**
402
+ * Constructs the flat config items for Stylistic linting, applying customized
403
+ * formatting settings such as quotes, indentation, and spacing.
404
+ * @param options Stylistic configuration options.
405
+ * @returns Promise resolving to stylistic ESLint config items.
406
+ */
320
407
  async function stylistic(options) {
321
408
  const resolved = (0, defu.defu)(options, stylisticDefaults);
322
- const config = (await importModule(import("@stylistic/eslint-plugin"))).configs.customize({
409
+ const stylePlugin = await importModule(import("@stylistic/eslint-plugin"));
410
+ const baseRules = stylePlugin.configs.customize({
323
411
  pluginName: "style",
324
412
  ...resolved.settings
325
- });
326
- const inheritedRules = config?.rules || {};
413
+ })?.rules || {};
327
414
  return [{
328
- ...config,
329
- name: "favorodera/stylistic",
415
+ name: "favorodera/stylistic/setup",
416
+ plugins: { style: stylePlugin }
417
+ }, {
418
+ name: "favorodera/stylistic/rules",
330
419
  files: resolved.files,
331
420
  rules: {
332
- ...inheritedRules,
421
+ ...baseRules,
333
422
  "style/quotes": [
334
423
  "error",
335
424
  "single",
@@ -366,24 +455,27 @@ const tailwindDefaults = {
366
455
  settings: { detectComponentClasses: true }
367
456
  };
368
457
  /**
369
- * Tailwind linting via `eslint-plugin-better-tailwindcss`.
370
- * @param options - Tailwind configuration options
371
- * @returns Promise resolving to Tailwind ESLint config items
458
+ * Constructs the flat config items for Tailwind CSS linting, providing custom settings
459
+ * to parse and lint utility classes, and enforcing consistent ordering.
460
+ * @param options Tailwind configuration options.
461
+ * @returns Promise resolving to Tailwind ESLint config items.
372
462
  */
373
463
  async function tailwind(options) {
374
464
  const resolved = (0, defu.defu)(options, tailwindDefaults);
375
465
  const tailwindPlugin = await importModule(import("eslint-plugin-better-tailwindcss"));
376
- const inheritedRules = {
466
+ const baseRules = {
377
467
  ...tailwindPlugin.configs["recommended-error"].rules,
378
468
  ...tailwindPlugin.configs["stylistic-error"].rules
379
469
  };
380
470
  return [{
381
- name: "favorodera/tailwind",
382
- files: resolved.files,
471
+ name: "favorodera/tailwind/setup",
383
472
  plugins: { tailwind: tailwindPlugin },
384
- settings: { tailwindcss: resolved.settings },
473
+ settings: { tailwindcss: resolved.settings }
474
+ }, {
475
+ name: "favorodera/tailwind/rules",
476
+ files: resolved.files,
385
477
  rules: {
386
- ...(0, eslint_flat_config_utils.renamePluginsInRules)(inheritedRules, { "better-tailwindcss": "tailwind" }),
478
+ ...(0, eslint_flat_config_utils.renamePluginsInRules)(baseRules, { "better-tailwindcss": "tailwind" }),
387
479
  "tailwind/no-unregistered-classes": "off",
388
480
  "tailwind/enforce-consistent-line-wrapping": ["error", { group: "emptyLine" }],
389
481
  ...resolved.overrides
@@ -394,27 +486,371 @@ async function tailwind(options) {
394
486
  //#region src/configs/typescript.ts
395
487
  const typescriptDefaults = { files: [tsGlob] };
396
488
  /**
397
- * Typescript linting via `typescript-eslint`.
398
- * @param options - TypeScript configuration options
399
- * @returns Array of TypeScript ESLint config items
489
+ * Constructs the flat config items for TypeScript linting, initializing the parser
490
+ * and extending the recommended and strict type-aware rule sets.
491
+ * @param options TypeScript configuration options.
492
+ * @returns Promise resolving to TypeScript ESLint config items.
400
493
  */
401
494
  async function typescript(options) {
402
495
  const resolved = (0, defu.defu)(options, typescriptDefaults);
403
496
  const tsEsLint = await importModule(import("typescript-eslint"));
404
- const inheritedRules = Object.assign({}, ...[...tsEsLint.configs.recommended, ...tsEsLint.configs.strict].map((config) => config?.rules || {}));
497
+ const baseRules = extractRules(tsEsLint.configs.recommended, tsEsLint.configs.strict);
405
498
  return [{
406
- name: "favorodera/typescript",
407
- plugins: { ts: tsEsLint.plugin },
499
+ name: "favorodera/typescript/setup",
500
+ plugins: { ts: tsEsLint.plugin }
501
+ }, {
502
+ name: "favorodera/typescript/rules",
503
+ files: resolved.files,
408
504
  languageOptions: {
409
505
  parser: tsEsLint.parser,
410
506
  parserOptions: { sourceType: "module" }
411
507
  },
412
- files: resolved.files,
413
508
  rules: {
414
- ...(0, eslint_flat_config_utils.renamePluginsInRules)(inheritedRules, { "@typescript-eslint": "ts" }),
509
+ ...(0, eslint_flat_config_utils.renamePluginsInRules)(baseRules, { "@typescript-eslint": "ts" }),
415
510
  "ts/consistent-type-imports": ["error", { prefer: "type-imports" }],
416
511
  "ts/no-empty-object-type": ["error", { allowInterfaces: "with-single-extends" }],
417
- "ts/array-type": ["error", { default: "array" }],
512
+ "ts/array-type": ["error", {
513
+ default: "generic",
514
+ readonly: "generic"
515
+ }],
516
+ ...resolved.overrides
517
+ }
518
+ }];
519
+ }
520
+ //#endregion
521
+ //#region src/configs/jsonc.ts
522
+ const jsoncDefaults = { files: [
523
+ json5Glob,
524
+ jsoncGlob,
525
+ jsonGlob
526
+ ] };
527
+ /**
528
+ * Constructs the flat config items for JSON, JSON5, and JSONC linting, setting up
529
+ * the custom parser, rule validations, and sorting rules for package.json/tsconfig.json.
530
+ * @param options JSONC configuration options.
531
+ * @returns Promise resolving to JSONC ESLint config items.
532
+ */
533
+ async function jsonc(options) {
534
+ const resolved = (0, defu.defu)(options, jsoncDefaults);
535
+ return [
536
+ {
537
+ name: "favorodera/jsonc/setup",
538
+ plugins: { jsonc: await importModule(import("eslint-plugin-jsonc")) }
539
+ },
540
+ {
541
+ name: "favorodera/jsonc/rules",
542
+ files: resolved.files,
543
+ language: "jsonc/x",
544
+ rules: {
545
+ "jsonc/no-bigint-literals": "error",
546
+ "jsonc/no-binary-expression": "error",
547
+ "jsonc/no-binary-numeric-literals": "error",
548
+ "jsonc/no-dupe-keys": "error",
549
+ "jsonc/no-escape-sequence-in-identifier": "error",
550
+ "jsonc/no-floating-decimal": "error",
551
+ "jsonc/no-hexadecimal-numeric-literals": "error",
552
+ "jsonc/no-infinity": "error",
553
+ "jsonc/no-multi-str": "error",
554
+ "jsonc/no-nan": "error",
555
+ "jsonc/no-number-props": "error",
556
+ "jsonc/no-numeric-separators": "error",
557
+ "jsonc/no-octal": "error",
558
+ "jsonc/no-octal-escape": "error",
559
+ "jsonc/no-octal-numeric-literals": "error",
560
+ "jsonc/no-parenthesized": "error",
561
+ "jsonc/no-plus-sign": "error",
562
+ "jsonc/no-regexp-literals": "error",
563
+ "jsonc/no-sparse-arrays": "error",
564
+ "jsonc/no-template-literals": "error",
565
+ "jsonc/no-undefined-value": "error",
566
+ "jsonc/no-unicode-codepoint-escapes": "error",
567
+ "jsonc/no-useless-escape": "error",
568
+ "jsonc/space-unary-ops": "error",
569
+ "jsonc/valid-json-number": "error",
570
+ "jsonc/vue-custom-block/no-parsing-error": "error",
571
+ "jsonc/array-bracket-spacing": ["error", "never"],
572
+ "jsonc/comma-dangle": ["error", "never"],
573
+ "jsonc/comma-style": ["error", "last"],
574
+ "jsonc/indent": ["error", 2],
575
+ "jsonc/key-spacing": ["error", {
576
+ afterColon: true,
577
+ beforeColon: false
578
+ }],
579
+ "jsonc/object-curly-newline": ["error", {
580
+ consistent: true,
581
+ multiline: true
582
+ }],
583
+ "jsonc/object-curly-spacing": ["error", "always"],
584
+ "jsonc/object-property-newline": ["error", { allowAllPropertiesOnSameLine: true }],
585
+ "jsonc/quote-props": "error",
586
+ "jsonc/quotes": "error",
587
+ ...resolved.overrides
588
+ }
589
+ },
590
+ {
591
+ name: "favorodera/jsonc/sort/package-json",
592
+ files: [packageJsonGlob],
593
+ rules: {
594
+ "jsonc/sort-array-values": ["error", {
595
+ order: { type: "asc" },
596
+ pathPattern: "^files$"
597
+ }],
598
+ "jsonc/sort-keys": [
599
+ "error",
600
+ {
601
+ order: [
602
+ "publisher",
603
+ "name",
604
+ "displayName",
605
+ "type",
606
+ "version",
607
+ "private",
608
+ "packageManager",
609
+ "description",
610
+ "author",
611
+ "contributors",
612
+ "license",
613
+ "funding",
614
+ "homepage",
615
+ "repository",
616
+ "bugs",
617
+ "keywords",
618
+ "categories",
619
+ "sideEffects",
620
+ "imports",
621
+ "exports",
622
+ "main",
623
+ "module",
624
+ "unpkg",
625
+ "jsdelivr",
626
+ "types",
627
+ "typesVersions",
628
+ "bin",
629
+ "icon",
630
+ "files",
631
+ "engines",
632
+ "activationEvents",
633
+ "contributes",
634
+ "scripts",
635
+ "peerDependencies",
636
+ "peerDependenciesMeta",
637
+ "dependencies",
638
+ "optionalDependencies",
639
+ "devDependencies",
640
+ "pnpm",
641
+ "overrides",
642
+ "resolutions",
643
+ "husky",
644
+ "simple-git-hooks",
645
+ "lint-staged",
646
+ "eslintConfig"
647
+ ],
648
+ pathPattern: "^$"
649
+ },
650
+ {
651
+ order: { type: "asc" },
652
+ pathPattern: "^(?:dev|peer|optional|bundled)?[Dd]ependencies(Meta)?$"
653
+ },
654
+ {
655
+ order: { type: "asc" },
656
+ pathPattern: "^(?:resolutions|overrides|pnpm.overrides)$"
657
+ },
658
+ {
659
+ order: { type: "asc" },
660
+ pathPattern: "^workspaces\\.catalog$"
661
+ },
662
+ {
663
+ order: { type: "asc" },
664
+ pathPattern: "^workspaces\\.catalogs\\.[^.]+$"
665
+ },
666
+ {
667
+ order: [
668
+ "types",
669
+ "import",
670
+ "require",
671
+ "default"
672
+ ],
673
+ pathPattern: "^exports.*$"
674
+ },
675
+ {
676
+ order: [
677
+ "pre-commit",
678
+ "prepare-commit-msg",
679
+ "commit-msg",
680
+ "post-commit",
681
+ "pre-rebase",
682
+ "post-rewrite",
683
+ "post-checkout",
684
+ "post-merge",
685
+ "pre-push",
686
+ "pre-auto-gc"
687
+ ],
688
+ pathPattern: "^(?:gitHooks|husky|simple-git-hooks)$"
689
+ }
690
+ ]
691
+ }
692
+ },
693
+ {
694
+ name: "favorodera/jsonc/sort/tsconfig-json",
695
+ files: tsConfigGlob,
696
+ rules: { "jsonc/sort-keys": [
697
+ "error",
698
+ {
699
+ order: [
700
+ "extends",
701
+ "compilerOptions",
702
+ "references",
703
+ "files",
704
+ "include",
705
+ "exclude"
706
+ ],
707
+ pathPattern: "^$"
708
+ },
709
+ {
710
+ order: [
711
+ "incremental",
712
+ "composite",
713
+ "tsBuildInfoFile",
714
+ "disableSourceOfProjectReferenceRedirect",
715
+ "disableSolutionSearching",
716
+ "disableReferencedProjectLoad",
717
+ "target",
718
+ "jsx",
719
+ "jsxFactory",
720
+ "jsxFragmentFactory",
721
+ "jsxImportSource",
722
+ "lib",
723
+ "moduleDetection",
724
+ "noLib",
725
+ "reactNamespace",
726
+ "useDefineForClassFields",
727
+ "emitDecoratorMetadata",
728
+ "experimentalDecorators",
729
+ "libReplacement",
730
+ "baseUrl",
731
+ "rootDir",
732
+ "rootDirs",
733
+ "customConditions",
734
+ "module",
735
+ "moduleResolution",
736
+ "moduleSuffixes",
737
+ "noResolve",
738
+ "paths",
739
+ "resolveJsonModule",
740
+ "resolvePackageJsonExports",
741
+ "resolvePackageJsonImports",
742
+ "typeRoots",
743
+ "types",
744
+ "allowArbitraryExtensions",
745
+ "allowImportingTsExtensions",
746
+ "allowUmdGlobalAccess",
747
+ "allowJs",
748
+ "checkJs",
749
+ "maxNodeModuleJsDepth",
750
+ "strict",
751
+ "strictBindCallApply",
752
+ "strictFunctionTypes",
753
+ "strictNullChecks",
754
+ "strictPropertyInitialization",
755
+ "allowUnreachableCode",
756
+ "allowUnusedLabels",
757
+ "alwaysStrict",
758
+ "exactOptionalPropertyTypes",
759
+ "noFallthroughCasesInSwitch",
760
+ "noImplicitAny",
761
+ "noImplicitOverride",
762
+ "noImplicitReturns",
763
+ "noImplicitThis",
764
+ "noPropertyAccessFromIndexSignature",
765
+ "noUncheckedIndexedAccess",
766
+ "noUnusedLocals",
767
+ "noUnusedParameters",
768
+ "useUnknownInCatchVariables",
769
+ "declaration",
770
+ "declarationDir",
771
+ "declarationMap",
772
+ "downlevelIteration",
773
+ "emitBOM",
774
+ "emitDeclarationOnly",
775
+ "importHelpers",
776
+ "importsNotUsedAsValues",
777
+ "inlineSourceMap",
778
+ "inlineSources",
779
+ "mapRoot",
780
+ "newLine",
781
+ "noEmit",
782
+ "noEmitHelpers",
783
+ "noEmitOnError",
784
+ "outDir",
785
+ "outFile",
786
+ "preserveConstEnums",
787
+ "preserveValueImports",
788
+ "removeComments",
789
+ "sourceMap",
790
+ "sourceRoot",
791
+ "stripInternal",
792
+ "allowSyntheticDefaultImports",
793
+ "esModuleInterop",
794
+ "forceConsistentCasingInFileNames",
795
+ "isolatedDeclarations",
796
+ "isolatedModules",
797
+ "preserveSymlinks",
798
+ "verbatimModuleSyntax",
799
+ "erasableSyntaxOnly",
800
+ "skipDefaultLibCheck",
801
+ "skipLibCheck"
802
+ ],
803
+ pathPattern: "^compilerOptions$"
804
+ }
805
+ ] }
806
+ }
807
+ ];
808
+ }
809
+ //#endregion
810
+ //#region src/configs/jsdoc.ts
811
+ const jsdocDefaults = { files: [
812
+ jsGlob,
813
+ tsGlob,
814
+ vueGlob
815
+ ] };
816
+ /**
817
+ * Constructs the flat config items for JSDoc linting, ensuring comments follow
818
+ * proper styling, parameter checks, and types alignment.
819
+ * @param options JSDoc configuration options.
820
+ * @returns Promise resolving to JSDoc ESLint config items.
821
+ */
822
+ async function jsdoc(options) {
823
+ const resolved = (0, defu.defu)(options, jsdocDefaults);
824
+ const jsdocPlugin = await importModule(import("eslint-plugin-jsdoc"));
825
+ const baseRules = {
826
+ ...jsdocPlugin.configs["flat/recommended-typescript-error"]?.rules,
827
+ ...jsdocPlugin.configs["flat/stylistic-typescript-error"]?.rules
828
+ };
829
+ return [{
830
+ name: "favorodera/jsdoc/setup",
831
+ plugins: { jsdoc: jsdocPlugin }
832
+ }, {
833
+ name: "favorodera/tailwind/rules",
834
+ files: resolved.files,
835
+ rules: {
836
+ ...baseRules || {},
837
+ "jsdoc/check-access": "warn",
838
+ "jsdoc/check-param-names": "warn",
839
+ "jsdoc/check-property-names": "warn",
840
+ "jsdoc/check-types": "warn",
841
+ "jsdoc/empty-tags": "warn",
842
+ "jsdoc/implements-on-classes": "warn",
843
+ "jsdoc/no-defaults": "warn",
844
+ "jsdoc/no-multi-asterisks": "warn",
845
+ "jsdoc/require-param-name": "warn",
846
+ "jsdoc/require-property": "warn",
847
+ "jsdoc/require-property-description": "warn",
848
+ "jsdoc/require-property-name": "warn",
849
+ "jsdoc/require-returns-check": "warn",
850
+ "jsdoc/require-returns-description": "warn",
851
+ "jsdoc/require-yields-check": "warn",
852
+ "jsdoc/check-alignment": "warn",
853
+ "jsdoc/multiline-blocks": "warn",
418
854
  ...resolved.overrides
419
855
  }
420
856
  }];
@@ -422,9 +858,10 @@ async function typescript(options) {
422
858
  //#endregion
423
859
  //#region src/factory.ts
424
860
  /**
425
- * Factory to create a flat ESLint config
426
- * @param options - Configuration options for the ESLint config
427
- * @returns Flat ESLint config composer
861
+ * Factory to create a flat ESLint config.
862
+ * It builds an ESLint config by sequentially adding sub-configs based on the provided options.
863
+ * @param options Configuration options for enabling/disabling or configuring specific rule sets.
864
+ * @returns A flat config composer instance that can be exported directly or further modified.
428
865
  */
429
866
  function factory(options = {}) {
430
867
  const configs = [];
@@ -436,7 +873,9 @@ function factory(options = {}) {
436
873
  tailwind,
437
874
  imports,
438
875
  markdown,
439
- javascript
876
+ javascript,
877
+ jsonc,
878
+ jsdoc
440
879
  };
441
880
  for (const [key, configFunction] of Object.entries(configFunctions)) {
442
881
  const configOption = options[key];