@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/README.md +144 -1
- package/dist/index.cjs +530 -91
- package/dist/index.d.cts +1382 -44
- package/dist/index.d.mts +1382 -44
- package/dist/index.mjs +530 -91
- package/package.json +32 -28
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
|
|
32
|
+
/** Glob pattern for matching JavaScript files */
|
|
33
33
|
const jsGlob = "**/*.{js,cjs,mjs}";
|
|
34
|
-
/** Glob pattern for TypeScript
|
|
34
|
+
/** Glob pattern for matching TypeScript files */
|
|
35
35
|
const tsGlob = "**/*.{ts,cts,mts}";
|
|
36
|
-
/** Glob pattern for Vue
|
|
36
|
+
/** Glob pattern for matching Vue single-file components */
|
|
37
37
|
const vueGlob = "**/*.vue";
|
|
38
|
-
/** Glob pattern for Markdown
|
|
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
|
-
*
|
|
42
|
-
* Includes
|
|
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
|
|
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
|
|
103
|
-
* @param defaults
|
|
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
|
|
130
|
-
|
|
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
|
|
189
|
+
processor,
|
|
163
190
|
rules: {
|
|
164
|
-
...
|
|
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
|
|
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
|
|
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)(
|
|
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
|
-
*
|
|
246
|
-
*
|
|
247
|
-
* @
|
|
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
|
|
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
|
-
...
|
|
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
|
|
290
|
-
return [
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
"md/
|
|
299
|
-
|
|
300
|
-
|
|
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
|
|
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
|
-
|
|
329
|
-
|
|
415
|
+
name: "favorodera/stylistic/setup",
|
|
416
|
+
plugins: { style: stylePlugin }
|
|
417
|
+
}, {
|
|
418
|
+
name: "favorodera/stylistic/rules",
|
|
330
419
|
files: resolved.files,
|
|
331
420
|
rules: {
|
|
332
|
-
...
|
|
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
|
|
370
|
-
*
|
|
371
|
-
* @
|
|
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
|
|
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)(
|
|
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
|
-
*
|
|
398
|
-
*
|
|
399
|
-
* @
|
|
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
|
|
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)(
|
|
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", {
|
|
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
|
-
*
|
|
427
|
-
* @
|
|
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];
|