@ethang/eslint-config 21.2.4 → 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.
- package/build.ts +34 -0
- package/{README.md → dist/README.md} +2 -2
- package/dist/config.react.js +2 -0
- package/dist/config.react.js.map +1 -0
- package/dist/eslint.config.js +2 -0
- package/dist/package.json +68 -0
- package/eslint.config.js +26 -2
- package/package.json +7 -7
- package/src/README.md +100 -0
- package/src/build/create-config-file.ts +57 -0
- package/src/build/create-config.ts +96 -0
- package/src/build/get-react-version.ts +19 -0
- package/src/build/list-utilities.ts +124 -0
- package/src/build/rule-list.ts +284 -0
- package/src/build/update-readme.ts +195 -0
- package/src/build/update-rules.ts +124 -0
- package/src/config.angular.js +107 -0
- package/src/config.astro.js +68 -0
- package/src/config.react.js +117 -0
- package/src/config.solid.js +34 -0
- package/src/constants.js +16 -0
- package/src/eslint.config.js +1051 -0
- package/src/setup/a11y.ts +19 -0
- package/src/setup/angular.ts +40 -0
- package/src/setup/astro.ts +14 -0
- package/src/setup/barrel.ts +17 -0
- package/src/setup/compat.ts +13 -0
- package/src/setup/cspell.ts +83 -0
- package/src/setup/css.ts +12 -0
- package/src/setup/depend.ts +14 -0
- package/src/setup/eslint.ts +246 -0
- package/src/setup/gen-rules.ts +75 -0
- package/src/setup/json.ts +17 -0
- package/src/setup/lodash.ts +58 -0
- package/src/setup/markdown.ts +16 -0
- package/src/setup/n.ts +86 -0
- package/src/setup/perfectionist.ts +68 -0
- package/src/setup/react.ts +82 -0
- package/src/setup/solid.ts +21 -0
- package/src/setup/sonar.ts +39 -0
- package/src/setup/tailwind.ts +10 -0
- package/src/setup/tanstack-query.ts +9 -0
- package/src/setup/tanstack-router.ts +9 -0
- package/src/setup/typescript-eslint.ts +118 -0
- package/src/setup/unicorn.ts +38 -0
- package/tsconfig.json +5 -0
- package/config.react.js +0 -2
- package/config.react.js.map +0 -1
- /package/{chunk-WK3YS7OG.js → dist/chunk-WK3YS7OG.js} +0 -0
- /package/{chunk-WK3YS7OG.js.map → dist/chunk-WK3YS7OG.js.map} +0 -0
- /package/{config.angular.d.ts → dist/config.angular.d.ts} +0 -0
- /package/{config.angular.js → dist/config.angular.js} +0 -0
- /package/{config.angular.js.map → dist/config.angular.js.map} +0 -0
- /package/{config.astro.d.ts → dist/config.astro.d.ts} +0 -0
- /package/{config.astro.js → dist/config.astro.js} +0 -0
- /package/{config.astro.js.map → dist/config.astro.js.map} +0 -0
- /package/{config.react.d.ts → dist/config.react.d.ts} +0 -0
- /package/{config.solid.d.ts → dist/config.solid.d.ts} +0 -0
- /package/{config.solid.js → dist/config.solid.js} +0 -0
- /package/{config.solid.js.map → dist/config.solid.js.map} +0 -0
- /package/{constants.js → dist/constants.js} +0 -0
- /package/{constants.js.map → dist/constants.js.map} +0 -0
- /package/{eslint.config.d.ts → dist/eslint.config.d.ts} +0 -0
- /package/{eslint.config.js.map → dist/eslint.config.js.map} +0 -0
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import { MarkdownGenerator } from "@ethang/markdown-generator/markdown-generator.js";
|
|
2
|
+
import filter from "lodash/filter.js";
|
|
3
|
+
import flow from "lodash/flow.js";
|
|
4
|
+
import isArray from "lodash/isArray.js";
|
|
5
|
+
import map from "lodash/map.js";
|
|
6
|
+
import values from "lodash/values.js";
|
|
7
|
+
import { writeFileSync } from "node:fs";
|
|
8
|
+
import path from "node:path";
|
|
9
|
+
|
|
10
|
+
import type { genRules } from "../setup/gen-rules.ts";
|
|
11
|
+
|
|
12
|
+
import { getList } from "./list-utilities.ts";
|
|
13
|
+
|
|
14
|
+
const getRuleCount = (rules: ReturnType<typeof genRules>) => {
|
|
15
|
+
let count = 0;
|
|
16
|
+
for (const value of values(rules)) {
|
|
17
|
+
if ("error" === value || (isArray(value) && "error" === value[0])) {
|
|
18
|
+
count += 1;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return count;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const getImports = flow(
|
|
26
|
+
(rules: ReturnType<typeof getList>) => {
|
|
27
|
+
return filter(rules, (rule) => {
|
|
28
|
+
return 0 < getRuleCount(rule.list);
|
|
29
|
+
});
|
|
30
|
+
},
|
|
31
|
+
(filteredRules) => {
|
|
32
|
+
return map(filteredRules, (rule) => {
|
|
33
|
+
return `${getRuleCount(rule.list)} rules from [${rule.name}](${rule.url})`;
|
|
34
|
+
});
|
|
35
|
+
},
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
export const updateReadme = () => {
|
|
39
|
+
const md = new MarkdownGenerator();
|
|
40
|
+
md.header(1, "Relentless. Unapologetic.", 2);
|
|
41
|
+
md.link("View Config", "https://eslint-config-ethang.pages.dev/rules", 2);
|
|
42
|
+
md.alert("CAUTION", "Prettier is already included for styling!", 2);
|
|
43
|
+
|
|
44
|
+
const coreRules = map(
|
|
45
|
+
[
|
|
46
|
+
...getList("core"),
|
|
47
|
+
...getList("json"),
|
|
48
|
+
...getList("css"),
|
|
49
|
+
...getList("markdown"),
|
|
50
|
+
],
|
|
51
|
+
(rules) => {
|
|
52
|
+
return {
|
|
53
|
+
...rules,
|
|
54
|
+
count: 0,
|
|
55
|
+
};
|
|
56
|
+
},
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
let total = 0;
|
|
60
|
+
for (const list of coreRules) {
|
|
61
|
+
const count = getRuleCount(list.list);
|
|
62
|
+
total += count;
|
|
63
|
+
list.count = count;
|
|
64
|
+
}
|
|
65
|
+
coreRules.sort((a, b) => {
|
|
66
|
+
return b.count - a.count;
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
const ruleDocumentation = [`${total} errored rules.`];
|
|
70
|
+
for (const list of coreRules) {
|
|
71
|
+
if (0 < list.count) {
|
|
72
|
+
ruleDocumentation.push(
|
|
73
|
+
`${list.count} ${
|
|
74
|
+
1 >= list.count ? "rule" : "rules"
|
|
75
|
+
} from [${list.name}](${list.url})`,
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const astroRules = getList("astro");
|
|
81
|
+
const reactRules = getList("react");
|
|
82
|
+
const solidRules = getList("solid");
|
|
83
|
+
const angularRules = getList("angular");
|
|
84
|
+
const angularTemplateRules = getList("angular:template");
|
|
85
|
+
|
|
86
|
+
let astroCount = 0;
|
|
87
|
+
for (const astroRule of astroRules) {
|
|
88
|
+
astroCount += getRuleCount(astroRule.list);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
let reactCount = 0;
|
|
92
|
+
for (const reactRule of reactRules) {
|
|
93
|
+
reactCount += getRuleCount(reactRule.list);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
let solidCount = 0;
|
|
97
|
+
for (const solidRule of solidRules) {
|
|
98
|
+
solidCount += getRuleCount(solidRule.list);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
let angularCount = 0;
|
|
102
|
+
for (const angularRule of [...angularRules, ...angularTemplateRules]) {
|
|
103
|
+
angularCount += getRuleCount(angularRule.list);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
md.unorderedList(ruleDocumentation);
|
|
107
|
+
md.newLine();
|
|
108
|
+
md.header(1, "Add Even More!", 2);
|
|
109
|
+
md.unorderedList([
|
|
110
|
+
`${angularCount} rules for **Angular**`,
|
|
111
|
+
[
|
|
112
|
+
'`import angularConfig from "@ethang/eslint-config/config.angular.js";`',
|
|
113
|
+
getImports(angularRules),
|
|
114
|
+
getImports(angularTemplateRules),
|
|
115
|
+
],
|
|
116
|
+
`${astroCount} rules for **Astro**`,
|
|
117
|
+
[
|
|
118
|
+
'`import astroConfig from "@ethang/eslint-config/config.astro.js";`',
|
|
119
|
+
getImports(astroRules),
|
|
120
|
+
],
|
|
121
|
+
`${reactCount} rules for **React**`,
|
|
122
|
+
[
|
|
123
|
+
'`import reactConfig from "@ethang/eslint-config/config.react.js";`',
|
|
124
|
+
getImports(reactRules),
|
|
125
|
+
],
|
|
126
|
+
`${solidCount} rules for **Solid**`,
|
|
127
|
+
[
|
|
128
|
+
'`import solidConfig from "@ethang/eslint-config/config.solid.js";`',
|
|
129
|
+
getImports(solidRules),
|
|
130
|
+
],
|
|
131
|
+
]);
|
|
132
|
+
md.newLine();
|
|
133
|
+
md.header(1, "Install", 2);
|
|
134
|
+
md.inlineCode("pnpm i -D eslint typescript-eslint @ethang/eslint-config", 2);
|
|
135
|
+
md.bold("Requires TypesScript and tsconfig.json at root directory.", 2);
|
|
136
|
+
md.header(1, "Config", 2);
|
|
137
|
+
md.text("In **eslint.config.js**", 2);
|
|
138
|
+
md.codeBlock(
|
|
139
|
+
`import config from "@ethang/eslint-config/eslint.config.js";
|
|
140
|
+
import tseslint from "typescript-eslint";
|
|
141
|
+
import astroConfig from "@ethang/eslint-config/config.astro.js"; // OPTIONAL
|
|
142
|
+
import reactConfig from "@ethang/eslint-config/config.react.js"; // OPTIONAL
|
|
143
|
+
|
|
144
|
+
export default tseslint.config(
|
|
145
|
+
{
|
|
146
|
+
ignores: [], // Ignored files apply to all following configs
|
|
147
|
+
},
|
|
148
|
+
...config,
|
|
149
|
+
...astroConfig,
|
|
150
|
+
...reactConfig,
|
|
151
|
+
{
|
|
152
|
+
languageOptions: {
|
|
153
|
+
parserOptions: {
|
|
154
|
+
project: true,
|
|
155
|
+
tsconfigRootDir: import.meta.dirname,
|
|
156
|
+
},
|
|
157
|
+
},
|
|
158
|
+
rules: {
|
|
159
|
+
// Override rules from above configs
|
|
160
|
+
},
|
|
161
|
+
}
|
|
162
|
+
);`,
|
|
163
|
+
"js",
|
|
164
|
+
2,
|
|
165
|
+
);
|
|
166
|
+
md.bold("Scripts", 2);
|
|
167
|
+
md.codeBlock(
|
|
168
|
+
`"scripts": {
|
|
169
|
+
"lint": "eslint",
|
|
170
|
+
"lint:fix": "eslint . --fix",
|
|
171
|
+
}`,
|
|
172
|
+
"json",
|
|
173
|
+
2,
|
|
174
|
+
);
|
|
175
|
+
md.bold("Browserslist", 2);
|
|
176
|
+
md.text(
|
|
177
|
+
"This config will also lint for browserslist features. Make sure to set this in package.json. [More info.](https://github.com/browserslist/browserslist)",
|
|
178
|
+
2,
|
|
179
|
+
);
|
|
180
|
+
md.codeBlock(
|
|
181
|
+
`"browserslist": [
|
|
182
|
+
"defaults and fully supports es6-module",
|
|
183
|
+
"maintained node versions"
|
|
184
|
+
]`,
|
|
185
|
+
"json",
|
|
186
|
+
);
|
|
187
|
+
|
|
188
|
+
writeFileSync(
|
|
189
|
+
path.join(import.meta.dirname, "../README.md"),
|
|
190
|
+
md.render(),
|
|
191
|
+
"utf8",
|
|
192
|
+
);
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
updateReadme();
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import type { ConfigOptions } from "./create-config.ts";
|
|
2
|
+
|
|
3
|
+
import { createConfigFile } from "./create-config-file.ts";
|
|
4
|
+
|
|
5
|
+
export type ConfigFile = {
|
|
6
|
+
importString?: string;
|
|
7
|
+
label?: string;
|
|
8
|
+
name: string;
|
|
9
|
+
options?: ConfigOptions;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const importTsEslint = 'import tseslint from "typescript-eslint";';
|
|
13
|
+
|
|
14
|
+
export const coreFile = [
|
|
15
|
+
{
|
|
16
|
+
importString: 'import config from "@ethang/eslint-config/eslint.config.js',
|
|
17
|
+
label: "Core",
|
|
18
|
+
name: "core",
|
|
19
|
+
options: {
|
|
20
|
+
extraImports: [
|
|
21
|
+
'import { fixupPluginRules } from "@eslint/compat";', // TODO remove with v9 compat
|
|
22
|
+
'import eslintConfigPrettier from "eslint-config-prettier";',
|
|
23
|
+
'import eslintPluginPrettierRecommended from "eslint-plugin-prettier/recommended";',
|
|
24
|
+
],
|
|
25
|
+
includeIgnores: true,
|
|
26
|
+
includeLanguageOptions: true,
|
|
27
|
+
includeReactVersion: true,
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
name: "markdown",
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
name: "css",
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
name: "json",
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
name: "jsonc",
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
name: "json5",
|
|
44
|
+
},
|
|
45
|
+
];
|
|
46
|
+
|
|
47
|
+
const astroFile = [
|
|
48
|
+
{
|
|
49
|
+
importString:
|
|
50
|
+
'import astroConfig from "@ethang/eslint-config/config.astro.ts',
|
|
51
|
+
label: "Astro",
|
|
52
|
+
name: "astro",
|
|
53
|
+
options: {
|
|
54
|
+
extraImports: [importTsEslint],
|
|
55
|
+
includeIgnores: true,
|
|
56
|
+
includeLanguageOptions: true,
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
];
|
|
60
|
+
|
|
61
|
+
const reactFile = [
|
|
62
|
+
{
|
|
63
|
+
importString:
|
|
64
|
+
'import reactConfig from "@ethang/eslint-config/config.react.ts',
|
|
65
|
+
label: "React",
|
|
66
|
+
name: "react",
|
|
67
|
+
options: {
|
|
68
|
+
extraImports: [importTsEslint],
|
|
69
|
+
includeIgnores: true,
|
|
70
|
+
includeLanguageOptions: true,
|
|
71
|
+
includeReactVersion: true,
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
];
|
|
75
|
+
|
|
76
|
+
const solidFile = [
|
|
77
|
+
{
|
|
78
|
+
importString:
|
|
79
|
+
'import solidConfig from "@ethang/eslint-config/config.solid.ts',
|
|
80
|
+
label: "Solid",
|
|
81
|
+
name: "solid",
|
|
82
|
+
options: {
|
|
83
|
+
extraImports: [importTsEslint],
|
|
84
|
+
includeIgnores: true,
|
|
85
|
+
includeLanguageOptions: true,
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
];
|
|
89
|
+
|
|
90
|
+
const angularFile = [
|
|
91
|
+
{
|
|
92
|
+
importString:
|
|
93
|
+
'import angularConfig from "@ethang/eslint-config/config.angular.ts',
|
|
94
|
+
label: "Angular",
|
|
95
|
+
name: "angular",
|
|
96
|
+
options: {
|
|
97
|
+
extraImports: [importTsEslint, 'import angular from "angular-eslint";'],
|
|
98
|
+
globalIgnores: ["**/*.spec.ts", "src/main.server.ts"],
|
|
99
|
+
includeIgnores: true,
|
|
100
|
+
includeLanguageOptions: true,
|
|
101
|
+
processor: "angular.processInlineTemplates",
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
name: "angular:template",
|
|
106
|
+
options: {
|
|
107
|
+
extraImports: ['import { angularLanguageOptions } from "./constants.js"'],
|
|
108
|
+
includeAngularLanguageOptions: true,
|
|
109
|
+
includeLanguageOptions: false,
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
];
|
|
113
|
+
|
|
114
|
+
export const updateRules = async () => {
|
|
115
|
+
await Promise.all([
|
|
116
|
+
createConfigFile(coreFile, "eslint.config.js"),
|
|
117
|
+
createConfigFile(astroFile, "config.astro.js"),
|
|
118
|
+
createConfigFile(reactFile, "config.react.js"),
|
|
119
|
+
createConfigFile(solidFile, "config.solid.js"),
|
|
120
|
+
createConfigFile(angularFile, "config.angular.js"),
|
|
121
|
+
]);
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
await updateRules();
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
import { angularLanguageOptions } from "./constants.js";
|
|
3
|
+
import { ignores, languageOptions } from "./constants.js";
|
|
4
|
+
import angular from "angular-eslint";
|
|
5
|
+
import angularTemplate from "@angular-eslint/eslint-plugin-template";
|
|
6
|
+
import angularTS from "@angular-eslint/eslint-plugin";
|
|
7
|
+
import tseslint from "typescript-eslint";
|
|
8
|
+
|
|
9
|
+
export default tseslint.config(
|
|
10
|
+
{
|
|
11
|
+
ignores: ["**/*.spec.ts", "src/main.server.ts"],
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
files: ["**/*.ts"],
|
|
15
|
+
ignores,
|
|
16
|
+
languageOptions,
|
|
17
|
+
processor: angular.processInlineTemplates,
|
|
18
|
+
plugins: {
|
|
19
|
+
"@angular-eslint": angularTS,
|
|
20
|
+
},
|
|
21
|
+
rules: {
|
|
22
|
+
"@angular-eslint/component-class-suffix": "error",
|
|
23
|
+
"@angular-eslint/component-max-inline-declarations": "error",
|
|
24
|
+
"@angular-eslint/component-selector": [
|
|
25
|
+
"error",
|
|
26
|
+
{ prefix: "app", style: "kebab-case", type: "element" },
|
|
27
|
+
],
|
|
28
|
+
"@angular-eslint/consistent-component-styles": "error",
|
|
29
|
+
"@angular-eslint/contextual-decorator": "error",
|
|
30
|
+
"@angular-eslint/contextual-lifecycle": "error",
|
|
31
|
+
"@angular-eslint/directive-class-suffix": "error",
|
|
32
|
+
"@angular-eslint/directive-selector": [
|
|
33
|
+
"error",
|
|
34
|
+
{ prefix: "app", style: "camelCase", type: "attribute" },
|
|
35
|
+
],
|
|
36
|
+
"@angular-eslint/no-async-lifecycle-method": "error",
|
|
37
|
+
"@angular-eslint/no-attribute-decorator": "error",
|
|
38
|
+
"@angular-eslint/no-conflicting-lifecycle": "error",
|
|
39
|
+
"@angular-eslint/no-duplicates-in-metadata-arrays": "error",
|
|
40
|
+
"@angular-eslint/no-empty-lifecycle-method": "error",
|
|
41
|
+
"@angular-eslint/no-forward-ref": "error",
|
|
42
|
+
"@angular-eslint/no-input-prefix": "error",
|
|
43
|
+
"@angular-eslint/no-input-rename": "error",
|
|
44
|
+
"@angular-eslint/no-inputs-metadata-property": "error",
|
|
45
|
+
"@angular-eslint/no-lifecycle-call": "error",
|
|
46
|
+
"@angular-eslint/no-output-native": "error",
|
|
47
|
+
"@angular-eslint/no-output-on-prefix": "error",
|
|
48
|
+
"@angular-eslint/no-output-rename": "error",
|
|
49
|
+
"@angular-eslint/no-outputs-metadata-property": "error",
|
|
50
|
+
"@angular-eslint/no-pipe-impure": "error",
|
|
51
|
+
"@angular-eslint/no-queries-metadata-property": "error",
|
|
52
|
+
"@angular-eslint/pipe-prefix": "error",
|
|
53
|
+
"@angular-eslint/prefer-on-push-component-change-detection": "error",
|
|
54
|
+
"@angular-eslint/prefer-output-readonly": "error",
|
|
55
|
+
"@angular-eslint/prefer-signals": "error",
|
|
56
|
+
"@angular-eslint/prefer-standalone": "error",
|
|
57
|
+
"@angular-eslint/relative-url-prefix": "error",
|
|
58
|
+
"@angular-eslint/require-localize-metadata": "error",
|
|
59
|
+
"@angular-eslint/runtime-localize": "error",
|
|
60
|
+
"@angular-eslint/sort-lifecycle-methods": "error",
|
|
61
|
+
"@angular-eslint/use-component-selector": "error",
|
|
62
|
+
"@angular-eslint/use-component-view-encapsulation": "error",
|
|
63
|
+
"@angular-eslint/use-injectable-provided-in": "error",
|
|
64
|
+
"@angular-eslint/use-lifecycle-interface": "error",
|
|
65
|
+
"@angular-eslint/use-pipe-transform-interface": "error",
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
files: ["**/*.html"],
|
|
70
|
+
languageOptions: angularLanguageOptions,
|
|
71
|
+
plugins: {
|
|
72
|
+
"@angular-eslint/template": angularTemplate,
|
|
73
|
+
},
|
|
74
|
+
rules: {
|
|
75
|
+
"@angular-eslint/template/alt-text": "error",
|
|
76
|
+
"@angular-eslint/template/attributes-order": "error",
|
|
77
|
+
"@angular-eslint/template/banana-in-box": "error",
|
|
78
|
+
"@angular-eslint/template/button-has-type": "error",
|
|
79
|
+
"@angular-eslint/template/click-events-have-key-events": "error",
|
|
80
|
+
"@angular-eslint/template/conditional-complexity": "error",
|
|
81
|
+
"@angular-eslint/template/cyclomatic-complexity": "error",
|
|
82
|
+
"@angular-eslint/template/elements-content": "error",
|
|
83
|
+
"@angular-eslint/template/eqeqeq": "error",
|
|
84
|
+
"@angular-eslint/template/i18n": "off",
|
|
85
|
+
"@angular-eslint/template/interactive-supports-focus": "error",
|
|
86
|
+
"@angular-eslint/template/label-has-associated-control": "error",
|
|
87
|
+
"@angular-eslint/template/mouse-events-have-key-events": "error",
|
|
88
|
+
"@angular-eslint/template/no-any": "error",
|
|
89
|
+
"@angular-eslint/template/no-autofocus": "error",
|
|
90
|
+
"@angular-eslint/template/no-call-expression": "off",
|
|
91
|
+
"@angular-eslint/template/no-distracting-elements": "error",
|
|
92
|
+
"@angular-eslint/template/no-duplicate-attributes": "error",
|
|
93
|
+
"@angular-eslint/template/no-inline-styles": "error",
|
|
94
|
+
"@angular-eslint/template/no-interpolation-in-attributes": "error",
|
|
95
|
+
"@angular-eslint/template/no-negated-async": "error",
|
|
96
|
+
"@angular-eslint/template/no-positive-tabindex": "error",
|
|
97
|
+
"@angular-eslint/template/prefer-control-flow": "error",
|
|
98
|
+
"@angular-eslint/template/prefer-ngsrc": "warn",
|
|
99
|
+
"@angular-eslint/template/prefer-self-closing-tags": "error",
|
|
100
|
+
"@angular-eslint/template/prefer-static-string-properties": "error",
|
|
101
|
+
"@angular-eslint/template/role-has-required-aria": "error",
|
|
102
|
+
"@angular-eslint/template/table-scope": "error",
|
|
103
|
+
"@angular-eslint/template/use-track-by-function": "error",
|
|
104
|
+
"@angular-eslint/template/valid-aria": "error",
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
);
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
import { ignores, languageOptions } from "./constants.js";
|
|
3
|
+
import astro from "eslint-plugin-astro";
|
|
4
|
+
import tseslint from "typescript-eslint";
|
|
5
|
+
|
|
6
|
+
export default tseslint.config({
|
|
7
|
+
files: ["**/*.{astro}"],
|
|
8
|
+
ignores,
|
|
9
|
+
languageOptions,
|
|
10
|
+
plugins: {
|
|
11
|
+
astro: astro,
|
|
12
|
+
},
|
|
13
|
+
rules: {
|
|
14
|
+
"astro/jsx-a11y/alt-text": "error",
|
|
15
|
+
"astro/jsx-a11y/anchor-ambiguous-text": "error",
|
|
16
|
+
"astro/jsx-a11y/anchor-has-content": "error",
|
|
17
|
+
"astro/jsx-a11y/anchor-is-valid": "error",
|
|
18
|
+
"astro/jsx-a11y/aria-activedescendant-has-tabindex": "error",
|
|
19
|
+
"astro/jsx-a11y/aria-props": "error",
|
|
20
|
+
"astro/jsx-a11y/aria-proptypes": "error",
|
|
21
|
+
"astro/jsx-a11y/aria-role": "error",
|
|
22
|
+
"astro/jsx-a11y/aria-unsupported-elements": "error",
|
|
23
|
+
"astro/jsx-a11y/autocomplete-valid": "error",
|
|
24
|
+
"astro/jsx-a11y/click-events-have-key-events": "error",
|
|
25
|
+
"astro/jsx-a11y/control-has-associated-label": "error",
|
|
26
|
+
"astro/jsx-a11y/heading-has-content": "error",
|
|
27
|
+
"astro/jsx-a11y/html-has-lang": "error",
|
|
28
|
+
"astro/jsx-a11y/iframe-has-title": "error",
|
|
29
|
+
"astro/jsx-a11y/img-redundant-alt": "error",
|
|
30
|
+
"astro/jsx-a11y/interactive-supports-focus": "error",
|
|
31
|
+
"astro/jsx-a11y/label-has-associated-control": "error",
|
|
32
|
+
"astro/jsx-a11y/lang": "error",
|
|
33
|
+
"astro/jsx-a11y/media-has-caption": "error",
|
|
34
|
+
"astro/jsx-a11y/mouse-events-have-key-events": "error",
|
|
35
|
+
"astro/jsx-a11y/no-access-key": "error",
|
|
36
|
+
"astro/jsx-a11y/no-aria-hidden-on-focusable": "error",
|
|
37
|
+
"astro/jsx-a11y/no-autofocus": "error",
|
|
38
|
+
"astro/jsx-a11y/no-distracting-elements": "error",
|
|
39
|
+
"astro/jsx-a11y/no-interactive-element-to-noninteractive-role": "error",
|
|
40
|
+
"astro/jsx-a11y/no-noninteractive-element-interactions": "error",
|
|
41
|
+
"astro/jsx-a11y/no-noninteractive-element-to-interactive-role": "error",
|
|
42
|
+
"astro/jsx-a11y/no-noninteractive-tabindex": "error",
|
|
43
|
+
"astro/jsx-a11y/no-redundant-roles": "error",
|
|
44
|
+
"astro/jsx-a11y/no-static-element-interactions": "error",
|
|
45
|
+
"astro/jsx-a11y/prefer-tag-over-role": "error",
|
|
46
|
+
"astro/jsx-a11y/role-has-required-aria-props": "error",
|
|
47
|
+
"astro/jsx-a11y/role-supports-aria-props": "error",
|
|
48
|
+
"astro/jsx-a11y/scope": "error",
|
|
49
|
+
"astro/jsx-a11y/tabindex-no-positive": "error",
|
|
50
|
+
"astro/missing-client-only-directive-value": "error",
|
|
51
|
+
"astro/no-conflict-set-directives": "error",
|
|
52
|
+
"astro/no-deprecated-astro-canonicalurl": "error",
|
|
53
|
+
"astro/no-deprecated-astro-fetchcontent": "error",
|
|
54
|
+
"astro/no-deprecated-astro-resolve": "error",
|
|
55
|
+
"astro/no-deprecated-getentrybyslug": "error",
|
|
56
|
+
"astro/no-exports-from-components": "error",
|
|
57
|
+
"astro/no-set-html-directive": "off",
|
|
58
|
+
"astro/no-set-text-directive": "error",
|
|
59
|
+
"astro/no-unused-css-selector": "error",
|
|
60
|
+
"astro/no-unused-define-vars-in-style": "error",
|
|
61
|
+
"astro/prefer-class-list-directive": "error",
|
|
62
|
+
"astro/prefer-object-class-list": "error",
|
|
63
|
+
"astro/prefer-split-class-list": "error",
|
|
64
|
+
"astro/semi": "error",
|
|
65
|
+
"astro/sort-attributes": "error",
|
|
66
|
+
"astro/valid-compile": "error",
|
|
67
|
+
},
|
|
68
|
+
});
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
import { ignores, languageOptions } from "./constants.js";
|
|
3
|
+
import react from "@eslint-react/eslint-plugin";
|
|
4
|
+
import reactCompiler from "eslint-plugin-react-compiler";
|
|
5
|
+
import reactHooks from "eslint-plugin-react-hooks";
|
|
6
|
+
import tseslint from "typescript-eslint";
|
|
7
|
+
|
|
8
|
+
export default tseslint.config({
|
|
9
|
+
files: ["**/*.{jsx,tsx}"],
|
|
10
|
+
ignores,
|
|
11
|
+
languageOptions,
|
|
12
|
+
settings: {
|
|
13
|
+
react: { version: "19.0.0" },
|
|
14
|
+
},
|
|
15
|
+
plugins: {
|
|
16
|
+
react: react,
|
|
17
|
+
"react-hooks": reactHooks,
|
|
18
|
+
"react-compiler": reactCompiler,
|
|
19
|
+
},
|
|
20
|
+
rules: {
|
|
21
|
+
"react/avoid-shorthand-boolean": "off",
|
|
22
|
+
"react/avoid-shorthand-fragment": "off",
|
|
23
|
+
"react/debug/class-component": "off",
|
|
24
|
+
"react/debug/function-component": "off",
|
|
25
|
+
"react/debug/hook": "off",
|
|
26
|
+
"react/debug/is-from-react": "off",
|
|
27
|
+
"react/debug/react-hooks": "off",
|
|
28
|
+
"react/dom/no-children-in-void-dom-elements": "error",
|
|
29
|
+
"react/dom/no-dangerously-set-innerhtml": "error",
|
|
30
|
+
"react/dom/no-dangerously-set-innerhtml-with-children": "error",
|
|
31
|
+
"react/dom/no-find-dom-node": "error",
|
|
32
|
+
"react/dom/no-flush-sync": "error",
|
|
33
|
+
"react/dom/no-missing-button-type": "error",
|
|
34
|
+
"react/dom/no-missing-iframe-sandbox": "error",
|
|
35
|
+
"react/dom/no-namespace": "error",
|
|
36
|
+
"react/dom/no-render-return-value": "error",
|
|
37
|
+
"react/dom/no-script-url": "error",
|
|
38
|
+
"react/dom/no-unknown-property": "error",
|
|
39
|
+
"react/dom/no-unsafe-iframe-sandbox": "error",
|
|
40
|
+
"react/dom/no-unsafe-target-blank": "error",
|
|
41
|
+
"react/dom/no-void-elements-with-children": "error",
|
|
42
|
+
"react/ensure-forward-ref-using-ref": "error",
|
|
43
|
+
"react/hooks-extra/ensure-custom-hooks-using-other-hooks": "error",
|
|
44
|
+
"react/hooks-extra/ensure-use-callback-has-non-empty-deps": "error",
|
|
45
|
+
"react/hooks-extra/ensure-use-memo-has-non-empty-deps": "error",
|
|
46
|
+
"react/hooks-extra/no-direct-set-state-in-use-effect": "error",
|
|
47
|
+
"react/hooks-extra/no-direct-set-state-in-use-layout-effect": "error",
|
|
48
|
+
"react/hooks-extra/no-redundant-custom-hook": "error",
|
|
49
|
+
"react/hooks-extra/no-unnecessary-use-callback": "error",
|
|
50
|
+
"react/hooks-extra/no-unnecessary-use-memo": "error",
|
|
51
|
+
"react/hooks-extra/no-useless-custom-hooks": "error",
|
|
52
|
+
"react/hooks-extra/prefer-use-state-lazy-initialization": "error",
|
|
53
|
+
"react/jsx-no-duplicate-props": "error",
|
|
54
|
+
"react/jsx-uses-vars": "error",
|
|
55
|
+
"react/naming-convention/component-name": "error",
|
|
56
|
+
"react/naming-convention/filename": ["error", { rule: "kebab-case" }],
|
|
57
|
+
"react/naming-convention/filename-extension": "error",
|
|
58
|
+
"react/naming-convention/use-state": "error",
|
|
59
|
+
"react/no-access-state-in-setstate": "error",
|
|
60
|
+
"react/no-array-index-key": "error",
|
|
61
|
+
"react/no-children-count": "error",
|
|
62
|
+
"react/no-children-for-each": "error",
|
|
63
|
+
"react/no-children-map": "error",
|
|
64
|
+
"react/no-children-only": "error",
|
|
65
|
+
"react/no-children-prop": "error",
|
|
66
|
+
"react/no-children-to-array": "error",
|
|
67
|
+
"react/no-class-component": "error",
|
|
68
|
+
"react/no-clone-element": "error",
|
|
69
|
+
"react/no-comment-textnodes": "error",
|
|
70
|
+
"react/no-complex-conditional-rendering": "error",
|
|
71
|
+
"react/no-complicated-conditional-rendering": "error",
|
|
72
|
+
"react/no-component-will-mount": "error",
|
|
73
|
+
"react/no-component-will-receive-props": "error",
|
|
74
|
+
"react/no-component-will-update": "error",
|
|
75
|
+
"react/no-context-provider": "error",
|
|
76
|
+
"react/no-create-ref": "error",
|
|
77
|
+
"react/no-default-props": "error",
|
|
78
|
+
"react/no-direct-mutation-state": "error",
|
|
79
|
+
"react/no-duplicate-jsx-props": "error",
|
|
80
|
+
"react/no-duplicate-key": "error",
|
|
81
|
+
"react/no-forward-ref": "error",
|
|
82
|
+
"react/no-implicit-key": "error",
|
|
83
|
+
"react/no-leaked-conditional-rendering": "error",
|
|
84
|
+
"react/no-missing-component-display-name": "error",
|
|
85
|
+
"react/no-missing-context-display-name": "error",
|
|
86
|
+
"react/no-missing-key": "error",
|
|
87
|
+
"react/no-nested-components": "error",
|
|
88
|
+
"react/no-prop-types": "error",
|
|
89
|
+
"react/no-redundant-should-component-update": "error",
|
|
90
|
+
"react/no-set-state-in-component-did-mount": "error",
|
|
91
|
+
"react/no-set-state-in-component-did-update": "error",
|
|
92
|
+
"react/no-set-state-in-component-will-update": "error",
|
|
93
|
+
"react/no-string-refs": "error",
|
|
94
|
+
"react/no-unsafe-component-will-mount": "error",
|
|
95
|
+
"react/no-unsafe-component-will-receive-props": "error",
|
|
96
|
+
"react/no-unsafe-component-will-update": "error",
|
|
97
|
+
"react/no-unstable-context-value": "error",
|
|
98
|
+
"react/no-unstable-default-props": "error",
|
|
99
|
+
"react/no-unused-class-component-members": "error",
|
|
100
|
+
"react/no-unused-state": "error",
|
|
101
|
+
"react/no-use-context": "error",
|
|
102
|
+
"react/no-useless-fragment": "error",
|
|
103
|
+
"react/prefer-destructuring-assignment": "error",
|
|
104
|
+
"react/prefer-react-namespace-import": "error",
|
|
105
|
+
"react/prefer-read-only-props": "error",
|
|
106
|
+
"react/prefer-shorthand-boolean": "error",
|
|
107
|
+
"react/prefer-shorthand-fragment": "error",
|
|
108
|
+
"react/use-jsx-vars": "error",
|
|
109
|
+
"react/web-api/no-leaked-event-listener": "error",
|
|
110
|
+
"react/web-api/no-leaked-interval": "error",
|
|
111
|
+
"react/web-api/no-leaked-resize-observer": "error",
|
|
112
|
+
"react/web-api/no-leaked-timeout": "error",
|
|
113
|
+
"react-hooks/exhaustive-deps": "error",
|
|
114
|
+
"react-hooks/rules-of-hooks": "error",
|
|
115
|
+
"react-compiler/react-compiler": "error",
|
|
116
|
+
},
|
|
117
|
+
});
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
import { ignores, languageOptions } from "./constants.js";
|
|
3
|
+
import solid from "eslint-plugin-solid";
|
|
4
|
+
import tseslint from "typescript-eslint";
|
|
5
|
+
|
|
6
|
+
export default tseslint.config({
|
|
7
|
+
files: ["**/*.{jsx,tsx}"],
|
|
8
|
+
ignores,
|
|
9
|
+
languageOptions,
|
|
10
|
+
plugins: {
|
|
11
|
+
solid: solid,
|
|
12
|
+
},
|
|
13
|
+
rules: {
|
|
14
|
+
"solid/components-return-once": "error",
|
|
15
|
+
"solid/event-handlers": "error",
|
|
16
|
+
"solid/imports": "error",
|
|
17
|
+
"solid/jsx-no-duplicate-props": "error",
|
|
18
|
+
"solid/jsx-no-script-url": "error",
|
|
19
|
+
"solid/jsx-no-undef": "error",
|
|
20
|
+
"solid/jsx-uses-vars": "error",
|
|
21
|
+
"solid/no-array-handlers": "error",
|
|
22
|
+
"solid/no-destructure": "error",
|
|
23
|
+
"solid/no-innerhtml": "error",
|
|
24
|
+
"solid/no-proxy-apis": "off",
|
|
25
|
+
"solid/no-react-deps": "error",
|
|
26
|
+
"solid/no-react-specific-props": "error",
|
|
27
|
+
"solid/no-unknown-namespaces": "error",
|
|
28
|
+
"solid/prefer-for": "error",
|
|
29
|
+
"solid/prefer-show": "error",
|
|
30
|
+
"solid/reactivity": "error",
|
|
31
|
+
"solid/self-closing-comp": "error",
|
|
32
|
+
"solid/style-prop": "error",
|
|
33
|
+
},
|
|
34
|
+
});
|
package/src/constants.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import angularTemplateParser from "@angular-eslint/template-parser";
|
|
2
|
+
import { parser } from "typescript-eslint";
|
|
3
|
+
|
|
4
|
+
export const ignores = ["eslint.config.js", "node_modules", "dist"];
|
|
5
|
+
|
|
6
|
+
export const languageOptions = {
|
|
7
|
+
parser,
|
|
8
|
+
parserOptions: {
|
|
9
|
+
project: true,
|
|
10
|
+
tsconfigRootDir: import.meta.dirname,
|
|
11
|
+
},
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export const angularLanguageOptions = {
|
|
15
|
+
parser: angularTemplateParser,
|
|
16
|
+
};
|