@ethang/eslint-config 21.2.5 → 21.4.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.
Files changed (64) hide show
  1. package/build.ts +34 -0
  2. package/{README.md → dist/README.md} +2 -2
  3. package/dist/config.react.js +2 -0
  4. package/dist/config.react.js.map +1 -0
  5. package/dist/eslint.config.js +2 -0
  6. package/dist/package.json +68 -0
  7. package/eslint.config.js +26 -2
  8. package/package.json +5 -5
  9. package/src/README.md +100 -0
  10. package/src/build/create-config-file.ts +57 -0
  11. package/src/build/create-config.ts +96 -0
  12. package/src/build/get-react-version.ts +19 -0
  13. package/src/build/list-utilities.ts +124 -0
  14. package/src/build/rule-list.ts +284 -0
  15. package/src/build/update-readme.ts +195 -0
  16. package/src/build/update-rules.ts +124 -0
  17. package/src/config.angular.js +107 -0
  18. package/src/config.astro.js +68 -0
  19. package/src/config.react.js +117 -0
  20. package/src/config.solid.js +34 -0
  21. package/src/constants.js +16 -0
  22. package/src/eslint.config.js +1051 -0
  23. package/src/setup/a11y.ts +19 -0
  24. package/src/setup/angular.ts +40 -0
  25. package/src/setup/astro.ts +14 -0
  26. package/src/setup/barrel.ts +17 -0
  27. package/src/setup/compat.ts +13 -0
  28. package/src/setup/cspell.ts +83 -0
  29. package/src/setup/css.ts +12 -0
  30. package/src/setup/depend.ts +14 -0
  31. package/src/setup/eslint.ts +246 -0
  32. package/src/setup/gen-rules.ts +75 -0
  33. package/src/setup/json.ts +17 -0
  34. package/src/setup/lodash.ts +58 -0
  35. package/src/setup/markdown.ts +16 -0
  36. package/src/setup/n.ts +86 -0
  37. package/src/setup/perfectionist.ts +68 -0
  38. package/src/setup/react.ts +82 -0
  39. package/src/setup/solid.ts +21 -0
  40. package/src/setup/sonar.ts +39 -0
  41. package/src/setup/tailwind.ts +10 -0
  42. package/src/setup/tanstack-query.ts +9 -0
  43. package/src/setup/tanstack-router.ts +9 -0
  44. package/src/setup/typescript-eslint.ts +118 -0
  45. package/src/setup/unicorn.ts +38 -0
  46. package/tsconfig.json +5 -0
  47. package/config.react.js +0 -2
  48. package/config.react.js.map +0 -1
  49. /package/{chunk-WK3YS7OG.js → dist/chunk-WK3YS7OG.js} +0 -0
  50. /package/{chunk-WK3YS7OG.js.map → dist/chunk-WK3YS7OG.js.map} +0 -0
  51. /package/{config.angular.d.ts → dist/config.angular.d.ts} +0 -0
  52. /package/{config.angular.js → dist/config.angular.js} +0 -0
  53. /package/{config.angular.js.map → dist/config.angular.js.map} +0 -0
  54. /package/{config.astro.d.ts → dist/config.astro.d.ts} +0 -0
  55. /package/{config.astro.js → dist/config.astro.js} +0 -0
  56. /package/{config.astro.js.map → dist/config.astro.js.map} +0 -0
  57. /package/{config.react.d.ts → dist/config.react.d.ts} +0 -0
  58. /package/{config.solid.d.ts → dist/config.solid.d.ts} +0 -0
  59. /package/{config.solid.js → dist/config.solid.js} +0 -0
  60. /package/{config.solid.js.map → dist/config.solid.js.map} +0 -0
  61. /package/{constants.js → dist/constants.js} +0 -0
  62. /package/{constants.js.map → dist/constants.js.map} +0 -0
  63. /package/{eslint.config.d.ts → dist/eslint.config.d.ts} +0 -0
  64. /package/{eslint.config.js.map → dist/eslint.config.js.map} +0 -0
@@ -0,0 +1,57 @@
1
+ import map from "lodash/map.js";
2
+ import { writeFileSync } from "node:fs";
3
+ import path from "node:path";
4
+
5
+ import type { ConfigFile } from "./update-rules.ts";
6
+
7
+ import { createConfig } from "./create-config.ts";
8
+ import { getTypeImportStrings } from "./list-utilities.ts";
9
+
10
+ const mainFile = "eslint.config.js";
11
+
12
+ export const createConfigFile = async (
13
+ listConfigs: ConfigFile[],
14
+ fileName: string,
15
+ ) => {
16
+ let configFile = "// @ts-nocheck\n";
17
+
18
+ const imports = listConfigs.flatMap((list) => {
19
+ const importStrings = getTypeImportStrings(list.name);
20
+
21
+ if (list.options?.extraImports && 0 < list.options.extraImports.length) {
22
+ importStrings.push(...list.options.extraImports);
23
+ }
24
+
25
+ return importStrings;
26
+ });
27
+
28
+ // eslint-disable-next-line compat/compat
29
+ const importList = [
30
+ 'import { ignores, languageOptions } from "./constants.js";',
31
+ ...imports,
32
+ ].toSorted((a, b) => {
33
+ return (a ?? "").localeCompare(b ?? "");
34
+ });
35
+
36
+ for (const item of importList) {
37
+ configFile += `${item}\n`;
38
+ }
39
+
40
+ const configs = await Promise.all(
41
+ map(listConfigs, async (list) => {
42
+ return createConfig(list.name, list.options);
43
+ }),
44
+ );
45
+
46
+ configFile += `\nexport default tseslint.config(
47
+ ${configs.join("\n")}
48
+ ${mainFile === fileName ? "eslintConfigPrettier," : ""}
49
+ ${mainFile === fileName ? "eslintPluginPrettierRecommended," : ""}
50
+ );\n`;
51
+
52
+ writeFileSync(
53
+ path.join(import.meta.dirname, `../${fileName}`),
54
+ configFile,
55
+ "utf8",
56
+ );
57
+ };
@@ -0,0 +1,96 @@
1
+ import flow from "lodash/flow.js";
2
+ import isNil from "lodash/isNil.js";
3
+ import map from "lodash/map.js";
4
+
5
+ import { getLatestReact } from "./get-react-version.ts";
6
+ import {
7
+ getList,
8
+ getListJson,
9
+ getListPlugins,
10
+ getTypeFiles,
11
+ getTypeLanguage,
12
+ } from "./list-utilities.ts";
13
+
14
+ export type ConfigOptions = {
15
+ extraImports?: string[];
16
+ globalIgnores?: string[];
17
+ includeAngularLanguageOptions?: boolean;
18
+ includeIgnores?: boolean;
19
+ includeLanguageOptions?: boolean;
20
+ includeReactVersion?: boolean;
21
+ processor?: string;
22
+ };
23
+
24
+ const getIgnoresString = flow(
25
+ (globalIgnores: string[] | undefined) => {
26
+ return map(globalIgnores, (ignore) => {
27
+ return `"${ignore}"`;
28
+ });
29
+ },
30
+ (list) => list.join(", "),
31
+ );
32
+
33
+ export const createConfig = async (
34
+ type: string,
35
+ options: ConfigOptions = {},
36
+ ) => {
37
+ let config = "";
38
+ let settings;
39
+
40
+ if (!isNil(options.includeReactVersion)) {
41
+ const react = await getLatestReact();
42
+ settings = JSON.stringify({
43
+ react: { version: react?.version },
44
+ }).slice(1, -1);
45
+ }
46
+
47
+ const list = getList(type);
48
+ const ruleJson = getListJson(list);
49
+
50
+ let optionals = "";
51
+
52
+ if (!isNil(options.includeIgnores)) {
53
+ optionals += "\nignores,";
54
+ }
55
+
56
+ if (
57
+ !isNil(options.includeLanguageOptions) &&
58
+ isNil(options.includeAngularLanguageOptions)
59
+ ) {
60
+ optionals += "\nlanguageOptions,";
61
+ }
62
+
63
+ if (!isNil(options.includeAngularLanguageOptions)) {
64
+ optionals += "\nlanguageOptions: angularLanguageOptions,";
65
+ }
66
+
67
+ if (!isNil(options.processor)) {
68
+ optionals += `\nprocessor: ${options.processor},`;
69
+ }
70
+
71
+ if (!isNil(options.includeReactVersion) && !isNil(settings)) {
72
+ optionals += `\nsettings: {
73
+ ${settings}
74
+ },`;
75
+ }
76
+
77
+ const language = getTypeLanguage(type);
78
+
79
+ if (options.globalIgnores) {
80
+ config += `{
81
+ ignores: [${getIgnoresString(options.globalIgnores)}],
82
+ },`;
83
+ }
84
+
85
+ config += `{
86
+ files: ["${getTypeFiles(type)}"],${optionals}${language ? `language: "${language}",` : ""}
87
+ plugins: {
88
+ ${getListPlugins(list)}
89
+ },
90
+ rules: {
91
+ ${ruleJson}
92
+ },
93
+ },`;
94
+
95
+ return config;
96
+ };
@@ -0,0 +1,19 @@
1
+ import { parseFetchJson } from "@ethang/toolbelt/fetch/json.js";
2
+ import isError from "lodash/isError.js";
3
+ import { z } from "zod";
4
+
5
+ export const getLatestReact = async () => {
6
+ const response = await globalThis.fetch(
7
+ "https://registry.npmjs.org/react/latest",
8
+ );
9
+ const data = await parseFetchJson(
10
+ response,
11
+ z.object({ version: z.string() }),
12
+ );
13
+
14
+ if (isError(data)) {
15
+ return;
16
+ }
17
+
18
+ return data;
19
+ };
@@ -0,0 +1,124 @@
1
+ import filter from "lodash/filter.js";
2
+ import flow from "lodash/flow.js";
3
+ import isNil from "lodash/isNil.js";
4
+ import map from "lodash/map.js";
5
+
6
+ import { ruleList } from "./rule-list.ts";
7
+
8
+ const filterRuleListByType = (type: string) => {
9
+ return filter(ruleList, (list) => {
10
+ return list.type === type;
11
+ });
12
+ };
13
+
14
+ export const getList = flow(filterRuleListByType, (list) => {
15
+ return list.sort((a, b) => {
16
+ return (a.order ?? 0) - (b.order ?? 0);
17
+ });
18
+ });
19
+
20
+ export const getTypeImportStrings = flow(
21
+ filterRuleListByType,
22
+ (list) =>
23
+ map(list, (item) => {
24
+ return item.importString;
25
+ }),
26
+ (list) => filter(list, Boolean),
27
+ );
28
+
29
+ export const getListJson = flow(
30
+ (list: typeof ruleList) => {
31
+ return map(list, (item) => {
32
+ return JSON.stringify(item.list).slice(1, -1);
33
+ });
34
+ },
35
+ (list) => list.join(","),
36
+ );
37
+
38
+ export const getTypeLanguage = (type: string) => {
39
+ switch (type) {
40
+ case "css": {
41
+ return "css/css";
42
+ }
43
+
44
+ case "json": {
45
+ return "json/json";
46
+ }
47
+
48
+ case "json5": {
49
+ return "json/json5";
50
+ }
51
+
52
+ case "jsonc": {
53
+ return "json/jsonc";
54
+ }
55
+
56
+ default: {
57
+ return null;
58
+ }
59
+ }
60
+ };
61
+
62
+ export const getTypeFiles = (type: string) => {
63
+ switch (type) {
64
+ case "angular": {
65
+ return "**/*.ts";
66
+ }
67
+
68
+ case "angular:template": {
69
+ return "**/*.html";
70
+ }
71
+
72
+ case "astro": {
73
+ return "**/*.{astro}";
74
+ }
75
+
76
+ case "core": {
77
+ return "**/*.{js,ts,jsx,tsx,cjs,cts,mjs,mts}";
78
+ }
79
+
80
+ case "css": {
81
+ return "**/*.css";
82
+ }
83
+
84
+ case "json": {
85
+ return "**/*.json";
86
+ }
87
+
88
+ case "json5": {
89
+ return "**/*.json5";
90
+ }
91
+
92
+ case "jsonc": {
93
+ return "**/*.jsonc";
94
+ }
95
+
96
+ case "markdown": {
97
+ return "**/*.md";
98
+ }
99
+
100
+ case "react": {
101
+ return "**/*.{jsx,tsx}";
102
+ }
103
+
104
+ case "solid": {
105
+ return "**/*.{jsx,tsx}";
106
+ }
107
+
108
+ default: {
109
+ return "";
110
+ }
111
+ }
112
+ };
113
+
114
+ export const getListPlugins = (list: typeof ruleList) => {
115
+ let pluginString = "";
116
+
117
+ for (const item of list) {
118
+ if (!isNil(item.pluginName) && !isNil(item.pluginValue)) {
119
+ pluginString += `"${item.pluginName}": ${item.pluginValue},`;
120
+ }
121
+ }
122
+
123
+ return pluginString;
124
+ };
@@ -0,0 +1,284 @@
1
+ import { a11yRules } from "../setup/a11y.ts";
2
+ import { angularTemplateRules, angularTsRules } from "../setup/angular.js";
3
+ import { astroRules } from "../setup/astro.ts";
4
+ import { barrelRules } from "../setup/barrel.ts";
5
+ import { compatRules } from "../setup/compat.ts";
6
+ import { cspellRules } from "../setup/cspell.js";
7
+ import { cssRules } from "../setup/css.js";
8
+ import { dependRules } from "../setup/depend.ts";
9
+ import { eslintRules } from "../setup/eslint.ts";
10
+ import { jsonRules } from "../setup/json.ts";
11
+ import { lodashRules } from "../setup/lodash.ts";
12
+ import { markdownRules } from "../setup/markdown.ts";
13
+ import { perfectionistRules } from "../setup/perfectionist.ts";
14
+ import {
15
+ reactCompilerRules,
16
+ reactHookRules,
17
+ reactRules,
18
+ } from "../setup/react.ts";
19
+ import { solidRules } from "../setup/solid.ts";
20
+ import { sonarRules } from "../setup/sonar.ts";
21
+ import { tailwindRules } from "../setup/tailwind.js";
22
+ import { tanstackQueryRules } from "../setup/tanstack-query.ts";
23
+ import { tanstackRouterRules } from "../setup/tanstack-router.js";
24
+ import { typescriptRules } from "../setup/typescript-eslint.ts";
25
+ import { unicornRules } from "../setup/unicorn.ts";
26
+
27
+ const eslintJson = "@eslint/json";
28
+ const eslintJsonGithub = "https://github.com/eslint/json";
29
+
30
+ export const ruleList = [
31
+ {
32
+ importString: 'import depend from "eslint-plugin-depend";',
33
+ list: dependRules,
34
+ name: "eslint-plugin-depend",
35
+ order: 0,
36
+ pluginName: "depend",
37
+ pluginValue: "depend",
38
+ type: "core",
39
+ url: "https://github.com/es-tooling/eslint-plugin-depend/tree/main",
40
+ },
41
+ {
42
+ importString: 'import barrel from "eslint-plugin-barrel-files";',
43
+ list: barrelRules,
44
+ name: "eslint-plugin-barrel-files",
45
+ order: 1,
46
+ pluginName: "barrel",
47
+ pluginValue: "barrel",
48
+ type: "core",
49
+ url: "https://github.com/thepassle/eslint-plugin-barrel-files",
50
+ },
51
+ {
52
+ importString: 'import compat from "eslint-plugin-compat";',
53
+ list: compatRules,
54
+ name: "eslint-plugin-compat",
55
+ order: 2,
56
+ pluginName: "compat",
57
+ pluginValue: "compat",
58
+ type: "core",
59
+ url: "https://github.com/amilajack/eslint-plugin-compat",
60
+ },
61
+ {
62
+ importString: undefined,
63
+ list: eslintRules,
64
+ name: "@eslint/js",
65
+ order: 3,
66
+ pluginName: undefined,
67
+ pluginValue: undefined,
68
+ type: "core",
69
+ url: "https://github.com/eslint/eslint/tree/main/packages/js",
70
+ },
71
+ {
72
+ importString: 'import tseslint from "typescript-eslint";',
73
+ list: typescriptRules,
74
+ name: "@typescript/eslint",
75
+ order: 4,
76
+ pluginName: "@typescript-eslint",
77
+ pluginValue: "tseslint.plugin",
78
+ type: "core",
79
+ url: "https://github.com/typescript-eslint/typescript-eslint",
80
+ },
81
+ {
82
+ importString: 'import unicorn from "eslint-plugin-unicorn";',
83
+ list: unicornRules,
84
+ name: "sindresorhus/eslint-plugin-unicorn",
85
+ order: 5,
86
+ pluginName: "unicorn",
87
+ pluginValue: "unicorn",
88
+ type: "core",
89
+ url: "https://github.com/sindresorhus/eslint-plugin-unicorn",
90
+ },
91
+ {
92
+ importString: 'import lodashConfig from "eslint-plugin-lodash";',
93
+ list: lodashRules,
94
+ name: "eslint-plugin-lodash",
95
+ order: 6,
96
+ pluginName: "lodash",
97
+ pluginValue: "lodashConfig",
98
+ type: "core",
99
+ url: "https://github.com/wix-incubator/eslint-plugin-lodash",
100
+ },
101
+ {
102
+ importString: 'import sonar from "eslint-plugin-sonarjs";',
103
+ list: sonarRules,
104
+ name: "eslint-plugin-sonarjs",
105
+ order: 7,
106
+ pluginName: "sonar",
107
+ pluginValue: "fixupPluginRules(sonar)", // TODO remove with v9 compat
108
+ type: "core",
109
+ url: "https://github.com/SonarSource/SonarJS/blob/master/packages/jsts/src/rules/README.md",
110
+ },
111
+ {
112
+ importString: 'import tailwind from "eslint-plugin-tailwindcss";',
113
+ list: tailwindRules,
114
+ name: "eslint-plugin-tailwindcss",
115
+ order: 8,
116
+ pluginName: "tailwind",
117
+ pluginValue: "tailwind",
118
+ type: "core",
119
+ url: "https://github.com/francoismassart/eslint-plugin-tailwindcss",
120
+ },
121
+ {
122
+ importString: 'import perfectionist from "eslint-plugin-perfectionist";',
123
+ list: perfectionistRules,
124
+ name: "eslint-plugin-perfectionist",
125
+ order: 9,
126
+ pluginName: "perfectionist",
127
+ pluginValue: "perfectionist",
128
+ type: "core",
129
+ url: "https://github.com/azat-io/eslint-plugin-perfectionist",
130
+ },
131
+ {
132
+ importString: 'import tanstackQuery from "@tanstack/eslint-plugin-query";',
133
+ list: tanstackQueryRules,
134
+ name: "@tanstack/eslint-plugin-query",
135
+ order: 10,
136
+ pluginName: "@tanstack/query",
137
+ pluginValue: "tanstackQuery",
138
+ type: "core",
139
+ url: "https://tanstack.com/query/latest/docs/eslint/eslint-plugin-query",
140
+ },
141
+ {
142
+ importString:
143
+ 'import tanstackRouter from "@tanstack/eslint-plugin-router";',
144
+ list: tanstackRouterRules,
145
+ name: "@tanstack/eslint-plugin-router",
146
+ order: 11,
147
+ pluginName: "@tanstack/router",
148
+ pluginValue: "tanstackRouter",
149
+ type: "core",
150
+ url: "https://tanstack.com/router/latest/docs/eslint/eslint-plugin-router",
151
+ },
152
+ {
153
+ importString: 'import a11y from "eslint-plugin-jsx-a11y";',
154
+ list: a11yRules,
155
+ name: "jsx-a11y",
156
+ order: 12,
157
+ pluginName: "a11y",
158
+ pluginValue: "a11y",
159
+ type: "core",
160
+ url: "https://github.com/jsx-eslint/eslint-plugin-jsx-a11y",
161
+ },
162
+ {
163
+ importString: 'import cspell from "@cspell/eslint-plugin";',
164
+ list: cspellRules,
165
+ name: "@cspell/eslint-plugin",
166
+ order: 13,
167
+ pluginName: "cspell",
168
+ pluginValue: "cspell",
169
+ type: "core",
170
+ url: "https://github.com/streetsidesoftware/cspell/tree/main/packages/cspell-eslint-plugin",
171
+ },
172
+ {
173
+ importString: "import css from '@eslint/css';",
174
+ list: cssRules,
175
+ name: "@eslint/css",
176
+ order: 0,
177
+ pluginName: "css",
178
+ pluginValue: "css",
179
+ type: "css",
180
+ url: "https://github.com/eslint/css",
181
+ },
182
+ {
183
+ importString: 'import markdown from "@eslint/markdown";',
184
+ list: markdownRules,
185
+ name: "@eslint/markdown",
186
+ order: 0,
187
+ pluginName: "markdown",
188
+ pluginValue: "markdown",
189
+ type: "markdown",
190
+ url: "https://github.com/eslint/markdown",
191
+ },
192
+ {
193
+ importString: `import json from "${eslintJson}";`,
194
+ list: jsonRules,
195
+ name: eslintJson,
196
+ order: 0,
197
+ pluginName: "json",
198
+ pluginValue: "json",
199
+ type: "json",
200
+ url: eslintJsonGithub,
201
+ },
202
+ {
203
+ list: jsonRules,
204
+ name: eslintJson,
205
+ order: 0,
206
+ pluginName: "json",
207
+ pluginValue: "json",
208
+ type: "jsonc",
209
+ url: eslintJsonGithub,
210
+ },
211
+ {
212
+ list: jsonRules,
213
+ name: eslintJson,
214
+ order: 0,
215
+ pluginName: "json",
216
+ pluginValue: "json",
217
+ type: "json5",
218
+ url: eslintJsonGithub,
219
+ },
220
+ {
221
+ importString: 'import astro from "eslint-plugin-astro";',
222
+ list: astroRules,
223
+ name: "eslint-plugin-astro",
224
+ pluginName: "astro",
225
+ pluginValue: "astro",
226
+ type: "astro",
227
+ url: "https://github.com/ota-meshi/eslint-plugin-astro",
228
+ },
229
+ {
230
+ importString: 'import react from "@eslint-react/eslint-plugin";',
231
+ list: reactRules,
232
+ name: "@eslint-react/eslint-plugin",
233
+ pluginName: "react",
234
+ pluginValue: "react",
235
+ type: "react",
236
+ url: "https://eslint-react.xyz/",
237
+ },
238
+ {
239
+ importString: 'import reactHooks from "eslint-plugin-react-hooks";',
240
+ list: reactHookRules,
241
+ name: "eslint-plugin-react-hooks",
242
+ pluginName: "react-hooks",
243
+ pluginValue: "reactHooks",
244
+ type: "react",
245
+ url: "https://github.com/facebook/react/tree/main/packages/eslint-plugin-react-hooks",
246
+ },
247
+ {
248
+ importString: 'import reactCompiler from "eslint-plugin-react-compiler";',
249
+ list: reactCompilerRules,
250
+ name: "eslint-plugin-react-compiler",
251
+ pluginName: "react-compiler",
252
+ pluginValue: "reactCompiler",
253
+ type: "react",
254
+ url: "https://github.com/facebook/react/tree/main/compiler/packages/eslint-plugin-react-compiler",
255
+ },
256
+ {
257
+ importString: 'import solid from "eslint-plugin-solid";',
258
+ list: solidRules,
259
+ name: "eslint-plugin-solid",
260
+ pluginName: "solid",
261
+ pluginValue: "solid",
262
+ type: "solid",
263
+ url: "https://github.com/solidjs-community/eslint-plugin-solid",
264
+ },
265
+ {
266
+ importString: 'import angularTS from "@angular-eslint/eslint-plugin";',
267
+ list: angularTsRules,
268
+ name: "@angular-eslint/eslint-plugin",
269
+ pluginName: "@angular-eslint",
270
+ pluginValue: "angularTS",
271
+ type: "angular",
272
+ url: "https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin/README.md",
273
+ },
274
+ {
275
+ importString:
276
+ 'import angularTemplate from "@angular-eslint/eslint-plugin-template";',
277
+ list: angularTemplateRules,
278
+ name: "@angular-eslint/eslint-plugin-template",
279
+ pluginName: "@angular-eslint/template",
280
+ pluginValue: "angularTemplate",
281
+ type: "angular:template",
282
+ url: "https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin-template/README.md",
283
+ },
284
+ ];