@favorodera/eslint-config 0.0.1 → 0.0.2
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 +212 -444
- package/dist/index.d.cts +4417 -1649
- package/dist/index.d.mts +4418 -1650
- package/dist/index.mjs +211 -443
- package/package.json +3 -4
package/dist/index.cjs
CHANGED
|
@@ -24,51 +24,15 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
24
24
|
let eslint_flat_config_utils = require("eslint-flat-config-utils");
|
|
25
25
|
let defu = require("defu");
|
|
26
26
|
let eslint_merge_processors = require("eslint-merge-processors");
|
|
27
|
+
let eslint_processor_vue_blocks = require("eslint-processor-vue-blocks");
|
|
28
|
+
eslint_processor_vue_blocks = __toESM(eslint_processor_vue_blocks, 1);
|
|
27
29
|
let globals = require("globals");
|
|
28
30
|
globals = __toESM(globals, 1);
|
|
29
|
-
//#region src/utils.ts
|
|
30
|
-
/**
|
|
31
|
-
* Return the default export from a module-like object.
|
|
32
|
-
* If the module has no default export, return the original resolved value.
|
|
33
|
-
*
|
|
34
|
-
* @param module - module or promise resolving to a module
|
|
35
|
-
* @returns resolved module default or original module
|
|
36
|
-
*/
|
|
37
|
-
async function getModuleDefault(module) {
|
|
38
|
-
const resolvedModule = await module;
|
|
39
|
-
return resolvedModule.default || resolvedModule;
|
|
40
|
-
}
|
|
41
|
-
/**
|
|
42
|
-
* Normalize boolean or options value into merged options or null.
|
|
43
|
-
* Returns null when the input is false or undefined.
|
|
44
|
-
*
|
|
45
|
-
* @param value - boolean, options object, or undefined
|
|
46
|
-
* @param defaults - defaults to merge with
|
|
47
|
-
* @returns merged options or false
|
|
48
|
-
*/
|
|
49
|
-
function resolveOptions(value, defaults) {
|
|
50
|
-
if (!value) return false;
|
|
51
|
-
return (0, defu.defu)(value === true ? {} : value, defaults);
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* Rename rules by replacing configured plugin prefixes.
|
|
55
|
-
*
|
|
56
|
-
* @param rules - rules object to rename
|
|
57
|
-
* @param map - prefix map used for renaming
|
|
58
|
-
* @returns renamed rules object
|
|
59
|
-
*/
|
|
60
|
-
function renameRules(rules, map) {
|
|
61
|
-
return Object.fromEntries(Object.entries(rules).map(([key, value]) => {
|
|
62
|
-
for (const [from, to] of Object.entries(map)) if (key.startsWith(`${from}/`)) return [to + key.slice(from.length), value];
|
|
63
|
-
return [key, value];
|
|
64
|
-
}));
|
|
65
|
-
}
|
|
66
|
-
//#endregion
|
|
67
31
|
//#region src/globs.ts
|
|
68
32
|
/** Glob pattern for JavaScript linting */
|
|
69
|
-
const jsGlob = "
|
|
33
|
+
const jsGlob = "**/*.{js,cjs,mjs}";
|
|
70
34
|
/** Glob pattern for TypeScript linting */
|
|
71
|
-
const tsGlob = "
|
|
35
|
+
const tsGlob = "**/*.{ts,cts,mts}";
|
|
72
36
|
/** Glob pattern for Vue linting */
|
|
73
37
|
const vueGlob = "**/*.vue";
|
|
74
38
|
/** Glob pattern for Markdown linting */
|
|
@@ -78,8 +42,8 @@ const mdGlob = "**/*.md";
|
|
|
78
42
|
* Includes common build outputs, dependencies, caches, and temporary files
|
|
79
43
|
*/
|
|
80
44
|
const ignoresGlob = [
|
|
81
|
-
"**/node_modules",
|
|
82
|
-
"**/dist",
|
|
45
|
+
"**/node_modules/**",
|
|
46
|
+
"**/dist/**",
|
|
83
47
|
"**/package-lock.json",
|
|
84
48
|
"**/yarn.lock",
|
|
85
49
|
"**/pnpm-lock.yaml",
|
|
@@ -115,6 +79,35 @@ const ignoresGlob = [
|
|
|
115
79
|
"**/.*/skills"
|
|
116
80
|
];
|
|
117
81
|
//#endregion
|
|
82
|
+
//#region src/utils.ts
|
|
83
|
+
/**
|
|
84
|
+
* Resolves a module (or a promise of one) and returns its default export
|
|
85
|
+
* if present, otherwise returns the module itself.
|
|
86
|
+
*
|
|
87
|
+
* Handles both ESM modules (which wrap exports under `.default`) and
|
|
88
|
+
* 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
|
|
92
|
+
*/
|
|
93
|
+
async function importModule(module) {
|
|
94
|
+
const resolved = await module;
|
|
95
|
+
if (resolved !== null && typeof resolved === "object" && "default" in resolved) return resolved.default;
|
|
96
|
+
return resolved;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Normalize boolean or options value into merged options or null.
|
|
100
|
+
* 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
|
|
105
|
+
*/
|
|
106
|
+
function resolveOptions(value, defaults) {
|
|
107
|
+
if (!value) return false;
|
|
108
|
+
return (0, defu.defu)(value === true ? {} : value, defaults);
|
|
109
|
+
}
|
|
110
|
+
//#endregion
|
|
118
111
|
//#region src/configs/vue.ts
|
|
119
112
|
const sfcBlocksDefaults = { blocks: {
|
|
120
113
|
styles: true,
|
|
@@ -125,22 +118,21 @@ const vueDefaults = {
|
|
|
125
118
|
files: [vueGlob],
|
|
126
119
|
sfcBlocks: sfcBlocksDefaults
|
|
127
120
|
};
|
|
128
|
-
/**
|
|
129
|
-
* Vue SFC linting via `vue-eslint-parser`, `eslint-plugin-vue`, `typescript-eslint(parser)`.
|
|
130
|
-
* @param options - Vue configuration options
|
|
131
|
-
* @returns Promise resolving to Vue ESLint config items
|
|
132
|
-
*/
|
|
133
121
|
async function vue(options) {
|
|
134
122
|
const resolved = (0, defu.defu)(options, vueDefaults);
|
|
135
123
|
const sfcBlocks = resolveOptions(resolved.sfcBlocks, sfcBlocksDefaults);
|
|
136
|
-
const [vuePlugin, vueParser, tsEsLint
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
getModuleDefault(import("eslint-processor-vue-blocks"))
|
|
124
|
+
const [vuePlugin, vueParser, tsEsLint] = await Promise.all([
|
|
125
|
+
importModule(import("eslint-plugin-vue")),
|
|
126
|
+
importModule(import("vue-eslint-parser")),
|
|
127
|
+
importModule(import("typescript-eslint"))
|
|
141
128
|
]);
|
|
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 || {}));
|
|
142
134
|
return [{
|
|
143
|
-
name: "favorodera/vue
|
|
135
|
+
name: "favorodera/vue",
|
|
144
136
|
plugins: { vue: vuePlugin },
|
|
145
137
|
files: resolved.files,
|
|
146
138
|
languageOptions: {
|
|
@@ -167,21 +159,9 @@ async function vue(options) {
|
|
|
167
159
|
sourceType: "module"
|
|
168
160
|
}
|
|
169
161
|
},
|
|
170
|
-
processor: sfcBlocks === false ? vuePlugin.processors[".vue"] : (0, eslint_merge_processors.mergeProcessors)([vuePlugin.processors[".vue"],
|
|
162
|
+
processor: sfcBlocks === false ? vuePlugin.processors[".vue"] : (0, eslint_merge_processors.mergeProcessors)([vuePlugin.processors[".vue"], (0, eslint_processor_vue_blocks.default)(sfcBlocks)]),
|
|
171
163
|
rules: {
|
|
172
|
-
...
|
|
173
|
-
...vuePlugin.configs["flat/essential"].map((config) => config.rules).reduce((accumulator, currentConfig) => ({
|
|
174
|
-
...accumulator,
|
|
175
|
-
...currentConfig
|
|
176
|
-
}), {}),
|
|
177
|
-
...vuePlugin.configs["flat/strongly-recommended"].map((config) => config.rules).reduce((accumulator, currentConfig) => ({
|
|
178
|
-
...accumulator,
|
|
179
|
-
...currentConfig
|
|
180
|
-
}), {}),
|
|
181
|
-
...vuePlugin.configs["flat/recommended"].map((config) => config.rules).reduce((accumulator, currentConfig) => ({
|
|
182
|
-
...accumulator,
|
|
183
|
-
...currentConfig
|
|
184
|
-
}), {}),
|
|
164
|
+
...inheritedRules,
|
|
185
165
|
"vue/block-order": ["error", { order: [
|
|
186
166
|
"script",
|
|
187
167
|
"template",
|
|
@@ -203,43 +183,6 @@ async function vue(options) {
|
|
|
203
183
|
}];
|
|
204
184
|
}
|
|
205
185
|
//#endregion
|
|
206
|
-
//#region src/configs/typescript.ts
|
|
207
|
-
const typescriptDefaults = { files: [tsGlob] };
|
|
208
|
-
/**
|
|
209
|
-
* Extract and merge rules from a compatible config array.
|
|
210
|
-
* @param configs - Array of compatible ESLint configs
|
|
211
|
-
* @returns Merged rules object from all configs
|
|
212
|
-
*/
|
|
213
|
-
function extractRules(configs) {
|
|
214
|
-
return Object.assign({}, ...configs.map((config) => config.rules || {}));
|
|
215
|
-
}
|
|
216
|
-
/**
|
|
217
|
-
* Typescript linting via `typescript-eslint`.
|
|
218
|
-
* @param options - TypeScript configuration options
|
|
219
|
-
* @returns Promise resolving to TypeScript ESLint config items
|
|
220
|
-
*/
|
|
221
|
-
async function typescript(options) {
|
|
222
|
-
const resolved = (0, defu.defu)(options, typescriptDefaults);
|
|
223
|
-
const tsEsLint = await getModuleDefault(import("typescript-eslint"));
|
|
224
|
-
return [{
|
|
225
|
-
name: "favorodera/typescript/rules",
|
|
226
|
-
files: resolved.files,
|
|
227
|
-
plugins: { ts: tsEsLint.plugin },
|
|
228
|
-
languageOptions: {
|
|
229
|
-
parser: tsEsLint.parser,
|
|
230
|
-
parserOptions: { sourceType: "module" }
|
|
231
|
-
},
|
|
232
|
-
rules: {
|
|
233
|
-
...renameRules(extractRules(tsEsLint.configs.strict), { "@typescript-eslint": "ts" }),
|
|
234
|
-
...renameRules(extractRules(tsEsLint.configs.stylistic), { "@typescript-eslint": "ts" }),
|
|
235
|
-
"ts/consistent-type-imports": ["error", { prefer: "type-imports" }],
|
|
236
|
-
"ts/no-empty-object-type": ["error", { allowInterfaces: "with-single-extends" }],
|
|
237
|
-
"ts/array-type": ["error", { default: "array" }],
|
|
238
|
-
...resolved.overrides
|
|
239
|
-
}
|
|
240
|
-
}];
|
|
241
|
-
}
|
|
242
|
-
//#endregion
|
|
243
186
|
//#region src/configs/ignores.ts
|
|
244
187
|
const defaultPatterns = ignoresGlob;
|
|
245
188
|
/**
|
|
@@ -254,141 +197,25 @@ function ignores(patterns = []) {
|
|
|
254
197
|
}];
|
|
255
198
|
}
|
|
256
199
|
//#endregion
|
|
257
|
-
//#region src/configs/stylistic.ts
|
|
258
|
-
const stylisticDefaults = {
|
|
259
|
-
indent: 2,
|
|
260
|
-
experimental: false,
|
|
261
|
-
quotes: "single",
|
|
262
|
-
semi: false,
|
|
263
|
-
jsx: false
|
|
264
|
-
};
|
|
265
|
-
/**
|
|
266
|
-
* Code style via `@stylistic/eslint-plugin`.
|
|
267
|
-
* @param options - Stylistic configuration options
|
|
268
|
-
* @returns Promise resolving to stylistic ESLint config items
|
|
269
|
-
*/
|
|
270
|
-
async function stylistic(options) {
|
|
271
|
-
const resolved = (0, defu.defu)(options, stylisticDefaults);
|
|
272
|
-
const stylePlugin = await getModuleDefault(import("@stylistic/eslint-plugin"));
|
|
273
|
-
const customizedStyleConfig = stylePlugin.configs.customize({
|
|
274
|
-
pluginName: "style",
|
|
275
|
-
...resolved
|
|
276
|
-
});
|
|
277
|
-
return [{
|
|
278
|
-
name: "favorodera/stylistic/rules",
|
|
279
|
-
plugins: { style: stylePlugin },
|
|
280
|
-
rules: {
|
|
281
|
-
...customizedStyleConfig.rules,
|
|
282
|
-
"style/quotes": [
|
|
283
|
-
"error",
|
|
284
|
-
"single",
|
|
285
|
-
{ avoidEscape: true }
|
|
286
|
-
],
|
|
287
|
-
"style/no-multiple-empty-lines": ["error", {
|
|
288
|
-
max: 2,
|
|
289
|
-
maxEOF: 2,
|
|
290
|
-
maxBOF: 0
|
|
291
|
-
}],
|
|
292
|
-
"style/padded-blocks": "off",
|
|
293
|
-
"style/no-trailing-spaces": ["error", { skipBlankLines: true }],
|
|
294
|
-
"style/brace-style": "off",
|
|
295
|
-
"style/generator-star-spacing": ["error", {
|
|
296
|
-
after: true,
|
|
297
|
-
before: false
|
|
298
|
-
}],
|
|
299
|
-
"style/yield-star-spacing": ["error", {
|
|
300
|
-
after: true,
|
|
301
|
-
before: false
|
|
302
|
-
}],
|
|
303
|
-
...resolved.overrides
|
|
304
|
-
}
|
|
305
|
-
}];
|
|
306
|
-
}
|
|
307
|
-
//#endregion
|
|
308
|
-
//#region src/configs/tailwind.ts
|
|
309
|
-
const tailwindDefaults = {
|
|
310
|
-
files: [
|
|
311
|
-
jsGlob,
|
|
312
|
-
tsGlob,
|
|
313
|
-
vueGlob
|
|
314
|
-
],
|
|
315
|
-
settings: { detectComponentClasses: true }
|
|
316
|
-
};
|
|
317
|
-
/**
|
|
318
|
-
* Tailwind linting via `eslint-plugin-better-tailwindcss`.
|
|
319
|
-
* @param options - Tailwind configuration options
|
|
320
|
-
* @returns Promise resolving to Tailwind ESLint config items
|
|
321
|
-
*/
|
|
322
|
-
async function tailwind(options) {
|
|
323
|
-
const resolved = (0, defu.defu)(options, tailwindDefaults);
|
|
324
|
-
const tailwindPlugin = await getModuleDefault(import("eslint-plugin-better-tailwindcss"));
|
|
325
|
-
return [{
|
|
326
|
-
name: "favorodera/tailwind/rules",
|
|
327
|
-
plugins: { tailwind: tailwindPlugin },
|
|
328
|
-
files: resolved.files,
|
|
329
|
-
settings: { tailwindcss: resolved.settings },
|
|
330
|
-
rules: {
|
|
331
|
-
...renameRules(tailwindPlugin.configs["recommended-error"].rules, { "better-tailwindcss": "tailwind" }),
|
|
332
|
-
...renameRules(tailwindPlugin.configs["stylistic-error"].rules, { "better-tailwindcss": "tailwind" }),
|
|
333
|
-
"tailwind/no-unregistered-classes": "off",
|
|
334
|
-
"tailwind/enforce-consistent-line-wrapping": ["error", { group: "emptyLine" }],
|
|
335
|
-
...resolved.overrides
|
|
336
|
-
}
|
|
337
|
-
}];
|
|
338
|
-
}
|
|
339
|
-
//#endregion
|
|
340
|
-
//#region src/configs/comments.ts
|
|
341
|
-
const commentsDefaults = { files: [
|
|
342
|
-
jsGlob,
|
|
343
|
-
tsGlob,
|
|
344
|
-
vueGlob
|
|
345
|
-
] };
|
|
346
|
-
/**
|
|
347
|
-
* Comments linting via `@eslint-community/eslint-plugin-eslint-comments`
|
|
348
|
-
* @param options - Comments configuration options
|
|
349
|
-
* @returns Promise resolving to comments ESLint config items
|
|
350
|
-
*/
|
|
351
|
-
async function comments(options) {
|
|
352
|
-
const resolved = (0, defu.defu)(options, commentsDefaults);
|
|
353
|
-
const commentsPlugin = await getModuleDefault(import("@eslint-community/eslint-plugin-eslint-comments"));
|
|
354
|
-
return [{
|
|
355
|
-
name: "favorodera/comments/rules",
|
|
356
|
-
files: resolved.files,
|
|
357
|
-
plugins: { comments: commentsPlugin },
|
|
358
|
-
rules: {
|
|
359
|
-
...renameRules(commentsPlugin.configs.recommended?.rules || {}, { "@eslint-community/eslint-comments": "comments" }),
|
|
360
|
-
"comments/no-aggregating-enable": "error",
|
|
361
|
-
"comments/no-duplicate-disable": "error",
|
|
362
|
-
"comments/no-unlimited-disable": "error",
|
|
363
|
-
"comments/no-unused-enable": "error",
|
|
364
|
-
...resolved.overrides
|
|
365
|
-
}
|
|
366
|
-
}];
|
|
367
|
-
}
|
|
368
|
-
//#endregion
|
|
369
200
|
//#region src/configs/imports.ts
|
|
370
201
|
const importsDefaults = { files: [
|
|
371
202
|
jsGlob,
|
|
372
203
|
tsGlob,
|
|
373
204
|
vueGlob
|
|
374
205
|
] };
|
|
375
|
-
/**
|
|
376
|
-
* Imports & unused imports linting via `eslint-plugin-import-lite` and `eslint-plugin-unused-imports`.
|
|
377
|
-
* @param options - Imports & unused imports configuration options
|
|
378
|
-
* @returns Promise resolving to imports & unused imports ESLint config items
|
|
379
|
-
*/
|
|
380
206
|
async function imports(options) {
|
|
381
207
|
const resolved = (0, defu.defu)(options, importsDefaults);
|
|
382
|
-
const [importPlugin, unusedImportsPlugin] = await Promise.all([
|
|
208
|
+
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 || {};
|
|
383
210
|
return [{
|
|
384
|
-
name: "favorodera/imports
|
|
211
|
+
name: "favorodera/imports",
|
|
385
212
|
files: resolved.files,
|
|
386
213
|
plugins: {
|
|
387
214
|
"import": importPlugin,
|
|
388
215
|
"unused-imports": unusedImportsPlugin
|
|
389
216
|
},
|
|
390
217
|
rules: {
|
|
391
|
-
...
|
|
218
|
+
...(0, eslint_flat_config_utils.renamePluginsInRules)(inheritedRules, { "import-lite": "import" }),
|
|
392
219
|
"import/consistent-type-specifier-style": ["error", "top-level"],
|
|
393
220
|
"import/first": "error",
|
|
394
221
|
"import/no-duplicates": "error",
|
|
@@ -408,34 +235,6 @@ async function imports(options) {
|
|
|
408
235
|
}];
|
|
409
236
|
}
|
|
410
237
|
//#endregion
|
|
411
|
-
//#region src/configs/markdown.ts
|
|
412
|
-
const markdownDefaults = {
|
|
413
|
-
files: [mdGlob],
|
|
414
|
-
gfm: true
|
|
415
|
-
};
|
|
416
|
-
/**
|
|
417
|
-
* Markdown linting via `@eslint/markdown`.
|
|
418
|
-
* @param options - Markdown configuration options
|
|
419
|
-
* @returns Promise resolving to Markdown ESLint config items
|
|
420
|
-
*/
|
|
421
|
-
async function markdown(options) {
|
|
422
|
-
const resolved = (0, defu.defu)(options, markdownDefaults);
|
|
423
|
-
const markdownPlugin = await getModuleDefault(import("@eslint/markdown"));
|
|
424
|
-
return [{
|
|
425
|
-
name: "favorodera/markdown/rules",
|
|
426
|
-
files: resolved.files,
|
|
427
|
-
plugins: { md: markdownPlugin },
|
|
428
|
-
processor: (0, eslint_merge_processors.mergeProcessors)([markdownPlugin.processors?.markdown, eslint_merge_processors.processorPassThrough]),
|
|
429
|
-
language: resolved.gfm ? "md/gfm" : "md/commonmark",
|
|
430
|
-
rules: {
|
|
431
|
-
...renameRules(markdownPlugin.configs.recommended[0]?.rules || {}, { markdown: "md" }),
|
|
432
|
-
"md/fenced-code-language": "off",
|
|
433
|
-
"md/no-missing-label-refs": "off",
|
|
434
|
-
...resolved.overrides
|
|
435
|
-
}
|
|
436
|
-
}];
|
|
437
|
-
}
|
|
438
|
-
//#endregion
|
|
439
238
|
//#region src/configs/javascript.ts
|
|
440
239
|
const javascriptDefaults = { files: [
|
|
441
240
|
jsGlob,
|
|
@@ -449,9 +248,9 @@ const javascriptDefaults = { files: [
|
|
|
449
248
|
*/
|
|
450
249
|
async function javascript(options) {
|
|
451
250
|
const resolved = (0, defu.defu)(options, javascriptDefaults);
|
|
452
|
-
const
|
|
251
|
+
const inheritedRules = (await importModule(import("@eslint/js"))).configs.recommended.rules;
|
|
453
252
|
return [{
|
|
454
|
-
name: "favorodera/javascript
|
|
253
|
+
name: "favorodera/javascript",
|
|
455
254
|
files: resolved.files,
|
|
456
255
|
languageOptions: {
|
|
457
256
|
ecmaVersion: "latest",
|
|
@@ -466,189 +265,156 @@ async function javascript(options) {
|
|
|
466
265
|
}
|
|
467
266
|
},
|
|
468
267
|
linterOptions: { reportUnusedDisableDirectives: true },
|
|
469
|
-
plugins: { js: jsPlugin },
|
|
470
268
|
rules: {
|
|
471
|
-
...
|
|
269
|
+
...inheritedRules,
|
|
472
270
|
"accessor-pairs": ["error", {
|
|
473
271
|
enforceForClassMembers: true,
|
|
474
272
|
setWithoutGet: true
|
|
475
273
|
}],
|
|
476
274
|
"array-callback-return": "error",
|
|
477
275
|
"block-scoped-var": "error",
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
"
|
|
501
|
-
"no-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
"
|
|
536
|
-
"no-prototype-builtins": "error",
|
|
537
|
-
"no-redeclare": ["error", { builtinGlobals: false }],
|
|
538
|
-
"no-regex-spaces": "error",
|
|
539
|
-
"no-restricted-globals": [
|
|
540
|
-
"error",
|
|
541
|
-
{
|
|
542
|
-
message: "Use `globalThis` instead.",
|
|
543
|
-
name: "global"
|
|
544
|
-
},
|
|
545
|
-
{
|
|
546
|
-
message: "Use `globalThis` instead.",
|
|
547
|
-
name: "self"
|
|
548
|
-
}
|
|
549
|
-
],
|
|
550
|
-
"no-restricted-properties": [
|
|
551
|
-
"error",
|
|
552
|
-
{
|
|
553
|
-
message: "Use `Object.getPrototypeOf` or `Object.setPrototypeOf` instead.",
|
|
554
|
-
property: "__proto__"
|
|
555
|
-
},
|
|
556
|
-
{
|
|
557
|
-
message: "Use `Object.defineProperty` instead.",
|
|
558
|
-
property: "__defineGetter__"
|
|
559
|
-
},
|
|
560
|
-
{
|
|
561
|
-
message: "Use `Object.defineProperty` instead.",
|
|
562
|
-
property: "__defineSetter__"
|
|
563
|
-
},
|
|
564
|
-
{
|
|
565
|
-
message: "Use `Object.getOwnPropertyDescriptor` instead.",
|
|
566
|
-
property: "__lookupGetter__"
|
|
567
|
-
},
|
|
568
|
-
{
|
|
569
|
-
message: "Use `Object.getOwnPropertyDescriptor` instead.",
|
|
570
|
-
property: "__lookupSetter__"
|
|
571
|
-
}
|
|
572
|
-
],
|
|
573
|
-
"no-restricted-syntax": [
|
|
574
|
-
"error",
|
|
575
|
-
"TSEnumDeclaration[const=true]",
|
|
576
|
-
"TSExportAssignment"
|
|
577
|
-
],
|
|
578
|
-
"no-self-assign": ["error", { props: true }],
|
|
579
|
-
"no-self-compare": "error",
|
|
580
|
-
"no-sequences": "error",
|
|
581
|
-
"no-shadow-restricted-names": "error",
|
|
582
|
-
"no-sparse-arrays": "error",
|
|
583
|
-
"no-template-curly-in-string": "error",
|
|
584
|
-
"no-this-before-super": "error",
|
|
585
|
-
"no-throw-literal": "error",
|
|
586
|
-
"no-undef": "error",
|
|
587
|
-
"no-undef-init": "error",
|
|
588
|
-
"no-unexpected-multiline": "error",
|
|
589
|
-
"no-unmodified-loop-condition": "error",
|
|
590
|
-
"no-unneeded-ternary": ["error", { defaultAssignment: false }],
|
|
591
|
-
"no-unreachable": "error",
|
|
592
|
-
"no-unreachable-loop": "error",
|
|
593
|
-
"no-unsafe-finally": "error",
|
|
594
|
-
"no-unsafe-negation": "error",
|
|
595
|
-
"no-unused-expressions": ["error", {
|
|
596
|
-
allowShortCircuit: true,
|
|
597
|
-
allowTaggedTemplates: true,
|
|
598
|
-
allowTernary: true
|
|
599
|
-
}],
|
|
600
|
-
"no-unused-vars": ["error", {
|
|
601
|
-
args: "none",
|
|
602
|
-
caughtErrors: "none",
|
|
603
|
-
ignoreRestSiblings: true,
|
|
604
|
-
vars: "all"
|
|
605
|
-
}],
|
|
606
|
-
"no-use-before-define": ["error", {
|
|
607
|
-
classes: false,
|
|
608
|
-
functions: false,
|
|
609
|
-
variables: true
|
|
610
|
-
}],
|
|
611
|
-
"no-useless-backreference": "error",
|
|
612
|
-
"no-useless-call": "error",
|
|
613
|
-
"no-useless-catch": "error",
|
|
614
|
-
"no-useless-computed-key": "error",
|
|
615
|
-
"no-useless-constructor": "error",
|
|
616
|
-
"no-useless-rename": "error",
|
|
617
|
-
"no-useless-return": "error",
|
|
618
|
-
"no-var": "error",
|
|
619
|
-
"no-with": "error",
|
|
620
|
-
"object-shorthand": [
|
|
276
|
+
...resolved.overrides
|
|
277
|
+
}
|
|
278
|
+
}];
|
|
279
|
+
}
|
|
280
|
+
//#endregion
|
|
281
|
+
//#region src/configs/markdown.ts
|
|
282
|
+
const markdownDefaults = {
|
|
283
|
+
files: [mdGlob],
|
|
284
|
+
gfm: true
|
|
285
|
+
};
|
|
286
|
+
async function markdown(options) {
|
|
287
|
+
const resolved = (0, defu.defu)(options, markdownDefaults);
|
|
288
|
+
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
|
|
301
|
+
}
|
|
302
|
+
}];
|
|
303
|
+
}
|
|
304
|
+
//#endregion
|
|
305
|
+
//#region src/configs/stylistic.ts
|
|
306
|
+
const stylisticDefaults = {
|
|
307
|
+
settings: {
|
|
308
|
+
indent: 2,
|
|
309
|
+
experimental: false,
|
|
310
|
+
quotes: "single",
|
|
311
|
+
semi: false,
|
|
312
|
+
jsx: false
|
|
313
|
+
},
|
|
314
|
+
files: [
|
|
315
|
+
jsGlob,
|
|
316
|
+
tsGlob,
|
|
317
|
+
vueGlob
|
|
318
|
+
]
|
|
319
|
+
};
|
|
320
|
+
async function stylistic(options) {
|
|
321
|
+
const resolved = (0, defu.defu)(options, stylisticDefaults);
|
|
322
|
+
const config = (await importModule(import("@stylistic/eslint-plugin"))).configs.customize({
|
|
323
|
+
pluginName: "style",
|
|
324
|
+
...resolved.settings
|
|
325
|
+
});
|
|
326
|
+
const inheritedRules = config?.rules || {};
|
|
327
|
+
return [{
|
|
328
|
+
...config,
|
|
329
|
+
name: "favorodera/stylistic",
|
|
330
|
+
files: resolved.files,
|
|
331
|
+
rules: {
|
|
332
|
+
...inheritedRules,
|
|
333
|
+
"style/quotes": [
|
|
621
334
|
"error",
|
|
622
|
-
"
|
|
623
|
-
{
|
|
624
|
-
avoidQuotes: true,
|
|
625
|
-
ignoreConstructors: false
|
|
626
|
-
}
|
|
335
|
+
"single",
|
|
336
|
+
{ avoidEscape: true }
|
|
627
337
|
],
|
|
628
|
-
"
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
338
|
+
"style/no-multiple-empty-lines": ["error", {
|
|
339
|
+
max: 2,
|
|
340
|
+
maxEOF: 2,
|
|
341
|
+
maxBOF: 0
|
|
632
342
|
}],
|
|
633
|
-
"
|
|
634
|
-
|
|
635
|
-
|
|
343
|
+
"style/padded-blocks": "off",
|
|
344
|
+
"style/no-trailing-spaces": ["error", { skipBlankLines: true }],
|
|
345
|
+
"style/brace-style": "off",
|
|
346
|
+
"style/generator-star-spacing": ["error", {
|
|
347
|
+
after: true,
|
|
348
|
+
before: false
|
|
636
349
|
}],
|
|
637
|
-
"
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
"prefer-rest-params": "error",
|
|
641
|
-
"prefer-spread": "error",
|
|
642
|
-
"prefer-template": "error",
|
|
643
|
-
"symbol-description": "error",
|
|
644
|
-
"unicode-bom": ["error", "never"],
|
|
645
|
-
"use-isnan": ["error", {
|
|
646
|
-
enforceForIndexOf: true,
|
|
647
|
-
enforceForSwitchCase: true
|
|
350
|
+
"style/yield-star-spacing": ["error", {
|
|
351
|
+
after: true,
|
|
352
|
+
before: false
|
|
648
353
|
}],
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
354
|
+
...resolved.overrides
|
|
355
|
+
}
|
|
356
|
+
}];
|
|
357
|
+
}
|
|
358
|
+
//#endregion
|
|
359
|
+
//#region src/configs/tailwind.ts
|
|
360
|
+
const tailwindDefaults = {
|
|
361
|
+
files: [
|
|
362
|
+
jsGlob,
|
|
363
|
+
tsGlob,
|
|
364
|
+
vueGlob
|
|
365
|
+
],
|
|
366
|
+
settings: { detectComponentClasses: true }
|
|
367
|
+
};
|
|
368
|
+
/**
|
|
369
|
+
* Tailwind linting via `eslint-plugin-better-tailwindcss`.
|
|
370
|
+
* @param options - Tailwind configuration options
|
|
371
|
+
* @returns Promise resolving to Tailwind ESLint config items
|
|
372
|
+
*/
|
|
373
|
+
async function tailwind(options) {
|
|
374
|
+
const resolved = (0, defu.defu)(options, tailwindDefaults);
|
|
375
|
+
const tailwindPlugin = await importModule(import("eslint-plugin-better-tailwindcss"));
|
|
376
|
+
const inheritedRules = {
|
|
377
|
+
...tailwindPlugin.configs["recommended-error"].rules,
|
|
378
|
+
...tailwindPlugin.configs["stylistic-error"].rules
|
|
379
|
+
};
|
|
380
|
+
return [{
|
|
381
|
+
name: "favorodera/tailwind",
|
|
382
|
+
files: resolved.files,
|
|
383
|
+
plugins: { tailwind: tailwindPlugin },
|
|
384
|
+
settings: { tailwindcss: resolved.settings },
|
|
385
|
+
rules: {
|
|
386
|
+
...(0, eslint_flat_config_utils.renamePluginsInRules)(inheritedRules, { "better-tailwindcss": "tailwind" }),
|
|
387
|
+
"tailwind/no-unregistered-classes": "off",
|
|
388
|
+
"tailwind/enforce-consistent-line-wrapping": ["error", { group: "emptyLine" }],
|
|
389
|
+
...resolved.overrides
|
|
390
|
+
}
|
|
391
|
+
}];
|
|
392
|
+
}
|
|
393
|
+
//#endregion
|
|
394
|
+
//#region src/configs/typescript.ts
|
|
395
|
+
const typescriptDefaults = { files: [tsGlob] };
|
|
396
|
+
/**
|
|
397
|
+
* Typescript linting via `typescript-eslint`.
|
|
398
|
+
* @param options - TypeScript configuration options
|
|
399
|
+
* @returns Array of TypeScript ESLint config items
|
|
400
|
+
*/
|
|
401
|
+
async function typescript(options) {
|
|
402
|
+
const resolved = (0, defu.defu)(options, typescriptDefaults);
|
|
403
|
+
const tsEsLint = await importModule(import("typescript-eslint"));
|
|
404
|
+
const inheritedRules = Object.assign({}, ...[...tsEsLint.configs.recommended, ...tsEsLint.configs.strict].map((config) => config?.rules || {}));
|
|
405
|
+
return [{
|
|
406
|
+
name: "favorodera/typescript",
|
|
407
|
+
plugins: { ts: tsEsLint.plugin },
|
|
408
|
+
languageOptions: {
|
|
409
|
+
parser: tsEsLint.parser,
|
|
410
|
+
parserOptions: { sourceType: "module" }
|
|
411
|
+
},
|
|
412
|
+
files: resolved.files,
|
|
413
|
+
rules: {
|
|
414
|
+
...(0, eslint_flat_config_utils.renamePluginsInRules)(inheritedRules, { "@typescript-eslint": "ts" }),
|
|
415
|
+
"ts/consistent-type-imports": ["error", { prefer: "type-imports" }],
|
|
416
|
+
"ts/no-empty-object-type": ["error", { allowInterfaces: "with-single-extends" }],
|
|
417
|
+
"ts/array-type": ["error", { default: "array" }],
|
|
652
418
|
...resolved.overrides
|
|
653
419
|
}
|
|
654
420
|
}];
|
|
@@ -663,27 +429,29 @@ async function javascript(options) {
|
|
|
663
429
|
function factory(options = {}) {
|
|
664
430
|
const configs = [];
|
|
665
431
|
configs.push(ignores(options.ignores));
|
|
666
|
-
const
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
if (markdownOptions) configs.push(markdown(markdownOptions));
|
|
681
|
-
if (javascriptOptions) configs.push(javascript(javascriptOptions));
|
|
432
|
+
const configFunctions = {
|
|
433
|
+
vue,
|
|
434
|
+
typescript,
|
|
435
|
+
stylistic,
|
|
436
|
+
tailwind,
|
|
437
|
+
imports,
|
|
438
|
+
markdown,
|
|
439
|
+
javascript
|
|
440
|
+
};
|
|
441
|
+
for (const [key, configFunction] of Object.entries(configFunctions)) {
|
|
442
|
+
const configOption = options[key];
|
|
443
|
+
const resolved = resolveOptions(configOption ?? true, {});
|
|
444
|
+
if (resolved) configs.push(configFunction(resolved));
|
|
445
|
+
}
|
|
682
446
|
let composer = new eslint_flat_config_utils.FlatConfigComposer();
|
|
683
|
-
composer = composer.append(...configs)
|
|
447
|
+
composer = composer.append(...configs).renamePlugins({
|
|
448
|
+
"better-tailwindcss": "tailwind",
|
|
449
|
+
"@typescript-eslint": "ts",
|
|
450
|
+
"markdown": "md",
|
|
451
|
+
"import-lite": "import"
|
|
452
|
+
});
|
|
684
453
|
return composer;
|
|
685
454
|
}
|
|
686
455
|
//#endregion
|
|
687
456
|
exports.factory = factory;
|
|
688
|
-
exports.
|
|
689
|
-
exports.renameRules = renameRules;
|
|
457
|
+
exports.importModule = importModule;
|