@eslint-react/jsx 1.40.2 → 1.40.3-beta.1
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/dist/index.d.mts +20 -50
- package/dist/index.d.ts +20 -50
- package/dist/index.js +65 -54
- package/dist/index.mjs +56 -43
- package/package.json +4 -4
package/dist/index.d.mts
CHANGED
|
@@ -50,7 +50,8 @@ declare function hasAttribute(name: string, attributes: TSESTree.JSXOpeningEleme
|
|
|
50
50
|
declare function hasAnyAttribute(names: string[], attributes: TSESTree.JSXOpeningElement["attributes"], initialScope?: Scope): boolean;
|
|
51
51
|
declare function hasEveryAttribute(names: string[], attributes: TSESTree.JSXOpeningElement["attributes"], initialScope?: Scope): boolean;
|
|
52
52
|
|
|
53
|
-
|
|
53
|
+
type JSXDetectionHint = bigint;
|
|
54
|
+
declare const JSXDetectionHint: {
|
|
54
55
|
readonly None: 0n;
|
|
55
56
|
readonly SkipUndefined: bigint;
|
|
56
57
|
readonly SkipNullLiteral: bigint;
|
|
@@ -64,69 +65,38 @@ declare const JSXValueHint: {
|
|
|
64
65
|
readonly StrictLogical: bigint;
|
|
65
66
|
readonly StrictConditional: bigint;
|
|
66
67
|
};
|
|
67
|
-
declare const
|
|
68
|
+
declare const DEFAULT_JSX_DETECTION_HINT: bigint;
|
|
69
|
+
|
|
68
70
|
/**
|
|
69
|
-
* Heuristic decision to determine if a node is a JSX
|
|
71
|
+
* Heuristic decision to determine if a node is a JSX-like node.
|
|
70
72
|
* @param node The AST node to check
|
|
71
73
|
* @param jsxCtx The requirements for the check
|
|
72
74
|
* @param jsxCtx.getScope The function to get the scope of a node
|
|
73
|
-
* @param hint The `
|
|
75
|
+
* @param hint The `JSXDetectionHint` to use
|
|
74
76
|
* @returns boolean
|
|
75
77
|
*/
|
|
76
|
-
declare function
|
|
78
|
+
declare function isJSXLike(node: TSESTree$1.Node | _ | null, jsxCtx: {
|
|
77
79
|
getScope: (node: TSESTree$1.Node) => Scope;
|
|
78
|
-
}, hint?:
|
|
80
|
+
}, hint?: JSXDetectionHint): boolean;
|
|
79
81
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
*/
|
|
85
|
-
declare function isFragmentElement(node: TSESTree.Node): boolean;
|
|
86
|
-
/**
|
|
87
|
-
* Check if a node has a `key` prop
|
|
88
|
-
* @param node The AST node to check
|
|
89
|
-
* @param initialScope The initial scope to start searching for the `key` attribute
|
|
90
|
-
* @returns `true` if the node is a `JSXElement` of `Keyed Component` type
|
|
91
|
-
*/
|
|
92
|
-
declare function isKeyedElement(node: TSESTree.Node, initialScope?: Scope): boolean;
|
|
93
|
-
/**
|
|
94
|
-
* Check if a node is a `JSXFragment` of `Built-in Component` type
|
|
95
|
-
* @param node The AST node to check
|
|
96
|
-
* @returns `true` if the node is a `JSXFragment` of `Built-in Component` type
|
|
97
|
-
*/
|
|
98
|
-
declare function isBuiltInElement(node: TSESTree.Node): boolean;
|
|
99
|
-
/**
|
|
100
|
-
* Check if a node is a `JSXElement` of `User-Defined Component` type
|
|
101
|
-
* @param node The AST node to check
|
|
102
|
-
* @returns `true` if the node is a `JSXElement` of `User-Defined Component` type
|
|
103
|
-
*/
|
|
104
|
-
declare function isUserDefinedElement(node: TSESTree.Node): boolean;
|
|
82
|
+
declare function isJsxFragmentElement(node: TSESTree.Node): boolean;
|
|
83
|
+
declare function isJsxKeyedElement(node: TSESTree.Node, initialScope?: Scope): boolean;
|
|
84
|
+
declare function isJsxBuiltInElement(node: TSESTree.Node): boolean;
|
|
85
|
+
declare function isJsxUserDefinedElement(node: TSESTree.Node): boolean;
|
|
105
86
|
|
|
106
87
|
/**
|
|
107
|
-
* Check if a node is a
|
|
108
|
-
* @param node The AST node to check
|
|
109
|
-
* @returns boolean `true` if the node is a Literal or JSXText
|
|
110
|
-
*/
|
|
111
|
-
declare const isLiteral: (node: TSESTree.Node | null | undefined) => node is TSESTree.JSXText | TSESTree.BigIntLiteral | TSESTree.BooleanLiteral | TSESTree.NullLiteral | TSESTree.NumberLiteral | TSESTree.RegExpLiteral | TSESTree.StringLiteral;
|
|
112
|
-
/**
|
|
113
|
-
* Check if a Literal or JSXText node is whitespace
|
|
88
|
+
* Check if a node is a `JSXFragment` or a `Fragment` element
|
|
114
89
|
* @param node The AST node to check
|
|
115
|
-
* @returns
|
|
90
|
+
* @returns `true` if the node is a `JSXFragment` or a `Fragment` element
|
|
116
91
|
*/
|
|
117
|
-
declare function
|
|
118
|
-
|
|
119
|
-
* Check if a Literal or JSXText node is a line break
|
|
120
|
-
* @param node The AST node to check
|
|
121
|
-
* @returns boolean
|
|
122
|
-
*/
|
|
123
|
-
declare function isLineBreak(node: TSESTree.Node): boolean;
|
|
92
|
+
declare function isJsxFragment(node: TSESTree.Node | null | _): boolean;
|
|
93
|
+
|
|
124
94
|
/**
|
|
125
|
-
* Check if a
|
|
95
|
+
* Check if a node is a `JSXText` or a `Literal` node
|
|
126
96
|
* @param node The AST node to check
|
|
127
|
-
* @returns
|
|
97
|
+
* @returns `true` if the node is a `JSXText` or a `Literal` node
|
|
128
98
|
*/
|
|
129
|
-
declare function
|
|
99
|
+
declare function isJsxText(node: TSESTree.Node | null | _): node is TSESTree.JSXText | TSESTree.Literal;
|
|
130
100
|
|
|
131
101
|
/**
|
|
132
102
|
* Get the stringified representation of a JSX node
|
|
@@ -135,4 +105,4 @@ declare function isPaddingSpaces(node: TSESTree.Node): boolean;
|
|
|
135
105
|
*/
|
|
136
106
|
declare function toString(node: TSESTree$1.JSXIdentifier | TSESTree$1.JSXMemberExpression | TSESTree$1.JSXNamespacedName | TSESTree$1.JSXOpeningElement | TSESTree$1.JSXClosingElement | TSESTree$1.JSXOpeningFragment | TSESTree$1.JSXClosingFragment | TSESTree$1.JSXText): string;
|
|
137
107
|
|
|
138
|
-
export {
|
|
108
|
+
export { DEFAULT_JSX_DETECTION_HINT, JSXDetectionHint, findParentAttribute, getAttribute, getAttributeName, getAttributeValue, getElementType, hasAnyAttribute, hasAttribute, hasEveryAttribute, isJSXLike, isJsxBuiltInElement, isJsxFragment, isJsxFragmentElement, isJsxKeyedElement, isJsxText, isJsxUserDefinedElement, toString };
|
package/dist/index.d.ts
CHANGED
|
@@ -50,7 +50,8 @@ declare function hasAttribute(name: string, attributes: TSESTree.JSXOpeningEleme
|
|
|
50
50
|
declare function hasAnyAttribute(names: string[], attributes: TSESTree.JSXOpeningElement["attributes"], initialScope?: Scope): boolean;
|
|
51
51
|
declare function hasEveryAttribute(names: string[], attributes: TSESTree.JSXOpeningElement["attributes"], initialScope?: Scope): boolean;
|
|
52
52
|
|
|
53
|
-
|
|
53
|
+
type JSXDetectionHint = bigint;
|
|
54
|
+
declare const JSXDetectionHint: {
|
|
54
55
|
readonly None: 0n;
|
|
55
56
|
readonly SkipUndefined: bigint;
|
|
56
57
|
readonly SkipNullLiteral: bigint;
|
|
@@ -64,69 +65,38 @@ declare const JSXValueHint: {
|
|
|
64
65
|
readonly StrictLogical: bigint;
|
|
65
66
|
readonly StrictConditional: bigint;
|
|
66
67
|
};
|
|
67
|
-
declare const
|
|
68
|
+
declare const DEFAULT_JSX_DETECTION_HINT: bigint;
|
|
69
|
+
|
|
68
70
|
/**
|
|
69
|
-
* Heuristic decision to determine if a node is a JSX
|
|
71
|
+
* Heuristic decision to determine if a node is a JSX-like node.
|
|
70
72
|
* @param node The AST node to check
|
|
71
73
|
* @param jsxCtx The requirements for the check
|
|
72
74
|
* @param jsxCtx.getScope The function to get the scope of a node
|
|
73
|
-
* @param hint The `
|
|
75
|
+
* @param hint The `JSXDetectionHint` to use
|
|
74
76
|
* @returns boolean
|
|
75
77
|
*/
|
|
76
|
-
declare function
|
|
78
|
+
declare function isJSXLike(node: TSESTree$1.Node | _ | null, jsxCtx: {
|
|
77
79
|
getScope: (node: TSESTree$1.Node) => Scope;
|
|
78
|
-
}, hint?:
|
|
80
|
+
}, hint?: JSXDetectionHint): boolean;
|
|
79
81
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
*/
|
|
85
|
-
declare function isFragmentElement(node: TSESTree.Node): boolean;
|
|
86
|
-
/**
|
|
87
|
-
* Check if a node has a `key` prop
|
|
88
|
-
* @param node The AST node to check
|
|
89
|
-
* @param initialScope The initial scope to start searching for the `key` attribute
|
|
90
|
-
* @returns `true` if the node is a `JSXElement` of `Keyed Component` type
|
|
91
|
-
*/
|
|
92
|
-
declare function isKeyedElement(node: TSESTree.Node, initialScope?: Scope): boolean;
|
|
93
|
-
/**
|
|
94
|
-
* Check if a node is a `JSXFragment` of `Built-in Component` type
|
|
95
|
-
* @param node The AST node to check
|
|
96
|
-
* @returns `true` if the node is a `JSXFragment` of `Built-in Component` type
|
|
97
|
-
*/
|
|
98
|
-
declare function isBuiltInElement(node: TSESTree.Node): boolean;
|
|
99
|
-
/**
|
|
100
|
-
* Check if a node is a `JSXElement` of `User-Defined Component` type
|
|
101
|
-
* @param node The AST node to check
|
|
102
|
-
* @returns `true` if the node is a `JSXElement` of `User-Defined Component` type
|
|
103
|
-
*/
|
|
104
|
-
declare function isUserDefinedElement(node: TSESTree.Node): boolean;
|
|
82
|
+
declare function isJsxFragmentElement(node: TSESTree.Node): boolean;
|
|
83
|
+
declare function isJsxKeyedElement(node: TSESTree.Node, initialScope?: Scope): boolean;
|
|
84
|
+
declare function isJsxBuiltInElement(node: TSESTree.Node): boolean;
|
|
85
|
+
declare function isJsxUserDefinedElement(node: TSESTree.Node): boolean;
|
|
105
86
|
|
|
106
87
|
/**
|
|
107
|
-
* Check if a node is a
|
|
108
|
-
* @param node The AST node to check
|
|
109
|
-
* @returns boolean `true` if the node is a Literal or JSXText
|
|
110
|
-
*/
|
|
111
|
-
declare const isLiteral: (node: TSESTree.Node | null | undefined) => node is TSESTree.JSXText | TSESTree.BigIntLiteral | TSESTree.BooleanLiteral | TSESTree.NullLiteral | TSESTree.NumberLiteral | TSESTree.RegExpLiteral | TSESTree.StringLiteral;
|
|
112
|
-
/**
|
|
113
|
-
* Check if a Literal or JSXText node is whitespace
|
|
88
|
+
* Check if a node is a `JSXFragment` or a `Fragment` element
|
|
114
89
|
* @param node The AST node to check
|
|
115
|
-
* @returns
|
|
90
|
+
* @returns `true` if the node is a `JSXFragment` or a `Fragment` element
|
|
116
91
|
*/
|
|
117
|
-
declare function
|
|
118
|
-
|
|
119
|
-
* Check if a Literal or JSXText node is a line break
|
|
120
|
-
* @param node The AST node to check
|
|
121
|
-
* @returns boolean
|
|
122
|
-
*/
|
|
123
|
-
declare function isLineBreak(node: TSESTree.Node): boolean;
|
|
92
|
+
declare function isJsxFragment(node: TSESTree.Node | null | _): boolean;
|
|
93
|
+
|
|
124
94
|
/**
|
|
125
|
-
* Check if a
|
|
95
|
+
* Check if a node is a `JSXText` or a `Literal` node
|
|
126
96
|
* @param node The AST node to check
|
|
127
|
-
* @returns
|
|
97
|
+
* @returns `true` if the node is a `JSXText` or a `Literal` node
|
|
128
98
|
*/
|
|
129
|
-
declare function
|
|
99
|
+
declare function isJsxText(node: TSESTree.Node | null | _): node is TSESTree.JSXText | TSESTree.Literal;
|
|
130
100
|
|
|
131
101
|
/**
|
|
132
102
|
* Get the stringified representation of a JSX node
|
|
@@ -135,4 +105,4 @@ declare function isPaddingSpaces(node: TSESTree.Node): boolean;
|
|
|
135
105
|
*/
|
|
136
106
|
declare function toString(node: TSESTree$1.JSXIdentifier | TSESTree$1.JSXMemberExpression | TSESTree$1.JSXNamespacedName | TSESTree$1.JSXOpeningElement | TSESTree$1.JSXClosingElement | TSESTree$1.JSXOpeningFragment | TSESTree$1.JSXClosingFragment | TSESTree$1.JSXText): string;
|
|
137
107
|
|
|
138
|
-
export {
|
|
108
|
+
export { DEFAULT_JSX_DETECTION_HINT, JSXDetectionHint, findParentAttribute, getAttribute, getAttributeName, getAttributeValue, getElementType, hasAnyAttribute, hasAttribute, hasEveryAttribute, isJSXLike, isJsxBuiltInElement, isJsxFragment, isJsxFragmentElement, isJsxKeyedElement, isJsxText, isJsxUserDefinedElement, toString };
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var AST = require('@eslint-react/ast');
|
|
4
4
|
var eff = require('@eslint-react/eff');
|
|
5
5
|
var types = require('@typescript-eslint/types');
|
|
6
6
|
var VAR = require('@eslint-react/var');
|
|
@@ -24,7 +24,7 @@ function _interopNamespace(e) {
|
|
|
24
24
|
return Object.freeze(n);
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
var
|
|
27
|
+
var AST__namespace = /*#__PURE__*/_interopNamespace(AST);
|
|
28
28
|
var VAR__namespace = /*#__PURE__*/_interopNamespace(VAR);
|
|
29
29
|
|
|
30
30
|
// src/find-parent-attribute.ts
|
|
@@ -32,7 +32,7 @@ function findParentAttribute(node, test = eff.constTrue) {
|
|
|
32
32
|
const guard = (node2) => {
|
|
33
33
|
return node2.type === types.AST_NODE_TYPES.JSXAttribute && test(node2);
|
|
34
34
|
};
|
|
35
|
-
return
|
|
35
|
+
return AST__namespace.findParentNode(node, guard);
|
|
36
36
|
}
|
|
37
37
|
function toString(node) {
|
|
38
38
|
switch (node.type) {
|
|
@@ -138,7 +138,9 @@ function hasAnyAttribute(names, attributes, initialScope) {
|
|
|
138
138
|
function hasEveryAttribute(names, attributes, initialScope) {
|
|
139
139
|
return names.every((n) => hasAttribute(n, attributes, initialScope));
|
|
140
140
|
}
|
|
141
|
-
|
|
141
|
+
|
|
142
|
+
// src/jsx-detection-hint.ts
|
|
143
|
+
var JSXDetectionHint = {
|
|
142
144
|
None: 0n,
|
|
143
145
|
SkipUndefined: 1n << 0n,
|
|
144
146
|
SkipNullLiteral: 1n << 1n,
|
|
@@ -152,72 +154,85 @@ var JSXValueHint = {
|
|
|
152
154
|
StrictLogical: 1n << 9n,
|
|
153
155
|
StrictConditional: 1n << 10n
|
|
154
156
|
};
|
|
155
|
-
var
|
|
156
|
-
|
|
157
|
+
var DEFAULT_JSX_DETECTION_HINT = 0n | JSXDetectionHint.SkipUndefined | JSXDetectionHint.SkipBooleanLiteral;
|
|
158
|
+
|
|
159
|
+
// src/is-jsx.ts
|
|
160
|
+
function isJSXLike(node, jsxCtx, hint = DEFAULT_JSX_DETECTION_HINT) {
|
|
157
161
|
switch (node?.type) {
|
|
162
|
+
case types.AST_NODE_TYPES.JSXText:
|
|
158
163
|
case types.AST_NODE_TYPES.JSXElement:
|
|
159
164
|
case types.AST_NODE_TYPES.JSXFragment:
|
|
165
|
+
case types.AST_NODE_TYPES.JSXAttribute:
|
|
166
|
+
case types.AST_NODE_TYPES.JSXClosingElement:
|
|
167
|
+
case types.AST_NODE_TYPES.JSXClosingFragment:
|
|
168
|
+
case types.AST_NODE_TYPES.JSXEmptyExpression:
|
|
169
|
+
case types.AST_NODE_TYPES.JSXExpressionContainer:
|
|
170
|
+
case types.AST_NODE_TYPES.JSXIdentifier:
|
|
160
171
|
case types.AST_NODE_TYPES.JSXMemberExpression:
|
|
172
|
+
case types.AST_NODE_TYPES.JSXOpeningElement:
|
|
173
|
+
case types.AST_NODE_TYPES.JSXOpeningFragment:
|
|
174
|
+
case types.AST_NODE_TYPES.JSXSpreadAttribute:
|
|
175
|
+
case types.AST_NODE_TYPES.JSXSpreadChild:
|
|
161
176
|
case types.AST_NODE_TYPES.JSXNamespacedName: {
|
|
162
177
|
return true;
|
|
163
178
|
}
|
|
164
179
|
case types.AST_NODE_TYPES.Literal: {
|
|
165
180
|
switch (typeof node.value) {
|
|
166
181
|
case "boolean":
|
|
167
|
-
return !(hint &
|
|
182
|
+
return !(hint & JSXDetectionHint.SkipBooleanLiteral);
|
|
168
183
|
case "string":
|
|
169
|
-
return !(hint &
|
|
184
|
+
return !(hint & JSXDetectionHint.SkipStringLiteral);
|
|
170
185
|
case "number":
|
|
171
|
-
return !(hint &
|
|
186
|
+
return !(hint & JSXDetectionHint.SkipNumberLiteral);
|
|
172
187
|
case "bigint":
|
|
173
|
-
return !(hint &
|
|
188
|
+
return !(hint & JSXDetectionHint.SkipBigIntLiteral);
|
|
174
189
|
}
|
|
175
190
|
if (node.value == null) {
|
|
176
|
-
return !(hint &
|
|
191
|
+
return !(hint & JSXDetectionHint.SkipNullLiteral);
|
|
177
192
|
}
|
|
178
193
|
return false;
|
|
179
194
|
}
|
|
180
195
|
case types.AST_NODE_TYPES.TemplateLiteral: {
|
|
181
|
-
return !(hint &
|
|
196
|
+
return !(hint & JSXDetectionHint.SkipStringLiteral);
|
|
182
197
|
}
|
|
183
198
|
case types.AST_NODE_TYPES.ArrayExpression: {
|
|
184
|
-
if (hint &
|
|
185
|
-
return node.elements.every((n) =>
|
|
199
|
+
if (hint & JSXDetectionHint.StrictArray) {
|
|
200
|
+
return node.elements.every((n) => isJSXLike(n, jsxCtx, hint));
|
|
186
201
|
}
|
|
187
|
-
return node.elements.some((n) =>
|
|
202
|
+
return node.elements.some((n) => isJSXLike(n, jsxCtx, hint));
|
|
188
203
|
}
|
|
189
204
|
case types.AST_NODE_TYPES.LogicalExpression: {
|
|
190
|
-
if (hint &
|
|
191
|
-
return
|
|
205
|
+
if (hint & JSXDetectionHint.StrictLogical) {
|
|
206
|
+
return isJSXLike(node.left, jsxCtx, hint) && isJSXLike(node.right, jsxCtx, hint);
|
|
192
207
|
}
|
|
193
|
-
return
|
|
208
|
+
return isJSXLike(node.left, jsxCtx, hint) || isJSXLike(node.right, jsxCtx, hint);
|
|
194
209
|
}
|
|
195
210
|
case types.AST_NODE_TYPES.ConditionalExpression: {
|
|
196
211
|
let leftHasJSX2 = function(node2) {
|
|
197
212
|
if (Array.isArray(node2.consequent)) {
|
|
198
213
|
if (node2.consequent.length === 0) {
|
|
199
|
-
return !(hint &
|
|
214
|
+
return !(hint & JSXDetectionHint.SkipEmptyArray);
|
|
200
215
|
}
|
|
201
|
-
if (hint &
|
|
202
|
-
return node2.consequent.every((n) =>
|
|
216
|
+
if (hint & JSXDetectionHint.StrictArray) {
|
|
217
|
+
return node2.consequent.every((n) => isJSXLike(n, jsxCtx, hint));
|
|
203
218
|
}
|
|
204
|
-
return node2.consequent.some((n) =>
|
|
219
|
+
return node2.consequent.some((n) => isJSXLike(n, jsxCtx, hint));
|
|
205
220
|
}
|
|
206
|
-
return
|
|
221
|
+
return isJSXLike(node2.consequent, jsxCtx, hint);
|
|
207
222
|
}, rightHasJSX2 = function(node2) {
|
|
208
|
-
return
|
|
223
|
+
return isJSXLike(node2.alternate, jsxCtx, hint);
|
|
209
224
|
};
|
|
210
|
-
if (hint &
|
|
225
|
+
if (hint & JSXDetectionHint.StrictConditional) {
|
|
211
226
|
return leftHasJSX2(node) && rightHasJSX2(node);
|
|
212
227
|
}
|
|
213
228
|
return leftHasJSX2(node) || rightHasJSX2(node);
|
|
214
229
|
}
|
|
215
230
|
case types.AST_NODE_TYPES.SequenceExpression: {
|
|
216
231
|
const exp = node.expressions.at(-1);
|
|
217
|
-
return
|
|
232
|
+
return isJSXLike(exp, jsxCtx, hint);
|
|
218
233
|
}
|
|
219
234
|
case types.AST_NODE_TYPES.CallExpression: {
|
|
220
|
-
if (hint &
|
|
235
|
+
if (hint & JSXDetectionHint.SkipCreateElement) {
|
|
221
236
|
return false;
|
|
222
237
|
}
|
|
223
238
|
switch (node.callee.type) {
|
|
@@ -231,44 +246,42 @@ function isJSXValue(node, jsxCtx, hint = DEFAULT_JSX_VALUE_HINT) {
|
|
|
231
246
|
case types.AST_NODE_TYPES.Identifier: {
|
|
232
247
|
const { name } = node;
|
|
233
248
|
if (name === "undefined") {
|
|
234
|
-
return !(hint &
|
|
249
|
+
return !(hint & JSXDetectionHint.SkipUndefined);
|
|
235
250
|
}
|
|
236
|
-
if (
|
|
251
|
+
if (AST__namespace.isJSXTagNameExpression(node)) {
|
|
237
252
|
return true;
|
|
238
253
|
}
|
|
239
254
|
const variable = VAR__namespace.findVariable(name, jsxCtx.getScope(node));
|
|
240
255
|
const variableNode = variable && VAR__namespace.getVariableInitNode(variable, 0);
|
|
241
|
-
return !!variableNode &&
|
|
256
|
+
return !!variableNode && isJSXLike(variableNode, jsxCtx, hint);
|
|
242
257
|
}
|
|
243
258
|
}
|
|
244
259
|
return false;
|
|
245
260
|
}
|
|
246
|
-
function
|
|
261
|
+
function isJsxFragmentElement(node) {
|
|
247
262
|
if (node.type !== types.AST_NODE_TYPES.JSXElement) return false;
|
|
248
263
|
return getElementType(node).split(".").at(-1) === "Fragment";
|
|
249
264
|
}
|
|
250
|
-
function
|
|
265
|
+
function isJsxKeyedElement(node, initialScope) {
|
|
251
266
|
return node.type === types.AST_NODE_TYPES.JSXElement && hasAttribute("key", node.openingElement.attributes, initialScope);
|
|
252
267
|
}
|
|
253
|
-
function
|
|
254
|
-
return node.type === types.AST_NODE_TYPES.JSXElement && node.openingElement.name.type === types.AST_NODE_TYPES.JSXIdentifier &&
|
|
268
|
+
function isJsxBuiltInElement(node) {
|
|
269
|
+
return node.type === types.AST_NODE_TYPES.JSXElement && node.openingElement.name.type === types.AST_NODE_TYPES.JSXIdentifier && /^[a-z]/u.test(node.openingElement.name.name);
|
|
255
270
|
}
|
|
256
|
-
function
|
|
271
|
+
function isJsxUserDefinedElement(node) {
|
|
257
272
|
return node.type === types.AST_NODE_TYPES.JSXElement && node.openingElement.name.type === types.AST_NODE_TYPES.JSXIdentifier && /^[A-Z]/u.test(node.openingElement.name.name);
|
|
258
273
|
}
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
return
|
|
262
|
-
}
|
|
263
|
-
function isLineBreak(node) {
|
|
264
|
-
return isLiteral(node) && isWhiteSpace(node) && AST3__namespace.isMultiLine(node);
|
|
274
|
+
function isJsxFragment(node) {
|
|
275
|
+
if (node == null) return false;
|
|
276
|
+
return node.type === types.AST_NODE_TYPES.JSXFragment || isJsxFragmentElement(node);
|
|
265
277
|
}
|
|
266
|
-
function
|
|
267
|
-
|
|
278
|
+
function isJsxText(node) {
|
|
279
|
+
if (node == null) return false;
|
|
280
|
+
return node.type === types.AST_NODE_TYPES.JSXText || node.type === types.AST_NODE_TYPES.Literal;
|
|
268
281
|
}
|
|
269
282
|
|
|
270
|
-
exports.
|
|
271
|
-
exports.
|
|
283
|
+
exports.DEFAULT_JSX_DETECTION_HINT = DEFAULT_JSX_DETECTION_HINT;
|
|
284
|
+
exports.JSXDetectionHint = JSXDetectionHint;
|
|
272
285
|
exports.findParentAttribute = findParentAttribute;
|
|
273
286
|
exports.getAttribute = getAttribute;
|
|
274
287
|
exports.getAttributeName = getAttributeName;
|
|
@@ -277,13 +290,11 @@ exports.getElementType = getElementType;
|
|
|
277
290
|
exports.hasAnyAttribute = hasAnyAttribute;
|
|
278
291
|
exports.hasAttribute = hasAttribute;
|
|
279
292
|
exports.hasEveryAttribute = hasEveryAttribute;
|
|
280
|
-
exports.
|
|
281
|
-
exports.
|
|
282
|
-
exports.
|
|
283
|
-
exports.
|
|
284
|
-
exports.
|
|
285
|
-
exports.
|
|
286
|
-
exports.
|
|
287
|
-
exports.isUserDefinedElement = isUserDefinedElement;
|
|
288
|
-
exports.isWhiteSpace = isWhiteSpace;
|
|
293
|
+
exports.isJSXLike = isJSXLike;
|
|
294
|
+
exports.isJsxBuiltInElement = isJsxBuiltInElement;
|
|
295
|
+
exports.isJsxFragment = isJsxFragment;
|
|
296
|
+
exports.isJsxFragmentElement = isJsxFragmentElement;
|
|
297
|
+
exports.isJsxKeyedElement = isJsxKeyedElement;
|
|
298
|
+
exports.isJsxText = isJsxText;
|
|
299
|
+
exports.isJsxUserDefinedElement = isJsxUserDefinedElement;
|
|
289
300
|
exports.toString = toString;
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as AST from '@eslint-react/ast';
|
|
2
2
|
import { constTrue } from '@eslint-react/eff';
|
|
3
3
|
import { AST_NODE_TYPES } from '@typescript-eslint/types';
|
|
4
4
|
import * as VAR from '@eslint-react/var';
|
|
@@ -9,7 +9,7 @@ function findParentAttribute(node, test = constTrue) {
|
|
|
9
9
|
const guard = (node2) => {
|
|
10
10
|
return node2.type === AST_NODE_TYPES.JSXAttribute && test(node2);
|
|
11
11
|
};
|
|
12
|
-
return
|
|
12
|
+
return AST.findParentNode(node, guard);
|
|
13
13
|
}
|
|
14
14
|
function toString(node) {
|
|
15
15
|
switch (node.type) {
|
|
@@ -115,7 +115,9 @@ function hasAnyAttribute(names, attributes, initialScope) {
|
|
|
115
115
|
function hasEveryAttribute(names, attributes, initialScope) {
|
|
116
116
|
return names.every((n) => hasAttribute(n, attributes, initialScope));
|
|
117
117
|
}
|
|
118
|
-
|
|
118
|
+
|
|
119
|
+
// src/jsx-detection-hint.ts
|
|
120
|
+
var JSXDetectionHint = {
|
|
119
121
|
None: 0n,
|
|
120
122
|
SkipUndefined: 1n << 0n,
|
|
121
123
|
SkipNullLiteral: 1n << 1n,
|
|
@@ -129,72 +131,85 @@ var JSXValueHint = {
|
|
|
129
131
|
StrictLogical: 1n << 9n,
|
|
130
132
|
StrictConditional: 1n << 10n
|
|
131
133
|
};
|
|
132
|
-
var
|
|
133
|
-
|
|
134
|
+
var DEFAULT_JSX_DETECTION_HINT = 0n | JSXDetectionHint.SkipUndefined | JSXDetectionHint.SkipBooleanLiteral;
|
|
135
|
+
|
|
136
|
+
// src/is-jsx.ts
|
|
137
|
+
function isJSXLike(node, jsxCtx, hint = DEFAULT_JSX_DETECTION_HINT) {
|
|
134
138
|
switch (node?.type) {
|
|
139
|
+
case AST_NODE_TYPES.JSXText:
|
|
135
140
|
case AST_NODE_TYPES.JSXElement:
|
|
136
141
|
case AST_NODE_TYPES.JSXFragment:
|
|
142
|
+
case AST_NODE_TYPES.JSXAttribute:
|
|
143
|
+
case AST_NODE_TYPES.JSXClosingElement:
|
|
144
|
+
case AST_NODE_TYPES.JSXClosingFragment:
|
|
145
|
+
case AST_NODE_TYPES.JSXEmptyExpression:
|
|
146
|
+
case AST_NODE_TYPES.JSXExpressionContainer:
|
|
147
|
+
case AST_NODE_TYPES.JSXIdentifier:
|
|
137
148
|
case AST_NODE_TYPES.JSXMemberExpression:
|
|
149
|
+
case AST_NODE_TYPES.JSXOpeningElement:
|
|
150
|
+
case AST_NODE_TYPES.JSXOpeningFragment:
|
|
151
|
+
case AST_NODE_TYPES.JSXSpreadAttribute:
|
|
152
|
+
case AST_NODE_TYPES.JSXSpreadChild:
|
|
138
153
|
case AST_NODE_TYPES.JSXNamespacedName: {
|
|
139
154
|
return true;
|
|
140
155
|
}
|
|
141
156
|
case AST_NODE_TYPES.Literal: {
|
|
142
157
|
switch (typeof node.value) {
|
|
143
158
|
case "boolean":
|
|
144
|
-
return !(hint &
|
|
159
|
+
return !(hint & JSXDetectionHint.SkipBooleanLiteral);
|
|
145
160
|
case "string":
|
|
146
|
-
return !(hint &
|
|
161
|
+
return !(hint & JSXDetectionHint.SkipStringLiteral);
|
|
147
162
|
case "number":
|
|
148
|
-
return !(hint &
|
|
163
|
+
return !(hint & JSXDetectionHint.SkipNumberLiteral);
|
|
149
164
|
case "bigint":
|
|
150
|
-
return !(hint &
|
|
165
|
+
return !(hint & JSXDetectionHint.SkipBigIntLiteral);
|
|
151
166
|
}
|
|
152
167
|
if (node.value == null) {
|
|
153
|
-
return !(hint &
|
|
168
|
+
return !(hint & JSXDetectionHint.SkipNullLiteral);
|
|
154
169
|
}
|
|
155
170
|
return false;
|
|
156
171
|
}
|
|
157
172
|
case AST_NODE_TYPES.TemplateLiteral: {
|
|
158
|
-
return !(hint &
|
|
173
|
+
return !(hint & JSXDetectionHint.SkipStringLiteral);
|
|
159
174
|
}
|
|
160
175
|
case AST_NODE_TYPES.ArrayExpression: {
|
|
161
|
-
if (hint &
|
|
162
|
-
return node.elements.every((n) =>
|
|
176
|
+
if (hint & JSXDetectionHint.StrictArray) {
|
|
177
|
+
return node.elements.every((n) => isJSXLike(n, jsxCtx, hint));
|
|
163
178
|
}
|
|
164
|
-
return node.elements.some((n) =>
|
|
179
|
+
return node.elements.some((n) => isJSXLike(n, jsxCtx, hint));
|
|
165
180
|
}
|
|
166
181
|
case AST_NODE_TYPES.LogicalExpression: {
|
|
167
|
-
if (hint &
|
|
168
|
-
return
|
|
182
|
+
if (hint & JSXDetectionHint.StrictLogical) {
|
|
183
|
+
return isJSXLike(node.left, jsxCtx, hint) && isJSXLike(node.right, jsxCtx, hint);
|
|
169
184
|
}
|
|
170
|
-
return
|
|
185
|
+
return isJSXLike(node.left, jsxCtx, hint) || isJSXLike(node.right, jsxCtx, hint);
|
|
171
186
|
}
|
|
172
187
|
case AST_NODE_TYPES.ConditionalExpression: {
|
|
173
188
|
let leftHasJSX2 = function(node2) {
|
|
174
189
|
if (Array.isArray(node2.consequent)) {
|
|
175
190
|
if (node2.consequent.length === 0) {
|
|
176
|
-
return !(hint &
|
|
191
|
+
return !(hint & JSXDetectionHint.SkipEmptyArray);
|
|
177
192
|
}
|
|
178
|
-
if (hint &
|
|
179
|
-
return node2.consequent.every((n) =>
|
|
193
|
+
if (hint & JSXDetectionHint.StrictArray) {
|
|
194
|
+
return node2.consequent.every((n) => isJSXLike(n, jsxCtx, hint));
|
|
180
195
|
}
|
|
181
|
-
return node2.consequent.some((n) =>
|
|
196
|
+
return node2.consequent.some((n) => isJSXLike(n, jsxCtx, hint));
|
|
182
197
|
}
|
|
183
|
-
return
|
|
198
|
+
return isJSXLike(node2.consequent, jsxCtx, hint);
|
|
184
199
|
}, rightHasJSX2 = function(node2) {
|
|
185
|
-
return
|
|
200
|
+
return isJSXLike(node2.alternate, jsxCtx, hint);
|
|
186
201
|
};
|
|
187
|
-
if (hint &
|
|
202
|
+
if (hint & JSXDetectionHint.StrictConditional) {
|
|
188
203
|
return leftHasJSX2(node) && rightHasJSX2(node);
|
|
189
204
|
}
|
|
190
205
|
return leftHasJSX2(node) || rightHasJSX2(node);
|
|
191
206
|
}
|
|
192
207
|
case AST_NODE_TYPES.SequenceExpression: {
|
|
193
208
|
const exp = node.expressions.at(-1);
|
|
194
|
-
return
|
|
209
|
+
return isJSXLike(exp, jsxCtx, hint);
|
|
195
210
|
}
|
|
196
211
|
case AST_NODE_TYPES.CallExpression: {
|
|
197
|
-
if (hint &
|
|
212
|
+
if (hint & JSXDetectionHint.SkipCreateElement) {
|
|
198
213
|
return false;
|
|
199
214
|
}
|
|
200
215
|
switch (node.callee.type) {
|
|
@@ -208,40 +223,38 @@ function isJSXValue(node, jsxCtx, hint = DEFAULT_JSX_VALUE_HINT) {
|
|
|
208
223
|
case AST_NODE_TYPES.Identifier: {
|
|
209
224
|
const { name } = node;
|
|
210
225
|
if (name === "undefined") {
|
|
211
|
-
return !(hint &
|
|
226
|
+
return !(hint & JSXDetectionHint.SkipUndefined);
|
|
212
227
|
}
|
|
213
|
-
if (
|
|
228
|
+
if (AST.isJSXTagNameExpression(node)) {
|
|
214
229
|
return true;
|
|
215
230
|
}
|
|
216
231
|
const variable = VAR.findVariable(name, jsxCtx.getScope(node));
|
|
217
232
|
const variableNode = variable && VAR.getVariableInitNode(variable, 0);
|
|
218
|
-
return !!variableNode &&
|
|
233
|
+
return !!variableNode && isJSXLike(variableNode, jsxCtx, hint);
|
|
219
234
|
}
|
|
220
235
|
}
|
|
221
236
|
return false;
|
|
222
237
|
}
|
|
223
|
-
function
|
|
238
|
+
function isJsxFragmentElement(node) {
|
|
224
239
|
if (node.type !== AST_NODE_TYPES.JSXElement) return false;
|
|
225
240
|
return getElementType(node).split(".").at(-1) === "Fragment";
|
|
226
241
|
}
|
|
227
|
-
function
|
|
242
|
+
function isJsxKeyedElement(node, initialScope) {
|
|
228
243
|
return node.type === AST_NODE_TYPES.JSXElement && hasAttribute("key", node.openingElement.attributes, initialScope);
|
|
229
244
|
}
|
|
230
|
-
function
|
|
231
|
-
return node.type === AST_NODE_TYPES.JSXElement && node.openingElement.name.type === AST_NODE_TYPES.JSXIdentifier &&
|
|
245
|
+
function isJsxBuiltInElement(node) {
|
|
246
|
+
return node.type === AST_NODE_TYPES.JSXElement && node.openingElement.name.type === AST_NODE_TYPES.JSXIdentifier && /^[a-z]/u.test(node.openingElement.name.name);
|
|
232
247
|
}
|
|
233
|
-
function
|
|
248
|
+
function isJsxUserDefinedElement(node) {
|
|
234
249
|
return node.type === AST_NODE_TYPES.JSXElement && node.openingElement.name.type === AST_NODE_TYPES.JSXIdentifier && /^[A-Z]/u.test(node.openingElement.name.name);
|
|
235
250
|
}
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
return
|
|
239
|
-
}
|
|
240
|
-
function isLineBreak(node) {
|
|
241
|
-
return isLiteral(node) && isWhiteSpace(node) && AST3.isMultiLine(node);
|
|
251
|
+
function isJsxFragment(node) {
|
|
252
|
+
if (node == null) return false;
|
|
253
|
+
return node.type === AST_NODE_TYPES.JSXFragment || isJsxFragmentElement(node);
|
|
242
254
|
}
|
|
243
|
-
function
|
|
244
|
-
|
|
255
|
+
function isJsxText(node) {
|
|
256
|
+
if (node == null) return false;
|
|
257
|
+
return node.type === AST_NODE_TYPES.JSXText || node.type === AST_NODE_TYPES.Literal;
|
|
245
258
|
}
|
|
246
259
|
|
|
247
|
-
export {
|
|
260
|
+
export { DEFAULT_JSX_DETECTION_HINT, JSXDetectionHint, findParentAttribute, getAttribute, getAttributeName, getAttributeValue, getElementType, hasAnyAttribute, hasAttribute, hasEveryAttribute, isJSXLike, isJsxBuiltInElement, isJsxFragment, isJsxFragmentElement, isJsxKeyedElement, isJsxText, isJsxUserDefinedElement, toString };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eslint-react/jsx",
|
|
3
|
-
"version": "1.40.
|
|
3
|
+
"version": "1.40.3-beta.1",
|
|
4
4
|
"description": "ESLint React's TSESTree AST utility module for static analysis of JSX.",
|
|
5
5
|
"homepage": "https://github.com/Rel1cx/eslint-react",
|
|
6
6
|
"bugs": {
|
|
@@ -39,9 +39,9 @@
|
|
|
39
39
|
"@typescript-eslint/types": "^8.29.0",
|
|
40
40
|
"@typescript-eslint/utils": "^8.29.0",
|
|
41
41
|
"ts-pattern": "^5.7.0",
|
|
42
|
-
"@eslint-react/
|
|
43
|
-
"@eslint-react/
|
|
44
|
-
"@eslint-react/var": "1.40.
|
|
42
|
+
"@eslint-react/eff": "1.40.3-beta.1",
|
|
43
|
+
"@eslint-react/ast": "1.40.3-beta.1",
|
|
44
|
+
"@eslint-react/var": "1.40.3-beta.1"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"tsup": "^8.4.0",
|