@eslint-react/jsx 5.8.17 → 5.8.19
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.ts +146 -382
- package/dist/index.js +144 -353
- package/package.json +6 -6
package/dist/index.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { RuleContext } from "@eslint-react/eslint";
|
|
|
4
4
|
|
|
5
5
|
//#region src/collapse-multiline-text.d.ts
|
|
6
6
|
/**
|
|
7
|
-
* Collapse a multiline JSX text string following React's whitespace rules
|
|
7
|
+
* Collapse a multiline JSX text string following React's whitespace rules
|
|
8
8
|
*
|
|
9
9
|
* This mirrors Babel's `cleanJSXElementLiteralChild` algorithm:
|
|
10
10
|
* 1. Split the raw text into lines.
|
|
@@ -12,185 +12,119 @@ import { RuleContext } from "@eslint-react/eslint";
|
|
|
12
12
|
* 3. Trim leading spaces on non-first lines and trailing spaces on non-last lines.
|
|
13
13
|
* 4. Collapse tabs into spaces.
|
|
14
14
|
* 5. Append a single space after each non-last non-empty line.
|
|
15
|
-
*
|
|
16
|
-
* @
|
|
17
|
-
* @returns The collapsed string, or `null` if the text contains only whitespace.
|
|
18
|
-
*
|
|
15
|
+
* @param text The raw JSX text string to collapse
|
|
16
|
+
* @returns The collapsed string, or `null` if the text contains only whitespace
|
|
19
17
|
* @see https://github.com/babel/babel/blob/main/packages/babel-types/src/utils/react/cleanJSXElementLiteralChild.ts
|
|
20
18
|
*/
|
|
21
19
|
declare function collapseMultilineText(text: string): string | null;
|
|
22
20
|
//#endregion
|
|
23
21
|
//#region src/find-attribute.d.ts
|
|
24
22
|
/**
|
|
25
|
-
* Find a JSX attribute (or spread attribute containing the property) by name
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
* @
|
|
36
|
-
* spread attributes).
|
|
37
|
-
* @param element - The `JSXElement` node to search.
|
|
38
|
-
* @param name - The attribute name to look for (e.g. `"className"`).
|
|
39
|
-
* @returns The matching `JSXAttribute` or `JSXSpreadAttribute`, or
|
|
40
|
-
* `undefined` when not found.
|
|
41
|
-
*
|
|
42
|
-
* @example
|
|
43
|
-
* ```ts
|
|
44
|
-
* const attr = findAttribute(context, node, "sandbox");
|
|
45
|
-
* if (attr != null) {
|
|
46
|
-
* // attribute (or spread containing it) exists on the element
|
|
47
|
-
* }
|
|
48
|
-
* ```
|
|
23
|
+
* Find a JSX attribute (or spread attribute containing the property) by name on a given element
|
|
24
|
+
*
|
|
25
|
+
* Returns the last matching attribute to mirror React's behavior where later props win,
|
|
26
|
+
* or `undefined` when the attribute is not present.
|
|
27
|
+
*
|
|
28
|
+
* Spread attributes are resolved when possible: if the spread argument is an identifier
|
|
29
|
+
* that resolves to an object expression, the object's properties are searched for a matching key.
|
|
30
|
+
* @param context The ESLint rule context (needed for variable resolution in spread attributes)
|
|
31
|
+
* @param element The `JSXElement` node to search
|
|
32
|
+
* @param name The attribute name to look for (ex: "className")
|
|
33
|
+
* @returns The matching `JSXAttribute` or `JSXSpreadAttribute`, or `undefined` when not found
|
|
49
34
|
*/
|
|
50
35
|
declare function findAttribute(context: RuleContext, element: TSESTree.JSXElement, name: string): TSESTreeJSXAttributeLike | undefined;
|
|
51
36
|
//#endregion
|
|
52
37
|
//#region src/find-parent-attribute.d.ts
|
|
53
38
|
/**
|
|
54
|
-
* Walk
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
* This is useful when a rule visitor enters a deeply
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
* @
|
|
62
|
-
* @param test - Optional predicate to filter candidate `JSXAttribute` nodes.
|
|
63
|
-
* When omitted every `JSXAttribute` ancestor matches.
|
|
64
|
-
* @returns The first matching `JSXAttribute` ancestor, or `null` if none is
|
|
65
|
-
* found before reaching the root.
|
|
66
|
-
*
|
|
67
|
-
* @example
|
|
68
|
-
* ```ts
|
|
69
|
-
* // Inside a Literal visitor, find the owning attribute:
|
|
70
|
-
* const attr = findParentAttribute(literalNode);
|
|
71
|
-
* if (attr != null) {
|
|
72
|
-
* console.log(getAttributeName(attr));
|
|
73
|
-
* }
|
|
74
|
-
* ```
|
|
39
|
+
* Walk up the AST from `node` to find the nearest ancestor that is a `JSXAttribute`
|
|
40
|
+
* and (optionally) passes a predicate
|
|
41
|
+
*
|
|
42
|
+
* This is useful when a rule visitor enters a deeply nested node (ex: a `Literal`
|
|
43
|
+
* inside an expression container) and needs to know which JSX attribute it belongs to.
|
|
44
|
+
* @param node The starting node for the upward search
|
|
45
|
+
* @param test Optional predicate to filter candidate `JSXAttribute` nodes. When omitted every `JSXAttribute` ancestor matches
|
|
46
|
+
* @returns The first matching `JSXAttribute` ancestor, or `null` if none is found before reaching the root
|
|
75
47
|
*/
|
|
76
48
|
declare function findParentAttribute(node: TSESTree.Node, test?: (node: TSESTree.JSXAttribute) => boolean): TSESTree.JSXAttribute | null;
|
|
77
49
|
//#endregion
|
|
78
50
|
//#region src/get-attribute-name.d.ts
|
|
79
51
|
/**
|
|
80
|
-
* Get the stringified name of a `JSXAttribute` node
|
|
52
|
+
* Get the stringified name of a `JSXAttribute` node
|
|
81
53
|
*
|
|
82
54
|
* Handles both simple identifiers and namespaced names:
|
|
83
|
-
*
|
|
84
|
-
* - `
|
|
85
|
-
* - `
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
* @param node - A `JSXAttribute` AST node.
|
|
89
|
-
* @returns The attribute name as a plain string.
|
|
90
|
-
*
|
|
91
|
-
* @example
|
|
92
|
-
* ```ts
|
|
93
|
-
* import { getAttributeName } from "@eslint-react/jsx";
|
|
94
|
-
*
|
|
95
|
-
* // Inside a rule visitor:
|
|
96
|
-
* JSXAttribute(node) {
|
|
97
|
-
* const name = getAttributeName(node); // "className"
|
|
98
|
-
* }
|
|
99
|
-
* ```
|
|
55
|
+
* - `className` -> `"className"`
|
|
56
|
+
* - `aria-label` -> `"aria-label"`
|
|
57
|
+
* - `xml:space` -> `"xml:space"`
|
|
58
|
+
* @param node A `JSXAttribute` AST node
|
|
59
|
+
* @returns The attribute name as a plain string
|
|
100
60
|
*/
|
|
101
61
|
declare function getAttributeName(node: TSESTree.JSXAttribute): string;
|
|
102
62
|
//#endregion
|
|
103
63
|
//#region src/get-attribute-static-value.d.ts
|
|
104
64
|
/**
|
|
105
|
-
* Find an attribute by name on a JSX element and collapse its value to a
|
|
106
|
-
*
|
|
65
|
+
* Find an attribute by name on a JSX element and collapse its value to a plain
|
|
66
|
+
* JavaScript value in a single step
|
|
107
67
|
*
|
|
108
68
|
* This is a convenience composition of {@link findAttribute} ->
|
|
109
|
-
* {@link resolveAttributeValue} -> `toStatic()`, with automatic handling
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
* @param
|
|
117
|
-
* @
|
|
118
|
-
* @param name - The attribute name to look up (e.g. `"className"`).
|
|
119
|
-
* @returns The static value of the attribute, or `undefined`.
|
|
120
|
-
*
|
|
121
|
-
* @example
|
|
122
|
-
* ```ts
|
|
123
|
-
* // <iframe sandbox="allow-scripts" />
|
|
124
|
-
* const sandbox = getAttributeStaticValue(context, node, "sandbox");
|
|
125
|
-
* // -> "allow-scripts"
|
|
126
|
-
*
|
|
127
|
-
* // <button type={dynamicVar} />
|
|
128
|
-
* const type = getAttributeStaticValue(context, node, "type");
|
|
129
|
-
* // -> undefined (cannot be resolved statically)
|
|
130
|
-
* ```
|
|
69
|
+
* {@link resolveAttributeValue} -> `toStatic()`, with automatic handling of the
|
|
70
|
+
* `spreadProps` case (extracts the named property from the spread object).
|
|
71
|
+
*
|
|
72
|
+
* Returns `undefined` when the attribute is absent or when its value cannot be
|
|
73
|
+
* statically determined.
|
|
74
|
+
* @param context The ESLint rule context
|
|
75
|
+
* @param element The `JSXElement` node to inspect
|
|
76
|
+
* @param name The attribute name to look up (ex: "className")
|
|
77
|
+
* @returns The static value of the attribute, or `undefined`
|
|
131
78
|
*/
|
|
132
79
|
declare function getAttributeStaticValue(context: RuleContext, element: TSESTree.JSXElement, name: string): unknown;
|
|
133
80
|
//#endregion
|
|
134
81
|
//#region src/jsx-attribute-value.d.ts
|
|
135
82
|
/**
|
|
136
|
-
* Discriminated union representing the resolved value of a JSX attribute
|
|
83
|
+
* Discriminated union representing the resolved value of a JSX attribute
|
|
137
84
|
*
|
|
138
85
|
* Each variant carries the original AST `node` (where applicable) and a
|
|
139
86
|
* `toStatic()` helper that attempts to collapse the value into a plain
|
|
140
87
|
* JavaScript value at analysis time.
|
|
141
|
-
*
|
|
142
|
-
* @example
|
|
143
|
-
* ```ts
|
|
144
|
-
* const value = resolveAttributeValue(context, attr);
|
|
145
|
-
* switch (value.kind) {
|
|
146
|
-
* case "literal":
|
|
147
|
-
* console.log(value.toStatic()); // string | number | boolean | …
|
|
148
|
-
* break;
|
|
149
|
-
* case "unknown":
|
|
150
|
-
* // dynamic – toStatic() may return `undefined`
|
|
151
|
-
* break;
|
|
152
|
-
* }
|
|
153
|
-
* ```
|
|
154
88
|
*/
|
|
155
89
|
type JsxAttributeValue = JsxAttributeValueBoolean | JsxAttributeValueElement | JsxAttributeValueLiteral | JsxAttributeValueUnknown | JsxAttributeValueMissing | JsxAttributeValueSpreadChild | JsxAttributeValueSpreadProps;
|
|
156
|
-
/** Boolean attribute with no value (
|
|
90
|
+
/** Boolean attribute with no value (ex: `<input disabled />`) */
|
|
157
91
|
interface JsxAttributeValueBoolean {
|
|
158
92
|
readonly kind: "boolean";
|
|
159
93
|
readonly node: null;
|
|
160
94
|
toStatic(): true;
|
|
161
95
|
}
|
|
162
|
-
/** JSX element used as an attribute value (
|
|
96
|
+
/** JSX element used as an attribute value (ex: `<Slot icon=<Icon /> />`) */
|
|
163
97
|
interface JsxAttributeValueElement {
|
|
164
98
|
readonly kind: "element";
|
|
165
99
|
readonly node: TSESTree.JSXElement;
|
|
166
100
|
toStatic(): null;
|
|
167
101
|
}
|
|
168
|
-
/** Literal value (
|
|
102
|
+
/** Literal value (ex: `<img alt="photo" />`) */
|
|
169
103
|
interface JsxAttributeValueLiteral {
|
|
170
104
|
readonly kind: "literal";
|
|
171
105
|
readonly node: TSESTree.Literal;
|
|
172
106
|
toStatic(): TSESTree.Literal["value"];
|
|
173
107
|
}
|
|
174
|
-
/** Expression container value (
|
|
108
|
+
/** Expression container value (ex: `<Comp value={expr} />`) */
|
|
175
109
|
interface JsxAttributeValueUnknown {
|
|
176
110
|
readonly kind: "unknown";
|
|
177
111
|
readonly node: TSESTree.JSXExpressionContainer["expression"];
|
|
178
112
|
toStatic(): unknown;
|
|
179
113
|
}
|
|
180
|
-
/** Empty expression container (
|
|
114
|
+
/** Empty expression container (ex: `<Comp value={} />`) */
|
|
181
115
|
interface JsxAttributeValueMissing {
|
|
182
116
|
readonly kind: "missing";
|
|
183
117
|
readonly node: TSESTree.JSXEmptyExpression;
|
|
184
118
|
toStatic(): null;
|
|
185
119
|
}
|
|
186
|
-
/** Spread child expression (
|
|
120
|
+
/** Spread child expression (ex: `{...items}` as children) */
|
|
187
121
|
interface JsxAttributeValueSpreadChild {
|
|
188
122
|
readonly kind: "spreadChild";
|
|
189
123
|
getChildren(at: number): unknown;
|
|
190
124
|
readonly node: TSESTree.JSXSpreadChild["expression"];
|
|
191
125
|
toStatic(): null;
|
|
192
126
|
}
|
|
193
|
-
/** Spread props (
|
|
127
|
+
/** Spread props (ex: `<Comp {...props} />`) */
|
|
194
128
|
interface JsxAttributeValueSpreadProps {
|
|
195
129
|
readonly kind: "spreadProps";
|
|
196
130
|
getProperty(name: string): unknown;
|
|
@@ -200,38 +134,21 @@ interface JsxAttributeValueSpreadProps {
|
|
|
200
134
|
//#endregion
|
|
201
135
|
//#region src/get-attribute-value.d.ts
|
|
202
136
|
/**
|
|
203
|
-
* Find an attribute by name on a JSX element
|
|
204
|
-
* single call.
|
|
137
|
+
* Find an attribute by name on a JSX element and resolve its value in a single call
|
|
205
138
|
*
|
|
206
139
|
* This is a convenience composition of {@link findAttribute} and
|
|
207
140
|
* {@link resolveAttributeValue} that eliminates the most common two-step
|
|
208
|
-
* pattern in lint rules
|
|
209
|
-
*
|
|
210
|
-
*
|
|
211
|
-
*
|
|
212
|
-
*
|
|
213
|
-
* const value = resolveAttributeValue(context, attr);
|
|
214
|
-
* ```
|
|
215
|
-
*
|
|
216
|
-
* @param context - The ESLint rule context.
|
|
217
|
-
* @param element - The `JSXElement` node to search.
|
|
218
|
-
* @param name - The attribute name to look up (e.g. `"className"`).
|
|
219
|
-
* @returns A {@link JsxAttributeValue} descriptor, or `undefined` when the
|
|
220
|
-
* attribute is not present on the element.
|
|
221
|
-
*
|
|
222
|
-
* @example
|
|
223
|
-
* ```ts
|
|
224
|
-
* const value = getAttributeValue(context, node, "sandbox");
|
|
225
|
-
* if (value?.kind === "literal") {
|
|
226
|
-
* console.log(value.toStatic()); // the literal value
|
|
227
|
-
* }
|
|
228
|
-
* ```
|
|
141
|
+
* pattern in lint rules.
|
|
142
|
+
* @param context The ESLint rule context
|
|
143
|
+
* @param element The `JSXElement` node to search
|
|
144
|
+
* @param name The attribute name to look up (ex: "className")
|
|
145
|
+
* @returns A {@link JsxAttributeValue} descriptor, or `null` when the attribute is not present on the element
|
|
229
146
|
*/
|
|
230
|
-
declare function getAttributeValue(context: RuleContext, element: TSESTree.JSXElement, name: string): JsxAttributeValue |
|
|
147
|
+
declare function getAttributeValue(context: RuleContext, element: TSESTree.JSXElement, name: string): JsxAttributeValue | null;
|
|
231
148
|
//#endregion
|
|
232
149
|
//#region src/get-children.d.ts
|
|
233
150
|
/**
|
|
234
|
-
* Get the
|
|
151
|
+
* Get the meaningful children of a JSX element or fragment
|
|
235
152
|
*
|
|
236
153
|
* Mirrors Babel's `buildChildren` helper:
|
|
237
154
|
* 1. Iterate over `element.children`.
|
|
@@ -239,112 +156,72 @@ declare function getAttributeValue(context: RuleContext, element: TSESTree.JSXEl
|
|
|
239
156
|
* 3. Skip `JSXExpressionContainer` nodes whose expression is empty.
|
|
240
157
|
* 4. Skip `JSXEmptyExpression` nodes.
|
|
241
158
|
* 5. Collect everything else.
|
|
242
|
-
*
|
|
243
|
-
* @
|
|
244
|
-
* @returns An array of children nodes that contribute to rendered output.
|
|
245
|
-
*
|
|
246
|
-
* @example
|
|
247
|
-
* ```ts
|
|
248
|
-
* import { getChildren } from "@eslint-react/jsx";
|
|
249
|
-
*
|
|
250
|
-
* // <div>
|
|
251
|
-
* // <span />
|
|
252
|
-
* // </div>
|
|
253
|
-
* //
|
|
254
|
-
* // Raw children: [JSXText("\n "), JSXElement(<span />), JSXText("\n")]
|
|
255
|
-
* // getChildren: [JSXElement(<span />)]
|
|
256
|
-
*
|
|
257
|
-
* const meaningful = getChildren(node);
|
|
258
|
-
* ```
|
|
159
|
+
* @param element A `JSXElement` or `JSXFragment` node
|
|
160
|
+
* @returns An array of children nodes that contribute to rendered output
|
|
259
161
|
*/
|
|
260
162
|
declare function getChildren(element: TSESTreeJSXElementLike): TSESTree.JSXChild[];
|
|
261
163
|
//#endregion
|
|
262
164
|
//#region src/get-element-type.d.ts
|
|
263
165
|
/**
|
|
264
|
-
* Get the string representation of a JSX element's type
|
|
265
|
-
*
|
|
266
|
-
* - `<div>`
|
|
267
|
-
* - `<Foo.Bar>`
|
|
268
|
-
* - `<React.Fragment>`
|
|
269
|
-
* - `<></>`
|
|
270
|
-
*
|
|
271
|
-
* @
|
|
272
|
-
* @returns The fully-qualified element type string.
|
|
166
|
+
* Get the string representation of a JSX element's type
|
|
167
|
+
*
|
|
168
|
+
* - `<div>` -> `"div"`
|
|
169
|
+
* - `<Foo.Bar>` -> `"Foo.Bar"`
|
|
170
|
+
* - `<React.Fragment>` -> `"React.Fragment"`
|
|
171
|
+
* - `<></>` -> `""`
|
|
172
|
+
* @param node A `JSXElement` or `JSXFragment` node
|
|
173
|
+
* @returns The fully-qualified element type string
|
|
273
174
|
*/
|
|
274
175
|
declare function getElementFullType(node: TSESTreeJSXElementLike): string;
|
|
275
176
|
/**
|
|
276
|
-
* Get the
|
|
277
|
-
*
|
|
278
|
-
* - `<Foo.Bar.Baz>` -> `"Baz"`
|
|
279
|
-
* - `<div>` -> `"div"`
|
|
280
|
-
* - `<></>` -> `""`
|
|
177
|
+
* Get the self name (last dot-separated segment) of a JSX element type
|
|
281
178
|
*
|
|
282
|
-
*
|
|
283
|
-
*
|
|
179
|
+
* - `<Foo.Bar.Baz>` -> `"Baz"`
|
|
180
|
+
* - `<div>` -> `"div"`
|
|
181
|
+
* - `<></>` -> `""`
|
|
182
|
+
* @param node A `JSXElement` or `JSXFragment` node
|
|
183
|
+
* @returns The last segment of the element type, or `""` for fragments
|
|
284
184
|
*/
|
|
285
185
|
declare function getElementSelfType(node: TSESTreeJSXElementLike): string;
|
|
286
186
|
//#endregion
|
|
287
187
|
//#region src/has-any-attribute.d.ts
|
|
288
188
|
/**
|
|
289
|
-
* Check whether a JSX element carries
|
|
189
|
+
* Check whether a JSX element carries at least one of the given attributes
|
|
290
190
|
*
|
|
291
191
|
* This is a batch variant of {@link hasAttribute} for the common pattern of
|
|
292
|
-
* short-circuiting on multiple prop names
|
|
293
|
-
*
|
|
294
|
-
* ```ts
|
|
295
|
-
* // before
|
|
296
|
-
* if (hasAttribute(ctx, el, "key")) return;
|
|
297
|
-
* if (hasAttribute(ctx, el, "ref")) return;
|
|
298
|
-
*
|
|
299
|
-
* // after
|
|
300
|
-
* if (hasAnyAttribute(ctx, el, ["key", "ref"])) return;
|
|
301
|
-
* ```
|
|
192
|
+
* short-circuiting on multiple prop names.
|
|
302
193
|
*
|
|
303
194
|
* Spread attributes are taken into account (see {@link findAttribute}).
|
|
304
|
-
*
|
|
305
|
-
* @param
|
|
306
|
-
*
|
|
307
|
-
* @
|
|
308
|
-
* @param names - The attribute names to look for.
|
|
309
|
-
* @returns `true` when **at least one** of the attributes is present.
|
|
195
|
+
* @param context The ESLint rule context (needed for variable resolution in spread attributes)
|
|
196
|
+
* @param element The `JSXElement` node to inspect
|
|
197
|
+
* @param names The attribute names to look for
|
|
198
|
+
* @returns `true` when at least one of the attributes is present
|
|
310
199
|
*/
|
|
311
|
-
declare function hasAnyAttribute(context: RuleContext, element: TSESTree.JSXElement, names:
|
|
200
|
+
declare function hasAnyAttribute(context: RuleContext, element: TSESTree.JSXElement, names: string[]): boolean;
|
|
312
201
|
//#endregion
|
|
313
202
|
//#region src/has-attribute.d.ts
|
|
314
203
|
/**
|
|
315
|
-
* Check whether a JSX element carries a given attribute (prop)
|
|
204
|
+
* Check whether a JSX element carries a given attribute (prop)
|
|
316
205
|
*
|
|
317
206
|
* This is a thin convenience wrapper around {@link findAttribute} for the
|
|
318
207
|
* common case where you only need a boolean answer.
|
|
319
208
|
*
|
|
320
209
|
* Spread attributes are taken into account: `<Comp {...{ disabled: true }} />`
|
|
321
210
|
* will report `true` for `"disabled"`.
|
|
322
|
-
*
|
|
323
|
-
* @param
|
|
324
|
-
*
|
|
325
|
-
* @
|
|
326
|
-
* @param name - The attribute name to look for (e.g. `"className"`).
|
|
327
|
-
* @returns `true` when the attribute is present on the element.
|
|
328
|
-
*
|
|
329
|
-
* @example
|
|
330
|
-
* ```ts
|
|
331
|
-
* import { hasAttribute } from "@eslint-react/jsx";
|
|
332
|
-
*
|
|
333
|
-
* if (hasAttribute(context, node, "key")) {
|
|
334
|
-
* // element has a `key` prop
|
|
335
|
-
* }
|
|
336
|
-
* ```
|
|
211
|
+
* @param context The ESLint rule context (needed for variable resolution in spread attributes)
|
|
212
|
+
* @param element The `JSXElement` node to inspect
|
|
213
|
+
* @param name The attribute name to look for (ex: "className")
|
|
214
|
+
* @returns `true` when the attribute is present on the element
|
|
337
215
|
*/
|
|
338
216
|
declare function hasAttribute(context: RuleContext, element: TSESTree.JSXElement, name: string): boolean;
|
|
339
217
|
//#endregion
|
|
340
218
|
//#region src/has-children.d.ts
|
|
341
219
|
/**
|
|
342
|
-
* Check whether a JSX element (or fragment) has
|
|
343
|
-
*
|
|
344
|
-
* string expression.
|
|
220
|
+
* Check whether a JSX element (or fragment) has meaningful children, that is,
|
|
221
|
+
* at least one child that is not purely whitespace text or an empty string expression
|
|
345
222
|
*
|
|
346
223
|
* A `JSXText` child whose `raw` content is empty after trimming is considered
|
|
347
|
-
* non-meaningful because it is typically a code-formatting
|
|
224
|
+
* non-meaningful because it is typically a code-formatting artifact
|
|
348
225
|
* (indentation between tags). While React's client renderer preserves these
|
|
349
226
|
* nodes as text nodes, they rarely represent intentionally rendered content.
|
|
350
227
|
*
|
|
@@ -352,231 +229,132 @@ declare function hasAttribute(context: RuleContext, element: TSESTree.JSXElement
|
|
|
352
229
|
* non-meaningful because React's reconciler and SSR renderer explicitly skip
|
|
353
230
|
* empty strings, producing no DOM node.
|
|
354
231
|
*
|
|
355
|
-
* Unlike {@link getChildren}
|
|
356
|
-
* newline
|
|
357
|
-
* (see {@link isWhitespaceText}). As a result `hasChildren(node)` is
|
|
232
|
+
* Unlike {@link getChildren} (which only filters whitespace that contains a
|
|
233
|
+
* newline) this check treats any whitespace-only text as non-meaningful
|
|
234
|
+
* (see {@link isWhitespaceText}). As a result `hasChildren(node)` is not
|
|
358
235
|
* always equal to `getChildren(node).length > 0`: they differ for
|
|
359
236
|
* whitespace-only children that have no newline, such as `<div> </div>` or
|
|
360
237
|
* `<div>\t\t</div>`. Choose the API that matches your rule's intent.
|
|
361
|
-
*
|
|
362
|
-
* @
|
|
363
|
-
* @returns `true` when the element has at least one meaningful child.
|
|
364
|
-
*
|
|
365
|
-
* @example
|
|
366
|
-
* ```ts
|
|
367
|
-
* import { hasChildren } from "@eslint-react/jsx";
|
|
368
|
-
*
|
|
369
|
-
* // <div>hello</div> -> true
|
|
370
|
-
* // <div> {expr} </div> -> true
|
|
371
|
-
* // <div> </div> -> false (whitespace-only)
|
|
372
|
-
* // <div> -> false (whitespace-only, with newlines)
|
|
373
|
-
* // </div>
|
|
374
|
-
* // <div></div> -> false (no children at all)
|
|
375
|
-
* // <div>{""}</div> -> false (empty string expression)
|
|
376
|
-
*
|
|
377
|
-
* if (hasChildren(node)) {
|
|
378
|
-
* // element renders visible content
|
|
379
|
-
* }
|
|
380
|
-
* ```
|
|
238
|
+
* @param element A `JSXElement` or `JSXFragment` node
|
|
239
|
+
* @returns `true` when the element has at least one meaningful child
|
|
381
240
|
*/
|
|
382
241
|
declare function hasChildren(element: TSESTreeJSXElementLike): boolean;
|
|
383
242
|
//#endregion
|
|
384
243
|
//#region src/has-every-attribute.d.ts
|
|
385
244
|
/**
|
|
386
|
-
* Check whether a JSX element carries
|
|
245
|
+
* Check whether a JSX element carries all of the given attributes (props)
|
|
387
246
|
*
|
|
388
247
|
* This is a batch variant of {@link hasAttribute} for the common pattern
|
|
389
248
|
* where a rule needs to verify that a set of required props are all present.
|
|
390
249
|
*
|
|
391
250
|
* Spread attributes are taken into account (see {@link findAttribute}).
|
|
392
|
-
*
|
|
393
|
-
* @param
|
|
394
|
-
*
|
|
395
|
-
* @
|
|
396
|
-
* @param names - The attribute names to look for.
|
|
397
|
-
* @returns `true` when **every** name in `names` is present on the element.
|
|
398
|
-
*
|
|
399
|
-
* @example
|
|
400
|
-
* ```ts
|
|
401
|
-
* import { hasEveryAttribute } from "@eslint-react/jsx";
|
|
402
|
-
*
|
|
403
|
-
* // Ensure both `alt` and `src` are provided on an <img>
|
|
404
|
-
* if (hasEveryAttribute(context, node, ["alt", "src"])) {
|
|
405
|
-
* // element has both props
|
|
406
|
-
* }
|
|
407
|
-
* ```
|
|
251
|
+
* @param context The ESLint rule context (needed for variable resolution in spread attributes)
|
|
252
|
+
* @param element The `JSXElement` node to inspect
|
|
253
|
+
* @param names The attribute names to look for
|
|
254
|
+
* @returns `true` when every name in `names` is present on the element
|
|
408
255
|
*/
|
|
409
|
-
declare function hasEveryAttribute(context: RuleContext, element: TSESTree.JSXElement, names:
|
|
256
|
+
declare function hasEveryAttribute(context: RuleContext, element: TSESTree.JSXElement, names: string[]): boolean;
|
|
410
257
|
//#endregion
|
|
411
258
|
//#region src/is-element.d.ts
|
|
412
259
|
/**
|
|
413
|
-
* A test that determines whether a JSX element matches
|
|
260
|
+
* A test that determines whether a JSX element matches
|
|
414
261
|
*
|
|
415
|
-
* - `string`
|
|
416
|
-
*
|
|
417
|
-
* - `
|
|
418
|
-
* given strings
|
|
419
|
-
* - `function` — receives the element type string and returns a boolean
|
|
262
|
+
* - `string` matches against the full element type (ex: "div", "React.Fragment")
|
|
263
|
+
* - `string[]` matches when the element type equals any of the given strings
|
|
264
|
+
* - `function` receives the element type string and returns a boolean
|
|
420
265
|
*/
|
|
421
266
|
type ElementTest = string | readonly string[] | ((elementType: string, node: TSESTreeJSXElementLike) => boolean);
|
|
422
267
|
/**
|
|
423
268
|
* Check whether a node is a `JSXElement` (or `JSXFragment`) and optionally
|
|
424
|
-
* matches a given test
|
|
269
|
+
* matches a given test
|
|
425
270
|
*
|
|
426
271
|
* Modelled after
|
|
427
272
|
* [`hast-util-is-element`](https://github.com/syntax-tree/hast-util-is-element):
|
|
428
273
|
* the `test` parameter controls what counts as a match.
|
|
429
274
|
*
|
|
430
|
-
* When called
|
|
275
|
+
* When called without a test, the function acts as a simple type-guard
|
|
431
276
|
* for `JSXElement | JSXFragment`.
|
|
432
|
-
*
|
|
433
|
-
* @param
|
|
434
|
-
* @
|
|
435
|
-
* @returns `true` when the node is a matching JSX element.
|
|
436
|
-
*
|
|
437
|
-
* @example
|
|
438
|
-
* ```ts
|
|
439
|
-
* import { isElement } from "@eslint-react/jsx";
|
|
440
|
-
*
|
|
441
|
-
* // Type-guard only — any JSX element or fragment
|
|
442
|
-
* if (isElement(node)) { … }
|
|
443
|
-
*
|
|
444
|
-
* // Match a single tag name
|
|
445
|
-
* if (isElement(node, "iframe")) { … }
|
|
446
|
-
*
|
|
447
|
-
* // Match one of several tag names
|
|
448
|
-
* if (isElement(node, ["button", "input", "select"])) { … }
|
|
449
|
-
*
|
|
450
|
-
* // Custom predicate
|
|
451
|
-
* if (isElement(node, (type) => type.endsWith(".Provider"))) { … }
|
|
452
|
-
* ```
|
|
277
|
+
* @param node The AST node to test
|
|
278
|
+
* @param test Optional test to match the element type against
|
|
279
|
+
* @returns `true` when the node is a matching JSX element
|
|
453
280
|
*/
|
|
454
281
|
declare function isElement(node: TSESTree.Node | null | undefined, test?: ElementTest): node is TSESTreeJSXElementLike;
|
|
455
282
|
//#endregion
|
|
456
283
|
//#region src/is-fragment-element.d.ts
|
|
457
284
|
/**
|
|
458
|
-
* Check whether a node is a React
|
|
285
|
+
* Check whether a node is a React Fragment element
|
|
459
286
|
*
|
|
460
|
-
*
|
|
287
|
+
* Recognizes both the shorthand `<>...</>` syntax (`JSXFragment`) and the
|
|
461
288
|
* explicit `<Fragment>` / `<React.Fragment>` form (`JSXElement`).
|
|
462
289
|
*
|
|
463
|
-
* The comparison is performed against the
|
|
464
|
-
* segment) of both the node and the configured factory, so
|
|
465
|
-
*
|
|
466
|
-
*
|
|
467
|
-
*
|
|
468
|
-
* @
|
|
469
|
-
* @param jsxFragmentFactory - The configured fragment factory string
|
|
470
|
-
* (e.g. `"React.Fragment"`). Defaults to
|
|
471
|
-
* `"React.Fragment"`.
|
|
472
|
-
* @returns `true` when the node represents a React Fragment.
|
|
473
|
-
*
|
|
474
|
-
* @example
|
|
475
|
-
* ```ts
|
|
476
|
-
* // Using the default factory
|
|
477
|
-
* if (isFragmentElement(node)) { … }
|
|
478
|
-
*
|
|
479
|
-
* // With a custom factory from jsxConfig
|
|
480
|
-
* const config = getJsxConfig(context);
|
|
481
|
-
* if (isFragmentElement(node, config.jsxFragmentFactory)) { … }
|
|
482
|
-
* ```
|
|
290
|
+
* The comparison is performed against the self name (last dot-separated
|
|
291
|
+
* segment) of both the node and the configured factory, so `<React.Fragment>`
|
|
292
|
+
* matches `"React.Fragment"` and `<Fragment>` matches `"Fragment"`.
|
|
293
|
+
* @param node The AST node to test
|
|
294
|
+
* @param jsxFragmentFactory The configured fragment factory string (ex: "React.Fragment")
|
|
295
|
+
* @returns `true` when the node represents a React Fragment
|
|
483
296
|
*/
|
|
484
297
|
declare function isFragmentElement(node: TSESTree.Node, jsxFragmentFactory?: string): node is TSESTreeJSXElementLike;
|
|
485
298
|
//#endregion
|
|
486
299
|
//#region src/is-host-element.d.ts
|
|
487
300
|
/**
|
|
488
|
-
* Check whether a node is a
|
|
301
|
+
* Check whether a node is a host (intrinsic / DOM) element
|
|
489
302
|
*
|
|
490
303
|
* A host element is a `JSXElement` whose tag name is a plain `JSXIdentifier`
|
|
491
|
-
* starting with a lowercase letter
|
|
304
|
+
* starting with a lowercase letter, the same heuristic React uses to
|
|
492
305
|
* distinguish `<div>` from `<MyComponent>`.
|
|
493
|
-
*
|
|
494
|
-
* @
|
|
495
|
-
* @returns `true` when the node is a `JSXElement` with a lowercase tag name.
|
|
496
|
-
*
|
|
497
|
-
* @example
|
|
498
|
-
* ```ts
|
|
499
|
-
* // <div className="box" /> -> true
|
|
500
|
-
* // <span /> -> true
|
|
501
|
-
* // <MyComponent /> -> false
|
|
502
|
-
* // <Foo.Bar /> -> false
|
|
503
|
-
* isHostElement(node);
|
|
504
|
-
* ```
|
|
306
|
+
* @param node The AST node to test
|
|
307
|
+
* @returns `true` when the node is a `JSXElement` with a lowercase tag name
|
|
505
308
|
*/
|
|
506
309
|
declare function isHostElement(node: TSESTree.Node): node is TSESTree.JSXElement;
|
|
507
310
|
//#endregion
|
|
508
311
|
//#region src/is-whitespace.d.ts
|
|
509
312
|
/**
|
|
510
|
-
* Check whether a JSX child node is
|
|
511
|
-
* trim away during rendering
|
|
313
|
+
* Check whether a JSX child node is whitespace padding that React would
|
|
314
|
+
* trim away during rendering
|
|
512
315
|
*
|
|
513
316
|
* A child is considered whitespace padding when it is a `JSXText` node whose
|
|
514
317
|
* content is empty after applying React's whitespace normalization
|
|
515
318
|
* (see {@link collapseMultilineText}, modelled after Babel's
|
|
516
319
|
* `cleanJSXElementLiteralChild`). This is the whitespace that appears between
|
|
517
|
-
* JSX tags purely for formatting
|
|
518
|
-
*
|
|
519
|
-
*
|
|
520
|
-
* <div>
|
|
521
|
-
* <span /> ← the text between </span> and the next tag is padding
|
|
522
|
-
* <span />
|
|
523
|
-
* </div>
|
|
524
|
-
* ```
|
|
525
|
-
*
|
|
526
|
-
* @param node - A JSX child node.
|
|
527
|
-
* @returns `true` when the node is purely formatting whitespace.
|
|
320
|
+
* JSX tags purely for formatting.
|
|
321
|
+
* @param node A JSX child node
|
|
322
|
+
* @returns `true` when the node is purely formatting whitespace
|
|
528
323
|
*/
|
|
529
324
|
declare function isWhitespace(node: TSESTree.JSXChild): boolean;
|
|
530
325
|
/**
|
|
531
|
-
* Check whether a JSX child node is
|
|
326
|
+
* Check whether a JSX child node is any whitespace-only text
|
|
532
327
|
*
|
|
533
|
-
* This is a looser variant of {@link isWhitespace}
|
|
328
|
+
* This is a looser variant of {@link isWhitespace}; it matches every
|
|
534
329
|
* `JSXText` node whose raw content is empty after trimming, regardless of
|
|
535
330
|
* whether it contains a newline.
|
|
536
|
-
*
|
|
537
|
-
* @
|
|
538
|
-
* @returns `true` when the node is a whitespace‑only `JSXText`.
|
|
331
|
+
* @param node A JSX child node
|
|
332
|
+
* @returns `true` when the node is a whitespace-only `JSXText`
|
|
539
333
|
*/
|
|
540
334
|
declare function isWhitespaceText(node: TSESTree.JSXChild): boolean;
|
|
541
335
|
/**
|
|
542
|
-
* Check whether a JSX child node is an
|
|
336
|
+
* Check whether a JSX child node is an empty string expression (`{""}`)
|
|
543
337
|
*
|
|
544
338
|
* React's reconciler and SSR renderer explicitly skip empty strings,
|
|
545
339
|
* producing no DOM node (see `ReactChildFiber.js` and `ReactFizzConfigDOM.js`).
|
|
546
340
|
* Such expressions are therefore treated as non-rendered children, in the same
|
|
547
341
|
* way as whitespace padding.
|
|
548
|
-
*
|
|
549
|
-
* @
|
|
550
|
-
* @returns `true` when the node is a `{""}` expression container.
|
|
551
|
-
*
|
|
552
|
-
* @example
|
|
553
|
-
* ```ts
|
|
554
|
-
* import { isEmptyStringExpression } from "@eslint-react/jsx";
|
|
555
|
-
*
|
|
556
|
-
* // <div>{""}</div> -> the expression container is an empty string expression
|
|
557
|
-
* const meaningful = element.children.filter(
|
|
558
|
-
* (child) => !isEmptyStringExpression(child),
|
|
559
|
-
* );
|
|
560
|
-
* ```
|
|
342
|
+
* @param node A JSX child node
|
|
343
|
+
* @returns `true` when the node is a `{""}` expression container
|
|
561
344
|
*/
|
|
562
345
|
declare function isEmptyStringExpression(node: TSESTree.JSXChild): boolean;
|
|
563
346
|
//#endregion
|
|
564
347
|
//#region src/jsx-detection-hint.d.ts
|
|
565
348
|
/**
|
|
566
|
-
* BitFlags for configuring JSX detection behavior
|
|
567
|
-
*
|
|
568
|
-
* Used by {@link isJsxLike} to control which AST node kinds are
|
|
569
|
-
* considered "JSX-like". Combine flags with the `|` operator.
|
|
570
|
-
*
|
|
571
|
-
* @example
|
|
572
|
-
* ```ts
|
|
573
|
-
* const hint = JsxDetectionHint.DoNotIncludeJsxWithBooleanValue
|
|
574
|
-
* | JsxDetectionHint.DoNotIncludeJsxWithStringValue;
|
|
349
|
+
* BitFlags for configuring JSX detection behavior
|
|
575
350
|
*
|
|
576
|
-
* isJsxLike
|
|
577
|
-
*
|
|
351
|
+
* Used by `isJsxLike` to control which AST node kinds are considered
|
|
352
|
+
* "JSX-like". Combine flags with the `|` operator.
|
|
578
353
|
*/
|
|
579
354
|
type JsxDetectionHint = bigint;
|
|
355
|
+
/**
|
|
356
|
+
* Hints for JSX detection
|
|
357
|
+
*/
|
|
580
358
|
declare const JsxDetectionHint: {
|
|
581
359
|
readonly None: 0n;
|
|
582
360
|
readonly DoNotIncludeJsxWithNullValue: bigint;
|
|
@@ -592,9 +370,9 @@ declare const JsxDetectionHint: {
|
|
|
592
370
|
readonly RequireBothBranchesOfConditionalExpressionToBeJsx: bigint;
|
|
593
371
|
};
|
|
594
372
|
/**
|
|
595
|
-
* Default JSX detection
|
|
373
|
+
* Default JSX detection hint
|
|
596
374
|
*
|
|
597
|
-
* Skips number, bigint, boolean, string, and undefined literals
|
|
375
|
+
* Skips number, bigint, boolean, string, and undefined literals,
|
|
598
376
|
* the value types that are commonly returned alongside JSX in React
|
|
599
377
|
* components but are not themselves renderable elements.
|
|
600
378
|
*/
|
|
@@ -603,28 +381,14 @@ declare const DEFAULT_JSX_DETECTION_HINT: JsxDetectionHint;
|
|
|
603
381
|
//#region src/resolve-attribute-value.d.ts
|
|
604
382
|
/**
|
|
605
383
|
* Resolve the value of a JSX attribute (or spread attribute) into a
|
|
606
|
-
* {@link JsxAttributeValue} descriptor that can be inspected further
|
|
607
|
-
*
|
|
608
|
-
* This is the low
|
|
609
|
-
* node that the caller has already located.
|
|
610
|
-
* name
|
|
611
|
-
*
|
|
612
|
-
* @param
|
|
613
|
-
* @
|
|
614
|
-
* @returns A discriminated‑union descriptor of the attribute's value.
|
|
615
|
-
*
|
|
616
|
-
* @example
|
|
617
|
-
* ```ts
|
|
618
|
-
* import { findAttribute, resolveAttributeValue } from "@eslint-react/jsx";
|
|
619
|
-
*
|
|
620
|
-
* const attr = findAttribute(context, element, "sandbox");
|
|
621
|
-
* if (attr != null) {
|
|
622
|
-
* const value = resolveAttributeValue(context, attr);
|
|
623
|
-
* if (value.kind === "literal") {
|
|
624
|
-
* console.log(value.toStatic());
|
|
625
|
-
* }
|
|
626
|
-
* }
|
|
627
|
-
* ```
|
|
384
|
+
* {@link JsxAttributeValue} descriptor that can be inspected further
|
|
385
|
+
*
|
|
386
|
+
* This is the low-level building block; it operates on a single attribute
|
|
387
|
+
* node that the caller has already located. For the higher-level "find by
|
|
388
|
+
* name and resolve" combo, see {@link getAttributeValue}.
|
|
389
|
+
* @param context The ESLint rule context (needed for scope look-ups)
|
|
390
|
+
* @param attribute A `JSXAttribute` or `JSXSpreadAttribute` node
|
|
391
|
+
* @returns A discriminated-union descriptor of the attribute's value
|
|
628
392
|
*/
|
|
629
393
|
declare function resolveAttributeValue(context: RuleContext, attribute: TSESTreeJSXAttributeLike): JsxAttributeValue;
|
|
630
394
|
//#endregion
|