@fabdeh/eslint-config 0.10.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +201 -15
- package/dist/index.d.mts +15442 -13862
- package/dist/index.mjs +413 -178
- package/package.json +7 -5
package/dist/index.mjs
CHANGED
|
@@ -1,21 +1,60 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { statSync } from "node:fs";
|
|
3
|
-
import { readFile } from "node:fs/promises";
|
|
1
|
+
import { readFileSync, statSync } from "node:fs";
|
|
4
2
|
import { dirname, join, normalize, resolve } from "node:path";
|
|
5
3
|
import process from "node:process";
|
|
6
|
-
import {
|
|
4
|
+
import { globSync } from "glob";
|
|
7
5
|
import { isPackageExists } from "local-pkg";
|
|
8
6
|
import eslintComments from "@eslint-community/eslint-plugin-eslint-comments";
|
|
9
7
|
import * as importX from "eslint-plugin-import-x";
|
|
10
8
|
import preferArrowFunctions from "eslint-plugin-prefer-arrow-functions";
|
|
11
9
|
import unusedImports from "eslint-plugin-unused-imports";
|
|
12
10
|
import globals from "globals";
|
|
11
|
+
import tseslint from "typescript-eslint";
|
|
13
12
|
import jsdocPlugin from "eslint-plugin-jsdoc";
|
|
14
13
|
import { mergeProcessors, processorPassThrough } from "eslint-merge-processors";
|
|
15
14
|
import nodePlugin from "eslint-plugin-n";
|
|
16
15
|
import perfectionistPlugin from "eslint-plugin-perfectionist";
|
|
16
|
+
import { readFile } from "node:fs/promises";
|
|
17
|
+
import { findUp, findUpSync } from "find-up-simple";
|
|
17
18
|
import { configs } from "eslint-plugin-regexp";
|
|
18
19
|
import unicornPlugin from "eslint-plugin-unicorn";
|
|
20
|
+
import { FlatConfigComposer } from "eslint-flat-config-utils";
|
|
21
|
+
//#region src/config-presets.ts
|
|
22
|
+
const CONFIG_PRESET_FULL_ON = {
|
|
23
|
+
angular: true,
|
|
24
|
+
gitignore: true,
|
|
25
|
+
jsdoc: true,
|
|
26
|
+
jsonc: true,
|
|
27
|
+
markdown: true,
|
|
28
|
+
ngrx: true,
|
|
29
|
+
playwright: true,
|
|
30
|
+
pnpm: true,
|
|
31
|
+
regexp: true,
|
|
32
|
+
stylistic: { experimental: true },
|
|
33
|
+
tailwindcss: true,
|
|
34
|
+
toml: true,
|
|
35
|
+
typescript: { enableErasableSyntaxOnly: true },
|
|
36
|
+
unicorn: true,
|
|
37
|
+
vitest: true,
|
|
38
|
+
yaml: true
|
|
39
|
+
};
|
|
40
|
+
const CONFIG_PRESET_FULL_OFF = {
|
|
41
|
+
angular: false,
|
|
42
|
+
gitignore: false,
|
|
43
|
+
jsdoc: false,
|
|
44
|
+
jsonc: false,
|
|
45
|
+
markdown: false,
|
|
46
|
+
ngrx: false,
|
|
47
|
+
playwright: false,
|
|
48
|
+
pnpm: false,
|
|
49
|
+
regexp: false,
|
|
50
|
+
stylistic: false,
|
|
51
|
+
tailwindcss: false,
|
|
52
|
+
toml: false,
|
|
53
|
+
typescript: false,
|
|
54
|
+
unicorn: false,
|
|
55
|
+
vitest: false,
|
|
56
|
+
yaml: false
|
|
57
|
+
};
|
|
19
58
|
/**
|
|
20
59
|
* A glob pattern that matches JavaScript and TypeScript source files (including JSX/TSX).
|
|
21
60
|
*/
|
|
@@ -167,7 +206,7 @@ function isDirectory(path) {
|
|
|
167
206
|
* @returns The root directory of the workspace.
|
|
168
207
|
*/
|
|
169
208
|
function getWorkspaceRoot(dir, candidateRoot) {
|
|
170
|
-
if (process.env
|
|
209
|
+
if (process.env["NX_WORKSPACE_ROOT"]) return process.env["NX_WORKSPACE_ROOT"];
|
|
171
210
|
if (dirname(dir) === dir) return candidateRoot;
|
|
172
211
|
if ([
|
|
173
212
|
join(dir, "nx.json"),
|
|
@@ -211,12 +250,38 @@ function isPackageInScope(name) {
|
|
|
211
250
|
* @returns A promise that resolves when the operation is complete.
|
|
212
251
|
*/
|
|
213
252
|
async function ensurePackages(packages) {
|
|
214
|
-
if (process.env
|
|
253
|
+
if (process.env["CI"] || !process.stdout.isTTY || !IS_CWD_IN_SCOPE) return;
|
|
215
254
|
const nonExistingPackages = packages.filter((i) => i && !isPackageInScope(i));
|
|
216
255
|
if (nonExistingPackages.length === 0) return;
|
|
217
256
|
if (await (await import("@clack/prompts")).confirm({ message: `${nonExistingPackages.length === 1 ? "Package is" : "Packages are"} required for this config: ${nonExistingPackages.join(", ")}. Do you want to install them?` })) await import("@antfu/install-pkg").then((i) => i.installPackage(nonExistingPackages, { dev: true }));
|
|
218
257
|
}
|
|
219
258
|
/**
|
|
259
|
+
* Detects whether the current process is running in an interactive editor environment.
|
|
260
|
+
*
|
|
261
|
+
* The check returns `false` in CI and Git hook\/`lint-staged` contexts to avoid
|
|
262
|
+
* editor-specific behavior in non-interactive executions.
|
|
263
|
+
*
|
|
264
|
+
* Editor detection is based on common environment variables from VS Code,
|
|
265
|
+
* JetBrains IDEs, Vim\/Neovim, and Zed.
|
|
266
|
+
*
|
|
267
|
+
* @returns `true` when execution appears to be inside a supported editor; otherwise `false`.
|
|
268
|
+
*/
|
|
269
|
+
function isInEditorEnv() {
|
|
270
|
+
if (process.env["CI"]) return false;
|
|
271
|
+
if (isInGitHooksOrLintStaged()) return false;
|
|
272
|
+
return !!(process.env["VSCODE_PID"] || process.env["VSCODE_CWD"] || process.env["JETBRAINS_IDE"] || process.env["VIM"] || process.env["NVIM"] || process.env["ZED_ENVIRONMENT"] && !process.env["ZED_TERM"]);
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Detects whether the current process is running from a Git hook or `lint\-staged`.
|
|
276
|
+
*
|
|
277
|
+
* It checks common environment variables set by Git tooling and npm lifecycle scripts.
|
|
278
|
+
*
|
|
279
|
+
* @returns `true` when execution appears to be in a Git hook or `lint\-staged` context.
|
|
280
|
+
*/
|
|
281
|
+
function isInGitHooksOrLintStaged() {
|
|
282
|
+
return !!(process.env["GIT_PARAMS"] || process.env["VSCODE_GIT_COMMAND"] || process.env["npm_lifecycle_script"]?.startsWith("lint-staged") || process.env["npm_lifecycle_script"]?.startsWith("nano-staged"));
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
220
285
|
* Returns the object representation of the configuration or an empty object if it is a boolean.
|
|
221
286
|
*
|
|
222
287
|
* @param options - The {@link DefineConfigOptions} object to extract the sub-options from.
|
|
@@ -277,10 +342,10 @@ function pathToGlobPattern(options) {
|
|
|
277
342
|
*
|
|
278
343
|
* @returns Absolute path to the first existing Playwright test directory, or `undefined` if none is found.
|
|
279
344
|
*/
|
|
280
|
-
|
|
281
|
-
const playwrightConfigs =
|
|
345
|
+
function getPlaywrightDirectory() {
|
|
346
|
+
const playwrightConfigs = globSync("**/playwright.config.ts", { ignore: ["**/node_modules/**"] });
|
|
282
347
|
for (const config of playwrightConfigs) try {
|
|
283
|
-
const configContent =
|
|
348
|
+
const configContent = readFileSync(config, "utf-8");
|
|
284
349
|
const match = /testDir:\s*["'](.+)["'],?/.exec(configContent);
|
|
285
350
|
if (match) {
|
|
286
351
|
const testDir = match[1];
|
|
@@ -296,15 +361,17 @@ async function getPlaywrightDirectory() {
|
|
|
296
361
|
*
|
|
297
362
|
* @param options - Configuration options for Angular ESLint.
|
|
298
363
|
* @param options.enableAccessibilityRules - Whether to enable accessibility rules for HTML templates.
|
|
299
|
-
* @param options.tsOverrides - Additional TypeScript rule overrides.
|
|
300
|
-
* @param options.htmlOverrides - Additional HTML rule overrides.
|
|
301
364
|
* @param options.prefix - The prefix to use for Angular component and directive selectors.
|
|
302
365
|
* @returns A promise that resolves to an array of ESLint configurations.
|
|
303
366
|
*/
|
|
304
367
|
async function angular(options = {}) {
|
|
305
368
|
const angularEslint = await interopDefault(import("angular-eslint"));
|
|
306
|
-
const { enableAccessibilityRules = true,
|
|
307
|
-
|
|
369
|
+
const { enableAccessibilityRules = true, overrides = {}, prefix = "app", ignoreClassNamePatternForInjectableProvidedIn: ignoreClassNamePattern, componentStylesMode = "string", preferOnPushOnly = true, banExperimentalApi = true, banDeveloperPreviewApi = true, inlineTemplateAndStyles = false } = options;
|
|
370
|
+
const tsOverrides = {};
|
|
371
|
+
const htmlOverrides = {};
|
|
372
|
+
for (const [key, value] of Object.entries(overrides)) if (key.startsWith("@angular-eslint/template/")) htmlOverrides[key] = value;
|
|
373
|
+
else if (key.startsWith("@angular-eslint/")) tsOverrides[key] = value;
|
|
374
|
+
return [{
|
|
308
375
|
name: "fabdeh/angular/rules",
|
|
309
376
|
plugins: { "@angular-eslint": angularEslint.tsPlugin },
|
|
310
377
|
processor: angularEslint.processInlineTemplates,
|
|
@@ -392,7 +459,7 @@ async function angular(options = {}) {
|
|
|
392
459
|
...enableAccessibilityRules ? angularEslint.configs.templateAccessibility.find((c) => c.name === "angular-eslint/template-accessibility")?.rules : {},
|
|
393
460
|
...htmlOverrides
|
|
394
461
|
}
|
|
395
|
-
}
|
|
462
|
+
}];
|
|
396
463
|
}
|
|
397
464
|
//#endregion
|
|
398
465
|
//#region src/configs/comments.ts
|
|
@@ -406,7 +473,7 @@ async function angular(options = {}) {
|
|
|
406
473
|
* @returns The configuration array for ESLint comments rules.
|
|
407
474
|
*/
|
|
408
475
|
function comments() {
|
|
409
|
-
return
|
|
476
|
+
return [{
|
|
410
477
|
name: "fabdeh/comments/rules",
|
|
411
478
|
files: [GLOB_SRC],
|
|
412
479
|
plugins: { "@eslint-community/eslint-comments": eslintComments },
|
|
@@ -418,7 +485,7 @@ function comments() {
|
|
|
418
485
|
"@eslint-community/eslint-comments/no-unused-disable": "error",
|
|
419
486
|
"@eslint-community/eslint-comments/no-unused-enable": "error"
|
|
420
487
|
}
|
|
421
|
-
}
|
|
488
|
+
}];
|
|
422
489
|
}
|
|
423
490
|
//#endregion
|
|
424
491
|
//#region src/configs/ignore.ts
|
|
@@ -427,13 +494,13 @@ function comments() {
|
|
|
427
494
|
*
|
|
428
495
|
* @param userIgnores - An array of user-defined glob patterns to ignore. Defaults to an empty array.
|
|
429
496
|
* @param fromFactory - An optional suffix to add to the config name.
|
|
430
|
-
* @returns A
|
|
497
|
+
* @returns A TypedConfig[] object containing the combined "ignore" patterns.
|
|
431
498
|
*/
|
|
432
499
|
function ignores(userIgnores = [], fromFactory) {
|
|
433
|
-
return
|
|
500
|
+
return [{
|
|
434
501
|
name: `fabdeh/ignores${fromFactory ? `/${fromFactory}` : ""}`,
|
|
435
502
|
ignores: [...!fromFactory || fromFactory === "workspace" ? GLOB_EXCLUDE : [], ...userIgnores]
|
|
436
|
-
}
|
|
503
|
+
}];
|
|
437
504
|
}
|
|
438
505
|
//#endregion
|
|
439
506
|
//#region src/configs/imports.ts
|
|
@@ -442,11 +509,11 @@ function ignores(userIgnores = [], fromFactory) {
|
|
|
442
509
|
*
|
|
443
510
|
* @param options - An object containing stylistic options.
|
|
444
511
|
* @param options.stylistic - A boolean indicating whether to include stylistic rules. Defaults to true.
|
|
445
|
-
* @returns A
|
|
512
|
+
* @returns A TypedConfig[] object with the specified import rules.
|
|
446
513
|
*/
|
|
447
514
|
function imports(options = {}) {
|
|
448
515
|
const { stylistic = true } = options;
|
|
449
|
-
return
|
|
516
|
+
return [{
|
|
450
517
|
name: "fabdeh/imports/rules",
|
|
451
518
|
files: [GLOB_SRC],
|
|
452
519
|
plugins: { "import-x": importX },
|
|
@@ -480,7 +547,7 @@ function imports(options = {}) {
|
|
|
480
547
|
"import-x/named": "off",
|
|
481
548
|
"import-x/no-deprecated": "off"
|
|
482
549
|
}
|
|
483
|
-
}
|
|
550
|
+
}];
|
|
484
551
|
}
|
|
485
552
|
//#endregion
|
|
486
553
|
//#region src/configs/javascript.ts
|
|
@@ -500,8 +567,8 @@ function imports(options = {}) {
|
|
|
500
567
|
* ```
|
|
501
568
|
*/
|
|
502
569
|
function javascript(options = {}) {
|
|
503
|
-
const { overrides = {} } = options;
|
|
504
|
-
return
|
|
570
|
+
const { isInEditor = false, overrides = {} } = options;
|
|
571
|
+
return [{
|
|
505
572
|
name: "fabdeh/javascript/setup",
|
|
506
573
|
languageOptions: {
|
|
507
574
|
ecmaVersion: "latest",
|
|
@@ -716,7 +783,10 @@ function javascript(options = {}) {
|
|
|
716
783
|
singleReturnOnly: true,
|
|
717
784
|
allowNamedFunctions: true
|
|
718
785
|
}],
|
|
719
|
-
"prefer-const": "error",
|
|
786
|
+
"prefer-const": [isInEditor ? "warn" : "error", {
|
|
787
|
+
destructuring: "all",
|
|
788
|
+
ignoreReadBeforeAssign: true
|
|
789
|
+
}],
|
|
720
790
|
"prefer-exponentiation-operator": "error",
|
|
721
791
|
"prefer-object-spread": "error",
|
|
722
792
|
"prefer-promise-reject-errors": "error",
|
|
@@ -729,7 +799,7 @@ function javascript(options = {}) {
|
|
|
729
799
|
"symbol-description": "error",
|
|
730
800
|
"unicode-bom": ["error", "never"],
|
|
731
801
|
"use-isnan": ["error", { enforceForIndexOf: true }],
|
|
732
|
-
"unused-imports/no-unused-imports": "error",
|
|
802
|
+
"unused-imports/no-unused-imports": isInEditor ? "warn" : "error",
|
|
733
803
|
"unused-imports/no-unused-vars": ["error", {
|
|
734
804
|
args: "after-used",
|
|
735
805
|
argsIgnorePattern: "^_",
|
|
@@ -752,7 +822,7 @@ function javascript(options = {}) {
|
|
|
752
822
|
"@typescript-eslint/no-this-alias": "error",
|
|
753
823
|
...overrides
|
|
754
824
|
}
|
|
755
|
-
}
|
|
825
|
+
}];
|
|
756
826
|
}
|
|
757
827
|
//#endregion
|
|
758
828
|
//#region src/configs/jsdoc.ts
|
|
@@ -828,7 +898,7 @@ function getJsDocRules(level, stylistic, mode) {
|
|
|
828
898
|
*/
|
|
829
899
|
function jsdoc(options = {}) {
|
|
830
900
|
const { stylistic = true } = options;
|
|
831
|
-
return
|
|
901
|
+
return [{
|
|
832
902
|
name: "fabdeh/jsdoc/rules",
|
|
833
903
|
files: [GLOB_SRC],
|
|
834
904
|
plugins: { jsdoc: jsdocPlugin },
|
|
@@ -837,7 +907,7 @@ function jsdoc(options = {}) {
|
|
|
837
907
|
name: "fabdeh/jsdoc/ts-only/rules",
|
|
838
908
|
files: [GLOB_TS],
|
|
839
909
|
rules: getJsDocRules("warn", !!stylistic, "tsOnly")
|
|
840
|
-
}
|
|
910
|
+
}];
|
|
841
911
|
}
|
|
842
912
|
//#endregion
|
|
843
913
|
//#region src/configs/jsonc.ts
|
|
@@ -848,7 +918,7 @@ function jsdoc(options = {}) {
|
|
|
848
918
|
* @param options.files - An array of glob patterns to specify the JSONC files to lint. Defaults to `[GLOB_JSON, GLOB_JSON5, GLOB_JSONC]`.
|
|
849
919
|
* @param options.overrides - Additional rules or configurations to override the default settings.
|
|
850
920
|
* @param options.stylistic - A boolean or object to enable or configure stylistic rules. Defaults to `true`.
|
|
851
|
-
* @returns A promise that resolves to a `
|
|
921
|
+
* @returns A promise that resolves to a `TypedConfig[]` containing the ESLint configuration.
|
|
852
922
|
* @example
|
|
853
923
|
* ```typescript
|
|
854
924
|
* const config = await jsonc({
|
|
@@ -867,7 +937,7 @@ async function jsonc(options = {}) {
|
|
|
867
937
|
], overrides = {}, stylistic = true } = options;
|
|
868
938
|
const { indent = 2 } = typeof stylistic === "object" ? stylistic : {};
|
|
869
939
|
const [jsoncPlugin, jsoncParser] = await Promise.all([interopDefault(import("eslint-plugin-jsonc")), interopDefault(import("jsonc-eslint-parser"))]);
|
|
870
|
-
return
|
|
940
|
+
return [{
|
|
871
941
|
name: "fabdeh/jsonc/setup",
|
|
872
942
|
plugins: { jsonc: jsoncPlugin }
|
|
873
943
|
}, {
|
|
@@ -921,7 +991,7 @@ async function jsonc(options = {}) {
|
|
|
921
991
|
} : {},
|
|
922
992
|
...overrides
|
|
923
993
|
}
|
|
924
|
-
}
|
|
994
|
+
}];
|
|
925
995
|
}
|
|
926
996
|
//#endregion
|
|
927
997
|
//#region src/configs/markdown.ts
|
|
@@ -934,7 +1004,7 @@ async function jsonc(options = {}) {
|
|
|
934
1004
|
* @param options - An object containing file and override options.
|
|
935
1005
|
* @param options.files - An array of glob patterns to specify the Markdown files to lint.
|
|
936
1006
|
* @param options.overrides - An object containing rule overrides.
|
|
937
|
-
* @returns A promise that resolves to a
|
|
1007
|
+
* @returns A promise that resolves to a TypedConfig[] containing the ESLint configurations.
|
|
938
1008
|
* @example
|
|
939
1009
|
* ```typescript
|
|
940
1010
|
* const config = await markdown({
|
|
@@ -948,75 +1018,81 @@ async function jsonc(options = {}) {
|
|
|
948
1018
|
async function markdown(options = {}) {
|
|
949
1019
|
const { files = [GLOB_MARKDOWN], overrides = {} } = options;
|
|
950
1020
|
const markdownPlugin = await interopDefault(import("@eslint/markdown"));
|
|
951
|
-
return
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
1021
|
+
return [
|
|
1022
|
+
{
|
|
1023
|
+
name: "fabdeh/markdown/setup",
|
|
1024
|
+
plugins: { markdown: markdownPlugin }
|
|
1025
|
+
},
|
|
1026
|
+
{
|
|
1027
|
+
name: "fabdeh/markdown/processor",
|
|
1028
|
+
files,
|
|
1029
|
+
ignores: [GLOB_MARKDOWN_IN_MARKDOWN],
|
|
1030
|
+
processor: mergeProcessors([markdownPlugin.processors.markdown, processorPassThrough])
|
|
1031
|
+
},
|
|
1032
|
+
{
|
|
1033
|
+
name: "fabdeh/markdown/parser",
|
|
1034
|
+
files,
|
|
1035
|
+
languageOptions: { parser: {
|
|
1036
|
+
meta: { name: "parser-plain" },
|
|
1037
|
+
parseForESLint: (code) => ({
|
|
1038
|
+
ast: {
|
|
1039
|
+
body: [],
|
|
1040
|
+
comments: [],
|
|
1041
|
+
loc: {
|
|
1042
|
+
end: code.length,
|
|
1043
|
+
start: 0
|
|
1044
|
+
},
|
|
1045
|
+
range: [0, code.length],
|
|
1046
|
+
tokens: [],
|
|
1047
|
+
type: "Program"
|
|
971
1048
|
},
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
}
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
"markdown/no-duplicate-headings": "error"
|
|
1049
|
+
scopeManager: null,
|
|
1050
|
+
services: { isPlain: true },
|
|
1051
|
+
visitorKeys: { Program: [] }
|
|
1052
|
+
})
|
|
1053
|
+
} }
|
|
1054
|
+
},
|
|
1055
|
+
{
|
|
1056
|
+
name: "fabdeh/markdown/disables",
|
|
1057
|
+
languageOptions: { parserOptions: { ecmaFeatures: { impliedStrict: true } } },
|
|
1058
|
+
files: [GLOB_MARKDOWN_CODE],
|
|
1059
|
+
rules: {
|
|
1060
|
+
...tseslint.configs.disableTypeChecked.rules,
|
|
1061
|
+
"import-x/newline-after-import": "off",
|
|
1062
|
+
"no-alert": "off",
|
|
1063
|
+
"no-console": "off",
|
|
1064
|
+
"no-labels": "off",
|
|
1065
|
+
"no-lone-blocks": "off",
|
|
1066
|
+
"no-restricted-syntax": "off",
|
|
1067
|
+
"no-undef": "off",
|
|
1068
|
+
"no-unused-expressions": "off",
|
|
1069
|
+
"no-unused-labels": "off",
|
|
1070
|
+
"no-unused-vars": "off",
|
|
1071
|
+
"@stylistic/comma-dangle": "off",
|
|
1072
|
+
"@stylistic/eol-last": "off",
|
|
1073
|
+
"@typescript-eslint/consistent-type-imports": "off",
|
|
1074
|
+
"@typescript-eslint/explicit-function-return-type": "off",
|
|
1075
|
+
"@typescript-eslint/no-namespace": "off",
|
|
1076
|
+
"@typescript-eslint/no-redeclare": "off",
|
|
1077
|
+
"@typescript-eslint/no-require-imports": "off",
|
|
1078
|
+
"@typescript-eslint/no-unused-expressions": "off",
|
|
1079
|
+
"@typescript-eslint/no-unused-vars": "off",
|
|
1080
|
+
"@typescript-eslint/no-use-before-define": "off",
|
|
1081
|
+
"unicode-bom": "off",
|
|
1082
|
+
"unused-imports/no-unused-imports": "off",
|
|
1083
|
+
"unused-imports/no-unused-vars": "off",
|
|
1084
|
+
...overrides
|
|
1085
|
+
}
|
|
1086
|
+
},
|
|
1087
|
+
{
|
|
1088
|
+
name: "fabdeh/markdown/rules",
|
|
1089
|
+
files,
|
|
1090
|
+
rules: {
|
|
1091
|
+
...markdownPlugin.configs.recommended.at(0)?.rules,
|
|
1092
|
+
"markdown/no-duplicate-headings": "error"
|
|
1093
|
+
}
|
|
1018
1094
|
}
|
|
1019
|
-
|
|
1095
|
+
];
|
|
1020
1096
|
}
|
|
1021
1097
|
//#endregion
|
|
1022
1098
|
//#region src/configs/rules-configs/naming-convention.ts
|
|
@@ -1127,15 +1203,16 @@ async function ngrx(options = {}) {
|
|
|
1127
1203
|
const { store = isPackageExists("@ngrx/store"), effects = isPackageExists("@ngrx/effects"), signals = isPackageExists("@ngrx/signals"), useRelaxedNamingConventionForCamelAndPascalCases = false } = options;
|
|
1128
1204
|
const configs = [];
|
|
1129
1205
|
let addOperatorsRules = false;
|
|
1206
|
+
const registerPluginFiles = [];
|
|
1130
1207
|
const ngrxOperatorsFiles = [];
|
|
1131
1208
|
if (store) {
|
|
1132
1209
|
const { files = DEFAULT_STORE_GLOB, enforceOperatorsRules = isPackageExists("@ngrx/operators"), overrides = {} } = typeof store === "object" ? store : {};
|
|
1133
1210
|
addOperatorsRules ||= enforceOperatorsRules;
|
|
1134
1211
|
ngrxOperatorsFiles.push(files);
|
|
1212
|
+
registerPluginFiles.push(files);
|
|
1135
1213
|
configs.push({
|
|
1136
1214
|
name: "fabdeh/ngrx-store/rules",
|
|
1137
1215
|
files,
|
|
1138
|
-
plugins: { "@ngrx": ngrxPlugin },
|
|
1139
1216
|
rules: {
|
|
1140
1217
|
...ngrxPlugin.configs.store.find((c) => c.name === "ngrx/store")?.rules,
|
|
1141
1218
|
"@typescript-eslint/naming-convention": [
|
|
@@ -1169,10 +1246,10 @@ async function ngrx(options = {}) {
|
|
|
1169
1246
|
const { files = DEFAULT_EFFECTS_GLOB, enforceOperatorsRules = isPackageExists("@ngrx/operators"), overrides = {} } = typeof effects === "object" ? effects : {};
|
|
1170
1247
|
addOperatorsRules ||= enforceOperatorsRules;
|
|
1171
1248
|
ngrxOperatorsFiles.push(files);
|
|
1249
|
+
registerPluginFiles.push(files);
|
|
1172
1250
|
configs.push({
|
|
1173
1251
|
name: "fabdeh/ngrx-effects/rules",
|
|
1174
1252
|
files,
|
|
1175
|
-
plugins: { "@ngrx": ngrxPlugin },
|
|
1176
1253
|
rules: {
|
|
1177
1254
|
...ngrxPlugin.configs.effects.find((c) => c.name === "ngrx/effects")?.rules,
|
|
1178
1255
|
"@typescript-eslint/naming-convention": [
|
|
@@ -1199,10 +1276,10 @@ async function ngrx(options = {}) {
|
|
|
1199
1276
|
const { files = DEFAULT_SIGNALS_GLOB, enforceOperatorsRules = isPackageExists("@ngrx/operators"), overrides = {} } = typeof signals === "object" ? signals : {};
|
|
1200
1277
|
addOperatorsRules ||= enforceOperatorsRules;
|
|
1201
1278
|
ngrxOperatorsFiles.push(files);
|
|
1279
|
+
registerPluginFiles.push(files);
|
|
1202
1280
|
configs.push({
|
|
1203
1281
|
name: "fabdeh/ngrx-signals/rules",
|
|
1204
1282
|
files,
|
|
1205
|
-
plugins: { "@ngrx": ngrxPlugin },
|
|
1206
1283
|
rules: {
|
|
1207
1284
|
...ngrxPlugin.configs.signals.find((c) => c.name === "ngrx/signals")?.rules,
|
|
1208
1285
|
"@typescript-eslint/naming-convention": [
|
|
@@ -1233,10 +1310,14 @@ async function ngrx(options = {}) {
|
|
|
1233
1310
|
if (addOperatorsRules) configs.push({
|
|
1234
1311
|
name: "fabdeh/ngrx-operators/rules",
|
|
1235
1312
|
files: [...ngrxOperatorsFiles],
|
|
1236
|
-
plugins: { "@ngrx": ngrxPlugin },
|
|
1237
1313
|
rules: { ...ngrxPlugin.configs.operators.find((c) => c.name === "ngrx/operators")?.rules }
|
|
1238
1314
|
});
|
|
1239
|
-
|
|
1315
|
+
if (registerPluginFiles.length > 0) configs.unshift({
|
|
1316
|
+
name: "fabdeh/ngrx/setup",
|
|
1317
|
+
files: [...registerPluginFiles],
|
|
1318
|
+
plugins: { "@ngrx": ngrxPlugin.configs.store.find((c) => c.name === "ngrx/base")?.plugins?.["@ngrx"] ?? {} }
|
|
1319
|
+
});
|
|
1320
|
+
return configs;
|
|
1240
1321
|
}
|
|
1241
1322
|
//#endregion
|
|
1242
1323
|
//#region src/configs/node.ts
|
|
@@ -1246,7 +1327,7 @@ async function ngrx(options = {}) {
|
|
|
1246
1327
|
* @returns An array defining Node.js rules, plugins, and their configurations.
|
|
1247
1328
|
*/
|
|
1248
1329
|
function node() {
|
|
1249
|
-
return
|
|
1330
|
+
return [{
|
|
1250
1331
|
name: "fabdeh/node/rules",
|
|
1251
1332
|
files: [GLOB_SRC],
|
|
1252
1333
|
plugins: { n: nodePlugin },
|
|
@@ -1263,7 +1344,7 @@ function node() {
|
|
|
1263
1344
|
"n/prefer-promises/fs": "error",
|
|
1264
1345
|
"n/process-exit-as-throw": "error"
|
|
1265
1346
|
}
|
|
1266
|
-
}
|
|
1347
|
+
}];
|
|
1267
1348
|
}
|
|
1268
1349
|
//#endregion
|
|
1269
1350
|
//#region src/configs/rules-configs/perfectionist-groups.ts
|
|
@@ -1325,7 +1406,7 @@ const SORT_UNION_OR_INTERSECTION_GROUPS = [
|
|
|
1325
1406
|
*/
|
|
1326
1407
|
function perfectionist() {
|
|
1327
1408
|
const rootDir = getWorkspaceRoot(process.cwd(), process.cwd());
|
|
1328
|
-
return
|
|
1409
|
+
return [{
|
|
1329
1410
|
name: "fabdeh/perfectionist/rules",
|
|
1330
1411
|
files: [GLOB_SRC],
|
|
1331
1412
|
plugins: { perfectionist: perfectionistPlugin },
|
|
@@ -1367,7 +1448,7 @@ function perfectionist() {
|
|
|
1367
1448
|
type: "natural"
|
|
1368
1449
|
}]
|
|
1369
1450
|
}
|
|
1370
|
-
}
|
|
1451
|
+
}];
|
|
1371
1452
|
}
|
|
1372
1453
|
//#endregion
|
|
1373
1454
|
//#region src/configs/playwright.ts
|
|
@@ -1430,36 +1511,141 @@ async function playwright(options = {}) {
|
|
|
1430
1511
|
//#endregion
|
|
1431
1512
|
//#region src/configs/pnpm.ts
|
|
1432
1513
|
/**
|
|
1514
|
+
* Detects whether the current PNPM workspace uses catalog definitions.
|
|
1515
|
+
*
|
|
1516
|
+
* Searches for a `pnpm-workspace.yaml` file and checks whether it contains
|
|
1517
|
+
* either the `catalog:` or `catalogs:` keys, which are used to define shared
|
|
1518
|
+
* dependency version catalogs in PNPM workspaces.
|
|
1519
|
+
*
|
|
1520
|
+
* @returns `true` when catalog configuration is present; otherwise `false`.
|
|
1521
|
+
*/
|
|
1522
|
+
async function detectCatalogUsage() {
|
|
1523
|
+
const workspaceFile = await findUp("pnpm-workspace.yaml");
|
|
1524
|
+
if (!workspaceFile) return false;
|
|
1525
|
+
const yaml = await readFile(workspaceFile, "utf-8");
|
|
1526
|
+
return yaml.includes("catalog:") || yaml.includes("catalogs:");
|
|
1527
|
+
}
|
|
1528
|
+
/**
|
|
1433
1529
|
* Generates an array containing configuration settings for PNPM workspace-specific rules and plugins.
|
|
1434
1530
|
*
|
|
1531
|
+
* @param options - The options
|
|
1435
1532
|
* @returns An array defining PNPM workspace rules, plugins, and their configurations.
|
|
1436
1533
|
*/
|
|
1437
|
-
async function pnpm() {
|
|
1438
|
-
const [pluginPnpm,
|
|
1534
|
+
async function pnpm(options = {}) {
|
|
1535
|
+
const [pluginPnpm, pluginYaml, yamlParser] = await Promise.all([
|
|
1439
1536
|
interopDefault(import("eslint-plugin-pnpm")),
|
|
1440
|
-
interopDefault(import("
|
|
1441
|
-
interopDefault(import("
|
|
1537
|
+
interopDefault(import("eslint-plugin-yml")),
|
|
1538
|
+
interopDefault(import("yaml-eslint-parser"))
|
|
1442
1539
|
]);
|
|
1443
|
-
|
|
1540
|
+
const { catalogs = await detectCatalogUsage(), isInEditor = false, json = true, sort = true, yaml = true } = options;
|
|
1541
|
+
const configs = [];
|
|
1542
|
+
if (json) configs.push({
|
|
1444
1543
|
name: "fabdeh/pnpm/package-json",
|
|
1445
1544
|
files: ["package.json", "**/package.json"],
|
|
1446
|
-
|
|
1545
|
+
language: "jsonc/x",
|
|
1447
1546
|
plugins: { pnpm: pluginPnpm },
|
|
1448
1547
|
rules: {
|
|
1449
|
-
"pnpm/json-enforce-catalog": "error",
|
|
1450
|
-
|
|
1451
|
-
|
|
1548
|
+
...catalogs ? { "pnpm/json-enforce-catalog": ["error", {
|
|
1549
|
+
autofix: !isInEditor,
|
|
1550
|
+
ignores: ["@types/vscode"]
|
|
1551
|
+
}] } : {},
|
|
1552
|
+
"pnpm/json-prefer-workspace-settings": ["error", { autofix: !isInEditor }],
|
|
1553
|
+
"pnpm/json-valid-catalog": ["error", { autofix: !isInEditor }]
|
|
1452
1554
|
}
|
|
1453
|
-
}
|
|
1555
|
+
});
|
|
1556
|
+
if (yaml) configs.push({
|
|
1454
1557
|
name: "fabdeh/pnpm/pnpm-workspace-yaml",
|
|
1455
1558
|
files: ["pnpm-workspace.yaml"],
|
|
1456
1559
|
languageOptions: { parser: yamlParser },
|
|
1457
1560
|
plugins: { pnpm: pluginPnpm },
|
|
1458
1561
|
rules: {
|
|
1562
|
+
"pnpm/yaml-enforce-settings": ["error", { settings: {
|
|
1563
|
+
shellEmulator: true,
|
|
1564
|
+
trustPolicy: "no-downgrade"
|
|
1565
|
+
} }],
|
|
1459
1566
|
"pnpm/yaml-no-duplicate-catalog-item": "error",
|
|
1460
1567
|
"pnpm/yaml-no-unused-catalog-item": "error"
|
|
1461
1568
|
}
|
|
1462
1569
|
});
|
|
1570
|
+
if (sort) configs.push({
|
|
1571
|
+
files: ["pnpm-workspace.yaml"],
|
|
1572
|
+
languageOptions: { parser: yamlParser },
|
|
1573
|
+
name: "antfu/pnpm/pnpm-workspace-yaml-sort",
|
|
1574
|
+
plugins: { yaml: pluginYaml },
|
|
1575
|
+
rules: { "yaml/sort-keys": [
|
|
1576
|
+
"error",
|
|
1577
|
+
{
|
|
1578
|
+
order: [
|
|
1579
|
+
...[
|
|
1580
|
+
"cacheDir",
|
|
1581
|
+
"catalogMode",
|
|
1582
|
+
"cleanupUnusedCatalogs",
|
|
1583
|
+
"dedupeDirectDeps",
|
|
1584
|
+
"deployAllFiles",
|
|
1585
|
+
"enablePrePostScripts",
|
|
1586
|
+
"engineStrict",
|
|
1587
|
+
"extendNodePath",
|
|
1588
|
+
"hoist",
|
|
1589
|
+
"hoistPattern",
|
|
1590
|
+
"hoistWorkspacePackages",
|
|
1591
|
+
"ignoreCompatibilityDb",
|
|
1592
|
+
"ignoreDepScripts",
|
|
1593
|
+
"ignoreScripts",
|
|
1594
|
+
"ignoreWorkspaceRootCheck",
|
|
1595
|
+
"managePackageManagerVersions",
|
|
1596
|
+
"minimumReleaseAge",
|
|
1597
|
+
"minimumReleaseAgeExclude",
|
|
1598
|
+
"modulesDir",
|
|
1599
|
+
"nodeLinker",
|
|
1600
|
+
"nodeVersion",
|
|
1601
|
+
"optimisticRepeatInstall",
|
|
1602
|
+
"packageManagerStrict",
|
|
1603
|
+
"packageManagerStrictVersion",
|
|
1604
|
+
"preferSymlinkedExecutables",
|
|
1605
|
+
"preferWorkspacePackages",
|
|
1606
|
+
"publicHoistPattern",
|
|
1607
|
+
"registrySupportsTimeField",
|
|
1608
|
+
"requiredScripts",
|
|
1609
|
+
"resolutionMode",
|
|
1610
|
+
"savePrefix",
|
|
1611
|
+
"scriptShell",
|
|
1612
|
+
"shamefullyHoist",
|
|
1613
|
+
"shellEmulator",
|
|
1614
|
+
"stateDir",
|
|
1615
|
+
"supportedArchitectures",
|
|
1616
|
+
"symlink",
|
|
1617
|
+
"tag",
|
|
1618
|
+
"trustPolicy",
|
|
1619
|
+
"trustPolicyExclude",
|
|
1620
|
+
"updateNotifier"
|
|
1621
|
+
],
|
|
1622
|
+
"packages",
|
|
1623
|
+
"overrides",
|
|
1624
|
+
"patchedDependencies",
|
|
1625
|
+
"catalog",
|
|
1626
|
+
"catalogs",
|
|
1627
|
+
...[
|
|
1628
|
+
"allowedDeprecatedVersions",
|
|
1629
|
+
"allowNonAppliedPatches",
|
|
1630
|
+
"configDependencies",
|
|
1631
|
+
"ignoredBuiltDependencies",
|
|
1632
|
+
"ignoredOptionalDependencies",
|
|
1633
|
+
"neverBuiltDependencies",
|
|
1634
|
+
"onlyBuiltDependencies",
|
|
1635
|
+
"onlyBuiltDependenciesFile",
|
|
1636
|
+
"packageExtensions",
|
|
1637
|
+
"peerDependencyRules"
|
|
1638
|
+
]
|
|
1639
|
+
],
|
|
1640
|
+
pathPattern: "^$"
|
|
1641
|
+
},
|
|
1642
|
+
{
|
|
1643
|
+
order: { type: "asc" },
|
|
1644
|
+
pathPattern: ".*"
|
|
1645
|
+
}
|
|
1646
|
+
] }
|
|
1647
|
+
});
|
|
1648
|
+
return configs;
|
|
1463
1649
|
}
|
|
1464
1650
|
//#endregion
|
|
1465
1651
|
//#region src/configs/regexp.ts
|
|
@@ -1473,7 +1659,7 @@ function regexp(options = {}) {
|
|
|
1473
1659
|
const { level, overrides } = options;
|
|
1474
1660
|
const config = configs["flat/recommended"];
|
|
1475
1661
|
const rules = Object.fromEntries(Object.entries(config.rules).map(([ruleName, ruleLevel]) => [ruleName, level === "warn" ? level : ruleLevel]));
|
|
1476
|
-
return
|
|
1662
|
+
return [{
|
|
1477
1663
|
name: "fabdeh/regexp/rules",
|
|
1478
1664
|
files: [GLOB_SRC],
|
|
1479
1665
|
plugins: { ...config.plugins },
|
|
@@ -1481,7 +1667,7 @@ function regexp(options = {}) {
|
|
|
1481
1667
|
...rules,
|
|
1482
1668
|
...overrides
|
|
1483
1669
|
}
|
|
1484
|
-
}
|
|
1670
|
+
}];
|
|
1485
1671
|
}
|
|
1486
1672
|
//#endregion
|
|
1487
1673
|
//#region src/configs/sort.ts
|
|
@@ -1499,7 +1685,7 @@ function regexp(options = {}) {
|
|
|
1499
1685
|
* @returns The ESLint configuration array with sorting rules.
|
|
1500
1686
|
*/
|
|
1501
1687
|
function sortPackageJson() {
|
|
1502
|
-
return
|
|
1688
|
+
return [{
|
|
1503
1689
|
name: "fabdeh/sort/package-json",
|
|
1504
1690
|
files: ["**/package.json"],
|
|
1505
1691
|
rules: {
|
|
@@ -1594,7 +1780,7 @@ function sortPackageJson() {
|
|
|
1594
1780
|
}
|
|
1595
1781
|
]
|
|
1596
1782
|
}
|
|
1597
|
-
}
|
|
1783
|
+
}];
|
|
1598
1784
|
}
|
|
1599
1785
|
/**
|
|
1600
1786
|
* Generates a TypeScript ESLint configuration array that enforces sorting rules for `tsconfig.json` files.
|
|
@@ -1606,7 +1792,7 @@ function sortPackageJson() {
|
|
|
1606
1792
|
* @returns The TypeScript ESLint configuration array with sorting rules.
|
|
1607
1793
|
*/
|
|
1608
1794
|
function sortTsConfig() {
|
|
1609
|
-
return
|
|
1795
|
+
return [{
|
|
1610
1796
|
name: "fabdeh/sort/tsconfig-json",
|
|
1611
1797
|
files: ["**/tsconfig.json", "**/tsconfig.*.json"],
|
|
1612
1798
|
rules: { "jsonc/sort-keys": [
|
|
@@ -1717,7 +1903,7 @@ function sortTsConfig() {
|
|
|
1717
1903
|
pathPattern: "^compilerOptions$"
|
|
1718
1904
|
}
|
|
1719
1905
|
] }
|
|
1720
|
-
}
|
|
1906
|
+
}];
|
|
1721
1907
|
}
|
|
1722
1908
|
//#endregion
|
|
1723
1909
|
//#region src/configs/stylistic.ts
|
|
@@ -1742,7 +1928,7 @@ async function stylistic(options = {}) {
|
|
|
1742
1928
|
};
|
|
1743
1929
|
const stylisticPlugin = await interopDefault(import("@stylistic/eslint-plugin"));
|
|
1744
1930
|
const config = stylisticPlugin.configs.customize(stylisticOptions);
|
|
1745
|
-
return
|
|
1931
|
+
return [{
|
|
1746
1932
|
name: "fabdeh/stylistic/rules",
|
|
1747
1933
|
files: [GLOB_SRC],
|
|
1748
1934
|
plugins: { "@stylistic": stylisticPlugin },
|
|
@@ -1762,7 +1948,7 @@ async function stylistic(options = {}) {
|
|
|
1762
1948
|
} }
|
|
1763
1949
|
]
|
|
1764
1950
|
}
|
|
1765
|
-
}
|
|
1951
|
+
}];
|
|
1766
1952
|
}
|
|
1767
1953
|
//#endregion
|
|
1768
1954
|
//#region src/configs/tailwindcss.ts
|
|
@@ -1796,8 +1982,8 @@ async function tailwindcss(options = {}) {
|
|
|
1796
1982
|
files = { files: filesGlob ?? [GLOB_SRC, "**/*.htm?(l)"] };
|
|
1797
1983
|
parserConfigs = [];
|
|
1798
1984
|
}
|
|
1799
|
-
return
|
|
1800
|
-
name: "
|
|
1985
|
+
return [...parserConfigs, {
|
|
1986
|
+
name: "fabdeh/tailwindcss/rules",
|
|
1801
1987
|
...files,
|
|
1802
1988
|
plugins: { "better-tailwindcss": betterTailwindcssPlugin },
|
|
1803
1989
|
settings: { "better-tailwindcss": settings },
|
|
@@ -1810,7 +1996,7 @@ async function tailwindcss(options = {}) {
|
|
|
1810
1996
|
"better-tailwindcss/no-restricted-classes": "error"
|
|
1811
1997
|
} : {}
|
|
1812
1998
|
}
|
|
1813
|
-
}
|
|
1999
|
+
}];
|
|
1814
2000
|
}
|
|
1815
2001
|
//#endregion
|
|
1816
2002
|
//#region src/configs/toml.ts
|
|
@@ -1827,10 +2013,9 @@ async function tailwindcss(options = {}) {
|
|
|
1827
2013
|
async function toml(options = {}) {
|
|
1828
2014
|
const { files = [GLOB_TOML], overrides = {}, stylistic = true } = options;
|
|
1829
2015
|
const { indent = 2 } = typeof stylistic === "object" ? stylistic : {};
|
|
1830
|
-
|
|
1831
|
-
return tseslint.config({
|
|
2016
|
+
return [{
|
|
1832
2017
|
name: "fabdeh/toml/setup",
|
|
1833
|
-
plugins: { toml:
|
|
2018
|
+
plugins: { toml: await interopDefault(import("eslint-plugin-toml")) }
|
|
1834
2019
|
}, {
|
|
1835
2020
|
name: "fabdeh/toml/rules",
|
|
1836
2021
|
files,
|
|
@@ -1860,7 +2045,7 @@ async function toml(options = {}) {
|
|
|
1860
2045
|
} : {},
|
|
1861
2046
|
...overrides
|
|
1862
2047
|
}
|
|
1863
|
-
}
|
|
2048
|
+
}];
|
|
1864
2049
|
}
|
|
1865
2050
|
//#endregion
|
|
1866
2051
|
//#region src/configs/rules-configs/member-ordering.ts
|
|
@@ -1908,7 +2093,7 @@ const MEMBER_ORDERING_OPTIONS = { default: [
|
|
|
1908
2093
|
* @param options.parserOptions - Options for the TypeScript parser.
|
|
1909
2094
|
* @param options.overrides - Additional rule overrides.
|
|
1910
2095
|
* @param isWorkspaceProject - A boolean indicating whether the project is a workspace project. Defaults to false.
|
|
1911
|
-
* @returns A
|
|
2096
|
+
* @returns A TypedConfig[] containing the TypeScript ESLint configuration.
|
|
1912
2097
|
*/
|
|
1913
2098
|
async function typescript(options = {}, isWorkspaceProject = false) {
|
|
1914
2099
|
const { enableErasableSyntaxOnly = false, overrides = {}, parserOptions = {}, stylistic = true, type = "app", useRelaxedNamingConventionForCamelAndPascalCases = false } = options;
|
|
@@ -1922,7 +2107,7 @@ async function typescript(options = {}, isWorkspaceProject = false) {
|
|
|
1922
2107
|
}
|
|
1923
2108
|
const tsconfigRootDir = getWorkspaceRoot(process.cwd(), process.cwd());
|
|
1924
2109
|
const defaultProject = getTsConfigFileName(tsconfigRootDir);
|
|
1925
|
-
return
|
|
2110
|
+
return [{
|
|
1926
2111
|
name: `fabdeh/${type}/typescript/setup`,
|
|
1927
2112
|
files: [GLOB_TS],
|
|
1928
2113
|
ignores: [`${GLOB_MARKDOWN}/**`],
|
|
@@ -2024,7 +2209,7 @@ async function typescript(options = {}, isWorkspaceProject = false) {
|
|
|
2024
2209
|
...erasableSyntaxOnlyRules,
|
|
2025
2210
|
...overrides
|
|
2026
2211
|
}
|
|
2027
|
-
}
|
|
2212
|
+
}];
|
|
2028
2213
|
}
|
|
2029
2214
|
//#endregion
|
|
2030
2215
|
//#region src/configs/unicorn.ts
|
|
@@ -2035,7 +2220,7 @@ async function typescript(options = {}, isWorkspaceProject = false) {
|
|
|
2035
2220
|
* @returns The configuration array for the Unicorn plugin.
|
|
2036
2221
|
*/
|
|
2037
2222
|
function unicorn(options = {}) {
|
|
2038
|
-
return
|
|
2223
|
+
return [{
|
|
2039
2224
|
name: "fabdeh/unicorn/rules",
|
|
2040
2225
|
files: [GLOB_SRC],
|
|
2041
2226
|
plugins: { unicorn: unicornPlugin },
|
|
@@ -2136,7 +2321,7 @@ function unicorn(options = {}) {
|
|
|
2136
2321
|
"unicorn/require-post-message-target-origin": "error",
|
|
2137
2322
|
"unicorn/throw-new-error": "error"
|
|
2138
2323
|
} }
|
|
2139
|
-
}
|
|
2324
|
+
}];
|
|
2140
2325
|
}
|
|
2141
2326
|
//#endregion
|
|
2142
2327
|
//#region src/configs/vitest.ts
|
|
@@ -2167,7 +2352,7 @@ async function vitest(options = {}) {
|
|
|
2167
2352
|
useJestDom ? interopDefault(import("eslint-plugin-jest-dom")) : Promise.resolve(void 0),
|
|
2168
2353
|
useTestingLibrary ? interopDefault(import("eslint-plugin-testing-library")) : Promise.resolve(void 0)
|
|
2169
2354
|
]);
|
|
2170
|
-
return
|
|
2355
|
+
return [{
|
|
2171
2356
|
name: "fabdeh/vitest/rules",
|
|
2172
2357
|
plugins: {
|
|
2173
2358
|
vitest: vitestPlugin,
|
|
@@ -2214,7 +2399,7 @@ async function vitest(options = {}) {
|
|
|
2214
2399
|
...getJsDocRules("off", true, "both"),
|
|
2215
2400
|
...overrides
|
|
2216
2401
|
}
|
|
2217
|
-
}
|
|
2402
|
+
}];
|
|
2218
2403
|
}
|
|
2219
2404
|
//#endregion
|
|
2220
2405
|
//#region src/configs/yaml.ts
|
|
@@ -2227,15 +2412,14 @@ async function vitest(options = {}) {
|
|
|
2227
2412
|
* @param options.stylistic - A boolean or object to specify stylistic rules. Defaults to `true`.
|
|
2228
2413
|
* @param options.stylistic.indent - The number of spaces for indentation or 'tab'. Defaults to `2`.
|
|
2229
2414
|
* @param options.stylistic.quotes - The type of quotes to use ('single', 'double', or 'backtick'). Defaults to `'single'`.
|
|
2230
|
-
* @returns A promise that resolves to a `
|
|
2415
|
+
* @returns A promise that resolves to a `TypedConfig[]` containing the ESLint configuration.
|
|
2231
2416
|
*/
|
|
2232
2417
|
async function yaml(options = {}) {
|
|
2233
2418
|
const { files = [GLOB_YAML], overrides = {}, stylistic = true } = options;
|
|
2234
2419
|
const { indent = 2, quotes = "single" } = typeof stylistic === "object" ? stylistic : {};
|
|
2235
|
-
|
|
2236
|
-
return tseslint.config({
|
|
2420
|
+
return [{
|
|
2237
2421
|
name: "fabdeh/yaml/setup",
|
|
2238
|
-
plugins: { yaml:
|
|
2422
|
+
plugins: { yaml: await interopDefault(import("eslint-plugin-yml")) }
|
|
2239
2423
|
}, {
|
|
2240
2424
|
name: "fabdeh/yaml/rules",
|
|
2241
2425
|
language: "yaml/yaml",
|
|
@@ -2267,7 +2451,7 @@ async function yaml(options = {}) {
|
|
|
2267
2451
|
} : {},
|
|
2268
2452
|
...overrides
|
|
2269
2453
|
}
|
|
2270
|
-
}
|
|
2454
|
+
}];
|
|
2271
2455
|
}
|
|
2272
2456
|
//#endregion
|
|
2273
2457
|
//#region src/shared/constants.ts
|
|
@@ -2289,18 +2473,24 @@ const OPTIONS_SYMBOL = Symbol("options");
|
|
|
2289
2473
|
* @param baseConfig - The base configuration to extend from.
|
|
2290
2474
|
* @param options - Configuration options.
|
|
2291
2475
|
* @param userConfigs - Additional user configurations that can be awaited.
|
|
2292
|
-
* @returns
|
|
2476
|
+
* @returns The merged ESLint configurations.
|
|
2293
2477
|
* @example
|
|
2294
2478
|
* ```typescript
|
|
2479
|
+
* import { defineProjectConfig } from '@fabdeh/eslint-config';
|
|
2480
|
+
*
|
|
2295
2481
|
* import baseConfig from '../../eslint.base.js';
|
|
2296
2482
|
*
|
|
2297
|
-
*
|
|
2483
|
+
* export default defineProjectConfig(baseConfig, { vitest: true, typescript: { parserOptions: { project: './tsconfig.json' } } });
|
|
2298
2484
|
* ```
|
|
2299
2485
|
*/
|
|
2300
|
-
|
|
2301
|
-
const
|
|
2302
|
-
const workspaceOptions = resolvedBaseConfig[OPTIONS_SYMBOL];
|
|
2486
|
+
function defineProjectConfig(baseConfig, options = {}, ...userConfigs) {
|
|
2487
|
+
const workspaceOptions = baseConfig[OPTIONS_SYMBOL];
|
|
2303
2488
|
const { angular: enableAngular = isPackageExists("@angular/core"), jsdoc: enableJsdoc = options.type === "lib", ngrx: enableNgrx = NGRX_PACKAGES.some((p) => isPackageExists(p)), tailwindcss: enableTailwind = false, typescript: typescriptOptions, vitest: enableVitest = isPackageExists("vitest") } = options;
|
|
2489
|
+
let isInEditor = workspaceOptions.isInEditor;
|
|
2490
|
+
if (isInEditor === void 0) {
|
|
2491
|
+
isInEditor = isInEditorEnv();
|
|
2492
|
+
if (isInEditor) console.log("[@fabdeh/eslint-config] Detected running in editor, some rules are disabled.");
|
|
2493
|
+
}
|
|
2304
2494
|
if (enableNgrx && !enableAngular) throw new Error("NgRx rules can only be enabled if Angular rules are also enabled.");
|
|
2305
2495
|
const configs = [];
|
|
2306
2496
|
const stylisticOptions = workspaceOptions.stylistic === false ? false : typeof workspaceOptions.stylistic === "object" ? workspaceOptions.stylistic : {};
|
|
@@ -2336,7 +2526,10 @@ async function defineProjectConfig(baseConfig, options = {}, ...userConfigs) {
|
|
|
2336
2526
|
stylistic: stylisticOptions
|
|
2337
2527
|
}));
|
|
2338
2528
|
}
|
|
2339
|
-
|
|
2529
|
+
let composer = new FlatConfigComposer();
|
|
2530
|
+
composer = composer.append(baseConfig, ...configs, ...userConfigs);
|
|
2531
|
+
if (isInEditor) composer = composer.disableRulesFix(["prefer-const", "unused-imports/no-unused-imports"], { builtinRules: () => import("eslint/use-at-your-own-risk").then((m) => m.builtinRules) });
|
|
2532
|
+
return composer;
|
|
2340
2533
|
}
|
|
2341
2534
|
//#endregion
|
|
2342
2535
|
//#region src/factories/standard-config.ts
|
|
@@ -2346,26 +2539,36 @@ async function defineProjectConfig(baseConfig, options = {}, ...userConfigs) {
|
|
|
2346
2539
|
*
|
|
2347
2540
|
* @param options - Configuration options.
|
|
2348
2541
|
* @param userConfigs - Additional user configurations that can be awaited.
|
|
2349
|
-
* @returns
|
|
2542
|
+
* @returns The merged ESLint configurations.
|
|
2350
2543
|
* @example
|
|
2351
2544
|
* ```typescript
|
|
2352
|
-
*
|
|
2545
|
+
* import { defineConfig } from '@fabdeh/eslint-config';
|
|
2546
|
+
*
|
|
2547
|
+
* export default defineConfig({ vitest: true, typescript: { parserOptions: { project: './tsconfig.json' } } });
|
|
2353
2548
|
* ```
|
|
2354
2549
|
*/
|
|
2355
|
-
|
|
2356
|
-
const { angular: enableAngular = isPackageExists("@angular/core"), gitignore: enableGitignore = true, jsdoc: enableJsdoc = options.type === "lib", ngrx: enableNgrx = NGRX_PACKAGES.some((p) => isPackageExists(p)), playwright: enablePlaywright = PLAYWRIGHT_PACKAGES.some((p) => isPackageExists(p)), pnpm: enableCatalogs =
|
|
2550
|
+
function defineConfig(options = {}, ...userConfigs) {
|
|
2551
|
+
const { angular: enableAngular = isPackageExists("@angular/core"), gitignore: enableGitignore = true, jsdoc: enableJsdoc = options.type === "lib", ngrx: enableNgrx = NGRX_PACKAGES.some((p) => isPackageExists(p)), playwright: enablePlaywright = PLAYWRIGHT_PACKAGES.some((p) => isPackageExists(p)), pnpm: enableCatalogs = !!findUpSync("pnpm-workspace.yaml"), regexp: enableRegexp = true, tailwindcss: enableTailwind = false, typescript: enableTypescript = isPackageExists("typescript"), unicorn: enableUnicorn = true, vitest: enableVitest = isPackageExists("vitest") } = options;
|
|
2552
|
+
let isInEditor = options.isInEditor;
|
|
2553
|
+
if (isInEditor === void 0) {
|
|
2554
|
+
isInEditor = isInEditorEnv();
|
|
2555
|
+
if (isInEditor) console.log("[@fabdeh/eslint-config] Detected running in editor, some rules are disabled.");
|
|
2556
|
+
}
|
|
2357
2557
|
if (enableNgrx && !enableAngular) throw new Error("NgRx rules can only be enabled if Angular rules are also enabled.");
|
|
2358
2558
|
const stylisticOptions = options.stylistic === false ? false : typeof options.stylistic === "object" ? options.stylistic : {};
|
|
2359
2559
|
const configs = [];
|
|
2360
|
-
if (enableGitignore) if (typeof enableGitignore === "object") configs.push(interopDefault(import("eslint-config-flat-gitignore")).then((r) =>
|
|
2560
|
+
if (enableGitignore) if (typeof enableGitignore === "object") configs.push(interopDefault(import("eslint-config-flat-gitignore")).then((r) => [r({
|
|
2361
2561
|
name: "fabdeh/gitignore",
|
|
2362
2562
|
...enableGitignore
|
|
2363
|
-
})))
|
|
2364
|
-
else configs.push(interopDefault(import("eslint-config-flat-gitignore")).then((r) =>
|
|
2563
|
+
})]));
|
|
2564
|
+
else configs.push(interopDefault(import("eslint-config-flat-gitignore")).then((r) => [r({
|
|
2365
2565
|
name: "fabdeh/gitignore",
|
|
2366
2566
|
strict: true
|
|
2367
|
-
})))
|
|
2368
|
-
configs.push(ignores(options.ignores), javascript({
|
|
2567
|
+
})]));
|
|
2568
|
+
configs.push(ignores(options.ignores), javascript({
|
|
2569
|
+
isInEditor,
|
|
2570
|
+
overrides: options.javascript?.overrides
|
|
2571
|
+
}), comments(), node(), imports({ stylistic: stylisticOptions }), perfectionist());
|
|
2369
2572
|
if (enableJsdoc) configs.push(jsdoc({ stylistic: stylisticOptions }));
|
|
2370
2573
|
if (enableUnicorn) {
|
|
2371
2574
|
const unicornOptions = resolveSubOptions(options, "unicorn");
|
|
@@ -2399,7 +2602,7 @@ async function defineConfig(options = {}, ...userConfigs) {
|
|
|
2399
2602
|
let e2eFolderPath;
|
|
2400
2603
|
if (enablePlaywright) {
|
|
2401
2604
|
const playwrightOptions = resolveSubOptions(options, "playwright");
|
|
2402
|
-
e2eFolderPath = playwrightOptions.e2eFolderPath ??
|
|
2605
|
+
e2eFolderPath = playwrightOptions.e2eFolderPath ?? getPlaywrightDirectory() ?? "e2e";
|
|
2403
2606
|
configs.push(playwright({
|
|
2404
2607
|
...playwrightOptions,
|
|
2405
2608
|
e2eFolderPath
|
|
@@ -2426,7 +2629,15 @@ async function defineConfig(options = {}, ...userConfigs) {
|
|
|
2426
2629
|
stylistic: stylisticOptions
|
|
2427
2630
|
}), sortPackageJson(), sortTsConfig());
|
|
2428
2631
|
}
|
|
2429
|
-
if (enableCatalogs)
|
|
2632
|
+
if (enableCatalogs) {
|
|
2633
|
+
const pnpmOptions = resolveSubOptions(options, "pnpm");
|
|
2634
|
+
configs.push(pnpm({
|
|
2635
|
+
isInEditor,
|
|
2636
|
+
json: options.jsonc !== false,
|
|
2637
|
+
yaml: options.yaml !== false,
|
|
2638
|
+
...pnpmOptions
|
|
2639
|
+
}));
|
|
2640
|
+
}
|
|
2430
2641
|
if (options.yaml ?? true) {
|
|
2431
2642
|
const yamlOptions = resolveSubOptions(options, "yaml");
|
|
2432
2643
|
configs.push(yaml({
|
|
@@ -2445,7 +2656,10 @@ async function defineConfig(options = {}, ...userConfigs) {
|
|
|
2445
2656
|
const markdownOptions = resolveSubOptions(options, "markdown");
|
|
2446
2657
|
configs.push(markdown(markdownOptions));
|
|
2447
2658
|
}
|
|
2448
|
-
|
|
2659
|
+
let composer = new FlatConfigComposer();
|
|
2660
|
+
composer = composer.append(...configs, ...userConfigs);
|
|
2661
|
+
if (isInEditor) composer = composer.disableRulesFix(["prefer-const", "unused-imports/no-unused-imports"], { builtinRules: () => import("eslint/use-at-your-own-risk").then((m) => m.builtinRules) });
|
|
2662
|
+
return composer;
|
|
2449
2663
|
}
|
|
2450
2664
|
//#endregion
|
|
2451
2665
|
//#region src/factories/workspace-config.ts
|
|
@@ -2456,25 +2670,35 @@ async function defineConfig(options = {}, ...userConfigs) {
|
|
|
2456
2670
|
*
|
|
2457
2671
|
* @param options - Configuration options.
|
|
2458
2672
|
* @param userConfigs - Additional user configurations that can be awaited.
|
|
2459
|
-
* @returns
|
|
2673
|
+
* @returns The merged ESLint configurations.
|
|
2460
2674
|
* @example
|
|
2461
2675
|
* ```typescript
|
|
2462
|
-
*
|
|
2676
|
+
* import { defineWorkspaceConfig } from '@fabdeh/eslint-config';
|
|
2677
|
+
*
|
|
2678
|
+
* export default defineWorkspaceConfig({ typescript: { parserOptions: { project: './tsconfig.json' } } });
|
|
2463
2679
|
* ```
|
|
2464
2680
|
*/
|
|
2465
|
-
|
|
2466
|
-
const { gitignore: enableGitignore = true, pnpm: enableCatalogs =
|
|
2681
|
+
function defineWorkspaceConfig(options = {}, ...userConfigs) {
|
|
2682
|
+
const { gitignore: enableGitignore = true, pnpm: enableCatalogs = !!findUpSync("pnpm-workspace.yaml"), regexp: enableRegexp = true, typescript: enableTypescript = isPackageExists("typescript"), unicorn: enableUnicorn = true } = options;
|
|
2683
|
+
let isInEditor = options.isInEditor;
|
|
2684
|
+
if (isInEditor === void 0) {
|
|
2685
|
+
isInEditor = isInEditorEnv();
|
|
2686
|
+
if (isInEditor) console.log("[@fabdeh/eslint-config] Detected running in editor, some rules are disabled.");
|
|
2687
|
+
}
|
|
2467
2688
|
const stylisticOptions = options.stylistic === false ? false : typeof options.stylistic === "object" ? options.stylistic : {};
|
|
2468
2689
|
const configs = [];
|
|
2469
|
-
if (enableGitignore) if (typeof enableGitignore === "object") configs.push(interopDefault(import("eslint-config-flat-gitignore")).then((r) =>
|
|
2690
|
+
if (enableGitignore) if (typeof enableGitignore === "object") configs.push(interopDefault(import("eslint-config-flat-gitignore")).then((r) => [r({
|
|
2470
2691
|
name: "fabdeh/gitignore",
|
|
2471
2692
|
...enableGitignore
|
|
2472
|
-
})))
|
|
2473
|
-
else configs.push(interopDefault(import("eslint-config-flat-gitignore")).then((r) =>
|
|
2693
|
+
})]));
|
|
2694
|
+
else configs.push(interopDefault(import("eslint-config-flat-gitignore")).then((r) => [r({
|
|
2474
2695
|
name: "fabdeh/gitignore",
|
|
2475
2696
|
strict: true
|
|
2476
|
-
})))
|
|
2477
|
-
configs.push(ignores(options.ignores, "workspace"), javascript({
|
|
2697
|
+
})]));
|
|
2698
|
+
configs.push(ignores(options.ignores, "workspace"), javascript({
|
|
2699
|
+
isInEditor,
|
|
2700
|
+
overrides: options.javascript?.overrides
|
|
2701
|
+
}), comments(), node(), imports({ stylistic: stylisticOptions }), perfectionist());
|
|
2478
2702
|
if (enableUnicorn) {
|
|
2479
2703
|
const unicornOptions = resolveSubOptions(options, "unicorn");
|
|
2480
2704
|
configs.push(unicorn(unicornOptions));
|
|
@@ -2499,7 +2723,15 @@ async function defineWorkspaceConfig(options = {}, ...userConfigs) {
|
|
|
2499
2723
|
stylistic: stylisticOptions
|
|
2500
2724
|
}), sortPackageJson(), sortTsConfig());
|
|
2501
2725
|
}
|
|
2502
|
-
if (enableCatalogs)
|
|
2726
|
+
if (enableCatalogs) {
|
|
2727
|
+
const pnpmOptions = resolveSubOptions(options, "pnpm");
|
|
2728
|
+
configs.push(pnpm({
|
|
2729
|
+
isInEditor,
|
|
2730
|
+
json: options.jsonc !== false,
|
|
2731
|
+
yaml: options.yaml !== false,
|
|
2732
|
+
...pnpmOptions
|
|
2733
|
+
}));
|
|
2734
|
+
}
|
|
2503
2735
|
if (options.yaml ?? true) {
|
|
2504
2736
|
const yamlOptions = resolveSubOptions(options, "yaml");
|
|
2505
2737
|
configs.push(yaml({
|
|
@@ -2518,9 +2750,12 @@ async function defineWorkspaceConfig(options = {}, ...userConfigs) {
|
|
|
2518
2750
|
const markdownOptions = resolveSubOptions(options, "markdown");
|
|
2519
2751
|
configs.push(markdown(markdownOptions));
|
|
2520
2752
|
}
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2753
|
+
let composer = new FlatConfigComposer();
|
|
2754
|
+
composer = composer.append(...configs, ...userConfigs);
|
|
2755
|
+
if (isInEditor) composer = composer.disableRulesFix(["prefer-const", "unused-imports/no-unused-imports"], { builtinRules: () => import("eslint/use-at-your-own-risk").then((m) => m.builtinRules) });
|
|
2756
|
+
const composerWithOptions = composer;
|
|
2757
|
+
composerWithOptions[OPTIONS_SYMBOL] = options;
|
|
2758
|
+
return composerWithOptions;
|
|
2524
2759
|
}
|
|
2525
2760
|
//#endregion
|
|
2526
|
-
export { GLOB_HTML, GLOB_JS, GLOB_SRC, GLOB_TESTS, GLOB_TS, STYLISTIC_CONFIG_DEFAULT, angular, comments, convertPathToPosix, defineConfig, defineProjectConfig, defineWorkspaceConfig, ensurePackages, getPlaywrightDirectory, getTsConfigFileName, getWorkspaceRoot, ignores, imports, interopDefault, isDirectory, isPackageInScope, javascript, jsdoc, jsonc, markdown, ngrx, node, pathToGlobPattern, perfectionist, playwright, pnpm, regexp, resolveSubOptions, sortPackageJson, sortTsConfig, stylistic, tailwindcss, toml, typescript, unicorn, vitest, yaml };
|
|
2761
|
+
export { CONFIG_PRESET_FULL_OFF, CONFIG_PRESET_FULL_ON, GLOB_HTML, GLOB_JS, GLOB_SRC, GLOB_TESTS, GLOB_TS, STYLISTIC_CONFIG_DEFAULT, angular, comments, convertPathToPosix, defineConfig, defineProjectConfig, defineWorkspaceConfig, ensurePackages, getPlaywrightDirectory, getTsConfigFileName, getWorkspaceRoot, ignores, imports, interopDefault, isDirectory, isInEditorEnv, isInGitHooksOrLintStaged, isPackageInScope, javascript, jsdoc, jsonc, markdown, ngrx, node, pathToGlobPattern, perfectionist, playwright, pnpm, regexp, resolveSubOptions, sortPackageJson, sortTsConfig, stylistic, tailwindcss, toml, typescript, unicorn, vitest, yaml };
|