@favorodera/eslint-config 0.0.3 → 0.0.5
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 +148 -1
- package/dist/index.cjs +569 -316
- package/dist/index.d.cts +6658 -1423
- package/dist/index.d.mts +6656 -1421
- package/dist/index.mjs +568 -315
- package/package.json +6 -2
package/dist/index.cjs
CHANGED
|
@@ -23,24 +23,37 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
23
23
|
//#endregion
|
|
24
24
|
let eslint_flat_config_utils = require("eslint-flat-config-utils");
|
|
25
25
|
let defu = require("defu");
|
|
26
|
+
let globals = require("globals");
|
|
27
|
+
globals = __toESM(globals, 1);
|
|
26
28
|
let eslint_merge_processors = require("eslint-merge-processors");
|
|
27
29
|
let eslint_processor_vue_blocks = require("eslint-processor-vue-blocks");
|
|
28
30
|
eslint_processor_vue_blocks = __toESM(eslint_processor_vue_blocks, 1);
|
|
29
|
-
let globals = require("globals");
|
|
30
|
-
globals = __toESM(globals, 1);
|
|
31
31
|
//#region src/globs.ts
|
|
32
|
+
/** Glob pattern for matching JavaScript files */
|
|
32
33
|
const jsGlob = "**/*.{js,cjs,mjs}";
|
|
34
|
+
/** Glob pattern for matching TypeScript files */
|
|
33
35
|
const tsGlob = "**/*.{ts,cts,mts}";
|
|
36
|
+
/** Glob pattern for matching Vue single-file components */
|
|
34
37
|
const vueGlob = "**/*.vue";
|
|
38
|
+
/** Glob pattern for matching Markdown files */
|
|
35
39
|
const mdGlob = "**/*.md";
|
|
40
|
+
/** Glob pattern for matching virtual files extracted from Markdown */
|
|
36
41
|
const mdInMdGlob = "**/*.md/*.md";
|
|
42
|
+
/** Glob pattern for matching code blocks embedded in Markdown files */
|
|
37
43
|
const codeInMdGlob = "**/*.md/**/*.{js,cjs,mjs,ts,cts,mts,vue}";
|
|
44
|
+
/** Glob pattern for matching JSON files */
|
|
38
45
|
const jsonGlob = "**/*.json";
|
|
46
|
+
/** Glob pattern for matching JSON5 files */
|
|
39
47
|
const json5Glob = "**/*.json5";
|
|
48
|
+
/** Glob pattern for matching JSON with Comments files */
|
|
40
49
|
const jsoncGlob = "**/*.jsonc";
|
|
50
|
+
/** Glob patterns for matching TypeScript configuration files */
|
|
41
51
|
const tsConfigGlob = ["**/tsconfig.json", "**/tsconfig.*.json"];
|
|
52
|
+
/** Glob pattern for matching package.json files */
|
|
42
53
|
const packageJsonGlob = "**/package.json";
|
|
43
|
-
|
|
54
|
+
//#endregion
|
|
55
|
+
//#region src/configs/ignores.ts
|
|
56
|
+
const defaultPatterns = [
|
|
44
57
|
"**/node_modules/**",
|
|
45
58
|
"**/dist/**",
|
|
46
59
|
"**/package-lock.json",
|
|
@@ -77,17 +90,36 @@ const ignoresGlob = [
|
|
|
77
90
|
"**/.agents",
|
|
78
91
|
"**/.*/skills"
|
|
79
92
|
];
|
|
93
|
+
/**
|
|
94
|
+
* Globs for ignoring files and directories from ESLint scanning.
|
|
95
|
+
* @param patterns Additional ignore patterns or a function to modify the defaults.
|
|
96
|
+
* @returns An array containing the ignore flat config item.
|
|
97
|
+
*/
|
|
98
|
+
function ignores(patterns = []) {
|
|
99
|
+
return [{
|
|
100
|
+
ignores: typeof patterns === "function" ? patterns(defaultPatterns) : [...defaultPatterns, ...patterns],
|
|
101
|
+
name: "favorodera/ignores"
|
|
102
|
+
}];
|
|
103
|
+
}
|
|
80
104
|
//#endregion
|
|
81
105
|
//#region src/utils.ts
|
|
82
106
|
/**
|
|
107
|
+
* Extracts and merges the rules from multiple ESLint configuration arrays.
|
|
108
|
+
* @param configArrays Rest parameter representing multiple arrays of ESLint flat config items.
|
|
109
|
+
* @returns A single object containing all the merged rules from the provided configurations.
|
|
110
|
+
*/
|
|
111
|
+
function extractRules(...configArrays) {
|
|
112
|
+
return Object.assign({}, ...configArrays.flat().map((config) => config?.rules || {}));
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
83
115
|
* Resolves a module (or a promise of one) and returns its default export
|
|
84
116
|
* if present, otherwise returns the module itself.
|
|
85
117
|
*
|
|
86
118
|
* Handles both ESM modules (which wrap exports under `.default`) and
|
|
87
119
|
* CJS / plain-object modules uniformly.
|
|
88
|
-
*
|
|
89
|
-
* @param module
|
|
90
|
-
* @returns The `.default` export if it exists, otherwise the module itself
|
|
120
|
+
* @template TModule The type of the module being imported.
|
|
121
|
+
* @param module A module or a promise that resolves to one.
|
|
122
|
+
* @returns The `.default` export if it exists, otherwise the module itself.
|
|
91
123
|
*/
|
|
92
124
|
async function importModule(module) {
|
|
93
125
|
const resolved = await module;
|
|
@@ -97,106 +129,15 @@ async function importModule(module) {
|
|
|
97
129
|
/**
|
|
98
130
|
* Normalize boolean or options value into merged options or null.
|
|
99
131
|
* Returns null when the input is false or undefined.
|
|
100
|
-
*
|
|
101
|
-
* @param value
|
|
102
|
-
* @param defaults
|
|
103
|
-
* @returns merged options or false
|
|
132
|
+
* @template TOptions The type of the options object.
|
|
133
|
+
* @param value The configuration value, which can be a boolean, an options object, or undefined.
|
|
134
|
+
* @param defaults The default options to merge with if `value` is true or an object.
|
|
135
|
+
* @returns The merged options object, or false if the feature is disabled.
|
|
104
136
|
*/
|
|
105
137
|
function resolveOptions(value, defaults) {
|
|
106
138
|
if (!value) return false;
|
|
107
139
|
return (0, defu.defu)(value === true ? {} : value, defaults);
|
|
108
140
|
}
|
|
109
|
-
function extractRules(...configArrays) {
|
|
110
|
-
return Object.assign({}, ...configArrays.flat().map((config) => config?.rules || {}));
|
|
111
|
-
}
|
|
112
|
-
//#endregion
|
|
113
|
-
//#region src/configs/vue.ts
|
|
114
|
-
const sfcBlocksDefaults = { blocks: {
|
|
115
|
-
styles: true,
|
|
116
|
-
customBlocks: true,
|
|
117
|
-
template: false
|
|
118
|
-
} };
|
|
119
|
-
const vueDefaults = {
|
|
120
|
-
files: [vueGlob],
|
|
121
|
-
sfcBlocks: sfcBlocksDefaults
|
|
122
|
-
};
|
|
123
|
-
async function vue(options) {
|
|
124
|
-
const resolved = (0, defu.defu)(options, vueDefaults);
|
|
125
|
-
const sfcBlocks = resolveOptions(resolved.sfcBlocks, sfcBlocksDefaults);
|
|
126
|
-
const [vuePlugin, vueParser, tsEsLint] = await Promise.all([
|
|
127
|
-
importModule(import("eslint-plugin-vue")),
|
|
128
|
-
importModule(import("vue-eslint-parser")),
|
|
129
|
-
importModule(import("typescript-eslint"))
|
|
130
|
-
]);
|
|
131
|
-
const baseRules = extractRules(vuePlugin.configs["flat/essential"], vuePlugin.configs["flat/strongly-recommended"], vuePlugin.configs["flat/recommended"]);
|
|
132
|
-
const processor = sfcBlocks === false ? vuePlugin.processors[".vue"] : (0, eslint_merge_processors.mergeProcessors)([vuePlugin.processors[".vue"], (0, eslint_processor_vue_blocks.default)(sfcBlocks)]);
|
|
133
|
-
return [{
|
|
134
|
-
name: "favorodera/vue/setup",
|
|
135
|
-
plugins: { vue: vuePlugin },
|
|
136
|
-
languageOptions: { globals: {
|
|
137
|
-
computed: "readonly",
|
|
138
|
-
defineEmits: "readonly",
|
|
139
|
-
defineExpose: "readonly",
|
|
140
|
-
defineProps: "readonly",
|
|
141
|
-
onMounted: "readonly",
|
|
142
|
-
onUnmounted: "readonly",
|
|
143
|
-
reactive: "readonly",
|
|
144
|
-
ref: "readonly",
|
|
145
|
-
shallowReactive: "readonly",
|
|
146
|
-
shallowRef: "readonly",
|
|
147
|
-
toRef: "readonly",
|
|
148
|
-
toRefs: "readonly",
|
|
149
|
-
watch: "readonly",
|
|
150
|
-
watchEffect: "readonly"
|
|
151
|
-
} }
|
|
152
|
-
}, {
|
|
153
|
-
name: "favorodera/vue/rules",
|
|
154
|
-
files: resolved.files,
|
|
155
|
-
languageOptions: {
|
|
156
|
-
parser: vueParser,
|
|
157
|
-
parserOptions: {
|
|
158
|
-
parser: tsEsLint.parser,
|
|
159
|
-
extraFileExtensions: [".vue"],
|
|
160
|
-
sourceType: "module"
|
|
161
|
-
}
|
|
162
|
-
},
|
|
163
|
-
processor,
|
|
164
|
-
rules: {
|
|
165
|
-
...baseRules,
|
|
166
|
-
"vue/block-order": ["error", { order: [
|
|
167
|
-
"script",
|
|
168
|
-
"template",
|
|
169
|
-
"style"
|
|
170
|
-
] }],
|
|
171
|
-
"vue/component-name-in-template-casing": ["error", "PascalCase"],
|
|
172
|
-
"vue/component-options-name-casing": ["error", "PascalCase"],
|
|
173
|
-
"vue/multi-word-component-names": "off",
|
|
174
|
-
"vue/block-tag-newline": ["error", {
|
|
175
|
-
multiline: "ignore",
|
|
176
|
-
singleline: "ignore"
|
|
177
|
-
}],
|
|
178
|
-
"vue/multiline-html-element-content-newline": ["error", {
|
|
179
|
-
allowEmptyLines: true,
|
|
180
|
-
ignores: ["pre", "textarea"]
|
|
181
|
-
}],
|
|
182
|
-
...resolved.overrides
|
|
183
|
-
}
|
|
184
|
-
}];
|
|
185
|
-
}
|
|
186
|
-
//#endregion
|
|
187
|
-
//#region src/configs/ignores.ts
|
|
188
|
-
const defaultPatterns = ignoresGlob;
|
|
189
|
-
/**
|
|
190
|
-
* Globs for ignoring files and directories from ESLint scanning.
|
|
191
|
-
* @param patterns - Additional ignore patterns or a function to modify the defaults.
|
|
192
|
-
* @returns An array containing the ignore flat config item.
|
|
193
|
-
*/
|
|
194
|
-
function ignores(patterns = []) {
|
|
195
|
-
return [{
|
|
196
|
-
name: "favorodera/ignores",
|
|
197
|
-
ignores: typeof patterns === "function" ? patterns(defaultPatterns) : [...defaultPatterns, ...patterns]
|
|
198
|
-
}];
|
|
199
|
-
}
|
|
200
141
|
//#endregion
|
|
201
142
|
//#region src/configs/imports.ts
|
|
202
143
|
const importsDefaults = { files: [
|
|
@@ -204,6 +145,12 @@ const importsDefaults = { files: [
|
|
|
204
145
|
tsGlob,
|
|
205
146
|
vueGlob
|
|
206
147
|
] };
|
|
148
|
+
/**
|
|
149
|
+
* Constructs the flat config items for imports linting, providing plugin setup and
|
|
150
|
+
* specific rules to enforce consistent import ordering and unused variable checks.
|
|
151
|
+
* @param options Configuration options for imports linting.
|
|
152
|
+
* @returns Promise resolving to imports ESLint config items.
|
|
153
|
+
*/
|
|
207
154
|
async function imports(options) {
|
|
208
155
|
const resolved = (0, defu.defu)(options, importsDefaults);
|
|
209
156
|
const [importPlugin, unusedImportsPlugin] = await Promise.all([importModule(import("eslint-plugin-import-lite")), importModule(import("eslint-plugin-unused-imports"))]);
|
|
@@ -215,16 +162,16 @@ async function imports(options) {
|
|
|
215
162
|
"unused-imports": unusedImportsPlugin
|
|
216
163
|
}
|
|
217
164
|
}, {
|
|
218
|
-
name: "favorodera/imports/rules",
|
|
219
165
|
files: resolved.files,
|
|
166
|
+
name: "favorodera/imports/rules",
|
|
220
167
|
rules: {
|
|
221
168
|
...(0, eslint_flat_config_utils.renamePluginsInRules)(baseRules, { "import-lite": "import" }),
|
|
222
|
-
"import/consistent-type-specifier-style": ["error", "top-level"],
|
|
169
|
+
"import/consistent-type-specifier-style": ["error", "prefer-top-level"],
|
|
223
170
|
"import/first": "error",
|
|
171
|
+
"import/newline-after-import": ["error", { count: 1 }],
|
|
224
172
|
"import/no-duplicates": "error",
|
|
225
173
|
"import/no-mutable-exports": "error",
|
|
226
174
|
"import/no-named-default": "error",
|
|
227
|
-
"import/newline-after-import": ["error", { count: 1 }],
|
|
228
175
|
"unused-imports/no-unused-imports": "error",
|
|
229
176
|
"unused-imports/no-unused-vars": ["error", {
|
|
230
177
|
args: "after-used",
|
|
@@ -245,18 +192,17 @@ const javascriptDefaults = { files: [
|
|
|
245
192
|
vueGlob
|
|
246
193
|
] };
|
|
247
194
|
/**
|
|
248
|
-
*
|
|
249
|
-
*
|
|
250
|
-
* @
|
|
195
|
+
* Constructs the flat config items for core JavaScript linting, setting up the required
|
|
196
|
+
* language options, globals, and recommended baseline rules.
|
|
197
|
+
* @param options Javascript configuration options.
|
|
198
|
+
* @returns Promise resolving to javascript ESLint config items.
|
|
251
199
|
*/
|
|
252
200
|
async function javascript(options) {
|
|
253
201
|
const resolved = (0, defu.defu)(options, javascriptDefaults);
|
|
254
202
|
const baseRules = (await importModule(import("@eslint/js"))).configs.recommended.rules;
|
|
255
203
|
return [{
|
|
256
|
-
name: "favorodera/javascript/setup",
|
|
257
204
|
languageOptions: {
|
|
258
205
|
ecmaVersion: "latest",
|
|
259
|
-
sourceType: "module",
|
|
260
206
|
globals: {
|
|
261
207
|
...globals.default.browser,
|
|
262
208
|
...globals.default.es2021,
|
|
@@ -264,12 +210,14 @@ async function javascript(options) {
|
|
|
264
210
|
document: "readonly",
|
|
265
211
|
navigator: "readonly",
|
|
266
212
|
window: "readonly"
|
|
267
|
-
}
|
|
213
|
+
},
|
|
214
|
+
sourceType: "module"
|
|
268
215
|
},
|
|
269
|
-
linterOptions: { reportUnusedDisableDirectives: true }
|
|
216
|
+
linterOptions: { reportUnusedDisableDirectives: true },
|
|
217
|
+
name: "favorodera/javascript/setup"
|
|
270
218
|
}, {
|
|
271
|
-
name: "favorodera/javascript/rules",
|
|
272
219
|
files: resolved.files,
|
|
220
|
+
name: "favorodera/javascript/rules",
|
|
273
221
|
rules: {
|
|
274
222
|
...baseRules,
|
|
275
223
|
"accessor-pairs": ["error", {
|
|
@@ -283,189 +231,50 @@ async function javascript(options) {
|
|
|
283
231
|
}];
|
|
284
232
|
}
|
|
285
233
|
//#endregion
|
|
286
|
-
//#region src/configs/
|
|
287
|
-
const
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
const resolved = (0, defu.defu)(options, markdownDefaults);
|
|
293
|
-
const markdownPlugin = await importModule(import("@eslint/markdown"));
|
|
294
|
-
const baseRules = extractRules(markdownPlugin.configs.recommended);
|
|
295
|
-
return [
|
|
296
|
-
{
|
|
297
|
-
name: "favorodera/markdown/setup",
|
|
298
|
-
plugins: { md: markdownPlugin }
|
|
299
|
-
},
|
|
300
|
-
{
|
|
301
|
-
name: "favorodera/markdown/rules",
|
|
302
|
-
files: resolved.files,
|
|
303
|
-
language: resolved.gfm ? "md/gfm" : "md/commonmark",
|
|
304
|
-
ignores: [mdInMdGlob],
|
|
305
|
-
processor: (0, eslint_merge_processors.mergeProcessors)([markdownPlugin.processors?.markdown, eslint_merge_processors.processorPassThrough]),
|
|
306
|
-
rules: {
|
|
307
|
-
...(0, eslint_flat_config_utils.renamePluginsInRules)(baseRules, { markdown: "md" }),
|
|
308
|
-
"md/fenced-code-language": "off",
|
|
309
|
-
"md/no-missing-label-refs": "off",
|
|
310
|
-
...resolved.overrides
|
|
311
|
-
}
|
|
312
|
-
},
|
|
313
|
-
{
|
|
314
|
-
name: "favorodera/markdown/disables/code",
|
|
315
|
-
files: [codeInMdGlob],
|
|
316
|
-
languageOptions: { parserOptions: { ecmaFeatures: { impliedStrict: true } } },
|
|
317
|
-
rules: {
|
|
318
|
-
"no-alert": "off",
|
|
319
|
-
"no-console": "off",
|
|
320
|
-
"no-labels": "off",
|
|
321
|
-
"no-lone-blocks": "off",
|
|
322
|
-
"no-restricted-syntax": "off",
|
|
323
|
-
"no-undef": "off",
|
|
324
|
-
"no-unused-expressions": "off",
|
|
325
|
-
"no-unused-labels": "off",
|
|
326
|
-
"no-unused-vars": "off",
|
|
327
|
-
"node/prefer-global/process": "off",
|
|
328
|
-
"style/comma-dangle": "off",
|
|
329
|
-
"style/eol-last": "off",
|
|
330
|
-
"style/padding-line-between-statements": "off",
|
|
331
|
-
"ts/consistent-type-imports": "off",
|
|
332
|
-
"ts/explicit-function-return-type": "off",
|
|
333
|
-
"ts/no-namespace": "off",
|
|
334
|
-
"ts/no-redeclare": "off",
|
|
335
|
-
"ts/no-require-imports": "off",
|
|
336
|
-
"ts/no-unused-expressions": "off",
|
|
337
|
-
"ts/no-unused-vars": "off",
|
|
338
|
-
"ts/no-use-before-define": "off",
|
|
339
|
-
"unicode-bom": "off",
|
|
340
|
-
"unused-imports/no-unused-imports": "off",
|
|
341
|
-
"unused-imports/no-unused-vars": "off"
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
];
|
|
345
|
-
}
|
|
346
|
-
//#endregion
|
|
347
|
-
//#region src/configs/stylistic.ts
|
|
348
|
-
const stylisticDefaults = {
|
|
349
|
-
settings: {
|
|
350
|
-
indent: 2,
|
|
351
|
-
experimental: false,
|
|
352
|
-
quotes: "single",
|
|
353
|
-
semi: false,
|
|
354
|
-
jsx: false
|
|
355
|
-
},
|
|
356
|
-
files: [
|
|
357
|
-
jsGlob,
|
|
358
|
-
tsGlob,
|
|
359
|
-
vueGlob
|
|
360
|
-
]
|
|
361
|
-
};
|
|
362
|
-
async function stylistic(options) {
|
|
363
|
-
const resolved = (0, defu.defu)(options, stylisticDefaults);
|
|
364
|
-
const stylePlugin = await importModule(import("@stylistic/eslint-plugin"));
|
|
365
|
-
const baseRules = stylePlugin.configs.customize({
|
|
366
|
-
pluginName: "style",
|
|
367
|
-
...resolved.settings
|
|
368
|
-
})?.rules || {};
|
|
369
|
-
return [{
|
|
370
|
-
name: "favorodera/stylistic/setup",
|
|
371
|
-
plugins: { style: stylePlugin }
|
|
372
|
-
}, {
|
|
373
|
-
name: "favorodera/stylistic/rules",
|
|
374
|
-
files: resolved.files,
|
|
375
|
-
rules: {
|
|
376
|
-
...baseRules,
|
|
377
|
-
"style/quotes": [
|
|
378
|
-
"error",
|
|
379
|
-
"single",
|
|
380
|
-
{ avoidEscape: true }
|
|
381
|
-
],
|
|
382
|
-
"style/no-multiple-empty-lines": ["error", {
|
|
383
|
-
max: 2,
|
|
384
|
-
maxEOF: 2,
|
|
385
|
-
maxBOF: 0
|
|
386
|
-
}],
|
|
387
|
-
"style/padded-blocks": "off",
|
|
388
|
-
"style/no-trailing-spaces": ["error", { skipBlankLines: true }],
|
|
389
|
-
"style/brace-style": "off",
|
|
390
|
-
"style/generator-star-spacing": ["error", {
|
|
391
|
-
after: true,
|
|
392
|
-
before: false
|
|
393
|
-
}],
|
|
394
|
-
"style/yield-star-spacing": ["error", {
|
|
395
|
-
after: true,
|
|
396
|
-
before: false
|
|
397
|
-
}],
|
|
398
|
-
...resolved.overrides
|
|
399
|
-
}
|
|
400
|
-
}];
|
|
401
|
-
}
|
|
402
|
-
//#endregion
|
|
403
|
-
//#region src/configs/tailwind.ts
|
|
404
|
-
const tailwindDefaults = {
|
|
405
|
-
files: [
|
|
406
|
-
jsGlob,
|
|
407
|
-
tsGlob,
|
|
408
|
-
vueGlob
|
|
409
|
-
],
|
|
410
|
-
settings: { detectComponentClasses: true }
|
|
411
|
-
};
|
|
234
|
+
//#region src/configs/jsdoc.ts
|
|
235
|
+
const jsdocDefaults = { files: [
|
|
236
|
+
jsGlob,
|
|
237
|
+
tsGlob,
|
|
238
|
+
vueGlob
|
|
239
|
+
] };
|
|
412
240
|
/**
|
|
413
|
-
*
|
|
414
|
-
*
|
|
415
|
-
* @
|
|
241
|
+
* Constructs the flat config items for JSDoc linting, ensuring comments follow
|
|
242
|
+
* proper styling, parameter checks, and types alignment.
|
|
243
|
+
* @param options JSDoc configuration options.
|
|
244
|
+
* @returns Promise resolving to JSDoc ESLint config items.
|
|
416
245
|
*/
|
|
417
|
-
async function
|
|
418
|
-
const resolved = (0, defu.defu)(options,
|
|
419
|
-
const
|
|
246
|
+
async function jsdoc(options) {
|
|
247
|
+
const resolved = (0, defu.defu)(options, jsdocDefaults);
|
|
248
|
+
const jsdocPlugin = await importModule(import("eslint-plugin-jsdoc"));
|
|
420
249
|
const baseRules = {
|
|
421
|
-
...
|
|
422
|
-
...
|
|
250
|
+
...jsdocPlugin.configs["flat/recommended-typescript-error"]?.rules,
|
|
251
|
+
...jsdocPlugin.configs["flat/stylistic-typescript-error"]?.rules
|
|
423
252
|
};
|
|
424
253
|
return [{
|
|
425
|
-
name: "favorodera/
|
|
426
|
-
plugins: {
|
|
427
|
-
settings: { tailwindcss: resolved.settings }
|
|
254
|
+
name: "favorodera/jsdoc/setup",
|
|
255
|
+
plugins: { jsdoc: jsdocPlugin }
|
|
428
256
|
}, {
|
|
429
|
-
name: "favorodera/tailwind/rules",
|
|
430
257
|
files: resolved.files,
|
|
258
|
+
name: "favorodera/tailwind/rules",
|
|
431
259
|
rules: {
|
|
432
|
-
...
|
|
433
|
-
"
|
|
434
|
-
"
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
const baseRules = extractRules(tsEsLint.configs.recommended, tsEsLint.configs.strict);
|
|
451
|
-
return [{
|
|
452
|
-
name: "favorodera/typescript/setup",
|
|
453
|
-
plugins: { ts: tsEsLint.plugin }
|
|
454
|
-
}, {
|
|
455
|
-
name: "favorodera/typescript/rules",
|
|
456
|
-
files: resolved.files,
|
|
457
|
-
languageOptions: {
|
|
458
|
-
parser: tsEsLint.parser,
|
|
459
|
-
parserOptions: { sourceType: "module" }
|
|
460
|
-
},
|
|
461
|
-
rules: {
|
|
462
|
-
...(0, eslint_flat_config_utils.renamePluginsInRules)(baseRules, { "@typescript-eslint": "ts" }),
|
|
463
|
-
"ts/consistent-type-imports": ["error", { prefer: "type-imports" }],
|
|
464
|
-
"ts/no-empty-object-type": ["error", { allowInterfaces: "with-single-extends" }],
|
|
465
|
-
"ts/array-type": ["error", {
|
|
466
|
-
default: "generic",
|
|
467
|
-
readonly: "generic"
|
|
468
|
-
}],
|
|
260
|
+
...baseRules,
|
|
261
|
+
"jsdoc/check-access": "warn",
|
|
262
|
+
"jsdoc/check-alignment": "warn",
|
|
263
|
+
"jsdoc/check-param-names": "warn",
|
|
264
|
+
"jsdoc/check-property-names": "warn",
|
|
265
|
+
"jsdoc/check-types": "warn",
|
|
266
|
+
"jsdoc/empty-tags": "warn",
|
|
267
|
+
"jsdoc/implements-on-classes": "warn",
|
|
268
|
+
"jsdoc/multiline-blocks": "warn",
|
|
269
|
+
"jsdoc/no-defaults": "warn",
|
|
270
|
+
"jsdoc/no-multi-asterisks": "warn",
|
|
271
|
+
"jsdoc/require-param-name": "warn",
|
|
272
|
+
"jsdoc/require-property": "warn",
|
|
273
|
+
"jsdoc/require-property-description": "warn",
|
|
274
|
+
"jsdoc/require-property-name": "warn",
|
|
275
|
+
"jsdoc/require-returns-check": "warn",
|
|
276
|
+
"jsdoc/require-returns-description": "warn",
|
|
277
|
+
"jsdoc/require-yields-check": "warn",
|
|
469
278
|
...resolved.overrides
|
|
470
279
|
}
|
|
471
280
|
}];
|
|
@@ -477,6 +286,12 @@ const jsoncDefaults = { files: [
|
|
|
477
286
|
jsoncGlob,
|
|
478
287
|
jsonGlob
|
|
479
288
|
] };
|
|
289
|
+
/**
|
|
290
|
+
* Constructs the flat config items for JSON, JSON5, and JSONC linting, setting up
|
|
291
|
+
* the custom parser, rule validations, and sorting rules for package.json/tsconfig.json.
|
|
292
|
+
* @param options JSONC configuration options.
|
|
293
|
+
* @returns Promise resolving to JSONC ESLint config items.
|
|
294
|
+
*/
|
|
480
295
|
async function jsonc(options) {
|
|
481
296
|
const resolved = (0, defu.defu)(options, jsoncDefaults);
|
|
482
297
|
return [
|
|
@@ -485,10 +300,18 @@ async function jsonc(options) {
|
|
|
485
300
|
plugins: { jsonc: await importModule(import("eslint-plugin-jsonc")) }
|
|
486
301
|
},
|
|
487
302
|
{
|
|
488
|
-
name: "favorodera/jsonc/rules",
|
|
489
303
|
files: resolved.files,
|
|
490
304
|
language: "jsonc/x",
|
|
305
|
+
name: "favorodera/jsonc/rules",
|
|
491
306
|
rules: {
|
|
307
|
+
"jsonc/array-bracket-spacing": ["error", "never"],
|
|
308
|
+
"jsonc/comma-dangle": ["error", "never"],
|
|
309
|
+
"jsonc/comma-style": ["error", "last"],
|
|
310
|
+
"jsonc/indent": ["error", 2],
|
|
311
|
+
"jsonc/key-spacing": ["error", {
|
|
312
|
+
afterColon: true,
|
|
313
|
+
beforeColon: false
|
|
314
|
+
}],
|
|
492
315
|
"jsonc/no-bigint-literals": "error",
|
|
493
316
|
"jsonc/no-binary-expression": "error",
|
|
494
317
|
"jsonc/no-binary-numeric-literals": "error",
|
|
@@ -512,17 +335,6 @@ async function jsonc(options) {
|
|
|
512
335
|
"jsonc/no-undefined-value": "error",
|
|
513
336
|
"jsonc/no-unicode-codepoint-escapes": "error",
|
|
514
337
|
"jsonc/no-useless-escape": "error",
|
|
515
|
-
"jsonc/space-unary-ops": "error",
|
|
516
|
-
"jsonc/valid-json-number": "error",
|
|
517
|
-
"jsonc/vue-custom-block/no-parsing-error": "error",
|
|
518
|
-
"jsonc/array-bracket-spacing": ["error", "never"],
|
|
519
|
-
"jsonc/comma-dangle": ["error", "never"],
|
|
520
|
-
"jsonc/comma-style": ["error", "last"],
|
|
521
|
-
"jsonc/indent": ["error", 2],
|
|
522
|
-
"jsonc/key-spacing": ["error", {
|
|
523
|
-
afterColon: true,
|
|
524
|
-
beforeColon: false
|
|
525
|
-
}],
|
|
526
338
|
"jsonc/object-curly-newline": ["error", {
|
|
527
339
|
consistent: true,
|
|
528
340
|
multiline: true
|
|
@@ -531,12 +343,15 @@ async function jsonc(options) {
|
|
|
531
343
|
"jsonc/object-property-newline": ["error", { allowAllPropertiesOnSameLine: true }],
|
|
532
344
|
"jsonc/quote-props": "error",
|
|
533
345
|
"jsonc/quotes": "error",
|
|
346
|
+
"jsonc/space-unary-ops": "error",
|
|
347
|
+
"jsonc/valid-json-number": "error",
|
|
348
|
+
"jsonc/vue-custom-block/no-parsing-error": "error",
|
|
534
349
|
...resolved.overrides
|
|
535
350
|
}
|
|
536
351
|
},
|
|
537
352
|
{
|
|
538
|
-
name: "favorodera/jsonc/sort/package-json",
|
|
539
353
|
files: [packageJsonGlob],
|
|
354
|
+
name: "favorodera/jsonc/sort/package-json",
|
|
540
355
|
rules: {
|
|
541
356
|
"jsonc/sort-array-values": ["error", {
|
|
542
357
|
order: { type: "asc" },
|
|
@@ -604,11 +419,11 @@ async function jsonc(options) {
|
|
|
604
419
|
},
|
|
605
420
|
{
|
|
606
421
|
order: { type: "asc" },
|
|
607
|
-
pathPattern:
|
|
422
|
+
pathPattern: String.raw`^workspaces\.catalog$`
|
|
608
423
|
},
|
|
609
424
|
{
|
|
610
425
|
order: { type: "asc" },
|
|
611
|
-
pathPattern:
|
|
426
|
+
pathPattern: String.raw`^workspaces\.catalogs\.[^.]+$`
|
|
612
427
|
},
|
|
613
428
|
{
|
|
614
429
|
order: [
|
|
@@ -638,8 +453,8 @@ async function jsonc(options) {
|
|
|
638
453
|
}
|
|
639
454
|
},
|
|
640
455
|
{
|
|
641
|
-
name: "favorodera/jsonc/sort/tsconfig-json",
|
|
642
456
|
files: tsConfigGlob,
|
|
457
|
+
name: "favorodera/jsonc/sort/tsconfig-json",
|
|
643
458
|
rules: { "jsonc/sort-keys": [
|
|
644
459
|
"error",
|
|
645
460
|
{
|
|
@@ -754,24 +569,461 @@ async function jsonc(options) {
|
|
|
754
569
|
];
|
|
755
570
|
}
|
|
756
571
|
//#endregion
|
|
572
|
+
//#region src/configs/markdown.ts
|
|
573
|
+
const markdownDefaults = {
|
|
574
|
+
files: [mdGlob],
|
|
575
|
+
gfm: true
|
|
576
|
+
};
|
|
577
|
+
/**
|
|
578
|
+
* Constructs the flat config items for Markdown linting, extracting and linting
|
|
579
|
+
* embedded code blocks within the document according to specified rules.
|
|
580
|
+
* @param options Markdown configuration options.
|
|
581
|
+
* @returns Promise resolving to Markdown ESLint config items.
|
|
582
|
+
*/
|
|
583
|
+
async function markdown(options) {
|
|
584
|
+
const resolved = (0, defu.defu)(options, markdownDefaults);
|
|
585
|
+
const markdownPlugin = await importModule(import("@eslint/markdown"));
|
|
586
|
+
const baseRules = extractRules(markdownPlugin.configs.recommended);
|
|
587
|
+
return [
|
|
588
|
+
{
|
|
589
|
+
name: "favorodera/markdown/setup",
|
|
590
|
+
plugins: { md: markdownPlugin }
|
|
591
|
+
},
|
|
592
|
+
{
|
|
593
|
+
files: resolved.files,
|
|
594
|
+
ignores: [mdInMdGlob],
|
|
595
|
+
language: resolved.gfm ? "md/gfm" : "md/commonmark",
|
|
596
|
+
name: "favorodera/markdown/rules",
|
|
597
|
+
processor: (0, eslint_merge_processors.mergeProcessors)([markdownPlugin.processors?.markdown, eslint_merge_processors.processorPassThrough]),
|
|
598
|
+
rules: {
|
|
599
|
+
...(0, eslint_flat_config_utils.renamePluginsInRules)(baseRules, { markdown: "md" }),
|
|
600
|
+
"md/fenced-code-language": "off",
|
|
601
|
+
"md/no-missing-label-refs": "off",
|
|
602
|
+
...resolved.overrides
|
|
603
|
+
}
|
|
604
|
+
},
|
|
605
|
+
{
|
|
606
|
+
files: [codeInMdGlob],
|
|
607
|
+
languageOptions: { parserOptions: { ecmaFeatures: { impliedStrict: true } } },
|
|
608
|
+
name: "favorodera/markdown/disables/code",
|
|
609
|
+
rules: {
|
|
610
|
+
"no-alert": "off",
|
|
611
|
+
"no-console": "off",
|
|
612
|
+
"no-labels": "off",
|
|
613
|
+
"no-lone-blocks": "off",
|
|
614
|
+
"no-restricted-syntax": "off",
|
|
615
|
+
"no-undef": "off",
|
|
616
|
+
"no-unused-expressions": "off",
|
|
617
|
+
"no-unused-labels": "off",
|
|
618
|
+
"no-unused-vars": "off",
|
|
619
|
+
"node/prefer-global/process": "off",
|
|
620
|
+
"style/comma-dangle": "off",
|
|
621
|
+
"style/eol-last": "off",
|
|
622
|
+
"style/padding-line-between-statements": "off",
|
|
623
|
+
"ts/consistent-type-imports": "off",
|
|
624
|
+
"ts/explicit-function-return-type": "off",
|
|
625
|
+
"ts/no-namespace": "off",
|
|
626
|
+
"ts/no-redeclare": "off",
|
|
627
|
+
"ts/no-require-imports": "off",
|
|
628
|
+
"ts/no-unused-expressions": "off",
|
|
629
|
+
"ts/no-unused-vars": "off",
|
|
630
|
+
"ts/no-use-before-define": "off",
|
|
631
|
+
"unicode-bom": "off",
|
|
632
|
+
"unused-imports/no-unused-imports": "off",
|
|
633
|
+
"unused-imports/no-unused-vars": "off"
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
];
|
|
637
|
+
}
|
|
638
|
+
//#endregion
|
|
639
|
+
//#region src/configs/node.ts
|
|
640
|
+
const nodeDefaults = { files: [
|
|
641
|
+
jsGlob,
|
|
642
|
+
tsGlob,
|
|
643
|
+
vueGlob
|
|
644
|
+
] };
|
|
645
|
+
/**
|
|
646
|
+
* Constructs the flat config items for Node.js linting, providing rules
|
|
647
|
+
* to enforce best practices for Node.js environments.
|
|
648
|
+
* @param options Node configuration options.
|
|
649
|
+
* @returns Promise resolving to Node ESLint config items.
|
|
650
|
+
*/
|
|
651
|
+
async function node(options) {
|
|
652
|
+
const resolved = (0, defu.defu)(options, nodeDefaults);
|
|
653
|
+
const nodePlugin = await importModule(import("eslint-plugin-n"));
|
|
654
|
+
const baseRules = nodePlugin.configs?.["flat/recommended"]?.rules || {};
|
|
655
|
+
return [{
|
|
656
|
+
name: "favorodera/node/setup",
|
|
657
|
+
plugins: { node: nodePlugin }
|
|
658
|
+
}, {
|
|
659
|
+
files: resolved.files,
|
|
660
|
+
name: "favorodera/node/rules",
|
|
661
|
+
rules: {
|
|
662
|
+
...(0, eslint_flat_config_utils.renamePluginsInRules)(baseRules, { n: "node" }),
|
|
663
|
+
"node/handle-callback-err": ["error", "^(err|error)$"],
|
|
664
|
+
"node/no-deprecated-api": "error",
|
|
665
|
+
"node/no-exports-assign": "error",
|
|
666
|
+
"node/no-missing-import": "off",
|
|
667
|
+
"node/no-new-require": "error",
|
|
668
|
+
"node/no-path-concat": "error",
|
|
669
|
+
"node/no-unpublished-import": "off",
|
|
670
|
+
"node/prefer-global/buffer": ["error", "never"],
|
|
671
|
+
"node/prefer-global/process": ["error", "never"],
|
|
672
|
+
"node/process-exit-as-throw": "error",
|
|
673
|
+
...resolved.overrides
|
|
674
|
+
}
|
|
675
|
+
}];
|
|
676
|
+
}
|
|
677
|
+
//#endregion
|
|
678
|
+
//#region src/configs/perfectionist.ts
|
|
679
|
+
const perfectionistDefaults = { files: [
|
|
680
|
+
jsGlob,
|
|
681
|
+
tsGlob,
|
|
682
|
+
vueGlob
|
|
683
|
+
] };
|
|
684
|
+
/**
|
|
685
|
+
* Constructs the flat config items for Perfectionist linting, providing rules
|
|
686
|
+
* to naturally sort objects, imports, classes, and other elements in your code.
|
|
687
|
+
* @param options Perfectionist configuration options.
|
|
688
|
+
* @returns Promise resolving to Perfectionist ESLint config items.
|
|
689
|
+
*/
|
|
690
|
+
async function perfectionist(options) {
|
|
691
|
+
const resolved = (0, defu.defu)(options, perfectionistDefaults);
|
|
692
|
+
const perfectionistPlugin = await importModule(import("eslint-plugin-perfectionist"));
|
|
693
|
+
const baseRules = perfectionistPlugin.configs["recommended-natural"]?.rules || {};
|
|
694
|
+
return [{
|
|
695
|
+
name: "favorodera/perfectionist/setup",
|
|
696
|
+
plugins: { perfectionist: perfectionistPlugin }
|
|
697
|
+
}, {
|
|
698
|
+
files: resolved.files,
|
|
699
|
+
name: "favorodera/perfectionist/rules",
|
|
700
|
+
rules: {
|
|
701
|
+
...baseRules,
|
|
702
|
+
"perfectionist/sort-exports": ["error", {
|
|
703
|
+
order: "asc",
|
|
704
|
+
type: "natural"
|
|
705
|
+
}],
|
|
706
|
+
"perfectionist/sort-imports": ["error", {
|
|
707
|
+
groups: [
|
|
708
|
+
"type-import",
|
|
709
|
+
[
|
|
710
|
+
"type-parent",
|
|
711
|
+
"type-sibling",
|
|
712
|
+
"type-index",
|
|
713
|
+
"type-internal"
|
|
714
|
+
],
|
|
715
|
+
"value-builtin",
|
|
716
|
+
"value-external",
|
|
717
|
+
"value-internal",
|
|
718
|
+
[
|
|
719
|
+
"value-parent",
|
|
720
|
+
"value-sibling",
|
|
721
|
+
"value-index"
|
|
722
|
+
],
|
|
723
|
+
"side-effect",
|
|
724
|
+
"ts-equals-import",
|
|
725
|
+
"unknown"
|
|
726
|
+
],
|
|
727
|
+
newlinesBetween: "ignore",
|
|
728
|
+
newlinesInside: "ignore",
|
|
729
|
+
order: "asc",
|
|
730
|
+
type: "natural"
|
|
731
|
+
}],
|
|
732
|
+
"perfectionist/sort-named-exports": ["error", {
|
|
733
|
+
order: "asc",
|
|
734
|
+
type: "natural"
|
|
735
|
+
}],
|
|
736
|
+
"perfectionist/sort-named-imports": ["error", {
|
|
737
|
+
order: "asc",
|
|
738
|
+
type: "natural"
|
|
739
|
+
}],
|
|
740
|
+
...resolved.overrides
|
|
741
|
+
}
|
|
742
|
+
}];
|
|
743
|
+
}
|
|
744
|
+
//#endregion
|
|
745
|
+
//#region src/configs/stylistic.ts
|
|
746
|
+
const stylisticDefaults = {
|
|
747
|
+
files: [
|
|
748
|
+
jsGlob,
|
|
749
|
+
tsGlob,
|
|
750
|
+
vueGlob
|
|
751
|
+
],
|
|
752
|
+
settings: {
|
|
753
|
+
experimental: false,
|
|
754
|
+
indent: 2,
|
|
755
|
+
jsx: false,
|
|
756
|
+
quotes: "single",
|
|
757
|
+
semi: false
|
|
758
|
+
}
|
|
759
|
+
};
|
|
760
|
+
/**
|
|
761
|
+
* Constructs the flat config items for Stylistic linting, applying customized
|
|
762
|
+
* formatting settings such as quotes, indentation, and spacing.
|
|
763
|
+
* @param options Stylistic configuration options.
|
|
764
|
+
* @returns Promise resolving to stylistic ESLint config items.
|
|
765
|
+
*/
|
|
766
|
+
async function stylistic(options) {
|
|
767
|
+
const resolved = (0, defu.defu)(options, stylisticDefaults);
|
|
768
|
+
const stylePlugin = await importModule(import("@stylistic/eslint-plugin"));
|
|
769
|
+
const baseRules = stylePlugin.configs.customize({
|
|
770
|
+
pluginName: "style",
|
|
771
|
+
...resolved.settings
|
|
772
|
+
})?.rules || {};
|
|
773
|
+
return [{
|
|
774
|
+
name: "favorodera/stylistic/setup",
|
|
775
|
+
plugins: { style: stylePlugin }
|
|
776
|
+
}, {
|
|
777
|
+
files: resolved.files,
|
|
778
|
+
name: "favorodera/stylistic/rules",
|
|
779
|
+
rules: {
|
|
780
|
+
...baseRules,
|
|
781
|
+
"style/brace-style": "off",
|
|
782
|
+
"style/generator-star-spacing": ["error", {
|
|
783
|
+
after: true,
|
|
784
|
+
before: false
|
|
785
|
+
}],
|
|
786
|
+
"style/no-multiple-empty-lines": ["error", {
|
|
787
|
+
max: 2,
|
|
788
|
+
maxBOF: 0,
|
|
789
|
+
maxEOF: 2
|
|
790
|
+
}],
|
|
791
|
+
"style/no-trailing-spaces": ["error", { skipBlankLines: true }],
|
|
792
|
+
"style/padded-blocks": "off",
|
|
793
|
+
"style/quotes": [
|
|
794
|
+
"error",
|
|
795
|
+
"single",
|
|
796
|
+
{ avoidEscape: true }
|
|
797
|
+
],
|
|
798
|
+
"style/yield-star-spacing": ["error", {
|
|
799
|
+
after: true,
|
|
800
|
+
before: false
|
|
801
|
+
}],
|
|
802
|
+
...resolved.overrides
|
|
803
|
+
}
|
|
804
|
+
}];
|
|
805
|
+
}
|
|
806
|
+
//#endregion
|
|
807
|
+
//#region src/configs/tailwind.ts
|
|
808
|
+
const tailwindDefaults = {
|
|
809
|
+
files: [
|
|
810
|
+
jsGlob,
|
|
811
|
+
tsGlob,
|
|
812
|
+
vueGlob
|
|
813
|
+
],
|
|
814
|
+
settings: { detectComponentClasses: true }
|
|
815
|
+
};
|
|
816
|
+
/**
|
|
817
|
+
* Constructs the flat config items for Tailwind CSS linting, providing custom settings
|
|
818
|
+
* to parse and lint utility classes, and enforcing consistent ordering.
|
|
819
|
+
* @param options Tailwind configuration options.
|
|
820
|
+
* @returns Promise resolving to Tailwind ESLint config items.
|
|
821
|
+
*/
|
|
822
|
+
async function tailwind(options) {
|
|
823
|
+
const resolved = (0, defu.defu)(options, tailwindDefaults);
|
|
824
|
+
const tailwindPlugin = await importModule(import("eslint-plugin-better-tailwindcss"));
|
|
825
|
+
const baseRules = {
|
|
826
|
+
...tailwindPlugin.configs["recommended-error"].rules,
|
|
827
|
+
...tailwindPlugin.configs["stylistic-error"].rules
|
|
828
|
+
};
|
|
829
|
+
return [{
|
|
830
|
+
name: "favorodera/tailwind/setup",
|
|
831
|
+
plugins: { tailwind: tailwindPlugin },
|
|
832
|
+
settings: { tailwindcss: resolved.settings }
|
|
833
|
+
}, {
|
|
834
|
+
files: resolved.files,
|
|
835
|
+
name: "favorodera/tailwind/rules",
|
|
836
|
+
rules: {
|
|
837
|
+
...(0, eslint_flat_config_utils.renamePluginsInRules)(baseRules, { "better-tailwindcss": "tailwind" }),
|
|
838
|
+
"tailwind/enforce-consistent-line-wrapping": ["error", { group: "emptyLine" }],
|
|
839
|
+
"tailwind/no-unregistered-classes": "off",
|
|
840
|
+
...resolved.overrides
|
|
841
|
+
}
|
|
842
|
+
}];
|
|
843
|
+
}
|
|
844
|
+
//#endregion
|
|
845
|
+
//#region src/configs/typescript.ts
|
|
846
|
+
const typescriptDefaults = { files: [tsGlob] };
|
|
847
|
+
/**
|
|
848
|
+
* Constructs the flat config items for TypeScript linting, initializing the parser
|
|
849
|
+
* and extending the recommended and strict type-aware rule sets.
|
|
850
|
+
* @param options TypeScript configuration options.
|
|
851
|
+
* @returns Promise resolving to TypeScript ESLint config items.
|
|
852
|
+
*/
|
|
853
|
+
async function typescript(options) {
|
|
854
|
+
const resolved = (0, defu.defu)(options, typescriptDefaults);
|
|
855
|
+
const tsEsLint = await importModule(import("typescript-eslint"));
|
|
856
|
+
const baseRules = extractRules(tsEsLint.configs.recommended, tsEsLint.configs.strict);
|
|
857
|
+
return [{
|
|
858
|
+
name: "favorodera/typescript/setup",
|
|
859
|
+
plugins: { ts: tsEsLint.plugin }
|
|
860
|
+
}, {
|
|
861
|
+
files: resolved.files,
|
|
862
|
+
languageOptions: {
|
|
863
|
+
parser: tsEsLint.parser,
|
|
864
|
+
parserOptions: { sourceType: "module" }
|
|
865
|
+
},
|
|
866
|
+
name: "favorodera/typescript/rules",
|
|
867
|
+
rules: {
|
|
868
|
+
...(0, eslint_flat_config_utils.renamePluginsInRules)(baseRules, { "@typescript-eslint": "ts" }),
|
|
869
|
+
"ts/array-type": ["error", {
|
|
870
|
+
default: "generic",
|
|
871
|
+
readonly: "generic"
|
|
872
|
+
}],
|
|
873
|
+
"ts/consistent-type-imports": ["error", { prefer: "type-imports" }],
|
|
874
|
+
"ts/no-empty-object-type": ["error", { allowInterfaces: "with-single-extends" }],
|
|
875
|
+
...resolved.overrides
|
|
876
|
+
}
|
|
877
|
+
}];
|
|
878
|
+
}
|
|
879
|
+
//#endregion
|
|
880
|
+
//#region src/configs/unicorn.ts
|
|
881
|
+
const unicornDefaults = { files: [
|
|
882
|
+
jsGlob,
|
|
883
|
+
tsGlob,
|
|
884
|
+
vueGlob
|
|
885
|
+
] };
|
|
886
|
+
/**
|
|
887
|
+
* Constructs the flat config items for Unicorn linting, providing a collection of
|
|
888
|
+
* awesome ESLint rules to improve code quality and enforce best practices.
|
|
889
|
+
* @param options Unicorn configuration options.
|
|
890
|
+
* @returns Promise resolving to Unicorn ESLint config items.
|
|
891
|
+
*/
|
|
892
|
+
async function unicorn(options) {
|
|
893
|
+
const resolved = (0, defu.defu)(options, unicornDefaults);
|
|
894
|
+
const unicornPlugin = await importModule(import("eslint-plugin-unicorn"));
|
|
895
|
+
const baseRules = unicornPlugin.configs["unopinionated"]?.rules || {};
|
|
896
|
+
return [{
|
|
897
|
+
name: "favorodera/unicorn/setup",
|
|
898
|
+
plugins: { unicorn: unicornPlugin }
|
|
899
|
+
}, {
|
|
900
|
+
files: resolved.files,
|
|
901
|
+
languageOptions: { globals: globals.default.builtin },
|
|
902
|
+
name: "favorodera/unicorn/rules",
|
|
903
|
+
rules: {
|
|
904
|
+
...baseRules,
|
|
905
|
+
"unicorn/consistent-empty-array-spread": "error",
|
|
906
|
+
"unicorn/error-message": "error",
|
|
907
|
+
"unicorn/escape-case": "error",
|
|
908
|
+
"unicorn/new-for-builtins": "error",
|
|
909
|
+
"unicorn/no-instanceof-builtins": "error",
|
|
910
|
+
"unicorn/no-new-array": "error",
|
|
911
|
+
"unicorn/no-new-buffer": "error",
|
|
912
|
+
"unicorn/number-literal-case": "error",
|
|
913
|
+
"unicorn/prefer-dom-node-text-content": "error",
|
|
914
|
+
"unicorn/prefer-includes": "error",
|
|
915
|
+
"unicorn/prefer-node-protocol": "error",
|
|
916
|
+
"unicorn/prefer-number-properties": "error",
|
|
917
|
+
"unicorn/prefer-string-starts-ends-with": "error",
|
|
918
|
+
"unicorn/prefer-type-error": "error",
|
|
919
|
+
"unicorn/throw-new-error": "error",
|
|
920
|
+
...resolved.overrides
|
|
921
|
+
}
|
|
922
|
+
}];
|
|
923
|
+
}
|
|
924
|
+
//#endregion
|
|
925
|
+
//#region src/configs/vue.ts
|
|
926
|
+
const sfcBlocksDefaults = { blocks: {
|
|
927
|
+
customBlocks: true,
|
|
928
|
+
styles: true,
|
|
929
|
+
template: false
|
|
930
|
+
} };
|
|
931
|
+
const vueDefaults = {
|
|
932
|
+
files: [vueGlob],
|
|
933
|
+
sfcBlocks: sfcBlocksDefaults
|
|
934
|
+
};
|
|
935
|
+
/**
|
|
936
|
+
* Constructs the flat config items for Vue linting, setting up the custom template parser,
|
|
937
|
+
* Vue block processors, and rules to enforce recommended component syntax.
|
|
938
|
+
* @param options Vue configuration options.
|
|
939
|
+
* @returns Promise resolving to Vue ESLint config items.
|
|
940
|
+
*/
|
|
941
|
+
async function vue(options) {
|
|
942
|
+
const resolved = (0, defu.defu)(options, vueDefaults);
|
|
943
|
+
const sfcBlocks = resolveOptions(resolved.sfcBlocks, sfcBlocksDefaults);
|
|
944
|
+
const [vuePlugin, vueParser, tsEsLint] = await Promise.all([
|
|
945
|
+
importModule(import("eslint-plugin-vue")),
|
|
946
|
+
importModule(import("vue-eslint-parser")),
|
|
947
|
+
importModule(import("typescript-eslint"))
|
|
948
|
+
]);
|
|
949
|
+
const baseRules = extractRules(vuePlugin.configs["flat/essential"], vuePlugin.configs["flat/strongly-recommended"], vuePlugin.configs["flat/recommended"]);
|
|
950
|
+
const processor = sfcBlocks === false ? vuePlugin.processors[".vue"] : (0, eslint_merge_processors.mergeProcessors)([vuePlugin.processors[".vue"], (0, eslint_processor_vue_blocks.default)(sfcBlocks)]);
|
|
951
|
+
return [{
|
|
952
|
+
languageOptions: { globals: {
|
|
953
|
+
computed: "readonly",
|
|
954
|
+
defineEmits: "readonly",
|
|
955
|
+
defineExpose: "readonly",
|
|
956
|
+
defineProps: "readonly",
|
|
957
|
+
onMounted: "readonly",
|
|
958
|
+
onUnmounted: "readonly",
|
|
959
|
+
reactive: "readonly",
|
|
960
|
+
ref: "readonly",
|
|
961
|
+
shallowReactive: "readonly",
|
|
962
|
+
shallowRef: "readonly",
|
|
963
|
+
toRef: "readonly",
|
|
964
|
+
toRefs: "readonly",
|
|
965
|
+
watch: "readonly",
|
|
966
|
+
watchEffect: "readonly"
|
|
967
|
+
} },
|
|
968
|
+
name: "favorodera/vue/setup",
|
|
969
|
+
plugins: { vue: vuePlugin }
|
|
970
|
+
}, {
|
|
971
|
+
files: resolved.files,
|
|
972
|
+
languageOptions: {
|
|
973
|
+
parser: vueParser,
|
|
974
|
+
parserOptions: {
|
|
975
|
+
extraFileExtensions: [".vue"],
|
|
976
|
+
parser: tsEsLint.parser,
|
|
977
|
+
sourceType: "module"
|
|
978
|
+
}
|
|
979
|
+
},
|
|
980
|
+
name: "favorodera/vue/rules",
|
|
981
|
+
processor,
|
|
982
|
+
rules: {
|
|
983
|
+
...baseRules,
|
|
984
|
+
"vue/block-order": ["error", { order: [
|
|
985
|
+
"script",
|
|
986
|
+
"template",
|
|
987
|
+
"style"
|
|
988
|
+
] }],
|
|
989
|
+
"vue/block-tag-newline": ["error", {
|
|
990
|
+
multiline: "ignore",
|
|
991
|
+
singleline: "ignore"
|
|
992
|
+
}],
|
|
993
|
+
"vue/component-name-in-template-casing": ["error", "PascalCase"],
|
|
994
|
+
"vue/component-options-name-casing": ["error", "PascalCase"],
|
|
995
|
+
"vue/multi-word-component-names": "off",
|
|
996
|
+
"vue/multiline-html-element-content-newline": ["error", {
|
|
997
|
+
allowEmptyLines: true,
|
|
998
|
+
ignores: ["pre", "textarea"]
|
|
999
|
+
}],
|
|
1000
|
+
...resolved.overrides
|
|
1001
|
+
}
|
|
1002
|
+
}];
|
|
1003
|
+
}
|
|
1004
|
+
//#endregion
|
|
757
1005
|
//#region src/factory.ts
|
|
758
1006
|
/**
|
|
759
|
-
* Factory to create a flat ESLint config
|
|
760
|
-
*
|
|
761
|
-
* @
|
|
1007
|
+
* Factory to create a flat ESLint config.
|
|
1008
|
+
* It builds an ESLint config by sequentially adding sub-configs based on the provided options.
|
|
1009
|
+
* @param options Configuration options for enabling/disabling or configuring specific rule sets.
|
|
1010
|
+
* @returns A flat config composer instance that can be exported directly or further modified.
|
|
762
1011
|
*/
|
|
763
1012
|
function factory(options = {}) {
|
|
764
|
-
const configs = [];
|
|
765
|
-
configs.push(ignores(options.ignores));
|
|
1013
|
+
const configs = [ignores(options.ignores)];
|
|
766
1014
|
const configFunctions = {
|
|
767
|
-
vue,
|
|
768
|
-
typescript,
|
|
769
|
-
stylistic,
|
|
770
|
-
tailwind,
|
|
771
1015
|
imports,
|
|
772
|
-
markdown,
|
|
773
1016
|
javascript,
|
|
774
|
-
|
|
1017
|
+
jsdoc,
|
|
1018
|
+
jsonc,
|
|
1019
|
+
markdown,
|
|
1020
|
+
node,
|
|
1021
|
+
perfectionist,
|
|
1022
|
+
stylistic,
|
|
1023
|
+
tailwind,
|
|
1024
|
+
typescript,
|
|
1025
|
+
unicorn,
|
|
1026
|
+
vue
|
|
775
1027
|
};
|
|
776
1028
|
for (const [key, configFunction] of Object.entries(configFunctions)) {
|
|
777
1029
|
const configOption = options[key];
|
|
@@ -780,10 +1032,11 @@ function factory(options = {}) {
|
|
|
780
1032
|
}
|
|
781
1033
|
let composer = new eslint_flat_config_utils.FlatConfigComposer();
|
|
782
1034
|
composer = composer.append(...configs).renamePlugins({
|
|
783
|
-
"better-tailwindcss": "tailwind",
|
|
784
1035
|
"@typescript-eslint": "ts",
|
|
1036
|
+
"better-tailwindcss": "tailwind",
|
|
1037
|
+
"import-lite": "import",
|
|
785
1038
|
"markdown": "md",
|
|
786
|
-
"
|
|
1039
|
+
"n": "node"
|
|
787
1040
|
});
|
|
788
1041
|
return composer;
|
|
789
1042
|
}
|