@ethang/eslint-config 19.2.8 → 19.2.10

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 CHANGED
@@ -5,9 +5,9 @@
5
5
  > [!CAUTION]
6
6
  > Do not use this with Prettier! Styling rules are included.
7
7
 
8
- - 884 errored rules.
8
+ - 885 errored rules.
9
9
  - 289 rules from [eslint-plugin-sonarjs](https://github.com/SonarSource/SonarJS/blob/master/packages/jsts/src/rules/README.md)
10
- - 144 rules from [@eslint/js](https://github.com/eslint/eslint/tree/main/packages/js)
10
+ - 145 rules from [@eslint/js](https://github.com/eslint/eslint/tree/main/packages/js)
11
11
  - 113 rules from [sindresorhus/eslint-plugin-unicorn](https://github.com/sindresorhus/eslint-plugin-unicorn)
12
12
  - 104 rules from [@typescript/eslint](https://github.com/typescript-eslint/typescript-eslint)
13
13
  - 91 rules from [@stylistic/eslint-plugin](https://eslint.style/)
@@ -0,0 +1,45 @@
1
+ import { getTypeImportStrings } from "./list-utils.mjs";
2
+ import { createConfig } from "./create-config.js";
3
+ import { writeFileSync } from "node:fs";
4
+ import { join } from "node:path";
5
+
6
+ export const createConfigFile = async (listConfigs, fileName) => {
7
+ let configFile = "";
8
+
9
+ const imports = listConfigs
10
+ .map((list) => {
11
+ const importStrings = getTypeImportStrings(list.name);
12
+
13
+ if (list.options?.extraImports?.length > 0) {
14
+ importStrings.push(...list.options.extraImports);
15
+ }
16
+
17
+ return importStrings;
18
+ })
19
+ .flat();
20
+
21
+ const importList = [
22
+ 'import { ignores, languageOptions } from "./constants.js";',
23
+ ...imports,
24
+ ].sort((a, b) => a.localeCompare(b));
25
+
26
+ importList.forEach((item) => {
27
+ configFile += `${item}\n`;
28
+ });
29
+
30
+ const configs = await Promise.all(
31
+ listConfigs.map((list) => {
32
+ return createConfig(list.name, list.options);
33
+ }),
34
+ );
35
+
36
+ configFile += `\nexport default tseslint.config(
37
+ ${configs.join("\n")}
38
+ );\n`;
39
+
40
+ writeFileSync(
41
+ join(import.meta.dirname, `../${fileName}`),
42
+ configFile,
43
+ "utf8",
44
+ );
45
+ };
@@ -0,0 +1,50 @@
1
+ import {
2
+ getList,
3
+ getListJson,
4
+ getListPlugins,
5
+ getTypeFiles,
6
+ } from "./list-utils.mjs";
7
+ import { getLatestReact } from "./get-react-version.js";
8
+
9
+ export const createConfig = async (type, options = {}) => {
10
+ let config = "";
11
+ let settings;
12
+
13
+ if (options.includeReactVersion) {
14
+ const react = await getLatestReact();
15
+ settings = JSON.stringify({
16
+ react: { version: react.version },
17
+ }).slice(1, -1);
18
+ }
19
+
20
+ const list = getList(type);
21
+ const ruleJson = getListJson(list);
22
+
23
+ let optionals = "";
24
+
25
+ if (options.includeIgnores) {
26
+ optionals += "\nignores,";
27
+ }
28
+
29
+ if (options.includeLanguageOptions) {
30
+ optionals += "\nlanguageOptions,";
31
+ }
32
+
33
+ if (options.includeReactVersion && settings) {
34
+ optionals += `\nsettings: {
35
+ ${settings}
36
+ },`;
37
+ }
38
+
39
+ config += `{
40
+ files: ["${getTypeFiles(type)}"],${optionals}
41
+ plugins: {
42
+ ${getListPlugins(list)}
43
+ },
44
+ rules: {
45
+ ${ruleJson}
46
+ },
47
+ },`;
48
+
49
+ return config;
50
+ };
@@ -0,0 +1,70 @@
1
+ import { ruleList } from "./rule-list.mjs";
2
+
3
+ export const getList = (type) => {
4
+ return ruleList
5
+ .filter((list) => list.type === type)
6
+ .sort((a, b) => a.order - b.order);
7
+ };
8
+
9
+ export const getListImportStrings = (list) => {
10
+ return list
11
+ .map((item) => {
12
+ return item.importString;
13
+ })
14
+ .filter(Boolean);
15
+ };
16
+
17
+ export const getTypeImportStrings = (type) => {
18
+ return ruleList
19
+ .filter((list) => list.type === type)
20
+ .map((item) => item.importString)
21
+ .filter(Boolean);
22
+ };
23
+
24
+ export const getListJson = (list) => {
25
+ return list
26
+ .map((list) => {
27
+ return JSON.stringify(list.list).slice(1, -1);
28
+ })
29
+ .join(",");
30
+ };
31
+
32
+ export const getTypeFiles = (type) => {
33
+ switch (type) {
34
+ case "core": {
35
+ return ["**/*.{js,ts,jsx,tsx,cjs,cts,mjs,mts}"];
36
+ }
37
+
38
+ case "markdown": {
39
+ return ["**/*.md"];
40
+ }
41
+
42
+ case "json": {
43
+ return ["**/*.{json,jsonc,json5}"];
44
+ }
45
+
46
+ case "react": {
47
+ return ["**/*.{jsx,tsx}"];
48
+ }
49
+
50
+ case "astro": {
51
+ return ["**/*.{astro}"];
52
+ }
53
+
54
+ case "solid": {
55
+ return ["**/*.{jsx,tsx}"];
56
+ }
57
+ }
58
+ };
59
+
60
+ export const getListPlugins = (list) => {
61
+ let pluginString = "";
62
+
63
+ for (const item of list) {
64
+ if (item.pluginName && item.pluginValue) {
65
+ pluginString += `"${item.pluginName}": ${item.pluginValue},`;
66
+ }
67
+ }
68
+
69
+ return pluginString;
70
+ };
@@ -0,0 +1,240 @@
1
+ import { dependRules } from "../setup/depend.js";
2
+ import { barrelRules } from "../setup/barrel.js";
3
+ import { compatRules } from "../setup/compat.js";
4
+ import { eslintRules } from "../setup/eslint.js";
5
+ import { nRules } from "../setup/n.js";
6
+ import { typescriptRules } from "../setup/typescript-eslint.js";
7
+ import { unicornRules } from "../setup/unicorn.js";
8
+ import { lodashRules } from "../setup/lodash.js";
9
+ import { sonarRules } from "../setup/sonar.js";
10
+ import { tanstackQueryRules } from "../setup/tanstack-query.js";
11
+ import { tailwindRules } from "../setup/tailwind.js";
12
+ import { stylisticRules } from "../setup/stylistic.js";
13
+ import { perfectionistRules } from "../setup/perfectionist.js";
14
+ import { a11yRules } from "../setup/a11y.js";
15
+ import { markdownRules } from "../setup/markdown.js";
16
+ import { jsonRules } from "../setup/json.js";
17
+ import { ethangRules } from "../setup/ethang.js";
18
+ import { astroRules } from "../setup/astro.js";
19
+ import { reactHookRules, reactRules } from "../setup/react.js";
20
+ import { solidRules } from "../setup/solid.js";
21
+ import { deprecatedRules } from "../setup/deprecated.js";
22
+
23
+ export const ruleList = [
24
+ {
25
+ list: dependRules,
26
+ name: "eslint-plugin-depend",
27
+ url: "https://github.com/es-tooling/eslint-plugin-depend/tree/main",
28
+ type: "core",
29
+ importString: 'import depend from "eslint-plugin-depend";',
30
+ order: 0,
31
+ pluginName: "depend",
32
+ pluginValue: "depend",
33
+ },
34
+ {
35
+ list: barrelRules,
36
+ name: "eslint-plugin-barrel-files",
37
+ url: "https://github.com/thepassle/eslint-plugin-barrel-files",
38
+ type: "core",
39
+ importString: 'import barrel from "eslint-plugin-barrel-files";',
40
+ order: 1,
41
+ pluginName: "barrel",
42
+ pluginValue: "barrel",
43
+ },
44
+ {
45
+ list: compatRules,
46
+ name: "eslint-plugin-compat",
47
+ url: "https://github.com/amilajack/eslint-plugin-compat",
48
+ type: "core",
49
+ importString: 'import compat from "eslint-plugin-compat";',
50
+ order: 2,
51
+ pluginName: "compat",
52
+ pluginValue: "compat",
53
+ },
54
+ {
55
+ list: eslintRules,
56
+ name: "@eslint/js",
57
+ url: "https://github.com/eslint/eslint/tree/main/packages/js",
58
+ type: "core",
59
+ importString: undefined,
60
+ order: 3,
61
+ pluginName: undefined,
62
+ pluginValue: undefined,
63
+ },
64
+ {
65
+ list: nRules,
66
+ name: "eslint-plugin-n",
67
+ url: "https://github.com/eslint-community/eslint-plugin-n",
68
+ type: "core",
69
+ importString: 'import n from "eslint-plugin-n";',
70
+ order: 4,
71
+ pluginName: "n",
72
+ pluginValue: "n",
73
+ },
74
+ {
75
+ list: typescriptRules,
76
+ name: "@typescript/eslint",
77
+ url: "https://github.com/typescript-eslint/typescript-eslint",
78
+ type: "core",
79
+ importString: 'import tseslint from "typescript-eslint";',
80
+ order: 5,
81
+ pluginName: "@typescript-eslint",
82
+ pluginValue: "tseslint.plugin",
83
+ },
84
+ {
85
+ list: unicornRules,
86
+ name: "sindresorhus/eslint-plugin-unicorn",
87
+ url: "https://github.com/sindresorhus/eslint-plugin-unicorn",
88
+ type: "core",
89
+ importString: 'import unicorn from "eslint-plugin-unicorn";',
90
+ order: 6,
91
+ pluginName: "unicorn",
92
+ pluginValue: "unicorn",
93
+ },
94
+ {
95
+ list: lodashRules,
96
+ name: "eslint-plugin-lodash",
97
+ url: "https://github.com/wix-incubator/eslint-plugin-lodash",
98
+ type: "core",
99
+ importString: 'import lodashConfig from "eslint-plugin-lodash";',
100
+ order: 7,
101
+ pluginName: "lodash",
102
+ pluginValue: "lodashConfig",
103
+ },
104
+ {
105
+ list: sonarRules,
106
+ name: "eslint-plugin-sonarjs",
107
+ url: "https://github.com/SonarSource/SonarJS/blob/master/packages/jsts/src/rules/README.md",
108
+ type: "core",
109
+ importString: 'import sonar from "eslint-plugin-sonarjs";',
110
+ order: 8,
111
+ pluginName: "sonar",
112
+ pluginValue: "sonar",
113
+ },
114
+ {
115
+ list: ethangRules,
116
+ name: "@ethang/eslint-plugin",
117
+ url: "https://github.com/eglove/eslint-plugin",
118
+ type: "core",
119
+ importString: 'import ethang from "@ethang/eslint-plugin";',
120
+ order: 9,
121
+ pluginName: "ethang",
122
+ pluginValue: "ethang",
123
+ },
124
+ {
125
+ list: tanstackQueryRules,
126
+ name: "@tanstack/eslint-plugin-query",
127
+ url: "https://tanstack.com/query/latest/docs/eslint/eslint-plugin-query",
128
+ type: "core",
129
+ importString: 'import tanstack from "@tanstack/eslint-plugin-query";',
130
+ order: 10,
131
+ pluginName: "@tanstack/query",
132
+ pluginValue: "tanstack",
133
+ },
134
+ {
135
+ list: tailwindRules,
136
+ name: "eslint-plugin-tailwindcss",
137
+ url: "https://github.com/francoismassart/eslint-plugin-tailwindcss",
138
+ type: "core",
139
+ importString: 'import tailwind from "eslint-plugin-tailwindcss";',
140
+ order: 11,
141
+ pluginName: "tailwind",
142
+ pluginValue: "tailwind",
143
+ },
144
+ {
145
+ list: stylisticRules,
146
+ name: "@stylistic/eslint-plugin",
147
+ url: "https://eslint.style/",
148
+ type: "core",
149
+ importString: 'import stylistic from "@stylistic/eslint-plugin";',
150
+ order: 12,
151
+ pluginName: "stylistic",
152
+ pluginValue: "stylistic",
153
+ },
154
+ {
155
+ list: perfectionistRules,
156
+ name: "eslint-plugin-perfectionist",
157
+ url: "https://github.com/azat-io/eslint-plugin-perfectionist",
158
+ type: "core",
159
+ importString: 'import perfectionist from "eslint-plugin-perfectionist";',
160
+ order: 13,
161
+ pluginName: "perfectionist",
162
+ pluginValue: "perfectionist",
163
+ },
164
+ {
165
+ list: a11yRules,
166
+ name: "jsx-a11y",
167
+ url: "https://github.com/jsx-eslint/eslint-plugin-jsx-a11y",
168
+ type: "core",
169
+ importString: 'import a11y from "eslint-plugin-jsx-a11y/lib/index.js";',
170
+ order: 14,
171
+ pluginName: "a11y",
172
+ pluginValue: "a11y",
173
+ },
174
+ {
175
+ list: deprecatedRules,
176
+ name: "@eslint/js",
177
+ url: "https://github.com/eslint/eslint/tree/main/packages/js",
178
+ type: "core",
179
+ importString: undefined,
180
+ order: 15,
181
+ pluginName: undefined,
182
+ pluginValue: undefined,
183
+ },
184
+ {
185
+ list: markdownRules,
186
+ name: "@eslint/markdown",
187
+ url: "https://github.com/eslint/markdown",
188
+ type: "markdown",
189
+ importString: 'import markdown from "@eslint/markdown";',
190
+ order: 0,
191
+ pluginName: "markdown",
192
+ pluginValue: "markdown",
193
+ },
194
+ {
195
+ list: jsonRules,
196
+ name: "@eslint/json",
197
+ url: "https://github.com/eslint/json",
198
+ type: "json",
199
+ importString: 'import json from "@eslint/json";',
200
+ order: 0,
201
+ pluginName: "json",
202
+ pluginValue: "json",
203
+ },
204
+ {
205
+ list: astroRules,
206
+ name: "eslint-plugin-astro",
207
+ url: "https://github.com/ota-meshi/eslint-plugin-astro",
208
+ type: "astro",
209
+ importString: 'import astro from "eslint-plugin-astro";',
210
+ pluginName: "astro",
211
+ pluginValue: "astro",
212
+ },
213
+ {
214
+ list: reactRules,
215
+ name: "@eslint-react/eslint-plugin",
216
+ url: "https://eslint-react.xyz/",
217
+ type: "react",
218
+ importString: 'import react from "@eslint-react/eslint-plugin";',
219
+ pluginName: "react",
220
+ pluginValue: "react",
221
+ },
222
+ {
223
+ list: reactHookRules,
224
+ name: "eslint-plugin-react-hooks",
225
+ url: "https://github.com/facebook/react/tree/main/packages/eslint-plugin-react-hooks",
226
+ type: "react",
227
+ importString: 'import reactHooks from "eslint-plugin-react-hooks";',
228
+ pluginName: "react-hooks",
229
+ pluginValue: "reactHooks",
230
+ },
231
+ {
232
+ list: solidRules,
233
+ name: "eslint-plugin-solid",
234
+ url: "https://github.com/solidjs-community/eslint-plugin-solid",
235
+ type: "solid",
236
+ importString: 'import solid from "eslint-plugin-solid";',
237
+ pluginName: "solid",
238
+ pluginValue: "solid",
239
+ },
240
+ ];
@@ -1,26 +1,7 @@
1
- import { dependRules } from "../setup/depend.js";
2
- import { barrelRules } from "../setup/barrel.js";
3
- import { compatRules } from "../setup/compat.js";
4
- import { eslintRules } from "../setup/eslint.js";
5
- import { nRules } from "../setup/n.js";
6
- import { typescriptRules } from "../setup/typescript-eslint.js";
7
- import { unicornRules } from "../setup/unicorn.js";
8
- import { lodashRules } from "../setup/lodash.js";
9
- import { sonarRules } from "../setup/sonar.js";
10
- import { tanstackQueryRules } from "../setup/tanstack-query.js";
11
- import { tailwindRules } from "../setup/tailwind.js";
12
- import { stylisticRules } from "../setup/stylistic.js";
13
- import { perfectionistRules } from "../setup/perfectionist.js";
14
- import { a11yRules } from "../setup/a11y.js";
15
1
  import { writeFileSync } from "node:fs";
16
2
  import { join } from "node:path";
17
3
  import { MarkdownGenerator } from "@ethang/markdown-generator/markdown-generator.js";
18
- import { markdownRules } from "../setup/markdown.js";
19
- import { jsonRules } from "../setup/json.js";
20
- import { astroRules } from "../setup/astro.js";
21
- import { reactRules } from "../setup/react.js";
22
- import { solidRules } from "../setup/solid.js";
23
- import { ethangRules } from "../setup/ethang.js";
4
+ import { getList } from "./list-utils.mjs";
24
5
 
25
6
  export const updateReadme = () => {
26
7
  const md = new MarkdownGenerator();
@@ -43,114 +24,51 @@ export const updateReadme = () => {
43
24
  return count;
44
25
  };
45
26
 
46
- const ruleList = [
47
- {
48
- list: dependRules,
49
- name: "eslint-plugin-depend",
50
- url: "https://github.com/es-tooling/eslint-plugin-depend/tree/main",
51
- },
52
- {
53
- list: barrelRules,
54
- name: "eslint-plugin-barrel-files",
55
- url: "https://github.com/thepassle/eslint-plugin-barrel-files",
56
- },
57
- {
58
- list: compatRules,
59
- name: "eslint-plugin-compat",
60
- url: "https://github.com/amilajack/eslint-plugin-compat",
61
- },
62
- {
63
- list: eslintRules,
64
- name: "@eslint/js",
65
- url: "https://github.com/eslint/eslint/tree/main/packages/js",
66
- },
67
- {
68
- list: nRules,
69
- name: "eslint-plugin-n",
70
- url: "https://github.com/eslint-community/eslint-plugin-n",
71
- },
72
- {
73
- list: typescriptRules,
74
- name: "@typescript/eslint",
75
- url: "https://github.com/typescript-eslint/typescript-eslint",
76
- },
77
- {
78
- list: unicornRules,
79
- name: "sindresorhus/eslint-plugin-unicorn",
80
- url: "https://github.com/sindresorhus/eslint-plugin-unicorn",
81
- },
82
- {
83
- list: lodashRules,
84
- name: "eslint-plugin-lodash",
85
- url: "https://github.com/wix-incubator/eslint-plugin-lodash",
86
- },
87
- {
88
- list: sonarRules,
89
- name: "eslint-plugin-sonarjs",
90
- url: "https://github.com/SonarSource/SonarJS/blob/master/packages/jsts/src/rules/README.md",
91
- },
92
- {
93
- list: tanstackQueryRules,
94
- name: "@tanstack/eslint-plugin-query",
95
- url: "https://tanstack.com/query/latest/docs/eslint/eslint-plugin-query",
96
- },
97
- {
98
- list: tailwindRules,
99
- name: "eslint-plugin-tailwindcss",
100
- url: "https://github.com/francoismassart/eslint-plugin-tailwindcss",
101
- },
102
- {
103
- list: stylisticRules,
104
- name: "@stylistic/eslint-plugin",
105
- url: "https://eslint.style/",
106
- },
107
- {
108
- list: perfectionistRules,
109
- name: "eslint-plugin-perfectionist",
110
- url: "https://github.com/azat-io/eslint-plugin-perfectionist",
111
- },
112
- {
113
- list: a11yRules,
114
- name: "jsx-a11y",
115
- url: "https://github.com/jsx-eslint/eslint-plugin-jsx-a11y",
116
- },
117
- {
118
- list: markdownRules,
119
- name: "@eslint/markdown",
120
- url: "https://github.com/eslint/markdown",
121
- },
122
- {
123
- list: jsonRules,
124
- name: "@eslint/json",
125
- url: "https://github.com/eslint/json",
126
- },
127
- {
128
- list: ethangRules,
129
- name: "@ethang/eslint-plugin",
130
- url: "https://github.com/eglove/eslint-plugin",
131
- },
27
+ const coreRules = [
28
+ ...getList("core"),
29
+ ...getList("json"),
30
+ ...getList("markdown"),
132
31
  ];
133
32
 
134
33
  let total = 0;
135
- for (const list of ruleList) {
34
+ for (const list of coreRules) {
136
35
  const count = getRuleCount(list.list);
137
36
  total += count;
138
37
  list["count"] = count;
139
38
  }
140
- ruleList.sort((a, b) => {
39
+ coreRules.sort((a, b) => {
141
40
  return b.count - a.count;
142
41
  });
143
42
 
144
43
  const ruleDocs = [`${total} errored rules.`];
145
- for (const list of ruleList) {
44
+ for (const list of coreRules) {
45
+ if (list.count < 1) {
46
+ continue;
47
+ }
48
+
146
49
  ruleDocs.push(
147
50
  `${list.count} ${list.count <= 1 ? "rule" : "rules"} from [${list.name}](${list.url})`,
148
51
  );
149
52
  }
150
53
 
151
- const astroCount = getRuleCount(astroRules);
152
- const reactCount = getRuleCount(reactRules);
153
- const solidCount = getRuleCount(solidRules);
54
+ const astroRules = getList("astro");
55
+ const reactRules = getList("react");
56
+ const solidRules = getList("solid");
57
+
58
+ let astroCount = 0;
59
+ for (const astroRule of astroRules) {
60
+ astroCount += getRuleCount(astroRule.list);
61
+ }
62
+
63
+ let reactCount = 0;
64
+ for (const reactRule of reactRules) {
65
+ reactCount += getRuleCount(reactRule.list);
66
+ }
67
+
68
+ let solidCount = 0;
69
+ for (const solidRule of solidRules) {
70
+ solidCount += getRuleCount(solidRule.list);
71
+ }
154
72
 
155
73
  md.unorderedList(ruleDocs);
156
74
  md.newLine();
@@ -159,17 +77,29 @@ export const updateReadme = () => {
159
77
  `${astroCount} rules for **Astro**`,
160
78
  [
161
79
  '`import astroConfig from "@ethang/eslint-config/config.astro.js";`',
162
- `${astroCount} rules from [eslint-plugin-astro](https://github.com/ota-meshi/eslint-plugin-astro)`,
80
+ ...astroRules
81
+ .filter((rule) => getRuleCount(rule.list) > 0)
82
+ .map((rule) => {
83
+ return `${getRuleCount(rule.list)} rules from [${rule.name}](${rule.url})`;
84
+ }),
163
85
  ],
164
86
  `${reactCount} rules for **React**`,
165
87
  [
166
88
  '`import reactConfig from "@ethang/eslint-config/config.react.js";`',
167
- `${reactCount} rules from [@eslint-react/eslint-plugin](https://eslint-react.xyz/)`,
89
+ ...reactRules
90
+ .filter((rule) => getRuleCount(rule.list) > 0)
91
+ .map((rule) => {
92
+ return `${getRuleCount(rule.list)} rules from [${rule.name}](${rule.url})`;
93
+ }),
168
94
  ],
169
95
  `${solidCount} rules for **Solid**`,
170
96
  [
171
97
  '`import solidConfig from "@ethang/eslint-config/config.solid.js";`',
172
- `${solidCount} rules from [eslint-plugin-solid](https://github.com/solidjs-community/eslint-plugin-solid)`,
98
+ ...solidRules
99
+ .filter((rule) => getRuleCount(rule.list) > 0)
100
+ .map((rule) => {
101
+ return `${getRuleCount(rule.list)} rules from [${rule.name}](${rule.url})`;
102
+ }),
173
103
  ],
174
104
  ]);
175
105
  md.newLine();
@@ -1,139 +1,83 @@
1
- import { dependRules } from "../setup/depend.js";
2
- import { barrelRules } from "../setup/barrel.js";
3
- import { compatRules } from "../setup/compat.js";
4
- import { eslintRules } from "../setup/eslint.js";
5
- import { nRules } from "../setup/n.js";
6
- import { typescriptRules } from "../setup/typescript-eslint.js";
7
- import { unicornRules } from "../setup/unicorn.js";
8
- import { lodashRules } from "../setup/lodash.js";
9
- import { sonarRules } from "../setup/sonar.js";
10
- import { tanstackQueryRules } from "../setup/tanstack-query.js";
11
- import { tailwindRules } from "../setup/tailwind.js";
12
- import { stylisticRules } from "../setup/stylistic.js";
13
- import { perfectionistRules } from "../setup/perfectionist.js";
14
- import { a11yRules } from "../setup/a11y.js";
15
- import { writeFileSync } from "node:fs";
16
- import { join } from "node:path";
17
- import { deprecatedRules } from "../setup/deprecated.js";
18
- import { markdownRules } from "../setup/markdown.js";
19
- import { jsonRules } from "../setup/json.js";
20
- import { getLatestReact } from "./get-react-version.mjs";
21
- import { ethangRules } from "../setup/ethang.js";
1
+ import { createConfigFile } from "./create-config-file.js";
22
2
 
23
- export const updateRules = async () => {
24
- let configFile = "";
25
- const react = await getLatestReact();
26
- const settings = JSON.stringify({
27
- react: { version: react.version },
28
- }).slice(1, -1);
29
-
30
- const jsRules = {
31
- ...dependRules,
32
- ...barrelRules,
33
- ...compatRules,
34
- ...eslintRules,
35
- ...nRules,
36
- ...typescriptRules,
37
- ...unicornRules,
38
- ...lodashRules,
39
- ...sonarRules,
40
- ...ethangRules,
41
- ...tanstackQueryRules,
42
- ...tailwindRules,
43
- ...stylisticRules,
44
- ...perfectionistRules,
45
- ...a11yRules,
46
- ...deprecatedRules,
47
- };
48
-
49
- const jsRulesJon = JSON.stringify(jsRules).slice(1, -1);
50
- const markdownRulesJson = JSON.stringify(markdownRules).slice(1, -1);
51
- const jsonRulesJson = JSON.stringify(jsonRules).slice(1, -1);
52
-
53
- const importList = [
54
- 'import parser from "@typescript-eslint/parser";',
55
- 'import a11y from "eslint-plugin-jsx-a11y/lib/index.js";',
56
- 'import n from "eslint-plugin-n";',
57
- 'import unicorn from "eslint-plugin-unicorn";',
58
- 'import tseslint from "typescript-eslint";',
59
- 'import sonar from "eslint-plugin-sonarjs";',
60
- 'import tanstack from "@tanstack/eslint-plugin-query";',
61
- 'import perfectionist from "eslint-plugin-perfectionist";',
62
- 'import depend from "eslint-plugin-depend";',
63
- 'import barrel from "eslint-plugin-barrel-files";',
64
- 'import compat from "eslint-plugin-compat";',
65
- 'import lodashConfig from "eslint-plugin-lodash";',
66
- 'import tailwind from "eslint-plugin-tailwindcss";',
67
- 'import stylistic from "@stylistic/eslint-plugin";',
68
- 'import markdown from "@eslint/markdown";',
69
- 'import json from "@eslint/json";',
70
- 'import { ignores } from "./constants.js";',
71
- 'import ethang from "@ethang/eslint-plugin";',
72
- ].sort((a, b) => {
73
- return a.localeCompare(b);
74
- });
75
-
76
- importList.forEach((item) => {
77
- configFile += `${item}\n`;
78
- });
79
-
80
- configFile += `\nexport const languageOptions = {
81
- parser,
82
- parserOptions: {
83
- project: true,
84
- tsconfigRootDir: import.meta.dirname,
3
+ export const coreFile = [
4
+ {
5
+ name: "core",
6
+ label: "Core",
7
+ importString: 'import config from "@ethang/eslint-config/eslint.config.js',
8
+ options: {
9
+ includeReactVersion: true,
10
+ includeLanguageOptions: true,
11
+ includeIgnores: true,
12
+ },
85
13
  },
86
- };
14
+ {
15
+ name: "markdown",
16
+ },
17
+ {
18
+ name: "json",
19
+ },
20
+ ];
87
21
 
88
- export default tseslint.config(
22
+ const astroFile = [
89
23
  {
90
- files: ["**/*.{js,ts,jsx,tsx,cjs,cts,mjs,mts}"],
91
- ignores,
92
- languageOptions,
93
- settings: {
94
- ${settings}
95
- },
96
- plugins: {
97
- "@tanstack/query": tanstack,
98
- "@typescript-eslint": tseslint.plugin,
99
- a11y,
100
- barrel,
101
- compat,
102
- depend,
103
- ethang,
104
- lodash: lodashConfig,
105
- n,
106
- perfectionist,
107
- sonar,
108
- stylistic,
109
- tailwind,
110
- unicorn,
111
- },
112
- rules: {
113
- ${jsRulesJon}
24
+ name: "astro",
25
+ label: "Astro",
26
+ importString:
27
+ 'import astroConfig from "@ethang/eslint-config/config.astro.js',
28
+ options: {
29
+ includeIgnores: true,
30
+ includeLanguageOptions: true,
31
+ extraImports: ['import tseslint from "typescript-eslint";'],
114
32
  },
115
33
  },
34
+ ];
35
+
36
+ const reactFile = [
116
37
  {
117
- files: ["**/*.md"],
118
- plugins: {
119
- markdown,
120
- },
121
- rules: {
122
- ${markdownRulesJson}
38
+ name: "react",
39
+ label: "React",
40
+ importString:
41
+ 'import reactConfig from "@ethang/eslint-config/config.react.js',
42
+ options: {
43
+ includeReactVersion: true,
44
+ includeIgnores: true,
45
+ includeLanguageOptions: true,
46
+ extraImports: ['import tseslint from "typescript-eslint";'],
123
47
  },
124
48
  },
49
+ ];
50
+
51
+ const solidFile = [
125
52
  {
126
- files: ["**/*.{json,jsonc,json5}"],
127
- plugins: { json },
128
- rules: {
129
- ${jsonRulesJson}
53
+ name: "solid",
54
+ label: "Solid",
55
+ importString:
56
+ 'import reactConfig from "@ethang/eslint-config/config.solid.js',
57
+ options: {
58
+ includeIgnores: true,
59
+ includeLanguageOptions: true,
60
+ extraImports: ['import tseslint from "typescript-eslint";'],
130
61
  },
131
62
  },
132
- );\n`;
63
+ ];
133
64
 
134
- writeFileSync(
135
- join(import.meta.dirname, "../eslint.config.js"),
136
- configFile,
137
- "utf8",
138
- );
65
+ export const secondaryRules = {
66
+ astro: astroFile,
67
+ react: reactFile,
68
+ solid: solidFile,
69
+ };
70
+
71
+ export const allRules = {
72
+ core: coreFile,
73
+ ...secondaryRules,
74
+ };
75
+
76
+ export const updateRules = async () => {
77
+ await Promise.all([
78
+ createConfigFile(coreFile, "eslint.config.js"),
79
+ createConfigFile(astroFile, "config.astro.js"),
80
+ createConfigFile(reactFile, "config.react.js"),
81
+ createConfigFile(solidFile, "config.solid.js"),
82
+ ]);
139
83
  };
package/build.mjs CHANGED
@@ -2,9 +2,6 @@
2
2
  import { projectBuilder } from "@ethang/project-builder/project-builder.js";
3
3
  import { updateRules } from "./build/update-rules.js";
4
4
  import { updateReadme } from "./build/update-readme.js";
5
- import { updateReactRules } from "./build/update-react-rules.js";
6
- import { updateSolidRules } from "./build/update-solid-rules.js";
7
- import { updateAstroRules } from "./build/update-astro-rules.js";
8
5
 
9
6
  await projectBuilder("eslint-config-ethang", "master", {
10
7
  isLibrary: true,
@@ -12,9 +9,6 @@ await projectBuilder("eslint-config-ethang", "master", {
12
9
  postInstall: async () => {
13
10
  console.log("Updating Rules...");
14
11
  await updateRules();
15
- await updateReactRules();
16
- updateSolidRules();
17
- updateAstroRules();
18
12
  updateReadme();
19
13
  },
20
14
  tsupOptions: {
package/config.astro.js CHANGED
@@ -1,5 +1,4 @@
1
- import { ignores } from "./constants.js";
2
- import { languageOptions } from "./eslint.config.js";
1
+ import { ignores, languageOptions } from "./constants.js";
3
2
  import astro from "eslint-plugin-astro";
4
3
  import tseslint from "typescript-eslint";
5
4
 
@@ -7,7 +6,9 @@ export default tseslint.config({
7
6
  files: ["**/*.{astro}"],
8
7
  ignores,
9
8
  languageOptions,
10
- plugins: { astro },
9
+ plugins: {
10
+ astro: astro,
11
+ },
11
12
  rules: {
12
13
  "astro/missing-client-only-directive-value": "error",
13
14
  "astro/no-conflict-set-directives": "error",
package/config.react.js CHANGED
@@ -1,5 +1,4 @@
1
- import { ignores } from "./constants.js";
2
- import { languageOptions } from "./eslint.config.js";
1
+ import { ignores, languageOptions } from "./constants.js";
3
2
  import react from "@eslint-react/eslint-plugin";
4
3
  import reactHooks from "eslint-plugin-react-hooks";
5
4
  import tseslint from "typescript-eslint";
@@ -8,16 +7,14 @@ export default tseslint.config({
8
7
  files: ["**/*.{jsx,tsx}"],
9
8
  ignores,
10
9
  languageOptions,
11
- plugins: {
12
- react,
13
- "react-hooks": reactHooks,
14
- },
15
10
  settings: {
16
11
  react: { version: "18.3.1" },
17
12
  },
13
+ plugins: {
14
+ react: react,
15
+ "react-hooks": reactHooks,
16
+ },
18
17
  rules: {
19
- "react-hooks/rules-of-hooks": "off",
20
- "react-hooks/exhaustive-deps": "off",
21
18
  "react/avoid-shorthand-boolean": "off",
22
19
  "react/avoid-shorthand-fragment": "off",
23
20
  "react/ensure-forward-ref-using-ref": "error",
@@ -92,5 +89,7 @@ export default tseslint.config({
92
89
  "react/debug/function-component": "off",
93
90
  "react/debug/is-from-react": "off",
94
91
  "react/debug/react-hooks": "off",
92
+ "react-hooks/rules-of-hooks": "off",
93
+ "react-hooks/exhaustive-deps": "off",
95
94
  },
96
95
  });
package/config.solid.js CHANGED
@@ -1,5 +1,4 @@
1
- import { ignores } from "./constants.js";
2
- import { languageOptions } from "./eslint.config.js";
1
+ import { ignores, languageOptions } from "./constants.js";
3
2
  import solid from "eslint-plugin-solid";
4
3
  import tseslint from "typescript-eslint";
5
4
 
@@ -7,7 +6,9 @@ export default tseslint.config({
7
6
  files: ["**/*.{jsx,tsx}"],
8
7
  ignores,
9
8
  languageOptions,
10
- plugins: { solid },
9
+ plugins: {
10
+ solid: solid,
11
+ },
11
12
  rules: {
12
13
  "solid/components-return-once": "error",
13
14
  "solid/event-handlers": "error",
package/constants.js CHANGED
@@ -1 +1,11 @@
1
+ import { parser } from "typescript-eslint";
2
+
1
3
  export const ignores = ["eslint.config.js", "node_modules", "dist"];
4
+
5
+ export const languageOptions = {
6
+ parser,
7
+ parserOptions: {
8
+ project: true,
9
+ tsconfigRootDir: import.meta.dirname,
10
+ },
11
+ };
package/eslint.config.js CHANGED
@@ -1,4 +1,4 @@
1
- import { ignores } from "./constants.js";
1
+ import { ignores, languageOptions } from "./constants.js";
2
2
  import a11y from "eslint-plugin-jsx-a11y/lib/index.js";
3
3
  import barrel from "eslint-plugin-barrel-files";
4
4
  import compat from "eslint-plugin-compat";
@@ -8,7 +8,6 @@ import json from "@eslint/json";
8
8
  import lodashConfig from "eslint-plugin-lodash";
9
9
  import markdown from "@eslint/markdown";
10
10
  import n from "eslint-plugin-n";
11
- import parser from "@typescript-eslint/parser";
12
11
  import perfectionist from "eslint-plugin-perfectionist";
13
12
  import sonar from "eslint-plugin-sonarjs";
14
13
  import stylistic from "@stylistic/eslint-plugin";
@@ -17,14 +16,6 @@ import tanstack from "@tanstack/eslint-plugin-query";
17
16
  import tseslint from "typescript-eslint";
18
17
  import unicorn from "eslint-plugin-unicorn";
19
18
 
20
- export const languageOptions = {
21
- parser,
22
- parserOptions: {
23
- project: true,
24
- tsconfigRootDir: import.meta.dirname,
25
- },
26
- };
27
-
28
19
  export default tseslint.config(
29
20
  {
30
21
  files: ["**/*.{js,ts,jsx,tsx,cjs,cts,mjs,mts}"],
@@ -34,20 +25,20 @@ export default tseslint.config(
34
25
  react: { version: "18.3.1" },
35
26
  },
36
27
  plugins: {
37
- "@tanstack/query": tanstack,
28
+ depend: depend,
29
+ barrel: barrel,
30
+ compat: compat,
31
+ n: n,
38
32
  "@typescript-eslint": tseslint.plugin,
39
- a11y,
40
- barrel,
41
- compat,
42
- depend,
43
- ethang,
33
+ unicorn: unicorn,
44
34
  lodash: lodashConfig,
45
- n,
46
- perfectionist,
47
- sonar,
48
- stylistic,
49
- tailwind,
50
- unicorn,
35
+ sonar: sonar,
36
+ ethang: ethang,
37
+ "@tanstack/query": tanstack,
38
+ tailwind: tailwind,
39
+ stylistic: stylistic,
40
+ perfectionist: perfectionist,
41
+ a11y: a11y,
51
42
  },
52
43
  rules: {
53
44
  "depend/ban-dependencies": ["error", { allowed: ["lodash"] }],
@@ -118,7 +109,7 @@ export default tseslint.config(
118
109
  "no-dupe-else-if": "error",
119
110
  "no-dupe-keys": "error",
120
111
  "no-duplicate-case": "error",
121
- "no-duplicate-imports": "off",
112
+ "no-duplicate-imports": "error",
122
113
  "no-else-return": "error",
123
114
  "no-empty": "error",
124
115
  "no-empty-character-class": "error",
@@ -309,7 +300,10 @@ export default tseslint.config(
309
300
  "@typescript-eslint/consistent-type-assertions": "error",
310
301
  "@typescript-eslint/consistent-type-definitions": ["error", "type"],
311
302
  "@typescript-eslint/consistent-type-exports": "error",
312
- "@typescript-eslint/consistent-type-imports": "error",
303
+ "@typescript-eslint/consistent-type-imports": [
304
+ "error",
305
+ { fixStyle: "inline-type-imports" },
306
+ ],
313
307
  "@typescript-eslint/default-param-last": "error",
314
308
  "@typescript-eslint/dot-notation": "error",
315
309
  "@typescript-eslint/explicit-function-return-type": "off",
@@ -1260,7 +1254,7 @@ export default tseslint.config(
1260
1254
  {
1261
1255
  files: ["**/*.md"],
1262
1256
  plugins: {
1263
- markdown,
1257
+ markdown: markdown,
1264
1258
  },
1265
1259
  rules: {
1266
1260
  "markdown/fenced-code-language": "error",
@@ -1274,7 +1268,9 @@ export default tseslint.config(
1274
1268
  },
1275
1269
  {
1276
1270
  files: ["**/*.{json,jsonc,json5}"],
1277
- plugins: { json },
1271
+ plugins: {
1272
+ json: json,
1273
+ },
1278
1274
  rules: {
1279
1275
  "json/no-duplicate-keys": "error",
1280
1276
  "json/no-empty-keys": "error",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ethang/eslint-config",
3
- "version": "19.2.8",
3
+ "version": "19.2.10",
4
4
  "repository": {
5
5
  "url": "git+https://github.com/eglove/eslint-config-ethang.git"
6
6
  },
package/setup/eslint.js CHANGED
@@ -30,7 +30,6 @@ const changedRules = [
30
30
  { name: "max-params", rule: "off" },
31
31
  { name: "new-cap", rule: "off" },
32
32
  { name: "no-array-constructor", rule: "off" },
33
- { name: "no-duplicate-imports", rule: "off" },
34
33
  { name: "no-empty-function", rule: "off" },
35
34
  { name: "no-implicit-globals", rule: "off" },
36
35
  { name: "no-implied-eval", rule: "off" },
package/setup/react.js CHANGED
@@ -25,6 +25,9 @@ const customHookRules = [
25
25
  const hookGen = genRules(reactHookRuleNames, customHookRules, "react-hooks");
26
26
 
27
27
  export const reactRules = {
28
- ...hookGen,
29
28
  ...reactGen,
30
29
  };
30
+
31
+ export const reactHookRules = {
32
+ ...hookGen,
33
+ };
@@ -20,6 +20,10 @@ const customRules = [
20
20
  name: "consistent-type-definitions",
21
21
  rule: ["error", "type"],
22
22
  },
23
+ {
24
+ name: "consistent-type-imports",
25
+ rule: ["error", { fixStyle: "inline-type-imports" }],
26
+ },
23
27
  {
24
28
  name: "explicit-function-return-type",
25
29
  rule: "off",
@@ -1,39 +0,0 @@
1
- import { writeFileSync } from "node:fs";
2
- import { join } from "node:path";
3
- import { astroRules } from "../setup/astro.js";
4
-
5
- export const updateAstroRules = () => {
6
- let configFile = "";
7
-
8
- const rulesJson = JSON.stringify(astroRules).slice(1, -1);
9
-
10
- const importList = [
11
- 'import astro from "eslint-plugin-astro";',
12
- 'import tseslint from "typescript-eslint";',
13
- 'import { languageOptions } from "./eslint.config.js";',
14
- 'import { ignores } from "./constants.js";',
15
- ].sort((a, b) => {
16
- return a.localeCompare(b);
17
- });
18
-
19
- importList.forEach((item) => {
20
- configFile += `${item}\n`;
21
- });
22
-
23
- configFile += `\nexport default tseslint.config({
24
- files: ["**/*.{astro}"],
25
- ignores,
26
- languageOptions,
27
- plugins: { astro },
28
- rules: {
29
- ${rulesJson}
30
- },
31
- });
32
- `;
33
-
34
- writeFileSync(
35
- join(import.meta.dirname, "../config.astro.js"),
36
- configFile,
37
- "utf8",
38
- );
39
- };
@@ -1,51 +0,0 @@
1
- import { reactRules } from "../setup/react.js";
2
- import { writeFileSync } from "node:fs";
3
- import { join } from "node:path";
4
- import { getLatestReact } from "./get-react-version.mjs";
5
-
6
- export const updateReactRules = async () => {
7
- let configFile = "";
8
- const react = await getLatestReact();
9
- const settings = JSON.stringify({
10
- react: { version: react.version },
11
- }).slice(1, -1);
12
-
13
- const rulesJson = JSON.stringify(reactRules).slice(1, -1);
14
-
15
- const importList = [
16
- 'import react from "@eslint-react/eslint-plugin";',
17
- 'import reactHooks from "eslint-plugin-react-hooks";',
18
- 'import tseslint from "typescript-eslint";',
19
- 'import { languageOptions } from "./eslint.config.js";',
20
- 'import { ignores } from "./constants.js";',
21
- ].sort((a, b) => {
22
- return a.localeCompare(b);
23
- });
24
-
25
- importList.forEach((item) => {
26
- configFile += `${item}\n`;
27
- });
28
-
29
- configFile += `\nexport default tseslint.config({
30
- files: ["**/*.{jsx,tsx}"],
31
- ignores,
32
- languageOptions,
33
- plugins: {
34
- react,
35
- "react-hooks": reactHooks,
36
- },
37
- settings: {
38
- ${settings}
39
- },
40
- rules: {
41
- ${rulesJson}
42
- },
43
- });
44
- `;
45
-
46
- writeFileSync(
47
- join(import.meta.dirname, "../config.react.js"),
48
- configFile,
49
- "utf8",
50
- );
51
- };
@@ -1,39 +0,0 @@
1
- import { solidRules } from "../setup/solid.js";
2
- import { writeFileSync } from "node:fs";
3
- import { join } from "node:path";
4
-
5
- export const updateSolidRules = () => {
6
- let configFile = "";
7
-
8
- const rulesJson = JSON.stringify(solidRules).slice(1, -1);
9
-
10
- const importList = [
11
- 'import solid from "eslint-plugin-solid";',
12
- 'import tseslint from "typescript-eslint";',
13
- 'import { languageOptions } from "./eslint.config.js";',
14
- 'import { ignores } from "./constants.js";',
15
- ].sort((a, b) => {
16
- return a.localeCompare(b);
17
- });
18
-
19
- importList.forEach((item) => {
20
- configFile += `${item}\n`;
21
- });
22
-
23
- configFile += `\nexport default tseslint.config({
24
- files: ["**/*.{jsx,tsx}"],
25
- ignores,
26
- languageOptions,
27
- plugins: { solid },
28
- rules: {
29
- ${rulesJson},
30
- },
31
- });
32
- `;
33
-
34
- writeFileSync(
35
- join(import.meta.dirname, "../config.solid.js"),
36
- configFile,
37
- "utf8",
38
- );
39
- };
package/update-rules.mjs DELETED
@@ -1,11 +0,0 @@
1
- import { updateRules } from "./build/update-rules.js";
2
- import { updateReactRules } from "./build/update-react-rules.js";
3
- import { updateSolidRules } from "./build/update-solid-rules.js";
4
- import { updateAstroRules } from "./build/update-astro-rules.js";
5
- import { updateReadme } from "./build/update-readme.js";
6
-
7
- await updateRules();
8
- await updateReactRules();
9
- updateSolidRules();
10
- updateAstroRules();
11
- updateReadme();