@ethang/eslint-config 19.0.6 → 19.0.8
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/.github/dependabot.yml +13 -13
- package/README.md +82 -83
- package/build/update-readme.js +152 -0
- package/build/update-rules.js +70 -0
- package/build.mjs +5 -0
- package/config.react.js +3 -6
- package/eslint.config.js +683 -119
- package/package.json +12 -11
- package/setup/a11y.js +25 -0
- package/setup/barrel.js +9 -0
- package/setup/compat.js +10 -0
- package/setup/depend.js +11 -0
- package/setup/eslint.js +72 -0
- package/setup/gen-rules.js +34 -0
- package/setup/lodash.js +19 -0
- package/setup/n.js +31 -0
- package/setup/perfectionist.js +78 -0
- package/setup/sonar.js +61 -0
- package/setup/stylistic.js +62 -0
- package/setup/tailwind.js +8 -0
- package/setup/tanstack-query.js +7 -0
- package/setup/typescript-eslint.js +124 -0
- package/setup/unicorn.js +32 -0
- package/tsconfig.json +6 -3
package/.github/dependabot.yml
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
version: 2
|
|
2
|
-
updates:
|
|
3
|
-
- package-ecosystem: "github-actions"
|
|
4
|
-
directory: /
|
|
5
|
-
schedule:
|
|
6
|
-
interval: daily
|
|
7
|
-
target-branch: "master"
|
|
8
|
-
|
|
9
|
-
- package-ecosystem: npm
|
|
10
|
-
directory: /
|
|
11
|
-
schedule:
|
|
12
|
-
interval: daily
|
|
13
|
-
target-branch: "master"
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
- package-ecosystem: "github-actions"
|
|
4
|
+
directory: /
|
|
5
|
+
schedule:
|
|
6
|
+
interval: daily
|
|
7
|
+
target-branch: "master"
|
|
8
|
+
|
|
9
|
+
- package-ecosystem: npm
|
|
10
|
+
directory: /
|
|
11
|
+
schedule:
|
|
12
|
+
interval: daily
|
|
13
|
+
target-branch: "master"
|
package/README.md
CHANGED
|
@@ -1,83 +1,82 @@
|
|
|
1
|
-
# Opinionated, Strict, Brutal, Unforgiving
|
|
2
|
-
|
|
3
|
-
[View Config](https://eslint-config-ethang.pages.dev/rules)
|
|
4
|
-
|
|
5
|
-
Do **NOT** use this with Prettier! Styling rules are included.
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
import
|
|
48
|
-
import
|
|
49
|
-
import
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
"
|
|
69
|
-
"lint": "eslint",
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
"
|
|
80
|
-
"
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
```
|
|
1
|
+
# Opinionated, Strict, Brutal, Unforgiving
|
|
2
|
+
|
|
3
|
+
[View Config](https://eslint-config-ethang.pages.dev/rules)
|
|
4
|
+
|
|
5
|
+
Do **NOT** use this with Prettier! Styling rules are included.
|
|
6
|
+
|
|
7
|
+
- 873 errored rules.
|
|
8
|
+
- 289 rules from [eslint-plugin-sonarjs](https://github.com/SonarSource/SonarJS/blob/master/packages/jsts/src/rules/README.md)
|
|
9
|
+
- 144 rules from [@eslint/js](https://github.com/eslint/eslint/tree/main/packages/js)
|
|
10
|
+
- 113 rules from [sindresorhus/eslint-plugin-unicorn](https://github.com/sindresorhus/eslint-plugin-unicorn)
|
|
11
|
+
- 103 rules from [@typescript/eslint](https://github.com/typescript-eslint/typescript-eslint)
|
|
12
|
+
- 91 rules from [@stylistic/eslint-plugin](https://eslint.style/)
|
|
13
|
+
- 42 rules from [eslint-plugin-lodash](https://github.com/wix-incubator/eslint-plugin-lodash)
|
|
14
|
+
- 35 rules from [jsx-a11y](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y)
|
|
15
|
+
- 20 rules from [eslint-plugin-n](https://github.com/eslint-community/eslint-plugin-n)
|
|
16
|
+
- 19 rules from [eslint-plugin-perfectionist](https://github.com/azat-io/eslint-plugin-perfectionist)
|
|
17
|
+
- 7 rules from [eslint-plugin-tailwindcss](https://github.com/francoismassart/eslint-plugin-tailwindcss)
|
|
18
|
+
- 4 rules from [eslint-plugin-barrel-files](https://github.com/thepassle/eslint-plugin-barrel-files)
|
|
19
|
+
- 4 rules from [@tanstack/eslint-plugin-query](https://tanstack.com/query/latest/docs/eslint/eslint-plugin-query)
|
|
20
|
+
- 1 rule from [eslint-plugin-depend](https://github.com/es-tooling/eslint-plugin-depend/tree/main)
|
|
21
|
+
- 1 rule from [eslint-plugin-compat](https://github.com/amilajack/eslint-plugin-compat)
|
|
22
|
+
|
|
23
|
+
# Add Even More!
|
|
24
|
+
|
|
25
|
+
- 51 rules for **Astro**
|
|
26
|
+
- `import astroConfig from "@ethang/eslint-config/config.astro.js";`
|
|
27
|
+
- 51 rules from [eslint-plugin-astro](https://github.com/ota-meshi/eslint-plugin-astro)
|
|
28
|
+
- 68 rules for **React**
|
|
29
|
+
- `import reactConfig from "@ethang/eslint-config/config.react.js";`
|
|
30
|
+
- 68 rules from [@eslint-react/eslint-plugin](https://eslint-react.xyz/)
|
|
31
|
+
- 18 rules for **Solid**
|
|
32
|
+
- `import solidConfig from "@ethang/eslint-config/config.solid.js";`
|
|
33
|
+
- 18 rules from [eslint-plugin-solid](https://github.com/solidjs-community/eslint-plugin-solid)
|
|
34
|
+
|
|
35
|
+
# Install
|
|
36
|
+
|
|
37
|
+
`pnpm i -D eslint typescript-eslint @ethang/eslint-config`
|
|
38
|
+
|
|
39
|
+
**Requires TypesScript and tsconfig.json at root directory.**
|
|
40
|
+
|
|
41
|
+
# Config
|
|
42
|
+
|
|
43
|
+
In **eslint.config.js**
|
|
44
|
+
|
|
45
|
+
```js
|
|
46
|
+
import config from "@ethang/eslint-config/eslint.config.js";
|
|
47
|
+
import tseslint from "typescript-eslint";
|
|
48
|
+
import astroConfig from "@ethang/eslint-config/config.astro.js"; // OPTIONAL
|
|
49
|
+
import reactConfig from "@ethang/eslint-config/config.react.js"; // OPTIONAL
|
|
50
|
+
|
|
51
|
+
export default tseslint.config(...config, ...astroConfig, ...reactConfig, {
|
|
52
|
+
languageOptions: {
|
|
53
|
+
parserOptions: {
|
|
54
|
+
project: true,
|
|
55
|
+
tsconfigRootDir: import.meta.dirname,
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
rules: {
|
|
59
|
+
// your custom rules here
|
|
60
|
+
},
|
|
61
|
+
});
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
**Scripts**:
|
|
65
|
+
|
|
66
|
+
```json
|
|
67
|
+
"scripts": {
|
|
68
|
+
"lint": "eslint",
|
|
69
|
+
"lint:fix": "eslint . --fix",
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
**Browserslist**
|
|
74
|
+
|
|
75
|
+
This config will also lint for browserslist features. Make sure to set this in package.json. [More info.](https://github.com/browserslist/browserslist)
|
|
76
|
+
|
|
77
|
+
```json
|
|
78
|
+
"browserslist": [
|
|
79
|
+
"defaults and fully supports es6-module",
|
|
80
|
+
"maintained node versions"
|
|
81
|
+
]
|
|
82
|
+
```
|
|
@@ -0,0 +1,152 @@
|
|
|
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 { readFileSync, writeFileSync } from "node:fs";
|
|
16
|
+
import { join } from "node:path";
|
|
17
|
+
|
|
18
|
+
export const updateReadme = () => {
|
|
19
|
+
const getRuleCount = (rules) => {
|
|
20
|
+
let count = 0;
|
|
21
|
+
Object.values(rules).forEach((value) => {
|
|
22
|
+
if (value === "error" || (Array.isArray(value) && value[0] === "error")) {
|
|
23
|
+
count += 1;
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
return count;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const ruleList = [
|
|
31
|
+
{
|
|
32
|
+
list: dependRules,
|
|
33
|
+
name: "eslint-plugin-depend",
|
|
34
|
+
url: "https://github.com/es-tooling/eslint-plugin-depend/tree/main",
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
list: barrelRules,
|
|
38
|
+
name: "eslint-plugin-barrel-files",
|
|
39
|
+
url: "https://github.com/thepassle/eslint-plugin-barrel-files",
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
list: compatRules,
|
|
43
|
+
name: "eslint-plugin-compat",
|
|
44
|
+
url: "https://github.com/amilajack/eslint-plugin-compat",
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
list: eslintRules,
|
|
48
|
+
name: "@eslint/js",
|
|
49
|
+
url: "https://github.com/eslint/eslint/tree/main/packages/js",
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
list: nRules,
|
|
53
|
+
name: "eslint-plugin-n",
|
|
54
|
+
url: "https://github.com/eslint-community/eslint-plugin-n",
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
list: typescriptRules,
|
|
58
|
+
name: "@typescript/eslint",
|
|
59
|
+
url: "https://github.com/typescript-eslint/typescript-eslint",
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
list: unicornRules,
|
|
63
|
+
name: "sindresorhus/eslint-plugin-unicorn",
|
|
64
|
+
url: "https://github.com/sindresorhus/eslint-plugin-unicorn",
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
list: lodashRules,
|
|
68
|
+
name: "eslint-plugin-lodash",
|
|
69
|
+
url: "https://github.com/wix-incubator/eslint-plugin-lodash",
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
list: sonarRules,
|
|
73
|
+
name: "eslint-plugin-sonarjs",
|
|
74
|
+
url: "https://github.com/SonarSource/SonarJS/blob/master/packages/jsts/src/rules/README.md",
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
list: tanstackQueryRules,
|
|
78
|
+
name: "@tanstack/eslint-plugin-query",
|
|
79
|
+
url: "https://tanstack.com/query/latest/docs/eslint/eslint-plugin-query",
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
list: tailwindRules,
|
|
83
|
+
name: "eslint-plugin-tailwindcss",
|
|
84
|
+
url: "https://github.com/francoismassart/eslint-plugin-tailwindcss",
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
list: stylisticRules,
|
|
88
|
+
name: "@stylistic/eslint-plugin",
|
|
89
|
+
url: "https://eslint.style/",
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
list: perfectionistRules,
|
|
93
|
+
name: "eslint-plugin-perfectionist",
|
|
94
|
+
url: "https://github.com/azat-io/eslint-plugin-perfectionist",
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
list: a11yRules,
|
|
98
|
+
name: "jsx-a11y",
|
|
99
|
+
url: "https://github.com/jsx-eslint/eslint-plugin-jsx-a11y",
|
|
100
|
+
},
|
|
101
|
+
];
|
|
102
|
+
|
|
103
|
+
let total = 0;
|
|
104
|
+
for (const list of ruleList) {
|
|
105
|
+
const count = getRuleCount(list.list);
|
|
106
|
+
total += count;
|
|
107
|
+
list["count"] = count;
|
|
108
|
+
}
|
|
109
|
+
ruleList.sort((a, b) => {
|
|
110
|
+
return b.count - a.count;
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
const ruleDocs = [`- ${total} errored rules.`];
|
|
114
|
+
for (const list of ruleList) {
|
|
115
|
+
ruleDocs.push(
|
|
116
|
+
`- ${list.count} ${list.count <= 1 ? "rule" : "rules"} from [${list.name}](${list.url})`,
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const readme = readFileSync(
|
|
121
|
+
join(import.meta.dirname, "../README.md"),
|
|
122
|
+
"utf8",
|
|
123
|
+
);
|
|
124
|
+
let readmeLines = readme.split("\n");
|
|
125
|
+
|
|
126
|
+
let start = 0;
|
|
127
|
+
let end = 0;
|
|
128
|
+
for (let index = 1; index < readmeLines.length; index++) {
|
|
129
|
+
if (
|
|
130
|
+
readmeLines[index] ===
|
|
131
|
+
"Do **NOT** use this with Prettier! Styling rules are included."
|
|
132
|
+
) {
|
|
133
|
+
start = index;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (readmeLines[index] === "# Add Even More!") {
|
|
137
|
+
end = index;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (start !== 0 && end !== 0) {
|
|
141
|
+
break;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
readmeLines = [
|
|
146
|
+
...readmeLines.splice(0, start + 2),
|
|
147
|
+
...ruleDocs,
|
|
148
|
+
...readmeLines.splice(end - 7),
|
|
149
|
+
].join("\n");
|
|
150
|
+
|
|
151
|
+
writeFileSync(join(import.meta.dirname, "../README.md"), readmeLines, "utf8");
|
|
152
|
+
};
|
|
@@ -0,0 +1,70 @@
|
|
|
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 { readFileSync, writeFileSync } from "node:fs";
|
|
16
|
+
import { join } from "node:path";
|
|
17
|
+
|
|
18
|
+
export const updateRules = () => {
|
|
19
|
+
const rules = {
|
|
20
|
+
...dependRules,
|
|
21
|
+
...barrelRules,
|
|
22
|
+
...compatRules,
|
|
23
|
+
...eslintRules,
|
|
24
|
+
...nRules,
|
|
25
|
+
...typescriptRules,
|
|
26
|
+
...unicornRules,
|
|
27
|
+
...lodashRules,
|
|
28
|
+
...sonarRules,
|
|
29
|
+
...tanstackQueryRules,
|
|
30
|
+
...tailwindRules,
|
|
31
|
+
...stylisticRules,
|
|
32
|
+
...perfectionistRules,
|
|
33
|
+
...a11yRules,
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
let jsonified = JSON.stringify(rules);
|
|
37
|
+
jsonified = jsonified.slice(1, -1);
|
|
38
|
+
|
|
39
|
+
const config = readFileSync(
|
|
40
|
+
join(import.meta.dirname, "../eslint.config.js"),
|
|
41
|
+
"utf8",
|
|
42
|
+
);
|
|
43
|
+
const lines = config.split("\n");
|
|
44
|
+
|
|
45
|
+
let rulesStart = 0;
|
|
46
|
+
let rulesEnd = 0;
|
|
47
|
+
for (let index = 1; index < lines.length; index++) {
|
|
48
|
+
if (lines[index].endsWith("rules: {")) {
|
|
49
|
+
rulesStart = index;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (0 !== rulesStart && lines[index].endsWith("},")) {
|
|
53
|
+
rulesEnd = index;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const updated = [
|
|
58
|
+
...lines.slice(0, rulesStart),
|
|
59
|
+
"rules: {",
|
|
60
|
+
jsonified,
|
|
61
|
+
"},",
|
|
62
|
+
...lines.slice(rulesEnd + 1),
|
|
63
|
+
].join("\n");
|
|
64
|
+
|
|
65
|
+
writeFileSync(
|
|
66
|
+
join(import.meta.dirname, "../eslint.config.js"),
|
|
67
|
+
updated,
|
|
68
|
+
"utf8",
|
|
69
|
+
);
|
|
70
|
+
};
|
package/build.mjs
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
import { projectBuilder } from "@ethang/project-builder/project-builder.js";
|
|
3
|
+
import { updateRules } from "./build/update-rules.js";
|
|
4
|
+
import { updateReadme } from "./build/update-readme.js";
|
|
5
|
+
|
|
6
|
+
updateRules();
|
|
7
|
+
updateReadme();
|
|
3
8
|
|
|
4
9
|
await projectBuilder("eslint-config-ethang", "master", {
|
|
5
10
|
isLibrary: true,
|
package/config.react.js
CHANGED
|
@@ -14,8 +14,8 @@ export default tseslint.config({
|
|
|
14
14
|
"react-hooks": reactHooks,
|
|
15
15
|
},
|
|
16
16
|
rules: {
|
|
17
|
-
"react-hooks/exhaustive-deps": "off", // fix w/ v9 compatibility
|
|
18
|
-
"react-hooks/rules-of-hooks": "off", // fix w/ v9 compatibility
|
|
17
|
+
"react-hooks/exhaustive-deps": "off", // TODO fix w/ v9 compatibility
|
|
18
|
+
"react-hooks/rules-of-hooks": "off", // TODO fix w/ v9 compatibility
|
|
19
19
|
"react/dom/no-children-in-void-dom-elements": "error",
|
|
20
20
|
"react/dom/no-dangerously-set-innerhtml": "error",
|
|
21
21
|
"react/dom/no-dangerously-set-innerhtml-with-children": "error",
|
|
@@ -35,10 +35,7 @@ export default tseslint.config({
|
|
|
35
35
|
"react/hooks-extra/no-direct-set-state-in-use-layout-effect": "error",
|
|
36
36
|
"react/hooks-extra/prefer-use-state-lazy-initialization": "error",
|
|
37
37
|
"react/naming-convention/component-name": "error",
|
|
38
|
-
"react/naming-convention/filename": [
|
|
39
|
-
"error",
|
|
40
|
-
{ rule: "kebab-case" },
|
|
41
|
-
],
|
|
38
|
+
"react/naming-convention/filename": ["error", { rule: "kebab-case" }],
|
|
42
39
|
"react/naming-convention/filename-extension": "error",
|
|
43
40
|
"react/naming-convention/use-state": "error",
|
|
44
41
|
"react/no-access-state-in-setstate": "error",
|