eslint-plugin-react-dom 5.20.1 → 5.20.3

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.
Files changed (2) hide show
  1. package/dist/index.js +157 -231
  2. package/package.json +7 -6
package/dist/index.js CHANGED
@@ -2,8 +2,8 @@ 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";
6
5
  import { Check, Extract } from "@eslint-react/ast";
6
+ import { createImportLookup } from "@eslint-react/var";
7
7
  import { AST_NODE_TYPES } from "@typescript-eslint/types";
8
8
  import { compare } from "compare-versions";
9
9
 
@@ -26,7 +26,7 @@ var __exportAll = (all, no_symbols) => {
26
26
  //#endregion
27
27
  //#region package.json
28
28
  var name$2 = "eslint-plugin-react-dom";
29
- var version = "5.20.1";
29
+ var version = "5.20.3";
30
30
 
31
31
  //#endregion
32
32
  //#region src/utils/create-rule.ts
@@ -53,11 +53,11 @@ function create$15(context) {
53
53
  if (!context.sourceCode.text.includes("dangerouslySetInnerHTML")) return {};
54
54
  return { JSXElement(node) {
55
55
  if (!hasAttribute(context, node, "dangerouslySetInnerHTML")) return;
56
- const childrenPropOrNode = findAttribute(context, node, "children") ?? node.children.find((child) => !isPaddingWhitespace(child));
57
- if (childrenPropOrNode == null) return;
56
+ const fact = findAttribute(context, node, "children") ?? node.children.find((child) => !isPaddingWhitespace(child));
57
+ if (fact == null) return;
58
58
  context.report({
59
59
  messageId: "default",
60
- node: childrenPropOrNode
60
+ node: fact
61
61
  });
62
62
  } };
63
63
  }
@@ -79,18 +79,17 @@ var no_dangerously_set_innerhtml_default = createRule({
79
79
  function create$14(context) {
80
80
  if (!context.sourceCode.text.includes("dangerouslySetInnerHTML")) return {};
81
81
  return { JSXElement(node) {
82
- const dsihProp = findAttribute(context, node, "dangerouslySetInnerHTML");
83
- if (dsihProp == null) return;
82
+ const prop = findAttribute(context, node, "dangerouslySetInnerHTML");
83
+ if (prop == null) return;
84
84
  context.report({
85
85
  messageId: "default",
86
- node: dsihProp
86
+ node: prop
87
87
  });
88
88
  } };
89
89
  }
90
90
 
91
91
  //#endregion
92
92
  //#region src/rules/no-find-dom-node/no-find-dom-node.ts
93
- const isFindDOMNodeCall = core.isAPICall("findDOMNode");
94
93
  const RULE_NAME$13 = "no-find-dom-node";
95
94
  var no_find_dom_node_default = createRule({
96
95
  meta: {
@@ -105,11 +104,26 @@ var no_find_dom_node_default = createRule({
105
104
  });
106
105
  function create$13(context) {
107
106
  if (!context.sourceCode.text.includes("findDOMNode")) return {};
107
+ const imports = createImportLookup(context.sourceCode.ast, {
108
+ builtinNamespaces: ["React", "ReactDOM"],
109
+ source: "react-dom"
110
+ });
108
111
  return { CallExpression(node) {
109
- if (isFindDOMNodeCall(context, node)) context.report({
110
- messageId: "default",
111
- node
112
- });
112
+ const callee = Extract.unwrap(node.callee);
113
+ switch (true) {
114
+ case Check.isIdentifier(callee) && (callee.name === "findDOMNode" || imports.has(callee.name, "findDOMNode")):
115
+ context.report({
116
+ messageId: "default",
117
+ node
118
+ });
119
+ return;
120
+ case callee.type === AST_NODE_TYPES.MemberExpression && Check.isIdentifier(callee.object) && Extract.getCalleeName(node) === "findDOMNode" && imports.hasNamespace(callee.object.name):
121
+ context.report({
122
+ messageId: "default",
123
+ node
124
+ });
125
+ return;
126
+ }
113
127
  } };
114
128
  }
115
129
 
@@ -129,41 +143,24 @@ var no_flush_sync_default = createRule({
129
143
  });
130
144
  function create$12(context) {
131
145
  if (!context.sourceCode.text.includes("flushSync")) return {};
132
- const reactDomNames = /* @__PURE__ */ new Set();
133
- const flushSyncNames = /* @__PURE__ */ new Set();
134
- return {
135
- CallExpression(node) {
136
- const callee = Extract.unwrap(node.callee);
137
- switch (true) {
138
- case Check.isIdentifier(callee) && flushSyncNames.has(callee.name):
139
- context.report({
140
- messageId: "default",
141
- node
142
- });
143
- return;
144
- case callee.type === AST_NODE_TYPES.MemberExpression && Check.isIdentifier(callee.object) && Extract.getCalleeName(node) === "flushSync" && reactDomNames.has(callee.object.name):
145
- context.report({
146
- messageId: "default",
147
- node
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
- }
146
+ const imports = createImportLookup(context.sourceCode.ast, { source: "react-dom" });
147
+ return { CallExpression(node) {
148
+ const callee = Extract.unwrap(node.callee);
149
+ switch (true) {
150
+ case Check.isIdentifier(callee) && imports.has(callee.name, "flushSync"):
151
+ context.report({
152
+ messageId: "default",
153
+ node
154
+ });
155
+ return;
156
+ case callee.type === AST_NODE_TYPES.MemberExpression && Check.isIdentifier(callee.object) && Extract.getCalleeName(node) === "flushSync" && imports.hasNamespace(callee.object.name):
157
+ context.report({
158
+ messageId: "default",
159
+ node
160
+ });
161
+ return;
165
162
  }
166
- };
163
+ } };
167
164
  }
168
165
 
169
166
  //#endregion
@@ -185,43 +182,26 @@ function create$11(context) {
185
182
  if (!context.sourceCode.text.includes("hydrate")) return {};
186
183
  const settings = getSettingsFromContext(context);
187
184
  if (compare(settings.version, "18.0.0", "<")) return {};
188
- const reactDomNames = /* @__PURE__ */ new Set();
189
- const hydrateNames = /* @__PURE__ */ new Set();
190
- return {
191
- CallExpression(node) {
192
- const callee = Extract.unwrap(node.callee);
193
- switch (true) {
194
- case Check.isIdentifier(callee) && hydrateNames.has(callee.name):
195
- context.report({
196
- fix: buildFix$2(context, node),
197
- messageId: "default",
198
- node
199
- });
200
- return;
201
- case callee.type === AST_NODE_TYPES.MemberExpression && Check.isIdentifier(callee.object) && Extract.getCalleeName(node) === "hydrate" && reactDomNames.has(callee.object.name):
202
- context.report({
203
- fix: buildFix$2(context, node),
204
- messageId: "default",
205
- node
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
- }
185
+ const imports = createImportLookup(context.sourceCode.ast, { source: "react-dom" });
186
+ return { CallExpression(node) {
187
+ const callee = Extract.unwrap(node.callee);
188
+ switch (true) {
189
+ case Check.isIdentifier(callee) && imports.has(callee.name, "hydrate"):
190
+ context.report({
191
+ fix: buildFix$2(context, node),
192
+ messageId: "default",
193
+ node
194
+ });
195
+ return;
196
+ case callee.type === AST_NODE_TYPES.MemberExpression && Check.isIdentifier(callee.object) && Extract.getCalleeName(node) === "hydrate" && imports.hasNamespace(callee.object.name):
197
+ context.report({
198
+ fix: buildFix$2(context, node),
199
+ messageId: "default",
200
+ node
201
+ });
202
+ return;
223
203
  }
224
- };
204
+ } };
225
205
  }
226
206
  function buildFix$2(context, node) {
227
207
  const getText = (n) => context.sourceCode.getText(n);
@@ -235,15 +215,17 @@ function buildFix$2(context, node) {
235
215
  //#endregion
236
216
  //#region src/utils/create-jsx-element-resolver.ts
237
217
  /**
238
- * Creates a resolver for JSX elements that determines both the JSX element type
239
- * and the underlying DOM element type.
218
+ * Creates a resolver for JSX elements that determines the underlying DOM element type.
240
219
  *
241
220
  * This resolver handles:
242
221
  * 1. Regular HTML elements (div, span, etc.)
243
- * 2. Polymorphic components (components that can render as different elements via a prop)
222
+ * 2. Polymorphic components (components that render as a different element via a prop,
223
+ * ex: `<Box as="a">`). Only static string values of the polymorphic prop are
224
+ * supported; `<Box as={Component}>` cannot be resolved statically and falls back
225
+ * to the JSX element's own name.
244
226
  *
245
227
  * @param context The ESLint rule context
246
- * @returns An object with a resolve method to determine element types
228
+ * @returns An object with a resolve method to determine the element type
247
229
  */
248
230
  function createJsxElementResolver(context) {
249
231
  const { polymorphicPropName } = getSettingsFromContext(context);
@@ -260,11 +242,12 @@ resolve(node) {
260
242
  domElementType: elementName,
261
243
  jsxElementType: elementName
262
244
  };
263
- if (elementName === elementName.toLowerCase() || polymorphicPropName == null) return result;
245
+ const nameNode = node.openingElement.name;
246
+ if (nameNode.type === AST_NODE_TYPES.JSXIdentifier && nameNode.name.charAt(0) === nameNode.name.charAt(0).toLowerCase()) return result;
264
247
  const polyPropValue = getAttributeStaticValue(context, node, polymorphicPropName);
265
248
  if (typeof polyPropValue === "string") return {
266
249
  ...result,
267
- domElementType: polyPropValue
250
+ domElementType: polyPropValue.toLowerCase()
268
251
  };
269
252
  return result;
270
253
  } };
@@ -296,14 +279,17 @@ var no_missing_button_type_default = createRule({
296
279
  function create$10(context) {
297
280
  const resolver = createJsxElementResolver(context);
298
281
  return { JSXElement(node) {
299
- if (resolver.resolve(node).domElementType !== "button") return;
282
+ const { domElementType } = resolver.resolve(node);
283
+ if (domElementType !== "button") return;
300
284
  if (hasAttribute(context, node, "type")) return;
301
285
  context.report({
302
286
  messageId: "missingTypeAttribute",
303
287
  node: node.openingElement,
304
288
  suggest: BUTTON_TYPES.map((type) => ({
305
289
  data: { type },
306
- fix: (fixer) => fixer.insertTextAfter(node.openingElement.name, ` type="${type}"`),
290
+ fix(fixer) {
291
+ return fixer.insertTextAfter(node.openingElement.name, ` type="${type}"`);
292
+ },
307
293
  messageId: "addTypeAttribute"
308
294
  }))
309
295
  });
@@ -369,18 +355,13 @@ function create$9(context) {
369
355
  //#endregion
370
356
  //#region src/rules/no-render-return-value/no-render-return-value.ts
371
357
  const RULE_NAME$8 = "no-render-return-value";
372
- const banParentTypes = [
358
+ const BANNED_PARENT_TYPES = [
373
359
  AST_NODE_TYPES.VariableDeclarator,
374
360
  AST_NODE_TYPES.Property,
375
361
  AST_NODE_TYPES.ReturnStatement,
376
362
  AST_NODE_TYPES.ArrowFunctionExpression,
377
363
  AST_NODE_TYPES.AssignmentExpression
378
364
  ];
379
- function isReturnValueUsed(node) {
380
- let parent = node.parent;
381
- while (Check.isTypeExpression(parent)) parent = parent.parent;
382
- return banParentTypes.includes(parent.type);
383
- }
384
365
  var no_render_return_value_default = createRule({
385
366
  meta: {
386
367
  type: "problem",
@@ -393,41 +374,33 @@ var no_render_return_value_default = createRule({
393
374
  defaultOptions: []
394
375
  });
395
376
  function create$8(context) {
396
- const reactDomNames = /* @__PURE__ */ new Set(["ReactDOM", "ReactDOM"]);
397
- const renderNames = /* @__PURE__ */ new Set();
398
- return {
399
- CallExpression(node) {
400
- const callee = Extract.unwrap(node.callee);
401
- switch (true) {
402
- case Check.isIdentifier(callee) && renderNames.has(callee.name) && isReturnValueUsed(node):
403
- context.report({
404
- messageId: "default",
405
- node
406
- });
407
- return;
408
- case callee.type === AST_NODE_TYPES.MemberExpression && Check.isIdentifier(callee.object) && Extract.getCalleeName(node) === "render" && reactDomNames.has(callee.object.name) && isReturnValueUsed(node):
409
- context.report({
410
- messageId: "default",
411
- node
412
- });
413
- return;
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
- }
377
+ if (!context.sourceCode.text.includes("render")) return {};
378
+ const imports = createImportLookup(context.sourceCode.ast, {
379
+ builtinNamespaces: ["ReactDOM"],
380
+ source: "react-dom"
381
+ });
382
+ return { CallExpression(node) {
383
+ const callee = Extract.unwrap(node.callee);
384
+ switch (true) {
385
+ case Check.isIdentifier(callee) && imports.has(callee.name, "render") && isReturnValueUsed(node):
386
+ context.report({
387
+ messageId: "default",
388
+ node
389
+ });
390
+ return;
391
+ case callee.type === AST_NODE_TYPES.MemberExpression && Check.isIdentifier(callee.object) && Extract.getCalleeName(node) === "render" && imports.hasNamespace(callee.object.name) && isReturnValueUsed(node):
392
+ context.report({
393
+ messageId: "default",
394
+ node
395
+ });
396
+ return;
429
397
  }
430
- };
398
+ } };
399
+ }
400
+ function isReturnValueUsed(node) {
401
+ let parent = node.parent;
402
+ while (Check.isTypeExpression(parent)) parent = parent.parent;
403
+ return BANNED_PARENT_TYPES.includes(parent.type);
431
404
  }
432
405
 
433
406
  //#endregion
@@ -449,50 +422,30 @@ function create$7(context) {
449
422
  if (!context.sourceCode.text.includes("render")) return {};
450
423
  const settings = getSettingsFromContext(context);
451
424
  if (compare(settings.version, "18.0.0", "<")) return {};
452
- const reactDomNames = /* @__PURE__ */ new Set(["ReactDOM", "ReactDOM"]);
453
- const renderNames = /* @__PURE__ */ new Set();
454
- return {
455
- CallExpression(node) {
456
- const callee = Extract.unwrap(node.callee);
457
- switch (true) {
458
- case Check.isIdentifier(callee) && renderNames.has(callee.name):
459
- context.report({
460
- fix: buildFix$1(context, node),
461
- messageId: "default",
462
- node
463
- });
464
- return;
465
- case callee.type === AST_NODE_TYPES.MemberExpression && Check.isIdentifier(callee.object) && Extract.getCalleeName(node) === "render" && reactDomNames.has(callee.object.name):
466
- context.report({
467
- fix: buildFix$1(context, node),
468
- messageId: "default",
469
- node
470
- });
471
- return;
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
- }
425
+ const imports = createImportLookup(context.sourceCode.ast, {
426
+ builtinNamespaces: ["ReactDOM"],
427
+ source: "react-dom"
428
+ });
429
+ return { CallExpression(node) {
430
+ const callee = Extract.unwrap(node.callee);
431
+ switch (true) {
432
+ case Check.isIdentifier(callee) && imports.has(callee.name, "render"):
433
+ context.report({
434
+ fix: buildFix$1(context, node),
435
+ messageId: "default",
436
+ node
437
+ });
438
+ return;
439
+ case callee.type === AST_NODE_TYPES.MemberExpression && Check.isIdentifier(callee.object) && Extract.getCalleeName(node) === "render" && imports.hasNamespace(callee.object.name):
440
+ context.report({
441
+ fix: buildFix$1(context, node),
442
+ messageId: "default",
443
+ node
444
+ });
445
+ return;
487
446
  }
488
- };
447
+ } };
489
448
  }
490
- /**
491
- * Provides a fixer function to replace `render(app, container)` with `createRoot(container).render(app)`
492
- * @param context The rule context
493
- * @param node The `CallExpression` node to fix
494
- * @returns A fixer function or null if the fix cannot be applied
495
- */
496
449
  function buildFix$1(context, node) {
497
450
  const getText = (n) => context.sourceCode.getText(n);
498
451
  return (fixer) => {
@@ -547,7 +500,8 @@ function create$5(context) {
547
500
  const styleProp = findAttribute(context, node, "style");
548
501
  if (styleProp == null) return;
549
502
  const styleValue = resolveAttributeValue(context, styleProp);
550
- if (typeof styleValue.toStatic() === "string") context.report({
503
+ if (typeof styleValue.toStatic() !== "string") return;
504
+ context.report({
551
505
  messageId: "default",
552
506
  node: styleValue.node ?? styleProp
553
507
  });
@@ -1637,23 +1591,10 @@ var no_unknown_property_default = createRule({
1637
1591
  create: create$4,
1638
1592
  defaultOptions: []
1639
1593
  });
1640
- /**
1641
- * Create function for the ESLint rule
1642
- * @param context ESLint rule context
1643
- * @returns Rule listener
1644
- */
1645
1594
  function create$4(context) {
1646
- /**
1647
- * Gets the ignore configuration from rule options
1648
- * @returns Array of attribute names to ignore
1649
- */
1650
1595
  function getIgnoreConfig() {
1651
1596
  return context.options[0]?.ignore ?? DEFAULTS.ignore;
1652
1597
  }
1653
- /**
1654
- * Gets the requireDataLowercase option from rule options
1655
- * @returns Whether data attributes must be lowercase
1656
- */
1657
1598
  function getRequireDataLowercase() {
1658
1599
  return context.options[0]?.requireDataLowercase ?? DEFAULTS.requireDataLowercase;
1659
1600
  }
@@ -1749,11 +1690,13 @@ var no_unsafe_iframe_sandbox_default = createRule({
1749
1690
  function create$3(context) {
1750
1691
  const resolver = createJsxElementResolver(context);
1751
1692
  return { JSXElement(node) {
1752
- if (resolver.resolve(node).domElementType !== "iframe") return;
1693
+ const { domElementType } = resolver.resolve(node);
1694
+ if (domElementType !== "iframe") return;
1753
1695
  const sandboxProp = findAttribute(context, node, "sandbox");
1754
1696
  if (sandboxProp == null) return;
1755
1697
  const sandboxValue = resolveAttributeValue(context, sandboxProp, "sandbox");
1756
- if (isUnsafeSandboxCombination(sandboxValue.toStatic())) context.report({
1698
+ if (!isUnsafeSandboxCombination(sandboxValue.toStatic())) return;
1699
+ context.report({
1757
1700
  messageId: "default",
1758
1701
  node: sandboxValue.node ?? sandboxProp
1759
1702
  });
@@ -1808,8 +1751,8 @@ function create$2(context) {
1808
1751
  const { domElementType } = resolver.resolve(node);
1809
1752
  if (domElementType !== "a") return;
1810
1753
  if (getAttributeStaticValue(context, node, "target") !== "_blank") return;
1811
- const hrefValueString = getAttributeStaticValue(context, node, "href");
1812
- if (!isExternalLinkLike(hrefValueString)) return;
1754
+ const hrefValue = getAttributeStaticValue(context, node, "href");
1755
+ if (!isExternalLinkLike(hrefValue)) return;
1813
1756
  const relProp = findAttribute(context, node, "rel");
1814
1757
  if (relProp == null) {
1815
1758
  context.report({
@@ -1824,8 +1767,8 @@ function create$2(context) {
1824
1767
  });
1825
1768
  return;
1826
1769
  }
1827
- const relValueString = getAttributeStaticValue(context, node, "rel");
1828
- if (isSafeRel(relValueString)) return;
1770
+ const relValue = getAttributeStaticValue(context, node, "rel");
1771
+ if (isSafeRel(relValue)) return;
1829
1772
  context.report({
1830
1773
  messageId: "default",
1831
1774
  node: relProp,
@@ -1858,43 +1801,26 @@ function create$1(context) {
1858
1801
  if (!context.sourceCode.text.includes("useFormState")) return {};
1859
1802
  const settings = getSettingsFromContext(context);
1860
1803
  if (compare(settings.version, "19.0.0", "<")) return {};
1861
- const reactDomNames = /* @__PURE__ */ new Set();
1862
- const useFormStateNames = /* @__PURE__ */ new Set();
1863
- return {
1864
- CallExpression(node) {
1865
- const callee = Extract.unwrap(node.callee);
1866
- switch (true) {
1867
- case Check.isIdentifier(callee) && useFormStateNames.has(callee.name):
1868
- context.report({
1869
- fix: buildFix(context, node),
1870
- messageId: "default",
1871
- node
1872
- });
1873
- return;
1874
- case callee.type === AST_NODE_TYPES.MemberExpression && Check.isIdentifier(callee.object) && Extract.getCalleeName(node) === "useFormState" && reactDomNames.has(callee.object.name):
1875
- context.report({
1876
- fix: buildFix(context, node),
1877
- messageId: "default",
1878
- node
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
- }
1804
+ const imports = createImportLookup(context.sourceCode.ast, { source: "react-dom" });
1805
+ return { CallExpression(node) {
1806
+ const callee = Extract.unwrap(node.callee);
1807
+ switch (true) {
1808
+ case Check.isIdentifier(callee) && imports.has(callee.name, "useFormState"):
1809
+ context.report({
1810
+ fix: buildFix(context, node),
1811
+ messageId: "default",
1812
+ node
1813
+ });
1814
+ return;
1815
+ case callee.type === AST_NODE_TYPES.MemberExpression && Check.isIdentifier(callee.object) && Extract.getCalleeName(node) === "useFormState" && imports.hasNamespace(callee.object.name):
1816
+ context.report({
1817
+ fix: buildFix(context, node),
1818
+ messageId: "default",
1819
+ node
1820
+ });
1821
+ return;
1896
1822
  }
1897
- };
1823
+ } };
1898
1824
  }
1899
1825
  function buildFix(context, node) {
1900
1826
  const { importSource } = getSettingsFromContext(context);
@@ -1905,7 +1831,7 @@ function buildFix(context, node) {
1905
1831
 
1906
1832
  //#endregion
1907
1833
  //#region src/rules/no-void-elements-with-children/lib.ts
1908
- const VOID_ELEMENTS = /* @__PURE__ */ new Set([
1834
+ const KNOWN_VOID_ELEMENTS = /* @__PURE__ */ new Set([
1909
1835
  "area",
1910
1836
  "base",
1911
1837
  "br",
@@ -1942,7 +1868,7 @@ function create(context) {
1942
1868
  const resolver = createJsxElementResolver(context);
1943
1869
  return { JSXElement(node) {
1944
1870
  const { domElementType } = resolver.resolve(node);
1945
- if (!VOID_ELEMENTS.has(domElementType)) return;
1871
+ if (!KNOWN_VOID_ELEMENTS.has(domElementType)) return;
1946
1872
  if (node.children.length > 0 || hasAnyAttribute(context, node, ["children", "dangerouslySetInnerHTML"])) context.report({
1947
1873
  data: { elementType: domElementType },
1948
1874
  messageId: "default",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-react-dom",
3
- "version": "5.20.1",
3
+ "version": "5.20.3",
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.1",
41
- "@eslint-react/core": "5.20.1",
42
- "@eslint-react/eslint": "5.20.1",
43
- "@eslint-react/jsx": "5.20.1",
44
- "@eslint-react/shared": "5.20.1",
40
+ "@eslint-react/ast": "5.20.3",
41
+ "@eslint-react/core": "5.20.3",
42
+ "@eslint-react/eslint": "5.20.3",
43
+ "@eslint-react/jsx": "5.20.3",
44
+ "@eslint-react/shared": "5.20.3",
45
+ "@eslint-react/var": "5.20.3",
45
46
  "@typescript-eslint/types": "^8.70.0",
46
47
  "@typescript-eslint/utils": "^8.70.0",
47
48
  "compare-versions": "^6.1.1"