@blumintinc/eslint-plugin-blumint 1.20.114 → 1.20.115
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/lib/index.js +1 -1
- package/lib/rules/no-jsx-in-hooks.js +39 -12
- package/package.json +1 -1
- package/release-manifest.json +14 -0
package/lib/index.js
CHANGED
|
@@ -13,20 +13,47 @@ const isJsxElement = (node) => {
|
|
|
13
13
|
node.type === utils_1.AST_NODE_TYPES.JSXFragment ||
|
|
14
14
|
node.type === utils_1.AST_NODE_TYPES.JSXExpressionContainer);
|
|
15
15
|
};
|
|
16
|
+
/**
|
|
17
|
+
* A type reference's name as dotted segments.
|
|
18
|
+
*
|
|
19
|
+
* A qualified name nests to the LEFT, so `React.JSX.Element` is a
|
|
20
|
+
* TSQualifiedName whose own `left` is another TSQualifiedName. Matching one
|
|
21
|
+
* nesting level at a time therefore recognizes `JSX.Element` but not the
|
|
22
|
+
* React-namespaced spelling of the same type; comparing whole paths recognizes
|
|
23
|
+
* both.
|
|
24
|
+
*/
|
|
25
|
+
const qualifiedSegments = (typeName) => {
|
|
26
|
+
if (typeName.type === utils_1.AST_NODE_TYPES.Identifier) {
|
|
27
|
+
return [typeName.name];
|
|
28
|
+
}
|
|
29
|
+
if (typeName.type === utils_1.AST_NODE_TYPES.TSQualifiedName) {
|
|
30
|
+
const left = qualifiedSegments(typeName.left);
|
|
31
|
+
return left && [...left, typeName.right.name];
|
|
32
|
+
}
|
|
33
|
+
return null;
|
|
34
|
+
};
|
|
35
|
+
/** JSX-producing type paths, written without the optional `React` qualifier. */
|
|
36
|
+
const JSX_TYPE_PATHS = new Set([
|
|
37
|
+
'JSX',
|
|
38
|
+
'JSX.Element',
|
|
39
|
+
'ReactNode',
|
|
40
|
+
'ReactElement',
|
|
41
|
+
]);
|
|
16
42
|
const isJsxReturnType = (node) => {
|
|
17
|
-
if (node.typeAnnotation.type
|
|
18
|
-
|
|
19
|
-
if (typeName.type === utils_1.AST_NODE_TYPES.Identifier) {
|
|
20
|
-
return ['JSX', 'ReactNode', 'ReactElement'].includes(typeName.name);
|
|
21
|
-
}
|
|
22
|
-
if (typeName.type === utils_1.AST_NODE_TYPES.TSQualifiedName) {
|
|
23
|
-
return (typeName.left.type === utils_1.AST_NODE_TYPES.Identifier &&
|
|
24
|
-
typeName.left.name === 'JSX' &&
|
|
25
|
-
typeName.right.type === utils_1.AST_NODE_TYPES.Identifier &&
|
|
26
|
-
typeName.right.name === 'Element');
|
|
27
|
-
}
|
|
43
|
+
if (node.typeAnnotation.type !== utils_1.AST_NODE_TYPES.TSTypeReference) {
|
|
44
|
+
return false;
|
|
28
45
|
}
|
|
29
|
-
|
|
46
|
+
const segments = qualifiedSegments(node.typeAnnotation.typeName);
|
|
47
|
+
if (!segments) {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* `React.` re-exports the same declarations, so it carries no meaning for
|
|
52
|
+
* this question. Every other qualifier names a type from a different module
|
|
53
|
+
* and must not match — `Foo.ReactNode` is not React's.
|
|
54
|
+
*/
|
|
55
|
+
const path = segments[0] === 'React' ? segments.slice(1) : segments;
|
|
56
|
+
return path.length > 0 && JSX_TYPE_PATHS.has(path.join('.'));
|
|
30
57
|
};
|
|
31
58
|
const containsJsxInBlockStatement = (node) => {
|
|
32
59
|
const variablesWithJsx = new Set();
|
package/package.json
CHANGED
package/release-manifest.json
CHANGED
|
@@ -1,4 +1,18 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"version": "1.20.115",
|
|
4
|
+
"date": "2026-08-05T18:41:41.153Z",
|
|
5
|
+
"rules": [
|
|
6
|
+
{
|
|
7
|
+
"name": "no-jsx-in-hooks",
|
|
8
|
+
"changeType": "fix",
|
|
9
|
+
"issues": [
|
|
10
|
+
1753
|
|
11
|
+
],
|
|
12
|
+
"summary": "detect React-qualified JSX return types (closes #1753)"
|
|
13
|
+
}
|
|
14
|
+
]
|
|
15
|
+
},
|
|
2
16
|
{
|
|
3
17
|
"version": "1.20.114",
|
|
4
18
|
"date": "2026-08-05T18:16:40.596Z",
|