eslint-plugin-react-dom 5.20.1 → 5.20.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/dist/index.js +108 -183
- package/package.json +7 -6
package/dist/index.js
CHANGED
|
@@ -4,6 +4,7 @@ import "@eslint-react/eslint";
|
|
|
4
4
|
import { findAttribute, getAttributeStaticValue, getElementFullType, hasAnyAttribute, hasAttribute, isHostElement, isPaddingWhitespace, resolveAttributeValue } from "@eslint-react/jsx";
|
|
5
5
|
import * as core from "@eslint-react/core";
|
|
6
6
|
import { Check, Extract } from "@eslint-react/ast";
|
|
7
|
+
import { createImportLookup } from "@eslint-react/var";
|
|
7
8
|
import { AST_NODE_TYPES } from "@typescript-eslint/types";
|
|
8
9
|
import { compare } from "compare-versions";
|
|
9
10
|
|
|
@@ -26,7 +27,7 @@ var __exportAll = (all, no_symbols) => {
|
|
|
26
27
|
//#endregion
|
|
27
28
|
//#region package.json
|
|
28
29
|
var name$2 = "eslint-plugin-react-dom";
|
|
29
|
-
var version = "5.20.
|
|
30
|
+
var version = "5.20.2";
|
|
30
31
|
|
|
31
32
|
//#endregion
|
|
32
33
|
//#region src/utils/create-rule.ts
|
|
@@ -129,41 +130,24 @@ var no_flush_sync_default = createRule({
|
|
|
129
130
|
});
|
|
130
131
|
function create$12(context) {
|
|
131
132
|
if (!context.sourceCode.text.includes("flushSync")) return {};
|
|
132
|
-
const
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
});
|
|
149
|
-
return;
|
|
150
|
-
}
|
|
151
|
-
},
|
|
152
|
-
ImportDeclaration(node) {
|
|
153
|
-
const [baseSource] = node.source.value.split("/");
|
|
154
|
-
if (baseSource !== "react-dom") return;
|
|
155
|
-
for (const specifier of node.specifiers) switch (specifier.type) {
|
|
156
|
-
case AST_NODE_TYPES.ImportSpecifier:
|
|
157
|
-
if (!Check.isIdentifier(specifier.imported)) continue;
|
|
158
|
-
if (specifier.imported.name === "flushSync") flushSyncNames.add(specifier.local.name);
|
|
159
|
-
continue;
|
|
160
|
-
case AST_NODE_TYPES.ImportDefaultSpecifier:
|
|
161
|
-
case AST_NODE_TYPES.ImportNamespaceSpecifier:
|
|
162
|
-
reactDomNames.add(specifier.local.name);
|
|
163
|
-
continue;
|
|
164
|
-
}
|
|
133
|
+
const imports = createImportLookup(context.sourceCode.ast, { source: "react-dom" });
|
|
134
|
+
return { CallExpression(node) {
|
|
135
|
+
const callee = Extract.unwrap(node.callee);
|
|
136
|
+
switch (true) {
|
|
137
|
+
case Check.isIdentifier(callee) && imports.has(callee.name, "flushSync"):
|
|
138
|
+
context.report({
|
|
139
|
+
messageId: "default",
|
|
140
|
+
node
|
|
141
|
+
});
|
|
142
|
+
return;
|
|
143
|
+
case callee.type === AST_NODE_TYPES.MemberExpression && Check.isIdentifier(callee.object) && Extract.getCalleeName(node) === "flushSync" && imports.hasNamespace(callee.object.name):
|
|
144
|
+
context.report({
|
|
145
|
+
messageId: "default",
|
|
146
|
+
node
|
|
147
|
+
});
|
|
148
|
+
return;
|
|
165
149
|
}
|
|
166
|
-
};
|
|
150
|
+
} };
|
|
167
151
|
}
|
|
168
152
|
|
|
169
153
|
//#endregion
|
|
@@ -185,43 +169,26 @@ function create$11(context) {
|
|
|
185
169
|
if (!context.sourceCode.text.includes("hydrate")) return {};
|
|
186
170
|
const settings = getSettingsFromContext(context);
|
|
187
171
|
if (compare(settings.version, "18.0.0", "<")) return {};
|
|
188
|
-
const
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
});
|
|
207
|
-
return;
|
|
208
|
-
}
|
|
209
|
-
},
|
|
210
|
-
ImportDeclaration(node) {
|
|
211
|
-
const [baseSource] = node.source.value.split("/");
|
|
212
|
-
if (baseSource !== "react-dom") return;
|
|
213
|
-
for (const specifier of node.specifiers) switch (specifier.type) {
|
|
214
|
-
case AST_NODE_TYPES.ImportSpecifier:
|
|
215
|
-
if (!Check.isIdentifier(specifier.imported)) continue;
|
|
216
|
-
if (specifier.imported.name === "hydrate") hydrateNames.add(specifier.local.name);
|
|
217
|
-
continue;
|
|
218
|
-
case AST_NODE_TYPES.ImportDefaultSpecifier:
|
|
219
|
-
case AST_NODE_TYPES.ImportNamespaceSpecifier:
|
|
220
|
-
reactDomNames.add(specifier.local.name);
|
|
221
|
-
continue;
|
|
222
|
-
}
|
|
172
|
+
const imports = createImportLookup(context.sourceCode.ast, { source: "react-dom" });
|
|
173
|
+
return { CallExpression(node) {
|
|
174
|
+
const callee = Extract.unwrap(node.callee);
|
|
175
|
+
switch (true) {
|
|
176
|
+
case Check.isIdentifier(callee) && imports.has(callee.name, "hydrate"):
|
|
177
|
+
context.report({
|
|
178
|
+
fix: buildFix$2(context, node),
|
|
179
|
+
messageId: "default",
|
|
180
|
+
node
|
|
181
|
+
});
|
|
182
|
+
return;
|
|
183
|
+
case callee.type === AST_NODE_TYPES.MemberExpression && Check.isIdentifier(callee.object) && Extract.getCalleeName(node) === "hydrate" && imports.hasNamespace(callee.object.name):
|
|
184
|
+
context.report({
|
|
185
|
+
fix: buildFix$2(context, node),
|
|
186
|
+
messageId: "default",
|
|
187
|
+
node
|
|
188
|
+
});
|
|
189
|
+
return;
|
|
223
190
|
}
|
|
224
|
-
};
|
|
191
|
+
} };
|
|
225
192
|
}
|
|
226
193
|
function buildFix$2(context, node) {
|
|
227
194
|
const getText = (n) => context.sourceCode.getText(n);
|
|
@@ -235,15 +202,17 @@ function buildFix$2(context, node) {
|
|
|
235
202
|
//#endregion
|
|
236
203
|
//#region src/utils/create-jsx-element-resolver.ts
|
|
237
204
|
/**
|
|
238
|
-
* Creates a resolver for JSX elements that determines
|
|
239
|
-
* and the underlying DOM element type.
|
|
205
|
+
* Creates a resolver for JSX elements that determines the underlying DOM element type.
|
|
240
206
|
*
|
|
241
207
|
* This resolver handles:
|
|
242
208
|
* 1. Regular HTML elements (div, span, etc.)
|
|
243
|
-
* 2. Polymorphic components (components that
|
|
209
|
+
* 2. Polymorphic components (components that render as a different element via a prop,
|
|
210
|
+
* ex: `<Box as="a">`). Only static string values of the polymorphic prop are
|
|
211
|
+
* supported; `<Box as={Component}>` cannot be resolved statically and falls back
|
|
212
|
+
* to the JSX element's own name.
|
|
244
213
|
*
|
|
245
214
|
* @param context The ESLint rule context
|
|
246
|
-
* @returns An object with a resolve method to determine element
|
|
215
|
+
* @returns An object with a resolve method to determine the element type
|
|
247
216
|
*/
|
|
248
217
|
function createJsxElementResolver(context) {
|
|
249
218
|
const { polymorphicPropName } = getSettingsFromContext(context);
|
|
@@ -260,11 +229,12 @@ resolve(node) {
|
|
|
260
229
|
domElementType: elementName,
|
|
261
230
|
jsxElementType: elementName
|
|
262
231
|
};
|
|
263
|
-
|
|
232
|
+
const nameNode = node.openingElement.name;
|
|
233
|
+
if (nameNode.type === AST_NODE_TYPES.JSXIdentifier && nameNode.name.charAt(0) === nameNode.name.charAt(0).toLowerCase()) return result;
|
|
264
234
|
const polyPropValue = getAttributeStaticValue(context, node, polymorphicPropName);
|
|
265
235
|
if (typeof polyPropValue === "string") return {
|
|
266
236
|
...result,
|
|
267
|
-
domElementType: polyPropValue
|
|
237
|
+
domElementType: polyPropValue.toLowerCase()
|
|
268
238
|
};
|
|
269
239
|
return result;
|
|
270
240
|
} };
|
|
@@ -393,41 +363,27 @@ var no_render_return_value_default = createRule({
|
|
|
393
363
|
defaultOptions: []
|
|
394
364
|
});
|
|
395
365
|
function create$8(context) {
|
|
396
|
-
const
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
},
|
|
416
|
-
ImportDeclaration(node) {
|
|
417
|
-
const [baseSource] = node.source.value.split("/");
|
|
418
|
-
if (baseSource !== "react-dom") return;
|
|
419
|
-
for (const specifier of node.specifiers) switch (specifier.type) {
|
|
420
|
-
case AST_NODE_TYPES.ImportSpecifier:
|
|
421
|
-
if (!Check.isIdentifier(specifier.imported)) continue;
|
|
422
|
-
if (specifier.imported.name === "render") renderNames.add(specifier.local.name);
|
|
423
|
-
continue;
|
|
424
|
-
case AST_NODE_TYPES.ImportDefaultSpecifier:
|
|
425
|
-
case AST_NODE_TYPES.ImportNamespaceSpecifier:
|
|
426
|
-
reactDomNames.add(specifier.local.name);
|
|
427
|
-
continue;
|
|
428
|
-
}
|
|
366
|
+
const imports = createImportLookup(context.sourceCode.ast, {
|
|
367
|
+
source: "react-dom",
|
|
368
|
+
builtinNamespaces: ["ReactDOM"]
|
|
369
|
+
});
|
|
370
|
+
return { CallExpression(node) {
|
|
371
|
+
const callee = Extract.unwrap(node.callee);
|
|
372
|
+
switch (true) {
|
|
373
|
+
case Check.isIdentifier(callee) && imports.has(callee.name, "render") && isReturnValueUsed(node):
|
|
374
|
+
context.report({
|
|
375
|
+
messageId: "default",
|
|
376
|
+
node
|
|
377
|
+
});
|
|
378
|
+
return;
|
|
379
|
+
case callee.type === AST_NODE_TYPES.MemberExpression && Check.isIdentifier(callee.object) && Extract.getCalleeName(node) === "render" && imports.hasNamespace(callee.object.name) && isReturnValueUsed(node):
|
|
380
|
+
context.report({
|
|
381
|
+
messageId: "default",
|
|
382
|
+
node
|
|
383
|
+
});
|
|
384
|
+
return;
|
|
429
385
|
}
|
|
430
|
-
};
|
|
386
|
+
} };
|
|
431
387
|
}
|
|
432
388
|
|
|
433
389
|
//#endregion
|
|
@@ -449,43 +405,29 @@ function create$7(context) {
|
|
|
449
405
|
if (!context.sourceCode.text.includes("render")) return {};
|
|
450
406
|
const settings = getSettingsFromContext(context);
|
|
451
407
|
if (compare(settings.version, "18.0.0", "<")) return {};
|
|
452
|
-
const
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
},
|
|
474
|
-
ImportDeclaration(node) {
|
|
475
|
-
const [baseSource] = node.source.value.split("/");
|
|
476
|
-
if (baseSource !== "react-dom") return;
|
|
477
|
-
for (const specifier of node.specifiers) switch (specifier.type) {
|
|
478
|
-
case AST_NODE_TYPES.ImportSpecifier:
|
|
479
|
-
if (!Check.isIdentifier(specifier.imported)) continue;
|
|
480
|
-
if (specifier.imported.name === "render") renderNames.add(specifier.local.name);
|
|
481
|
-
continue;
|
|
482
|
-
case AST_NODE_TYPES.ImportDefaultSpecifier:
|
|
483
|
-
case AST_NODE_TYPES.ImportNamespaceSpecifier:
|
|
484
|
-
reactDomNames.add(specifier.local.name);
|
|
485
|
-
continue;
|
|
486
|
-
}
|
|
408
|
+
const imports = createImportLookup(context.sourceCode.ast, {
|
|
409
|
+
source: "react-dom",
|
|
410
|
+
builtinNamespaces: ["ReactDOM"]
|
|
411
|
+
});
|
|
412
|
+
return { CallExpression(node) {
|
|
413
|
+
const callee = Extract.unwrap(node.callee);
|
|
414
|
+
switch (true) {
|
|
415
|
+
case Check.isIdentifier(callee) && imports.has(callee.name, "render"):
|
|
416
|
+
context.report({
|
|
417
|
+
fix: buildFix$1(context, node),
|
|
418
|
+
messageId: "default",
|
|
419
|
+
node
|
|
420
|
+
});
|
|
421
|
+
return;
|
|
422
|
+
case callee.type === AST_NODE_TYPES.MemberExpression && Check.isIdentifier(callee.object) && Extract.getCalleeName(node) === "render" && imports.hasNamespace(callee.object.name):
|
|
423
|
+
context.report({
|
|
424
|
+
fix: buildFix$1(context, node),
|
|
425
|
+
messageId: "default",
|
|
426
|
+
node
|
|
427
|
+
});
|
|
428
|
+
return;
|
|
487
429
|
}
|
|
488
|
-
};
|
|
430
|
+
} };
|
|
489
431
|
}
|
|
490
432
|
/**
|
|
491
433
|
* Provides a fixer function to replace `render(app, container)` with `createRoot(container).render(app)`
|
|
@@ -1858,43 +1800,26 @@ function create$1(context) {
|
|
|
1858
1800
|
if (!context.sourceCode.text.includes("useFormState")) return {};
|
|
1859
1801
|
const settings = getSettingsFromContext(context);
|
|
1860
1802
|
if (compare(settings.version, "19.0.0", "<")) return {};
|
|
1861
|
-
const
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
});
|
|
1880
|
-
return;
|
|
1881
|
-
}
|
|
1882
|
-
},
|
|
1883
|
-
ImportDeclaration(node) {
|
|
1884
|
-
const [baseSource] = node.source.value.split("/");
|
|
1885
|
-
if (baseSource !== "react-dom") return;
|
|
1886
|
-
for (const specifier of node.specifiers) switch (specifier.type) {
|
|
1887
|
-
case AST_NODE_TYPES.ImportSpecifier:
|
|
1888
|
-
if (!Check.isIdentifier(specifier.imported)) continue;
|
|
1889
|
-
if (specifier.imported.name === "useFormState") useFormStateNames.add(specifier.local.name);
|
|
1890
|
-
continue;
|
|
1891
|
-
case AST_NODE_TYPES.ImportDefaultSpecifier:
|
|
1892
|
-
case AST_NODE_TYPES.ImportNamespaceSpecifier:
|
|
1893
|
-
reactDomNames.add(specifier.local.name);
|
|
1894
|
-
continue;
|
|
1895
|
-
}
|
|
1803
|
+
const imports = createImportLookup(context.sourceCode.ast, { source: "react-dom" });
|
|
1804
|
+
return { CallExpression(node) {
|
|
1805
|
+
const callee = Extract.unwrap(node.callee);
|
|
1806
|
+
switch (true) {
|
|
1807
|
+
case Check.isIdentifier(callee) && imports.has(callee.name, "useFormState"):
|
|
1808
|
+
context.report({
|
|
1809
|
+
fix: buildFix(context, node),
|
|
1810
|
+
messageId: "default",
|
|
1811
|
+
node
|
|
1812
|
+
});
|
|
1813
|
+
return;
|
|
1814
|
+
case callee.type === AST_NODE_TYPES.MemberExpression && Check.isIdentifier(callee.object) && Extract.getCalleeName(node) === "useFormState" && imports.hasNamespace(callee.object.name):
|
|
1815
|
+
context.report({
|
|
1816
|
+
fix: buildFix(context, node),
|
|
1817
|
+
messageId: "default",
|
|
1818
|
+
node
|
|
1819
|
+
});
|
|
1820
|
+
return;
|
|
1896
1821
|
}
|
|
1897
|
-
};
|
|
1822
|
+
} };
|
|
1898
1823
|
}
|
|
1899
1824
|
function buildFix(context, node) {
|
|
1900
1825
|
const { importSource } = getSettingsFromContext(context);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-react-dom",
|
|
3
|
-
"version": "5.20.
|
|
3
|
+
"version": "5.20.2",
|
|
4
4
|
"description": "ESLint React's ESLint plugin for DOM related rules.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -37,11 +37,12 @@
|
|
|
37
37
|
"dist"
|
|
38
38
|
],
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@eslint-react/ast": "5.20.
|
|
41
|
-
"@eslint-react/core": "5.20.
|
|
42
|
-
"@eslint-react/eslint": "5.20.
|
|
43
|
-
"@eslint-react/jsx": "5.20.
|
|
44
|
-
"@eslint-react/shared": "5.20.
|
|
40
|
+
"@eslint-react/ast": "5.20.2",
|
|
41
|
+
"@eslint-react/core": "5.20.2",
|
|
42
|
+
"@eslint-react/eslint": "5.20.2",
|
|
43
|
+
"@eslint-react/jsx": "5.20.2",
|
|
44
|
+
"@eslint-react/shared": "5.20.2",
|
|
45
|
+
"@eslint-react/var": "5.20.2",
|
|
45
46
|
"@typescript-eslint/types": "^8.70.0",
|
|
46
47
|
"@typescript-eslint/utils": "^8.70.0",
|
|
47
48
|
"compare-versions": "^6.1.1"
|