eslint-plugin-react-dom 5.20.0 → 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 +110 -154
- package/package.json +8 -6
package/dist/index.js
CHANGED
|
@@ -2,7 +2,9 @@ import { DEFAULT_ESLINT_REACT_SETTINGS, RE_JAVASCRIPT_PROTOCOL, getSettingsFromC
|
|
|
2
2
|
import { ESLintUtils } from "@typescript-eslint/utils";
|
|
3
3
|
import "@eslint-react/eslint";
|
|
4
4
|
import { findAttribute, getAttributeStaticValue, getElementFullType, hasAnyAttribute, hasAttribute, isHostElement, isPaddingWhitespace, resolveAttributeValue } from "@eslint-react/jsx";
|
|
5
|
+
import * as core from "@eslint-react/core";
|
|
5
6
|
import { Check, Extract } from "@eslint-react/ast";
|
|
7
|
+
import { createImportLookup } from "@eslint-react/var";
|
|
6
8
|
import { AST_NODE_TYPES } from "@typescript-eslint/types";
|
|
7
9
|
import { compare } from "compare-versions";
|
|
8
10
|
|
|
@@ -25,7 +27,7 @@ var __exportAll = (all, no_symbols) => {
|
|
|
25
27
|
//#endregion
|
|
26
28
|
//#region package.json
|
|
27
29
|
var name$2 = "eslint-plugin-react-dom";
|
|
28
|
-
var version = "5.20.
|
|
30
|
+
var version = "5.20.2";
|
|
29
31
|
|
|
30
32
|
//#endregion
|
|
31
33
|
//#region src/utils/create-rule.ts
|
|
@@ -89,6 +91,7 @@ function create$14(context) {
|
|
|
89
91
|
|
|
90
92
|
//#endregion
|
|
91
93
|
//#region src/rules/no-find-dom-node/no-find-dom-node.ts
|
|
94
|
+
const isFindDOMNodeCall = core.isAPICall("findDOMNode");
|
|
92
95
|
const RULE_NAME$13 = "no-find-dom-node";
|
|
93
96
|
var no_find_dom_node_default = createRule({
|
|
94
97
|
meta: {
|
|
@@ -104,7 +107,7 @@ var no_find_dom_node_default = createRule({
|
|
|
104
107
|
function create$13(context) {
|
|
105
108
|
if (!context.sourceCode.text.includes("findDOMNode")) return {};
|
|
106
109
|
return { CallExpression(node) {
|
|
107
|
-
if (
|
|
110
|
+
if (isFindDOMNodeCall(context, node)) context.report({
|
|
108
111
|
messageId: "default",
|
|
109
112
|
node
|
|
110
113
|
});
|
|
@@ -127,11 +130,23 @@ var no_flush_sync_default = createRule({
|
|
|
127
130
|
});
|
|
128
131
|
function create$12(context) {
|
|
129
132
|
if (!context.sourceCode.text.includes("flushSync")) return {};
|
|
133
|
+
const imports = createImportLookup(context.sourceCode.ast, { source: "react-dom" });
|
|
130
134
|
return { CallExpression(node) {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
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;
|
|
149
|
+
}
|
|
135
150
|
} };
|
|
136
151
|
}
|
|
137
152
|
|
|
@@ -154,43 +169,26 @@ function create$11(context) {
|
|
|
154
169
|
if (!context.sourceCode.text.includes("hydrate")) return {};
|
|
155
170
|
const settings = getSettingsFromContext(context);
|
|
156
171
|
if (compare(settings.version, "18.0.0", "<")) return {};
|
|
157
|
-
const
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
});
|
|
176
|
-
return;
|
|
177
|
-
}
|
|
178
|
-
},
|
|
179
|
-
ImportDeclaration(node) {
|
|
180
|
-
const [baseSource] = node.source.value.split("/");
|
|
181
|
-
if (baseSource !== "react-dom") return;
|
|
182
|
-
for (const specifier of node.specifiers) switch (specifier.type) {
|
|
183
|
-
case AST_NODE_TYPES.ImportSpecifier:
|
|
184
|
-
if (!Check.isIdentifier(specifier.imported)) continue;
|
|
185
|
-
if (specifier.imported.name === "hydrate") hydrateNames.add(specifier.local.name);
|
|
186
|
-
continue;
|
|
187
|
-
case AST_NODE_TYPES.ImportDefaultSpecifier:
|
|
188
|
-
case AST_NODE_TYPES.ImportNamespaceSpecifier:
|
|
189
|
-
reactDomNames.add(specifier.local.name);
|
|
190
|
-
continue;
|
|
191
|
-
}
|
|
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;
|
|
192
190
|
}
|
|
193
|
-
};
|
|
191
|
+
} };
|
|
194
192
|
}
|
|
195
193
|
function buildFix$2(context, node) {
|
|
196
194
|
const getText = (n) => context.sourceCode.getText(n);
|
|
@@ -204,15 +202,17 @@ function buildFix$2(context, node) {
|
|
|
204
202
|
//#endregion
|
|
205
203
|
//#region src/utils/create-jsx-element-resolver.ts
|
|
206
204
|
/**
|
|
207
|
-
* Creates a resolver for JSX elements that determines
|
|
208
|
-
* and the underlying DOM element type.
|
|
205
|
+
* Creates a resolver for JSX elements that determines the underlying DOM element type.
|
|
209
206
|
*
|
|
210
207
|
* This resolver handles:
|
|
211
208
|
* 1. Regular HTML elements (div, span, etc.)
|
|
212
|
-
* 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.
|
|
213
213
|
*
|
|
214
214
|
* @param context The ESLint rule context
|
|
215
|
-
* @returns An object with a resolve method to determine element
|
|
215
|
+
* @returns An object with a resolve method to determine the element type
|
|
216
216
|
*/
|
|
217
217
|
function createJsxElementResolver(context) {
|
|
218
218
|
const { polymorphicPropName } = getSettingsFromContext(context);
|
|
@@ -229,11 +229,12 @@ resolve(node) {
|
|
|
229
229
|
domElementType: elementName,
|
|
230
230
|
jsxElementType: elementName
|
|
231
231
|
};
|
|
232
|
-
|
|
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;
|
|
233
234
|
const polyPropValue = getAttributeStaticValue(context, node, polymorphicPropName);
|
|
234
235
|
if (typeof polyPropValue === "string") return {
|
|
235
236
|
...result,
|
|
236
|
-
domElementType: polyPropValue
|
|
237
|
+
domElementType: polyPropValue.toLowerCase()
|
|
237
238
|
};
|
|
238
239
|
return result;
|
|
239
240
|
} };
|
|
@@ -362,41 +363,27 @@ var no_render_return_value_default = createRule({
|
|
|
362
363
|
defaultOptions: []
|
|
363
364
|
});
|
|
364
365
|
function create$8(context) {
|
|
365
|
-
const
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
},
|
|
385
|
-
ImportDeclaration(node) {
|
|
386
|
-
const [baseSource] = node.source.value.split("/");
|
|
387
|
-
if (baseSource !== "react-dom") return;
|
|
388
|
-
for (const specifier of node.specifiers) switch (specifier.type) {
|
|
389
|
-
case AST_NODE_TYPES.ImportSpecifier:
|
|
390
|
-
if (!Check.isIdentifier(specifier.imported)) continue;
|
|
391
|
-
if (specifier.imported.name === "render") renderNames.add(specifier.local.name);
|
|
392
|
-
continue;
|
|
393
|
-
case AST_NODE_TYPES.ImportDefaultSpecifier:
|
|
394
|
-
case AST_NODE_TYPES.ImportNamespaceSpecifier:
|
|
395
|
-
reactDomNames.add(specifier.local.name);
|
|
396
|
-
continue;
|
|
397
|
-
}
|
|
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;
|
|
398
385
|
}
|
|
399
|
-
};
|
|
386
|
+
} };
|
|
400
387
|
}
|
|
401
388
|
|
|
402
389
|
//#endregion
|
|
@@ -418,43 +405,29 @@ function create$7(context) {
|
|
|
418
405
|
if (!context.sourceCode.text.includes("render")) return {};
|
|
419
406
|
const settings = getSettingsFromContext(context);
|
|
420
407
|
if (compare(settings.version, "18.0.0", "<")) return {};
|
|
421
|
-
const
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
},
|
|
443
|
-
ImportDeclaration(node) {
|
|
444
|
-
const [baseSource] = node.source.value.split("/");
|
|
445
|
-
if (baseSource !== "react-dom") return;
|
|
446
|
-
for (const specifier of node.specifiers) switch (specifier.type) {
|
|
447
|
-
case AST_NODE_TYPES.ImportSpecifier:
|
|
448
|
-
if (!Check.isIdentifier(specifier.imported)) continue;
|
|
449
|
-
if (specifier.imported.name === "render") renderNames.add(specifier.local.name);
|
|
450
|
-
continue;
|
|
451
|
-
case AST_NODE_TYPES.ImportDefaultSpecifier:
|
|
452
|
-
case AST_NODE_TYPES.ImportNamespaceSpecifier:
|
|
453
|
-
reactDomNames.add(specifier.local.name);
|
|
454
|
-
continue;
|
|
455
|
-
}
|
|
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;
|
|
456
429
|
}
|
|
457
|
-
};
|
|
430
|
+
} };
|
|
458
431
|
}
|
|
459
432
|
/**
|
|
460
433
|
* Provides a fixer function to replace `render(app, container)` with `createRoot(container).render(app)`
|
|
@@ -1827,43 +1800,26 @@ function create$1(context) {
|
|
|
1827
1800
|
if (!context.sourceCode.text.includes("useFormState")) return {};
|
|
1828
1801
|
const settings = getSettingsFromContext(context);
|
|
1829
1802
|
if (compare(settings.version, "19.0.0", "<")) return {};
|
|
1830
|
-
const
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
});
|
|
1849
|
-
return;
|
|
1850
|
-
}
|
|
1851
|
-
},
|
|
1852
|
-
ImportDeclaration(node) {
|
|
1853
|
-
const [baseSource] = node.source.value.split("/");
|
|
1854
|
-
if (baseSource !== "react-dom") return;
|
|
1855
|
-
for (const specifier of node.specifiers) switch (specifier.type) {
|
|
1856
|
-
case AST_NODE_TYPES.ImportSpecifier:
|
|
1857
|
-
if (!Check.isIdentifier(specifier.imported)) continue;
|
|
1858
|
-
if (specifier.imported.name === "useFormState") useFormStateNames.add(specifier.local.name);
|
|
1859
|
-
continue;
|
|
1860
|
-
case AST_NODE_TYPES.ImportDefaultSpecifier:
|
|
1861
|
-
case AST_NODE_TYPES.ImportNamespaceSpecifier:
|
|
1862
|
-
reactDomNames.add(specifier.local.name);
|
|
1863
|
-
continue;
|
|
1864
|
-
}
|
|
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;
|
|
1865
1821
|
}
|
|
1866
|
-
};
|
|
1822
|
+
} };
|
|
1867
1823
|
}
|
|
1868
1824
|
function buildFix(context, node) {
|
|
1869
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,10 +37,12 @@
|
|
|
37
37
|
"dist"
|
|
38
38
|
],
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@eslint-react/ast": "5.20.
|
|
41
|
-
"@eslint-react/
|
|
42
|
-
"@eslint-react/
|
|
43
|
-
"@eslint-react/
|
|
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",
|
|
44
46
|
"@typescript-eslint/types": "^8.70.0",
|
|
45
47
|
"@typescript-eslint/utils": "^8.70.0",
|
|
46
48
|
"compare-versions": "^6.1.1"
|
|
@@ -51,7 +53,7 @@
|
|
|
51
53
|
"@types/react": "^19.3.0",
|
|
52
54
|
"@types/react-dom": "^19.3.0",
|
|
53
55
|
"dedent": "^1.7.2",
|
|
54
|
-
"eslint": "^10.
|
|
56
|
+
"eslint": "^10.11.0",
|
|
55
57
|
"tsdown": "^0.23.0",
|
|
56
58
|
"typescript": "6.0.3"
|
|
57
59
|
},
|