eslint-plugin-react-dom 1.52.3-next.9 → 2.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,34 +1,11 @@
1
- 'use strict';
2
-
3
- var shared = require('@eslint-react/shared');
4
- var ER = require('@eslint-react/core');
5
- var utils = require('@typescript-eslint/utils');
6
- var AST = require('@eslint-react/ast');
7
- var types = require('@typescript-eslint/types');
8
- var compareVersions = require('compare-versions');
9
- var kit = require('@eslint-react/kit');
10
- var eff = require('@eslint-react/eff');
11
-
12
- function _interopNamespace(e) {
13
- if (e && e.__esModule) return e;
14
- var n = Object.create(null);
15
- if (e) {
16
- Object.keys(e).forEach(function (k) {
17
- if (k !== 'default') {
18
- var d = Object.getOwnPropertyDescriptor(e, k);
19
- Object.defineProperty(n, k, d.get ? d : {
20
- enumerable: true,
21
- get: function () { return e[k]; }
22
- });
23
- }
24
- });
25
- }
26
- n.default = e;
27
- return Object.freeze(n);
28
- }
29
-
30
- var ER__namespace = /*#__PURE__*/_interopNamespace(ER);
31
- var AST__namespace = /*#__PURE__*/_interopNamespace(AST);
1
+ import { getDocsUrl, getSettingsFromContext, DEFAULT_ESLINT_REACT_SETTINGS } from '@eslint-react/shared';
2
+ import * as ER from '@eslint-react/core';
3
+ import { ESLintUtils } from '@typescript-eslint/utils';
4
+ import { unit } from '@eslint-react/eff';
5
+ import * as AST from '@eslint-react/ast';
6
+ import { AST_NODE_TYPES } from '@typescript-eslint/types';
7
+ import { compare } from 'compare-versions';
8
+ import { RegExp, Reporter } from '@eslint-react/kit';
32
9
 
33
10
  var __defProp = Object.defineProperty;
34
11
  var __export = (target, all) => {
@@ -62,17 +39,17 @@ var rules = {
62
39
  "react-dom/no-void-elements-with-children": "error"
63
40
  };
64
41
  var settings = {
65
- "react-x": shared.DEFAULT_ESLINT_REACT_SETTINGS
42
+ "react-x": DEFAULT_ESLINT_REACT_SETTINGS
66
43
  };
67
44
 
68
45
  // package.json
69
46
  var name2 = "eslint-plugin-react-dom";
70
- var version = "1.52.3-next.9";
47
+ var version = "2.0.0-beta.1";
71
48
  function createJsxElementResolver(context) {
72
- const { components, polymorphicPropName } = shared.getSettingsFromContext(context);
49
+ const { components, polymorphicPropName } = getSettingsFromContext(context);
73
50
  return {
74
51
  resolve(node) {
75
- const name3 = ER__namespace.getElementType(context, node);
52
+ const name3 = ER.getElementType(context, node);
76
53
  const component = components.findLast((c) => c.name === name3 || c.re.test(name3));
77
54
  const result = {
78
55
  attributes: component?.attributes ?? [],
@@ -83,14 +60,14 @@ function createJsxElementResolver(context) {
83
60
  return result;
84
61
  }
85
62
  const initialScope = context.sourceCode.getScope(node);
86
- const polymorphicPropAttr = ER__namespace.getAttribute(
63
+ const polymorphicPropAttr = ER.getAttribute(
87
64
  context,
88
65
  polymorphicPropName,
89
66
  node.openingElement.attributes,
90
67
  initialScope
91
68
  );
92
69
  if (polymorphicPropAttr != null) {
93
- const polymorphicPropValue = ER__namespace.getAttributeValue(
70
+ const polymorphicPropValue = ER.getAttributeValue(
94
71
  context,
95
72
  polymorphicPropAttr,
96
73
  polymorphicPropName
@@ -106,12 +83,45 @@ function createJsxElementResolver(context) {
106
83
  }
107
84
  };
108
85
  }
109
- var createRule = utils.ESLintUtils.RuleCreator(shared.getDocsUrl("dom"));
86
+ var createRule = ESLintUtils.RuleCreator(getDocsUrl("dom"));
110
87
 
111
88
  // src/utils/find-custom-component.ts
112
89
  function findCustomComponentProp(name3, props) {
113
90
  return props.findLast((a) => a.as === name3);
114
91
  }
92
+ function resolveAttribute(context, attributes, elementNode, attributeName) {
93
+ const customComponentProp = findCustomComponentProp(attributeName, attributes);
94
+ const propNameOnJsx = customComponentProp?.name ?? attributeName;
95
+ const attribute = ER.getAttribute(
96
+ context,
97
+ propNameOnJsx,
98
+ elementNode.openingElement.attributes,
99
+ context.sourceCode.getScope(elementNode)
100
+ );
101
+ if (attribute == null) {
102
+ return {
103
+ attribute: unit,
104
+ attributeName: propNameOnJsx,
105
+ attributeValue: unit,
106
+ attributeValueString: customComponentProp?.defaultValue
107
+ };
108
+ }
109
+ const attributeValue = ER.getAttributeValue(context, attribute, propNameOnJsx);
110
+ if (attributeValue.kind === "some" && typeof attributeValue.value === "string") {
111
+ return {
112
+ attribute,
113
+ attributeName: propNameOnJsx,
114
+ attributeValue,
115
+ attributeValueString: attributeValue.value
116
+ };
117
+ }
118
+ return {
119
+ attribute,
120
+ attributeName: propNameOnJsx,
121
+ attributeValue: unit,
122
+ attributeValueString: customComponentProp?.defaultValue ?? unit
123
+ };
124
+ }
115
125
 
116
126
  // src/rules/no-dangerously-set-innerhtml.ts
117
127
  var RULE_NAME = "no-dangerously-set-innerhtml";
@@ -137,7 +147,7 @@ function create(context) {
137
147
  if (!context.sourceCode.text.includes(dangerouslySetInnerHTML)) return {};
138
148
  return {
139
149
  JSXElement(node) {
140
- const attribute = ER__namespace.getAttribute(
150
+ const attribute = ER.getAttribute(
141
151
  context,
142
152
  dangerouslySetInnerHTML,
143
153
  node.openingElement.attributes,
@@ -176,8 +186,8 @@ function create2(context) {
176
186
  JSXElement(node) {
177
187
  const attributes = node.openingElement.attributes;
178
188
  const initialScope = context.sourceCode.getScope(node);
179
- const hasChildren = hasChildrenWithin(node) || ER__namespace.hasAttribute(context, "children", attributes, initialScope);
180
- if (hasChildren && ER__namespace.hasAttribute(context, dangerouslySetInnerHTML2, attributes, initialScope)) {
189
+ const hasChildren = hasChildrenWithin(node) || ER.hasAttribute(context, "children", attributes, initialScope);
190
+ if (hasChildren && ER.hasAttribute(context, dangerouslySetInnerHTML2, attributes, initialScope)) {
181
191
  context.report({
182
192
  messageId: "noDangerouslySetInnerhtmlWithChildren",
183
193
  node
@@ -187,7 +197,7 @@ function create2(context) {
187
197
  };
188
198
  }
189
199
  function hasChildrenWithin(node) {
190
- return node.children.length > 0 && node.children[0] != null && !AST__namespace.isLineBreak(node.children[0]);
200
+ return node.children.length > 0 && node.children[0] != null && !AST.isLineBreak(node.children[0]);
191
201
  }
192
202
  var RULE_NAME3 = "no-find-dom-node";
193
203
  var RULE_FEATURES3 = [];
@@ -214,13 +224,13 @@ function create3(context) {
214
224
  CallExpression(node) {
215
225
  const { callee } = node;
216
226
  switch (callee.type) {
217
- case types.AST_NODE_TYPES.Identifier:
227
+ case AST_NODE_TYPES.Identifier:
218
228
  if (callee.name === findDOMNode) {
219
229
  context.report({ messageId: "noFindDomNode", node });
220
230
  }
221
231
  return;
222
- case types.AST_NODE_TYPES.MemberExpression:
223
- if (callee.property.type === types.AST_NODE_TYPES.Identifier && callee.property.name === findDOMNode) {
232
+ case AST_NODE_TYPES.MemberExpression:
233
+ if (callee.property.type === AST_NODE_TYPES.Identifier && callee.property.name === findDOMNode) {
224
234
  context.report({ messageId: "noFindDomNode", node });
225
235
  }
226
236
  return;
@@ -253,13 +263,13 @@ function create4(context) {
253
263
  CallExpression(node) {
254
264
  const { callee } = node;
255
265
  switch (callee.type) {
256
- case types.AST_NODE_TYPES.Identifier:
266
+ case AST_NODE_TYPES.Identifier:
257
267
  if (callee.name === flushSync) {
258
268
  context.report({ messageId: "noFlushSync", node });
259
269
  }
260
270
  return;
261
- case types.AST_NODE_TYPES.MemberExpression:
262
- if (callee.property.type === types.AST_NODE_TYPES.Identifier && callee.property.name === flushSync) {
271
+ case AST_NODE_TYPES.MemberExpression:
272
+ if (callee.property.type === AST_NODE_TYPES.Identifier && callee.property.name === flushSync) {
263
273
  context.report({ messageId: "noFlushSync", node });
264
274
  }
265
275
  return;
@@ -291,21 +301,21 @@ var no_hydrate_default = createRule({
291
301
  var hydrate = "hydrate";
292
302
  function create5(context) {
293
303
  if (!context.sourceCode.text.includes(hydrate)) return {};
294
- const settings2 = shared.getSettingsFromContext(context);
295
- if (compareVersions.compare(settings2.version, "18.0.0", "<")) return {};
304
+ const settings2 = getSettingsFromContext(context);
305
+ if (compare(settings2.version, "18.0.0", "<")) return {};
296
306
  const reactDomNames = /* @__PURE__ */ new Set();
297
307
  const hydrateNames = /* @__PURE__ */ new Set();
298
308
  return {
299
309
  CallExpression(node) {
300
310
  switch (true) {
301
- case (node.callee.type === types.AST_NODE_TYPES.Identifier && hydrateNames.has(node.callee.name)):
311
+ case (node.callee.type === AST_NODE_TYPES.Identifier && hydrateNames.has(node.callee.name)):
302
312
  context.report({
303
313
  messageId: "noHydrate",
304
314
  node,
305
315
  fix: getFix(context, node)
306
316
  });
307
317
  return;
308
- case (node.callee.type === types.AST_NODE_TYPES.MemberExpression && node.callee.object.type === types.AST_NODE_TYPES.Identifier && node.callee.property.type === types.AST_NODE_TYPES.Identifier && node.callee.property.name === hydrate && reactDomNames.has(node.callee.object.name)):
318
+ case (node.callee.type === AST_NODE_TYPES.MemberExpression && node.callee.object.type === AST_NODE_TYPES.Identifier && node.callee.property.type === AST_NODE_TYPES.Identifier && node.callee.property.name === hydrate && reactDomNames.has(node.callee.object.name)):
309
319
  context.report({
310
320
  messageId: "noHydrate",
311
321
  node,
@@ -319,14 +329,14 @@ function create5(context) {
319
329
  if (baseSource !== "react-dom") return;
320
330
  for (const specifier of node.specifiers) {
321
331
  switch (specifier.type) {
322
- case types.AST_NODE_TYPES.ImportSpecifier:
323
- if (specifier.imported.type !== types.AST_NODE_TYPES.Identifier) continue;
332
+ case AST_NODE_TYPES.ImportSpecifier:
333
+ if (specifier.imported.type !== AST_NODE_TYPES.Identifier) continue;
324
334
  if (specifier.imported.name === hydrate) {
325
335
  hydrateNames.add(specifier.local.name);
326
336
  }
327
337
  continue;
328
- case types.AST_NODE_TYPES.ImportDefaultSpecifier:
329
- case types.AST_NODE_TYPES.ImportNamespaceSpecifier:
338
+ case AST_NODE_TYPES.ImportDefaultSpecifier:
339
+ case AST_NODE_TYPES.ImportNamespaceSpecifier:
330
340
  reactDomNames.add(specifier.local.name);
331
341
  continue;
332
342
  }
@@ -345,8 +355,13 @@ function getFix(context, node) {
345
355
  ];
346
356
  };
347
357
  }
358
+
359
+ // src/rules/no-missing-button-type.ts
348
360
  var RULE_NAME6 = "no-missing-button-type";
349
- var RULE_FEATURES6 = [];
361
+ var RULE_FEATURES6 = [
362
+ "FIX"
363
+ ];
364
+ var BUTTON_TYPES = ["button", "submit", "reset"];
350
365
  var no_missing_button_type_default = createRule({
351
366
  meta: {
352
367
  type: "problem",
@@ -354,7 +369,9 @@ var no_missing_button_type_default = createRule({
354
369
  description: "Enforces explicit `type` attribute for `button` elements.",
355
370
  [Symbol.for("rule_features")]: RULE_FEATURES6
356
371
  },
372
+ hasSuggestions: true,
357
373
  messages: {
374
+ addButtonType: "Add 'type' attribute with value '{{type}}'.",
358
375
  noMissingButtonType: "Add missing 'type' attribute on 'button' component."
359
376
  },
360
377
  schema: []
@@ -369,60 +386,42 @@ function create6(context) {
369
386
  JSXElement(node) {
370
387
  const { attributes, domElementType } = resolver.resolve(node);
371
388
  if (domElementType !== "button") return;
372
- const customComponentProp = findCustomComponentProp("type", attributes);
373
- const propNameOnJsx = customComponentProp?.name ?? "type";
374
- const attributeNode = ER__namespace.getAttribute(
375
- context,
376
- propNameOnJsx,
377
- node.openingElement.attributes,
378
- context.sourceCode.getScope(node)
379
- );
380
- if (attributeNode != null) {
381
- const attributeValue = ER__namespace.getAttributeValue(
382
- context,
383
- attributeNode,
384
- propNameOnJsx
385
- );
386
- if (attributeValue.kind === "some" && typeof attributeValue.value !== "string") {
387
- context.report({
388
- messageId: "noMissingButtonType",
389
- node: attributeNode
390
- });
391
- }
392
- return;
393
- }
394
- if (typeof customComponentProp?.defaultValue !== "string") {
389
+ const typeAttribute = resolveAttribute(context, attributes, node, "type");
390
+ if (typeAttribute.attributeValueString != null) return;
391
+ if (typeAttribute.attribute == null) {
395
392
  context.report({
396
393
  messageId: "noMissingButtonType",
397
- node
394
+ node: node.openingElement,
395
+ suggest: getSuggest((type) => (fixer) => {
396
+ return fixer.insertTextAfter(node.openingElement.name, ` ${typeAttribute.attributeName}="${type}"`);
397
+ })
398
398
  });
399
+ return;
399
400
  }
401
+ context.report({
402
+ messageId: "noMissingButtonType",
403
+ node: typeAttribute.attributeValue?.node ?? typeAttribute.attribute,
404
+ suggest: getSuggest((type) => (fixer) => {
405
+ if (typeAttribute.attribute == null) return null;
406
+ return fixer.replaceText(typeAttribute.attribute, `${typeAttribute.attributeName}="${type}"`);
407
+ })
408
+ });
400
409
  }
401
410
  };
402
411
  }
412
+ function getSuggest(getFix4) {
413
+ return BUTTON_TYPES.map((type) => ({
414
+ messageId: "addButtonType",
415
+ data: { type },
416
+ fix: getFix4(type)
417
+ }));
418
+ }
419
+
420
+ // src/rules/no-missing-iframe-sandbox.ts
403
421
  var RULE_NAME7 = "no-missing-iframe-sandbox";
404
- var RULE_FEATURES7 = [];
405
- var validTypes = [
406
- "",
407
- "allow-downloads",
408
- "allow-downloads-without-user-activation",
409
- "allow-forms",
410
- "allow-modals",
411
- "allow-orientation-lock",
412
- "allow-pointer-lock",
413
- "allow-popups",
414
- "allow-popups-to-escape-sandbox",
415
- "allow-presentation",
416
- "allow-same-origin",
417
- "allow-scripts",
418
- "allow-storage-access-by-user-activation",
419
- "allow-top-navigation",
420
- "allow-top-navigation-by-user-activation",
421
- "allow-top-navigation-to-custom-protocols"
422
+ var RULE_FEATURES7 = [
423
+ "FIX"
422
424
  ];
423
- function hasValidSandBox(value) {
424
- return typeof value === "string" && value.split(" ").every((value2) => validTypes.some((valid) => valid === value2));
425
- }
426
425
  var no_missing_iframe_sandbox_default = createRule({
427
426
  meta: {
428
427
  type: "problem",
@@ -430,7 +429,10 @@ var no_missing_iframe_sandbox_default = createRule({
430
429
  description: "Enforces explicit `sandbox` attribute for `iframe` elements.",
431
430
  [Symbol.for("rule_features")]: RULE_FEATURES7
432
431
  },
432
+ fixable: "code",
433
+ hasSuggestions: true,
433
434
  messages: {
435
+ addIframeSandbox: "Add 'sandbox' attribute with value '{{value}}'.",
434
436
  noMissingIframeSandbox: "Add missing 'sandbox' attribute on 'iframe' component."
435
437
  },
436
438
  schema: []
@@ -445,33 +447,34 @@ function create7(context) {
445
447
  JSXElement(node) {
446
448
  const { attributes, domElementType } = resolver.resolve(node);
447
449
  if (domElementType !== "iframe") return;
448
- const customComponentProp = findCustomComponentProp("sandbox", attributes);
449
- const propNameOnJsx = customComponentProp?.name ?? "sandbox";
450
- const attributeNode = ER__namespace.getAttribute(
451
- context,
452
- propNameOnJsx,
453
- node.openingElement.attributes,
454
- context.sourceCode.getScope(node)
455
- );
456
- if (attributeNode != null) {
457
- const attributeValue = ER__namespace.getAttributeValue(
458
- context,
459
- attributeNode,
460
- propNameOnJsx
461
- );
462
- if (attributeValue.kind === "some" && hasValidSandBox(attributeValue.value)) return;
450
+ const sandboxAttribute = resolveAttribute(context, attributes, node, "sandbox");
451
+ if (sandboxAttribute.attributeValueString != null) return;
452
+ if (sandboxAttribute.attribute == null) {
463
453
  context.report({
464
454
  messageId: "noMissingIframeSandbox",
465
- node: attributeNode
455
+ node: node.openingElement,
456
+ suggest: [{
457
+ messageId: "addIframeSandbox",
458
+ data: { value: "" },
459
+ fix(fixer) {
460
+ return fixer.insertTextAfter(node.openingElement.name, ` ${sandboxAttribute.attributeName}=""`);
461
+ }
462
+ }]
466
463
  });
467
464
  return;
468
465
  }
469
- if (!hasValidSandBox(customComponentProp?.defaultValue)) {
470
- context.report({
471
- messageId: "noMissingIframeSandbox",
472
- node
473
- });
474
- }
466
+ context.report({
467
+ messageId: "noMissingIframeSandbox",
468
+ node: sandboxAttribute.attributeValue?.node ?? sandboxAttribute.attribute,
469
+ suggest: [{
470
+ messageId: "addIframeSandbox",
471
+ data: { value: "" },
472
+ fix(fixer) {
473
+ if (sandboxAttribute.attribute == null) return null;
474
+ return fixer.replaceText(sandboxAttribute.attribute, `${sandboxAttribute.attributeName}=""`);
475
+ }
476
+ }]
477
+ });
475
478
  }
476
479
  };
477
480
  }
@@ -496,7 +499,7 @@ var no_namespace_default = createRule({
496
499
  function create8(context) {
497
500
  return {
498
501
  JSXElement(node) {
499
- const name3 = ER__namespace.getElementType(context, node);
502
+ const name3 = ER.getElementType(context, node);
500
503
  if (typeof name3 !== "string" || !name3.includes(":")) {
501
504
  return;
502
505
  }
@@ -533,21 +536,21 @@ var no_render_default = createRule({
533
536
  });
534
537
  function create9(context) {
535
538
  if (!context.sourceCode.text.includes("render")) return {};
536
- const settings2 = shared.getSettingsFromContext(context);
537
- if (compareVersions.compare(settings2.version, "18.0.0", "<")) return {};
539
+ const settings2 = getSettingsFromContext(context);
540
+ if (compare(settings2.version, "18.0.0", "<")) return {};
538
541
  const reactDomNames = /* @__PURE__ */ new Set(["ReactDOM", "ReactDom"]);
539
542
  const renderNames = /* @__PURE__ */ new Set();
540
543
  return {
541
544
  CallExpression(node) {
542
545
  switch (true) {
543
- case (node.callee.type === types.AST_NODE_TYPES.Identifier && renderNames.has(node.callee.name)):
546
+ case (node.callee.type === AST_NODE_TYPES.Identifier && renderNames.has(node.callee.name)):
544
547
  context.report({
545
548
  messageId: "noRender",
546
549
  node,
547
550
  fix: getFix2(context, node)
548
551
  });
549
552
  return;
550
- case (node.callee.type === types.AST_NODE_TYPES.MemberExpression && node.callee.object.type === types.AST_NODE_TYPES.Identifier && node.callee.property.type === types.AST_NODE_TYPES.Identifier && node.callee.property.name === "render" && reactDomNames.has(node.callee.object.name)):
553
+ case (node.callee.type === AST_NODE_TYPES.MemberExpression && node.callee.object.type === AST_NODE_TYPES.Identifier && node.callee.property.type === AST_NODE_TYPES.Identifier && node.callee.property.name === "render" && reactDomNames.has(node.callee.object.name)):
551
554
  context.report({
552
555
  messageId: "noRender",
553
556
  node,
@@ -561,14 +564,14 @@ function create9(context) {
561
564
  if (baseSource !== "react-dom") return;
562
565
  for (const specifier of node.specifiers) {
563
566
  switch (specifier.type) {
564
- case types.AST_NODE_TYPES.ImportSpecifier:
565
- if (specifier.imported.type !== types.AST_NODE_TYPES.Identifier) continue;
567
+ case AST_NODE_TYPES.ImportSpecifier:
568
+ if (specifier.imported.type !== AST_NODE_TYPES.Identifier) continue;
566
569
  if (specifier.imported.name === "render") {
567
570
  renderNames.add(specifier.local.name);
568
571
  }
569
572
  continue;
570
- case types.AST_NODE_TYPES.ImportDefaultSpecifier:
571
- case types.AST_NODE_TYPES.ImportNamespaceSpecifier:
573
+ case AST_NODE_TYPES.ImportDefaultSpecifier:
574
+ case AST_NODE_TYPES.ImportNamespaceSpecifier:
572
575
  reactDomNames.add(specifier.local.name);
573
576
  continue;
574
577
  }
@@ -590,11 +593,11 @@ function getFix2(context, node) {
590
593
  var RULE_NAME10 = "no-render-return-value";
591
594
  var RULE_FEATURES10 = [];
592
595
  var banParentTypes = [
593
- types.AST_NODE_TYPES.VariableDeclarator,
594
- types.AST_NODE_TYPES.Property,
595
- types.AST_NODE_TYPES.ReturnStatement,
596
- types.AST_NODE_TYPES.ArrowFunctionExpression,
597
- types.AST_NODE_TYPES.AssignmentExpression
596
+ AST_NODE_TYPES.VariableDeclarator,
597
+ AST_NODE_TYPES.Property,
598
+ AST_NODE_TYPES.ReturnStatement,
599
+ AST_NODE_TYPES.ArrowFunctionExpression,
600
+ AST_NODE_TYPES.AssignmentExpression
598
601
  ];
599
602
  var no_render_return_value_default = createRule({
600
603
  meta: {
@@ -618,13 +621,13 @@ function create10(context) {
618
621
  return {
619
622
  CallExpression(node) {
620
623
  switch (true) {
621
- case (node.callee.type === types.AST_NODE_TYPES.Identifier && renderNames.has(node.callee.name) && banParentTypes.includes(node.parent.type)):
624
+ case (node.callee.type === AST_NODE_TYPES.Identifier && renderNames.has(node.callee.name) && banParentTypes.includes(node.parent.type)):
622
625
  context.report({
623
626
  messageId: "noRenderReturnValue",
624
627
  node
625
628
  });
626
629
  return;
627
- case (node.callee.type === types.AST_NODE_TYPES.MemberExpression && node.callee.object.type === types.AST_NODE_TYPES.Identifier && node.callee.property.type === types.AST_NODE_TYPES.Identifier && node.callee.property.name === "render" && reactDomNames.has(node.callee.object.name) && banParentTypes.includes(node.parent.type)):
630
+ case (node.callee.type === AST_NODE_TYPES.MemberExpression && node.callee.object.type === AST_NODE_TYPES.Identifier && node.callee.property.type === AST_NODE_TYPES.Identifier && node.callee.property.name === "render" && reactDomNames.has(node.callee.object.name) && banParentTypes.includes(node.parent.type)):
628
631
  context.report({
629
632
  messageId: "noRenderReturnValue",
630
633
  node
@@ -637,14 +640,14 @@ function create10(context) {
637
640
  if (baseSource !== "react-dom") return;
638
641
  for (const specifier of node.specifiers) {
639
642
  switch (specifier.type) {
640
- case types.AST_NODE_TYPES.ImportSpecifier:
641
- if (specifier.imported.type !== types.AST_NODE_TYPES.Identifier) continue;
643
+ case AST_NODE_TYPES.ImportSpecifier:
644
+ if (specifier.imported.type !== AST_NODE_TYPES.Identifier) continue;
642
645
  if (specifier.imported.name === "render") {
643
646
  renderNames.add(specifier.local.name);
644
647
  }
645
648
  continue;
646
- case types.AST_NODE_TYPES.ImportDefaultSpecifier:
647
- case types.AST_NODE_TYPES.ImportNamespaceSpecifier:
649
+ case AST_NODE_TYPES.ImportDefaultSpecifier:
650
+ case AST_NODE_TYPES.ImportNamespaceSpecifier:
648
651
  reactDomNames.add(specifier.local.name);
649
652
  continue;
650
653
  }
@@ -673,12 +676,12 @@ var no_script_url_default = createRule({
673
676
  function create11(context) {
674
677
  return {
675
678
  JSXAttribute(node) {
676
- if (node.name.type !== types.AST_NODE_TYPES.JSXIdentifier || node.value == null) {
679
+ if (node.name.type !== AST_NODE_TYPES.JSXIdentifier || node.value == null) {
677
680
  return;
678
681
  }
679
- const attributeValue = ER__namespace.getAttributeValue(context, node, ER__namespace.getAttributeName(context, node));
682
+ const attributeValue = ER.getAttributeValue(context, node, ER.getAttributeName(context, node));
680
683
  if (attributeValue.kind === "none" || typeof attributeValue.value !== "string") return;
681
- if (kit.RegExp.JAVASCRIPT_PROTOCOL.test(attributeValue.value)) {
684
+ if (RegExp.JAVASCRIPT_PROTOCOL.test(attributeValue.value)) {
682
685
  context.report({
683
686
  messageId: "noScriptUrl",
684
687
  node: node.value
@@ -1655,7 +1658,7 @@ var no_unknown_property_default = createRule({
1655
1658
  defaultOptions: []
1656
1659
  });
1657
1660
  function create12(context) {
1658
- const report = kit.Reporter.make(context);
1661
+ const report = Reporter.make(context);
1659
1662
  function getIgnoreConfig() {
1660
1663
  return context.options[0]?.ignore || DEFAULTS.ignore;
1661
1664
  }
@@ -1742,15 +1745,17 @@ function getText(context, node) {
1742
1745
  return context.sourceCode.getText(node);
1743
1746
  }
1744
1747
  function testReactVersion(context, comparator, version2) {
1745
- const { version: localVersion } = shared.getSettingsFromContext(context);
1746
- return compareVersions.compare(localVersion, version2, comparator);
1748
+ const { version: localVersion } = getSettingsFromContext(context);
1749
+ return compare(localVersion, version2, comparator);
1747
1750
  }
1751
+
1752
+ // src/rules/no-unsafe-iframe-sandbox.ts
1748
1753
  var RULE_NAME13 = "no-unsafe-iframe-sandbox";
1749
1754
  var RULE_FEATURES12 = [];
1750
1755
  var unsafeSandboxValues = [
1751
1756
  ["allow-scripts", "allow-same-origin"]
1752
1757
  ];
1753
- function hasSafeSandbox(value) {
1758
+ function isSafeSandbox(value) {
1754
1759
  if (typeof value !== "string") return false;
1755
1760
  return !unsafeSandboxValues.some((values) => {
1756
1761
  return values.every((v) => value.includes(v));
@@ -1778,40 +1783,22 @@ function create13(context) {
1778
1783
  JSXElement(node) {
1779
1784
  const { attributes, domElementType } = resolver.resolve(node);
1780
1785
  if (domElementType !== "iframe") return;
1781
- const customComponentProp = findCustomComponentProp("sandbox", attributes);
1782
- const propNameOnJsx = customComponentProp?.name ?? "sandbox";
1783
- const attributeNode = ER__namespace.getAttribute(
1784
- context,
1785
- propNameOnJsx,
1786
- node.openingElement.attributes,
1787
- context.sourceCode.getScope(node)
1788
- );
1789
- if (attributeNode != null) {
1790
- const attributeValue = ER__namespace.getAttributeValue(
1791
- context,
1792
- attributeNode,
1793
- propNameOnJsx
1794
- );
1795
- if (attributeValue.kind === "some" && !hasSafeSandbox(attributeValue.value)) {
1796
- context.report({
1797
- messageId: "noUnsafeIframeSandbox",
1798
- node: attributeNode
1799
- });
1800
- return;
1801
- }
1802
- }
1803
- if (customComponentProp?.defaultValue == null) return;
1804
- if (!hasSafeSandbox(customComponentProp.defaultValue)) {
1786
+ const sandboxAttribute = resolveAttribute(context, attributes, node, "sandbox");
1787
+ if (!isSafeSandbox(sandboxAttribute.attributeValueString)) {
1805
1788
  context.report({
1806
1789
  messageId: "noUnsafeIframeSandbox",
1807
- node
1790
+ node: sandboxAttribute.attributeValue?.node ?? sandboxAttribute.attribute ?? node
1808
1791
  });
1809
1792
  }
1810
1793
  }
1811
1794
  };
1812
1795
  }
1796
+
1797
+ // src/rules/no-unsafe-target-blank.ts
1813
1798
  var RULE_NAME14 = "no-unsafe-target-blank";
1814
- var RULE_FEATURES13 = [];
1799
+ var RULE_FEATURES13 = [
1800
+ "FIX"
1801
+ ];
1815
1802
  function isExternalLinkLike(value) {
1816
1803
  if (value == null) return false;
1817
1804
  return value.startsWith("https://") || /^(?:\w+:|\/\/)/u.test(value);
@@ -1827,7 +1814,10 @@ var no_unsafe_target_blank_default = createRule({
1827
1814
  description: 'Disallow `target="_blank"` without `rel="noreferrer noopener"`.',
1828
1815
  [Symbol.for("rule_features")]: RULE_FEATURES13
1829
1816
  },
1817
+ fixable: "code",
1818
+ hasSuggestions: true,
1830
1819
  messages: {
1820
+ addRelNoreferrerNoopener: `Add 'rel="noreferrer noopener"' to the link to prevent security risks.`,
1831
1821
  noUnsafeTargetBlank: `Using 'target="_blank"' on an external link without 'rel="noreferrer noopener"' is a security risk.`
1832
1822
  },
1833
1823
  schema: []
@@ -1842,35 +1832,44 @@ function create14(context) {
1842
1832
  JSXElement(node) {
1843
1833
  const { attributes, domElementType } = resolver.resolve(node);
1844
1834
  if (domElementType !== "a") return;
1845
- const elementScope = context.sourceCode.getScope(node);
1846
- const getAttributeStringValue = (name3) => {
1847
- const customComponentProp = findCustomComponentProp(name3, attributes);
1848
- const propNameOnJsx = customComponentProp?.name ?? name3;
1849
- const attributeNode = ER__namespace.getAttribute(
1850
- context,
1851
- propNameOnJsx,
1852
- node.openingElement.attributes,
1853
- elementScope
1854
- );
1855
- if (attributeNode == null) return customComponentProp?.defaultValue;
1856
- const attributeValue = ER__namespace.getAttributeValue(context, attributeNode, propNameOnJsx);
1857
- if (attributeValue.kind === "some" && typeof attributeValue.value === "string") {
1858
- return attributeValue.value;
1859
- }
1860
- return eff.unit;
1861
- };
1862
- if (getAttributeStringValue("target") !== "_blank") {
1835
+ const targetAttribute = resolveAttribute(context, attributes, node, "target");
1836
+ if (targetAttribute.attributeValueString !== "_blank") {
1863
1837
  return;
1864
1838
  }
1865
- if (!isExternalLinkLike(getAttributeStringValue("href"))) {
1839
+ const hrefAttribute = resolveAttribute(context, attributes, node, "href");
1840
+ if (!isExternalLinkLike(hrefAttribute.attributeValueString)) {
1866
1841
  return;
1867
1842
  }
1868
- if (isSafeRel(getAttributeStringValue("rel"))) {
1843
+ const relAttribute = resolveAttribute(context, attributes, node, "rel");
1844
+ if (isSafeRel(relAttribute.attributeValueString)) {
1845
+ return;
1846
+ }
1847
+ if (relAttribute.attribute == null) {
1848
+ context.report({
1849
+ messageId: "noUnsafeTargetBlank",
1850
+ node: node.openingElement,
1851
+ suggest: [{
1852
+ messageId: "addRelNoreferrerNoopener",
1853
+ fix(fixer) {
1854
+ return fixer.insertTextAfter(
1855
+ node.openingElement.name,
1856
+ ` ${relAttribute.attributeName}="noreferrer noopener"`
1857
+ );
1858
+ }
1859
+ }]
1860
+ });
1869
1861
  return;
1870
1862
  }
1871
1863
  context.report({
1872
1864
  messageId: "noUnsafeTargetBlank",
1873
- node
1865
+ node: relAttribute.attributeValue?.node ?? relAttribute.attribute,
1866
+ suggest: [{
1867
+ messageId: "addRelNoreferrerNoopener",
1868
+ fix(fixer) {
1869
+ if (relAttribute.attribute == null) return null;
1870
+ return fixer.replaceText(relAttribute.attribute, `${relAttribute.attributeName}="noreferrer noopener"`);
1871
+ }
1872
+ }]
1874
1873
  });
1875
1874
  }
1876
1875
  };
@@ -1898,21 +1897,21 @@ var no_use_form_state_default = createRule({
1898
1897
  });
1899
1898
  function create15(context) {
1900
1899
  if (!context.sourceCode.text.includes("useFormState")) return {};
1901
- const settings2 = shared.getSettingsFromContext(context);
1902
- if (compareVersions.compare(settings2.version, "19.0.0", "<")) return {};
1900
+ const settings2 = getSettingsFromContext(context);
1901
+ if (compare(settings2.version, "19.0.0", "<")) return {};
1903
1902
  const reactDomNames = /* @__PURE__ */ new Set();
1904
1903
  const useFormStateNames = /* @__PURE__ */ new Set();
1905
1904
  return {
1906
1905
  CallExpression(node) {
1907
1906
  switch (true) {
1908
- case (node.callee.type === types.AST_NODE_TYPES.Identifier && useFormStateNames.has(node.callee.name)):
1907
+ case (node.callee.type === AST_NODE_TYPES.Identifier && useFormStateNames.has(node.callee.name)):
1909
1908
  context.report({
1910
1909
  messageId: "noUseFormState",
1911
1910
  node,
1912
1911
  fix: getFix3(context, node)
1913
1912
  });
1914
1913
  return;
1915
- case (node.callee.type === types.AST_NODE_TYPES.MemberExpression && node.callee.object.type === types.AST_NODE_TYPES.Identifier && node.callee.property.type === types.AST_NODE_TYPES.Identifier && node.callee.property.name === "useFormState" && reactDomNames.has(node.callee.object.name)):
1914
+ case (node.callee.type === AST_NODE_TYPES.MemberExpression && node.callee.object.type === AST_NODE_TYPES.Identifier && node.callee.property.type === AST_NODE_TYPES.Identifier && node.callee.property.name === "useFormState" && reactDomNames.has(node.callee.object.name)):
1916
1915
  context.report({
1917
1916
  messageId: "noUseFormState",
1918
1917
  node,
@@ -1926,14 +1925,14 @@ function create15(context) {
1926
1925
  if (baseSource !== "react-dom") return;
1927
1926
  for (const specifier of node.specifiers) {
1928
1927
  switch (specifier.type) {
1929
- case types.AST_NODE_TYPES.ImportSpecifier:
1930
- if (specifier.imported.type !== types.AST_NODE_TYPES.Identifier) continue;
1928
+ case AST_NODE_TYPES.ImportSpecifier:
1929
+ if (specifier.imported.type !== AST_NODE_TYPES.Identifier) continue;
1931
1930
  if (specifier.imported.name === "useFormState") {
1932
1931
  useFormStateNames.add(specifier.local.name);
1933
1932
  }
1934
1933
  continue;
1935
- case types.AST_NODE_TYPES.ImportDefaultSpecifier:
1936
- case types.AST_NODE_TYPES.ImportNamespaceSpecifier:
1934
+ case AST_NODE_TYPES.ImportDefaultSpecifier:
1935
+ case AST_NODE_TYPES.ImportNamespaceSpecifier:
1937
1936
  reactDomNames.add(specifier.local.name);
1938
1937
  continue;
1939
1938
  }
@@ -1942,7 +1941,7 @@ function create15(context) {
1942
1941
  };
1943
1942
  }
1944
1943
  function getFix3(context, node) {
1945
- const { importSource } = shared.getSettingsFromContext(context);
1944
+ const { importSource } = getSettingsFromContext(context);
1946
1945
  return (fixer) => {
1947
1946
  return [
1948
1947
  fixer.insertTextBefore(context.sourceCode.ast, `import { useActionState } from "${importSource}";
@@ -2006,7 +2005,7 @@ function create16(context) {
2006
2005
  }
2007
2006
  const { attributes } = node.openingElement;
2008
2007
  const initialScope = context.sourceCode.getScope(node);
2009
- const hasAttribute3 = (name3) => ER__namespace.hasAttribute(context, name3, attributes, initialScope);
2008
+ const hasAttribute3 = (name3) => ER.hasAttribute(context, name3, attributes, initialScope);
2010
2009
  if (hasAttribute3("children") || hasAttribute3("dangerouslySetInnerHTML")) {
2011
2010
  context.report({
2012
2011
  messageId: "noVoidElementsWithChildren",
@@ -2042,10 +2041,7 @@ var plugin = {
2042
2041
  "no-unsafe-iframe-sandbox": no_unsafe_iframe_sandbox_default,
2043
2042
  "no-unsafe-target-blank": no_unsafe_target_blank_default,
2044
2043
  "no-use-form-state": no_use_form_state_default,
2045
- "no-void-elements-with-children": no_void_elements_with_children_default,
2046
- // Part: deprecated rules
2047
- /** @deprecated Use `no-void-elements-with-children` instead */
2048
- "no-children-in-void-dom-elements": no_void_elements_with_children_default
2044
+ "no-void-elements-with-children": no_void_elements_with_children_default
2049
2045
  }
2050
2046
  };
2051
2047
 
@@ -2072,4 +2068,4 @@ var index_default = {
2072
2068
  }
2073
2069
  };
2074
2070
 
2075
- module.exports = index_default;
2071
+ export { index_default as default };