eslint-plugin-absolute 0.2.0 → 0.2.2
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/.absolutejs/eslint.cache.json +49 -0
- package/.absolutejs/prettier.cache.json +49 -0
- package/.absolutejs/tsconfig.tsbuildinfo +1 -0
- package/.claude/settings.local.json +8 -3
- package/.codex +0 -0
- package/dist/index.js +1500 -1421
- package/eslint.config.mjs +107 -0
- package/package.json +22 -20
- package/src/index.ts +15 -15
- package/src/rules/explicit-object-types.ts +42 -40
- package/src/rules/inline-style-limit.ts +56 -54
- package/src/rules/localize-react-props.ts +261 -266
- package/src/rules/max-depth-extended.ts +55 -66
- package/src/rules/max-jsx-nesting.ts +28 -36
- package/src/rules/min-var-length.ts +238 -208
- package/src/rules/no-button-navigation.ts +114 -156
- package/src/rules/no-explicit-return-types.ts +32 -36
- package/src/rules/no-inline-prop-types.ts +30 -30
- package/src/rules/no-multi-style-objects.ts +35 -42
- package/src/rules/no-nested-jsx-return.ts +100 -105
- package/src/rules/no-or-none-component.ts +17 -19
- package/src/rules/no-transition-cssproperties.ts +76 -70
- package/src/rules/no-unnecessary-div.ts +26 -34
- package/src/rules/no-unnecessary-key.ts +41 -75
- package/src/rules/no-useless-function.ts +18 -20
- package/src/rules/seperate-style-files.ts +19 -21
- package/src/rules/sort-exports.ts +382 -256
- package/src/rules/sort-keys-fixable.ts +486 -322
- package/src/rules/spring-naming-convention.ts +104 -89
- package/tsconfig.json +3 -1
|
@@ -4,33 +4,13 @@ type Options = [number?];
|
|
|
4
4
|
type MessageIds = "tooDeep";
|
|
5
5
|
|
|
6
6
|
export const maxDepthExtended: TSESLint.RuleModule<MessageIds, Options> = {
|
|
7
|
-
meta: {
|
|
8
|
-
type: "suggestion",
|
|
9
|
-
docs: {
|
|
10
|
-
description:
|
|
11
|
-
"disallow too many nested blocks except when the block only contains an early exit (return or throw)"
|
|
12
|
-
},
|
|
13
|
-
schema: [
|
|
14
|
-
{
|
|
15
|
-
// Accepts a single number as the maximum allowed depth.
|
|
16
|
-
type: "number"
|
|
17
|
-
}
|
|
18
|
-
],
|
|
19
|
-
messages: {
|
|
20
|
-
tooDeep:
|
|
21
|
-
"Blocks are nested too deeply ({{depth}}). Maximum allowed is {{maxDepth}} or an early exit."
|
|
22
|
-
}
|
|
23
|
-
},
|
|
24
|
-
|
|
25
|
-
defaultOptions: [1],
|
|
26
|
-
|
|
27
7
|
create(context) {
|
|
28
|
-
const option = context.options
|
|
8
|
+
const [option] = context.options;
|
|
29
9
|
const maxDepth = typeof option === "number" ? option : 1;
|
|
30
10
|
const functionStack: number[] = [];
|
|
31
11
|
|
|
32
12
|
// Helper to get ancestors of a node by walking its parent chain.
|
|
33
|
-
|
|
13
|
+
const getAncestors = (node: TSESTree.Node) => {
|
|
34
14
|
const ancestors: TSESTree.Node[] = [];
|
|
35
15
|
let current: TSESTree.Node | null | undefined = node.parent;
|
|
36
16
|
while (current) {
|
|
@@ -38,14 +18,14 @@ export const maxDepthExtended: TSESLint.RuleModule<MessageIds, Options> = {
|
|
|
38
18
|
current = current.parent;
|
|
39
19
|
}
|
|
40
20
|
return ancestors;
|
|
41
|
-
}
|
|
21
|
+
};
|
|
42
22
|
|
|
43
23
|
// Check if a block only contains a single early exit: return or throw.
|
|
44
|
-
|
|
24
|
+
const isEarlyExitBlock = (node: TSESTree.BlockStatement) => {
|
|
45
25
|
if (node.body.length !== 1) {
|
|
46
26
|
return false;
|
|
47
27
|
}
|
|
48
|
-
const first = node.body
|
|
28
|
+
const [first] = node.body;
|
|
49
29
|
if (!first) {
|
|
50
30
|
return false;
|
|
51
31
|
}
|
|
@@ -53,9 +33,21 @@ export const maxDepthExtended: TSESLint.RuleModule<MessageIds, Options> = {
|
|
|
53
33
|
first.type === "ReturnStatement" ||
|
|
54
34
|
first.type === "ThrowStatement"
|
|
55
35
|
);
|
|
56
|
-
}
|
|
36
|
+
};
|
|
57
37
|
|
|
58
|
-
|
|
38
|
+
const isFunctionBody = (node: TSESTree.BlockStatement) => {
|
|
39
|
+
const ancestors = getAncestors(node);
|
|
40
|
+
const [parent] = ancestors;
|
|
41
|
+
return (
|
|
42
|
+
parent &&
|
|
43
|
+
(parent.type === "FunctionDeclaration" ||
|
|
44
|
+
parent.type === "FunctionExpression" ||
|
|
45
|
+
parent.type === "ArrowFunctionExpression") &&
|
|
46
|
+
node === parent.body
|
|
47
|
+
);
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const incrementCurrentDepth = () => {
|
|
59
51
|
if (functionStack.length === 0) {
|
|
60
52
|
return null;
|
|
61
53
|
}
|
|
@@ -67,9 +59,9 @@ export const maxDepthExtended: TSESLint.RuleModule<MessageIds, Options> = {
|
|
|
67
59
|
const nextDepth = currentDepth + 1;
|
|
68
60
|
functionStack[index] = nextDepth;
|
|
69
61
|
return nextDepth;
|
|
70
|
-
}
|
|
62
|
+
};
|
|
71
63
|
|
|
72
|
-
|
|
64
|
+
const decrementCurrentDepth = () => {
|
|
73
65
|
if (functionStack.length === 0) {
|
|
74
66
|
return;
|
|
75
67
|
}
|
|
@@ -79,42 +71,29 @@ export const maxDepthExtended: TSESLint.RuleModule<MessageIds, Options> = {
|
|
|
79
71
|
return;
|
|
80
72
|
}
|
|
81
73
|
functionStack[index] = currentDepth - 1;
|
|
82
|
-
}
|
|
74
|
+
};
|
|
83
75
|
|
|
84
76
|
// Report if the current depth exceeds the allowed maximum.
|
|
85
|
-
|
|
77
|
+
const checkDepth = (node: TSESTree.BlockStatement, depth: number) => {
|
|
86
78
|
if (depth > maxDepth) {
|
|
87
79
|
context.report({
|
|
88
|
-
|
|
80
|
+
data: { depth, maxDepth },
|
|
89
81
|
messageId: "tooDeep",
|
|
90
|
-
|
|
82
|
+
node
|
|
91
83
|
});
|
|
92
84
|
}
|
|
93
|
-
}
|
|
85
|
+
};
|
|
94
86
|
|
|
95
87
|
return {
|
|
96
|
-
FunctionDeclaration() {
|
|
97
|
-
functionStack.push(0);
|
|
98
|
-
},
|
|
99
|
-
FunctionExpression() {
|
|
100
|
-
functionStack.push(0);
|
|
101
|
-
},
|
|
102
88
|
ArrowFunctionExpression() {
|
|
103
89
|
functionStack.push(0);
|
|
104
90
|
},
|
|
105
|
-
|
|
91
|
+
"ArrowFunctionExpression:exit"() {
|
|
92
|
+
functionStack.pop();
|
|
93
|
+
},
|
|
106
94
|
BlockStatement(node: TSESTree.BlockStatement) {
|
|
107
|
-
const ancestors = getAncestors(node);
|
|
108
|
-
const parent = ancestors.length > 0 ? ancestors[0] : undefined;
|
|
109
|
-
|
|
110
95
|
// Do not count if this block is the body of a function.
|
|
111
|
-
if (
|
|
112
|
-
parent &&
|
|
113
|
-
(parent.type === "FunctionDeclaration" ||
|
|
114
|
-
parent.type === "FunctionExpression" ||
|
|
115
|
-
parent.type === "ArrowFunctionExpression") &&
|
|
116
|
-
node === parent.body
|
|
117
|
-
) {
|
|
96
|
+
if (isFunctionBody(node)) {
|
|
118
97
|
return;
|
|
119
98
|
}
|
|
120
99
|
|
|
@@ -128,18 +107,8 @@ export const maxDepthExtended: TSESLint.RuleModule<MessageIds, Options> = {
|
|
|
128
107
|
checkDepth(node, depth);
|
|
129
108
|
}
|
|
130
109
|
},
|
|
131
|
-
|
|
132
110
|
"BlockStatement:exit"(node: TSESTree.BlockStatement) {
|
|
133
|
-
|
|
134
|
-
const parent = ancestors.length > 0 ? ancestors[0] : undefined;
|
|
135
|
-
|
|
136
|
-
if (
|
|
137
|
-
parent &&
|
|
138
|
-
(parent.type === "FunctionDeclaration" ||
|
|
139
|
-
parent.type === "FunctionExpression" ||
|
|
140
|
-
parent.type === "ArrowFunctionExpression") &&
|
|
141
|
-
node === parent.body
|
|
142
|
-
) {
|
|
111
|
+
if (isFunctionBody(node)) {
|
|
143
112
|
return;
|
|
144
113
|
}
|
|
145
114
|
|
|
@@ -149,16 +118,36 @@ export const maxDepthExtended: TSESLint.RuleModule<MessageIds, Options> = {
|
|
|
149
118
|
|
|
150
119
|
decrementCurrentDepth();
|
|
151
120
|
},
|
|
152
|
-
|
|
121
|
+
FunctionDeclaration() {
|
|
122
|
+
functionStack.push(0);
|
|
123
|
+
},
|
|
153
124
|
"FunctionDeclaration:exit"() {
|
|
154
125
|
functionStack.pop();
|
|
155
126
|
},
|
|
156
|
-
|
|
157
|
-
functionStack.
|
|
127
|
+
FunctionExpression() {
|
|
128
|
+
functionStack.push(0);
|
|
158
129
|
},
|
|
159
|
-
"
|
|
130
|
+
"FunctionExpression:exit"() {
|
|
160
131
|
functionStack.pop();
|
|
161
132
|
}
|
|
162
133
|
};
|
|
134
|
+
},
|
|
135
|
+
defaultOptions: [1],
|
|
136
|
+
meta: {
|
|
137
|
+
docs: {
|
|
138
|
+
description:
|
|
139
|
+
"disallow too many nested blocks except when the block only contains an early exit (return or throw)"
|
|
140
|
+
},
|
|
141
|
+
messages: {
|
|
142
|
+
tooDeep:
|
|
143
|
+
"Blocks are nested too deeply ({{depth}}). Maximum allowed is {{maxDepth}} or an early exit."
|
|
144
|
+
},
|
|
145
|
+
schema: [
|
|
146
|
+
{
|
|
147
|
+
// Accepts a single number as the maximum allowed depth.
|
|
148
|
+
type: "number"
|
|
149
|
+
}
|
|
150
|
+
],
|
|
151
|
+
type: "suggestion"
|
|
163
152
|
}
|
|
164
153
|
};
|
|
@@ -3,65 +3,57 @@ import { TSESLint, TSESTree } from "@typescript-eslint/utils";
|
|
|
3
3
|
type Options = [number];
|
|
4
4
|
type MessageIds = "tooDeeplyNested";
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
type: "suggestion",
|
|
9
|
-
docs: {
|
|
10
|
-
description:
|
|
11
|
-
"Warn when JSX elements are nested too deeply, suggesting refactoring into a separate component."
|
|
12
|
-
},
|
|
13
|
-
// The rule accepts a single numeric option (minimum 1)
|
|
14
|
-
schema: [
|
|
15
|
-
{
|
|
16
|
-
type: "number",
|
|
17
|
-
minimum: 1
|
|
18
|
-
}
|
|
19
|
-
],
|
|
20
|
-
messages: {
|
|
21
|
-
tooDeeplyNested:
|
|
22
|
-
"JSX element is nested too deeply ({{level}} levels, allowed is {{maxAllowed}} levels). Consider refactoring into a separate component."
|
|
23
|
-
}
|
|
24
|
-
},
|
|
25
|
-
|
|
26
|
-
defaultOptions: [1],
|
|
6
|
+
const isJSXAncestor = (node: TSESTree.Node) =>
|
|
7
|
+
node.type === "JSXElement" || node.type === "JSXFragment";
|
|
27
8
|
|
|
9
|
+
export const maxJSXNesting: TSESLint.RuleModule<MessageIds, Options> = {
|
|
28
10
|
create(context) {
|
|
29
|
-
const option = context.options
|
|
11
|
+
const [option] = context.options;
|
|
30
12
|
const maxAllowed = typeof option === "number" ? option : 1;
|
|
31
13
|
|
|
32
14
|
/**
|
|
33
15
|
* Calculates the JSX nesting level for the given node by traversing the node.parent chain.
|
|
34
|
-
* The level is computed by counting the current node (level 1) plus each ancestor
|
|
35
|
-
* that is a JSXElement or JSXFragment.
|
|
36
|
-
* @param {ASTNode} node The JSX element node.
|
|
37
|
-
* @returns {number} The nesting level.
|
|
38
16
|
*/
|
|
39
|
-
|
|
17
|
+
const getJSXNestingLevel = (node: TSESTree.Node) => {
|
|
40
18
|
let level = 1; // count the current node as level 1
|
|
41
19
|
let current: TSESTree.Node | null | undefined = node.parent;
|
|
42
20
|
while (current) {
|
|
43
|
-
|
|
44
|
-
current.type === "JSXElement" ||
|
|
45
|
-
current.type === "JSXFragment"
|
|
46
|
-
) {
|
|
47
|
-
level++;
|
|
48
|
-
}
|
|
21
|
+
level += isJSXAncestor(current) ? 1 : 0;
|
|
49
22
|
current = current.parent;
|
|
50
23
|
}
|
|
51
24
|
return level;
|
|
52
|
-
}
|
|
25
|
+
};
|
|
53
26
|
|
|
54
27
|
return {
|
|
55
28
|
JSXElement(node: TSESTree.JSXElement) {
|
|
56
29
|
const level = getJSXNestingLevel(node);
|
|
57
30
|
if (level > maxAllowed) {
|
|
58
31
|
context.report({
|
|
59
|
-
|
|
32
|
+
data: { level, maxAllowed },
|
|
60
33
|
messageId: "tooDeeplyNested",
|
|
61
|
-
|
|
34
|
+
node
|
|
62
35
|
});
|
|
63
36
|
}
|
|
64
37
|
}
|
|
65
38
|
};
|
|
39
|
+
},
|
|
40
|
+
defaultOptions: [1],
|
|
41
|
+
meta: {
|
|
42
|
+
docs: {
|
|
43
|
+
description:
|
|
44
|
+
"Warn when JSX elements are nested too deeply, suggesting refactoring into a separate component."
|
|
45
|
+
},
|
|
46
|
+
messages: {
|
|
47
|
+
tooDeeplyNested:
|
|
48
|
+
"JSX element is nested too deeply ({{level}} levels, allowed is {{maxAllowed}} levels). Consider refactoring into a separate component."
|
|
49
|
+
},
|
|
50
|
+
// The rule accepts a single numeric option (minimum 1)
|
|
51
|
+
schema: [
|
|
52
|
+
{
|
|
53
|
+
minimum: 1,
|
|
54
|
+
type: "number"
|
|
55
|
+
}
|
|
56
|
+
],
|
|
57
|
+
type: "suggestion"
|
|
66
58
|
}
|
|
67
59
|
};
|