eslint-plugin-react-dom 1.24.0-next.0 → 1.24.0-next.11

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 (3) hide show
  1. package/dist/index.js +165 -107
  2. package/dist/index.mjs +164 -106
  3. package/package.json +12 -13
package/dist/index.js CHANGED
@@ -1,12 +1,9 @@
1
1
  'use strict';
2
2
 
3
- var eff = require('@eslint-react/eff');
4
- var JSX3 = require('@eslint-react/jsx');
5
- var VAR = require('@eslint-react/var');
6
- var tsPattern = require('ts-pattern');
3
+ var JSX = require('@eslint-react/jsx');
7
4
  var shared = require('@eslint-react/shared');
5
+ var VAR = require('@eslint-react/var');
8
6
  var types = require('@typescript-eslint/types');
9
- var core = require('@eslint-react/core');
10
7
  var AST = require('@eslint-react/ast');
11
8
  var compareVersions = require('compare-versions');
12
9
 
@@ -28,31 +25,41 @@ function _interopNamespace(e) {
28
25
  return Object.freeze(n);
29
26
  }
30
27
 
31
- var JSX3__namespace = /*#__PURE__*/_interopNamespace(JSX3);
28
+ var JSX__namespace = /*#__PURE__*/_interopNamespace(JSX);
32
29
  var VAR__namespace = /*#__PURE__*/_interopNamespace(VAR);
33
30
  var AST__namespace = /*#__PURE__*/_interopNamespace(AST);
34
31
 
35
32
  // package.json
36
33
  var name = "eslint-plugin-react-dom";
37
- var version = "1.24.0-next.0";
38
- function getAdditionalAttributes(name2, additionalComponents) {
39
- return additionalComponents.findLast((c) => c.name === name2 || c.re.test(name2))?.attributes ?? [];
34
+ var version = "1.24.0-next.11";
35
+ var createRule = shared.createRuleForPlugin("dom");
36
+
37
+ // src/utils/find-custom-component.ts
38
+ function findCustomComponent(name2, components) {
39
+ return components.findLast((c) => c.name === name2 || c.re.test(name2));
40
+ }
41
+ function findCustomComponentProp(name2, props) {
42
+ return props.findLast((a) => a.as === name2);
40
43
  }
41
- function getAttributeStringValue(attributeName, element, context, additionalAttributes) {
42
- const attributeConfig = additionalAttributes.findLast((attr) => attr.as === attributeName);
43
- const actualAttributeName = attributeConfig?.name ?? attributeName;
44
- const actualAttributeNode = JSX3__namespace.findPropInAttributes(
45
- actualAttributeName,
46
- context.sourceCode.getScope(element),
47
- element.openingElement.attributes
44
+ function getElementNameOnJsxAndDom(node, context, polymorphicPropName, additionalComponents = []) {
45
+ const name2 = JSX__namespace.getElementName(node);
46
+ if (name2 === name2.toLowerCase()) return [name2, name2];
47
+ const component = additionalComponents.findLast((c) => c.name === name2 || c.re.test(name2));
48
+ if (component != null) return [name2, component.as];
49
+ if (polymorphicPropName == null) return [name2, name2];
50
+ const initialScope = context.sourceCode.getScope(node);
51
+ const attributeNode = JSX__namespace.getAttributeNode(
52
+ polymorphicPropName,
53
+ initialScope,
54
+ node.attributes
48
55
  );
49
- if (actualAttributeNode === eff._) return attributeConfig?.defaultValue;
50
- const actualAttributeScope = context.sourceCode.getScope(actualAttributeNode);
51
- const actualAttributeValue = JSX3__namespace.getPropValue(actualAttributeNode, actualAttributeScope);
52
- const actualAttributeValueResolved = VAR__namespace.toResolved(actualAttributeValue).value;
53
- return tsPattern.match(actualAttributeValueResolved).with(tsPattern.P.string, eff.identity).with({ [actualAttributeName]: tsPattern.P.select(tsPattern.P.string) }, eff.identity).otherwise(() => eff._);
56
+ if (attributeNode == null) return [name2, name2];
57
+ const polymorphicPropValue = VAR__namespace.toResolved(JSX__namespace.getAttributeStaticValue(attributeNode, initialScope)).value;
58
+ if (typeof polymorphicPropValue === "string") {
59
+ return [name2, polymorphicPropValue];
60
+ }
61
+ return [name2, name2];
54
62
  }
55
- var createRule = shared.createRuleForPlugin("dom");
56
63
 
57
64
  // src/rules/no-dangerously-set-innerhtml.ts
58
65
  var RULE_NAME = "no-dangerously-set-innerhtml";
@@ -73,14 +80,19 @@ var no_dangerously_set_innerhtml_default = createRule({
73
80
  },
74
81
  name: RULE_NAME,
75
82
  create(context) {
83
+ if (!context.sourceCode.text.includes("dangerouslySetInnerHTML")) return {};
76
84
  return {
77
85
  JSXElement(node) {
78
86
  const attributes = node.openingElement.attributes;
79
- const prop = JSX3__namespace.getProp("dangerouslySetInnerHTML", context.sourceCode.getScope(node), attributes);
80
- if (prop === eff._) return;
87
+ const attribute = JSX__namespace.getAttributeNode(
88
+ "dangerouslySetInnerHTML",
89
+ context.sourceCode.getScope(node),
90
+ attributes
91
+ );
92
+ if (attribute == null) return;
81
93
  context.report({
82
94
  messageId: "noDangerouslySetInnerhtml",
83
- node: prop
95
+ node: attribute
84
96
  });
85
97
  }
86
98
  };
@@ -105,13 +117,13 @@ var no_dangerously_set_innerhtml_with_children_default = createRule({
105
117
  },
106
118
  name: RULE_NAME2,
107
119
  create(context) {
120
+ if (!context.sourceCode.text.includes("dangerouslySetInnerHTML")) return {};
108
121
  return {
109
122
  JSXElement(node) {
110
123
  const attributes = node.openingElement.attributes;
111
124
  const initialScope = context.sourceCode.getScope(node);
112
- const hasChildren = hasChildrenWithin(node) || JSX3__namespace.hasProp("children", initialScope, attributes);
113
- const hasDangerouslySetInnerHTML = JSX3__namespace.hasProp("dangerouslySetInnerHTML", initialScope, attributes);
114
- if (hasChildren && hasDangerouslySetInnerHTML) {
125
+ const hasChildren = hasChildrenWithin(node) || JSX__namespace.hasAttribute("children", initialScope, attributes);
126
+ if (hasChildren && JSX__namespace.hasAttribute("dangerouslySetInnerHTML", initialScope, attributes)) {
115
127
  context.report({
116
128
  messageId: "noDangerouslySetInnerhtmlWithChildren",
117
129
  node
@@ -123,7 +135,7 @@ var no_dangerously_set_innerhtml_with_children_default = createRule({
123
135
  defaultOptions: []
124
136
  });
125
137
  function hasChildrenWithin(node) {
126
- return node.children.length > 0 && node.children[0] != null && !JSX3__namespace.isLineBreak(node.children[0]);
138
+ return node.children.length > 0 && node.children[0] != null && !JSX__namespace.isLineBreak(node.children[0]);
127
139
  }
128
140
  var RULE_NAME3 = "no-find-dom-node";
129
141
  var RULE_FEATURES3 = [
@@ -143,6 +155,7 @@ var no_find_dom_node_default = createRule({
143
155
  },
144
156
  name: RULE_NAME3,
145
157
  create(context) {
158
+ if (!context.sourceCode.text.includes("findDOMNode")) return {};
146
159
  return {
147
160
  CallExpression(node) {
148
161
  const { callee } = node;
@@ -182,26 +195,39 @@ var no_missing_button_type_default = createRule({
182
195
  name: RULE_NAME4,
183
196
  create(context) {
184
197
  const settings = shared.getSettingsFromContext(context);
198
+ const polymorphicPropName = settings.polymorphicPropName;
185
199
  const additionalComponents = settings.additionalComponents.filter((c) => c.as === "button");
186
200
  return {
187
201
  JSXElement(node) {
188
- const [name2, representName] = core.getElementNameAndRepresentName(
202
+ const [elementNameOnJsx, elementNameOnDom] = getElementNameOnJsxAndDom(
189
203
  node.openingElement,
190
204
  context,
191
- settings.polymorphicPropName,
192
- settings.additionalComponents
205
+ polymorphicPropName,
206
+ additionalComponents
193
207
  );
194
- if (representName !== "button") return;
195
- const getPropValue3 = (propName) => {
196
- return getAttributeStringValue(
197
- propName,
198
- node,
199
- context,
200
- getAdditionalAttributes(name2, additionalComponents)
201
- );
202
- };
203
- const prop = getPropValue3("type");
204
- if (typeof prop !== "string") {
208
+ if (elementNameOnDom !== "button") return;
209
+ const elementScope = context.sourceCode.getScope(node);
210
+ const customComponent = findCustomComponent(elementNameOnJsx, additionalComponents);
211
+ const customComponentProp = findCustomComponentProp("type", customComponent?.attributes ?? []);
212
+ const propNameOnJsx = customComponentProp?.name ?? "type";
213
+ const attributeNode = JSX__namespace.getAttributeNode(
214
+ propNameOnJsx,
215
+ elementScope,
216
+ node.openingElement.attributes
217
+ );
218
+ if (attributeNode != null) {
219
+ const attributeScope = context.sourceCode.getScope(attributeNode);
220
+ const attributeStaticValue = JSX__namespace.getAttributeStaticValue(attributeNode, attributeScope);
221
+ const attributeStringValue = JSX__namespace.toResolvedAttributeValue(propNameOnJsx, attributeStaticValue);
222
+ if (typeof attributeStringValue !== "string") {
223
+ context.report({
224
+ messageId: "noMissingButtonType",
225
+ node: attributeNode
226
+ });
227
+ }
228
+ return;
229
+ }
230
+ if (typeof customComponentProp?.defaultValue !== "string") {
205
231
  context.report({
206
232
  messageId: "noMissingButtonType",
207
233
  node
@@ -234,6 +260,9 @@ var validTypes = [
234
260
  "allow-top-navigation-by-user-activation",
235
261
  "allow-top-navigation-to-custom-protocols"
236
262
  ];
263
+ function hasValidSandBox(value) {
264
+ return typeof value === "string" && value.split(" ").every((value2) => validTypes.some((valid) => valid === value2));
265
+ }
237
266
  var no_missing_iframe_sandbox_default = createRule({
238
267
  meta: {
239
268
  type: "problem",
@@ -249,37 +278,41 @@ var no_missing_iframe_sandbox_default = createRule({
249
278
  name: RULE_NAME5,
250
279
  create(context) {
251
280
  const settings = shared.getSettingsFromContext(context);
281
+ const polymorphicPropName = settings.polymorphicPropName;
252
282
  const additionalComponents = settings.additionalComponents.filter((c) => c.as === "iframe");
253
283
  return {
254
284
  JSXElement(node) {
255
- const [name2, representName] = core.getElementNameAndRepresentName(
285
+ const [elementNameOnJsx, elementNameOnDom] = getElementNameOnJsxAndDom(
256
286
  node.openingElement,
257
287
  context,
258
- settings.polymorphicPropName,
259
- settings.additionalComponents
288
+ polymorphicPropName,
289
+ additionalComponents
260
290
  );
261
- if (representName !== "iframe") return;
262
- const getPropValue3 = (propName) => {
263
- return getAttributeStringValue(
264
- propName,
265
- node,
266
- context,
267
- getAdditionalAttributes(name2, additionalComponents)
268
- );
269
- };
270
- const sandboxValue = getPropValue3("sandbox");
271
- if (sandboxValue === eff._) {
291
+ if (elementNameOnDom !== "iframe") return;
292
+ const elementScope = context.sourceCode.getScope(node);
293
+ const customComponent = findCustomComponent(elementNameOnJsx, additionalComponents);
294
+ const customComponentProp = findCustomComponentProp("sandbox", customComponent?.attributes ?? []);
295
+ const propNameOnJsx = customComponentProp?.name ?? "sandbox";
296
+ const attributeNode = JSX__namespace.getAttributeNode(
297
+ propNameOnJsx,
298
+ elementScope,
299
+ node.openingElement.attributes
300
+ );
301
+ if (attributeNode != null) {
302
+ const attributeScope = context.sourceCode.getScope(attributeNode);
303
+ const attributeStaticValue = JSX__namespace.getAttributeStaticValue(attributeNode, attributeScope);
304
+ const attributeStringValue = JSX__namespace.toResolvedAttributeValue(propNameOnJsx, attributeStaticValue);
305
+ if (hasValidSandBox(attributeStringValue)) return;
272
306
  context.report({
273
307
  messageId: "noMissingIframeSandbox",
274
- node: node.openingElement
308
+ node: attributeNode
275
309
  });
276
310
  return;
277
311
  }
278
- const values = sandboxValue.split(" ");
279
- if (!values.every((value) => validTypes.some((validType) => validType === value))) {
312
+ if (!hasValidSandBox(customComponentProp?.defaultValue)) {
280
313
  context.report({
281
314
  messageId: "noMissingIframeSandbox",
282
- node: node.openingElement
315
+ node
283
316
  });
284
317
  }
285
318
  }
@@ -307,7 +340,7 @@ var no_namespace_default = createRule({
307
340
  create(context) {
308
341
  return {
309
342
  JSXOpeningElement(node) {
310
- const name2 = JSX3__namespace.getElementName(node);
343
+ const name2 = JSX__namespace.getElementName(node);
311
344
  if (typeof name2 !== "string" || !name2.includes(":")) {
312
345
  return;
313
346
  }
@@ -399,11 +432,11 @@ var no_script_url_default = createRule({
399
432
  if (node.name.type !== types.AST_NODE_TYPES.JSXIdentifier || node.value == null) {
400
433
  return;
401
434
  }
402
- const propScope = context.sourceCode.getScope(node);
403
- const propValue = JSX3__namespace.getPropValue(node, propScope);
404
- const propValueResolved = VAR__namespace.toResolved(propValue).value;
405
- if (typeof propValueResolved !== "string") return;
406
- if (shared.RE_JAVASCRIPT_PROTOCOL.test(propValueResolved)) {
435
+ const attributeScope = context.sourceCode.getScope(node);
436
+ const attributeValue = JSX__namespace.getAttributeStaticValue(node, attributeScope);
437
+ const attributeValueResolved = VAR__namespace.toResolved(attributeValue).value;
438
+ if (typeof attributeValueResolved !== "string") return;
439
+ if (shared.RE_JAVASCRIPT_PROTOCOL.test(attributeValueResolved)) {
407
440
  context.report({
408
441
  messageId: "noScriptUrl",
409
442
  node: node.value
@@ -1475,9 +1508,15 @@ var RULE_NAME10 = "no-unsafe-iframe-sandbox";
1475
1508
  var RULE_FEATURES9 = [
1476
1509
  "CHK"
1477
1510
  ];
1478
- var unsafeCombinations = [
1511
+ var unsafeSandboxValues = [
1479
1512
  ["allow-scripts", "allow-same-origin"]
1480
1513
  ];
1514
+ function hasNoneOrSafeSandbox(value) {
1515
+ if (value == null) return true;
1516
+ return !unsafeSandboxValues.some((values) => {
1517
+ return values.every((v) => value.includes(v));
1518
+ });
1519
+ }
1481
1520
  var no_unsafe_iframe_sandbox_default = createRule({
1482
1521
  meta: {
1483
1522
  type: "problem",
@@ -1493,31 +1532,41 @@ var no_unsafe_iframe_sandbox_default = createRule({
1493
1532
  name: RULE_NAME10,
1494
1533
  create(context) {
1495
1534
  const settings = shared.getSettingsFromContext(context);
1535
+ const polymorphicPropName = settings.polymorphicPropName;
1496
1536
  const additionalComponents = settings.additionalComponents.filter((c) => c.as === "iframe");
1497
1537
  return {
1498
1538
  JSXElement(node) {
1499
- const [name2, representName] = core.getElementNameAndRepresentName(
1539
+ const [elementNameOnJsx, elementNameOnDom] = getElementNameOnJsxAndDom(
1500
1540
  node.openingElement,
1501
1541
  context,
1502
- settings.polymorphicPropName,
1503
- settings.additionalComponents
1542
+ polymorphicPropName,
1543
+ additionalComponents
1504
1544
  );
1505
- if (representName !== "iframe") return;
1506
- const getPropValue3 = (propName) => {
1507
- return getAttributeStringValue(
1508
- propName,
1509
- node,
1510
- context,
1511
- getAdditionalAttributes(name2, additionalComponents)
1512
- );
1513
- };
1514
- const sandboxValue = getPropValue3("sandbox");
1515
- if (sandboxValue === eff._) return;
1516
- const values = sandboxValue.split(" ");
1517
- if (unsafeCombinations.some((unsafes) => unsafes.every((x) => values.includes(x)))) {
1545
+ if (elementNameOnDom !== "iframe") return;
1546
+ const elementScope = context.sourceCode.getScope(node);
1547
+ const customComponent = findCustomComponent(elementNameOnJsx, additionalComponents);
1548
+ const customComponentProp = findCustomComponentProp("sandbox", customComponent?.attributes ?? []);
1549
+ const propNameOnJsx = customComponentProp?.name ?? "sandbox";
1550
+ const attributeNode = JSX__namespace.getAttributeNode(
1551
+ propNameOnJsx,
1552
+ elementScope,
1553
+ node.openingElement.attributes
1554
+ );
1555
+ if (attributeNode != null) {
1556
+ const attributeScope = context.sourceCode.getScope(attributeNode);
1557
+ const attributeStaticValue = JSX__namespace.getAttributeStaticValue(attributeNode, attributeScope);
1558
+ const attributeStringValue = JSX__namespace.toResolvedAttributeValue(propNameOnJsx, attributeStaticValue);
1559
+ if (hasNoneOrSafeSandbox(attributeStringValue)) return;
1560
+ context.report({
1561
+ messageId: "noUnsafeIframeSandbox",
1562
+ node: attributeNode
1563
+ });
1564
+ return;
1565
+ }
1566
+ if (!hasNoneOrSafeSandbox(customComponentProp?.defaultValue)) {
1518
1567
  context.report({
1519
1568
  messageId: "noUnsafeIframeSandbox",
1520
- node: node.openingElement
1569
+ node
1521
1570
  });
1522
1571
  }
1523
1572
  }
@@ -1530,11 +1579,11 @@ var RULE_FEATURES10 = [
1530
1579
  "CHK"
1531
1580
  ];
1532
1581
  function isExternalLinkLike(value) {
1533
- if (value === eff._) return false;
1582
+ if (value == null) return false;
1534
1583
  return value.startsWith("https://") || /^(?:\w+:|\/\/)/u.test(value);
1535
1584
  }
1536
1585
  function isSafeRel(value) {
1537
- if (value === eff._) return false;
1586
+ if (value == null) return false;
1538
1587
  return value === "noreferrer" || /\bnoreferrer\b/u.test(value);
1539
1588
  }
1540
1589
  var no_unsafe_target_blank_default = createRule({
@@ -1552,36 +1601,45 @@ var no_unsafe_target_blank_default = createRule({
1552
1601
  name: RULE_NAME11,
1553
1602
  create(context) {
1554
1603
  const settings = shared.getSettingsFromContext(context);
1604
+ const polymorphicPropName = settings.polymorphicPropName;
1555
1605
  const additionalComponents = settings.additionalComponents.filter((c) => c.as === "a");
1556
1606
  return {
1557
1607
  JSXElement(node) {
1558
- const [name2, representName] = core.getElementNameAndRepresentName(
1608
+ const [elementNameOnJsx, elementNameOnDom] = getElementNameOnJsxAndDom(
1559
1609
  node.openingElement,
1560
1610
  context,
1561
- settings.polymorphicPropName,
1562
- settings.additionalComponents
1611
+ polymorphicPropName,
1612
+ additionalComponents
1563
1613
  );
1564
- if (representName !== "a") return;
1565
- const getPropValue3 = (propName) => {
1566
- return getAttributeStringValue(
1567
- propName,
1568
- node,
1569
- context,
1570
- getAdditionalAttributes(name2, additionalComponents)
1614
+ if (elementNameOnDom !== "a") return;
1615
+ const elementScope = context.sourceCode.getScope(node);
1616
+ const customComponent = findCustomComponent(elementNameOnJsx, additionalComponents);
1617
+ const getAttributeValue = (name2) => {
1618
+ const customComponentProp = findCustomComponentProp(name2, customComponent?.attributes ?? []);
1619
+ const propNameOnJsx = customComponentProp?.name ?? name2;
1620
+ const attributeNode = JSX__namespace.getAttributeNode(
1621
+ propNameOnJsx,
1622
+ elementScope,
1623
+ node.openingElement.attributes
1571
1624
  );
1625
+ if (attributeNode == null) return customComponentProp?.defaultValue;
1626
+ const attributeScope = context.sourceCode.getScope(attributeNode);
1627
+ const attributeStaticValue = JSX__namespace.getAttributeStaticValue(attributeNode, attributeScope);
1628
+ return JSX__namespace.toResolvedAttributeValue(propNameOnJsx, attributeStaticValue);
1572
1629
  };
1573
- if (getPropValue3("target") !== "_blank") {
1630
+ if (getAttributeValue("target") !== "_blank") {
1574
1631
  return;
1575
1632
  }
1576
- if (!isExternalLinkLike(getPropValue3("href"))) {
1633
+ if (!isExternalLinkLike(getAttributeValue("href"))) {
1577
1634
  return;
1578
1635
  }
1579
- if (!isSafeRel(getPropValue3("rel"))) {
1580
- context.report({
1581
- messageId: "noUnsafeTargetBlank",
1582
- node
1583
- });
1636
+ if (isSafeRel(getAttributeValue("rel"))) {
1637
+ return;
1584
1638
  }
1639
+ context.report({
1640
+ messageId: "noUnsafeTargetBlank",
1641
+ node
1642
+ });
1585
1643
  }
1586
1644
  };
1587
1645
  },
@@ -1625,7 +1683,7 @@ var no_void_elements_with_children_default = createRule({
1625
1683
  create(context) {
1626
1684
  return {
1627
1685
  JSXElement(node) {
1628
- const elementName = JSX3__namespace.getElementName(node.openingElement);
1686
+ const elementName = JSX__namespace.getElementName(node.openingElement);
1629
1687
  if (elementName.length === 0 || !voidElements.has(elementName)) {
1630
1688
  return;
1631
1689
  }
@@ -1640,8 +1698,8 @@ var no_void_elements_with_children_default = createRule({
1640
1698
  }
1641
1699
  const { attributes } = node.openingElement;
1642
1700
  const initialScope = context.sourceCode.getScope(node);
1643
- const hasAttribute = (name2) => JSX3__namespace.findPropInAttributes(name2, initialScope, attributes) !== eff._;
1644
- if (hasAttribute("children") || hasAttribute("dangerouslySetInnerHTML")) {
1701
+ const hasAttribute3 = (name2) => JSX__namespace.hasAttribute(name2, initialScope, attributes);
1702
+ if (hasAttribute3("children") || hasAttribute3("dangerouslySetInnerHTML")) {
1645
1703
  context.report({
1646
1704
  messageId: "noVoidElementsWithChildren",
1647
1705
  node,
package/dist/index.mjs CHANGED
@@ -1,34 +1,41 @@
1
- import { _, identity } from '@eslint-react/eff';
2
- import * as JSX3 from '@eslint-react/jsx';
3
- import * as VAR from '@eslint-react/var';
4
- import { match, P } from 'ts-pattern';
1
+ import * as JSX from '@eslint-react/jsx';
5
2
  import { createRuleForPlugin, getSettingsFromContext, RE_JAVASCRIPT_PROTOCOL } from '@eslint-react/shared';
3
+ import * as VAR from '@eslint-react/var';
6
4
  import { AST_NODE_TYPES } from '@typescript-eslint/types';
7
- import { getElementNameAndRepresentName } from '@eslint-react/core';
8
5
  import * as AST from '@eslint-react/ast';
9
6
  import { compare } from 'compare-versions';
10
7
 
11
8
  // package.json
12
9
  var name = "eslint-plugin-react-dom";
13
- var version = "1.24.0-next.0";
14
- function getAdditionalAttributes(name2, additionalComponents) {
15
- return additionalComponents.findLast((c) => c.name === name2 || c.re.test(name2))?.attributes ?? [];
10
+ var version = "1.24.0-next.11";
11
+ var createRule = createRuleForPlugin("dom");
12
+
13
+ // src/utils/find-custom-component.ts
14
+ function findCustomComponent(name2, components) {
15
+ return components.findLast((c) => c.name === name2 || c.re.test(name2));
16
+ }
17
+ function findCustomComponentProp(name2, props) {
18
+ return props.findLast((a) => a.as === name2);
16
19
  }
17
- function getAttributeStringValue(attributeName, element, context, additionalAttributes) {
18
- const attributeConfig = additionalAttributes.findLast((attr) => attr.as === attributeName);
19
- const actualAttributeName = attributeConfig?.name ?? attributeName;
20
- const actualAttributeNode = JSX3.findPropInAttributes(
21
- actualAttributeName,
22
- context.sourceCode.getScope(element),
23
- element.openingElement.attributes
20
+ function getElementNameOnJsxAndDom(node, context, polymorphicPropName, additionalComponents = []) {
21
+ const name2 = JSX.getElementName(node);
22
+ if (name2 === name2.toLowerCase()) return [name2, name2];
23
+ const component = additionalComponents.findLast((c) => c.name === name2 || c.re.test(name2));
24
+ if (component != null) return [name2, component.as];
25
+ if (polymorphicPropName == null) return [name2, name2];
26
+ const initialScope = context.sourceCode.getScope(node);
27
+ const attributeNode = JSX.getAttributeNode(
28
+ polymorphicPropName,
29
+ initialScope,
30
+ node.attributes
24
31
  );
25
- if (actualAttributeNode === _) return attributeConfig?.defaultValue;
26
- const actualAttributeScope = context.sourceCode.getScope(actualAttributeNode);
27
- const actualAttributeValue = JSX3.getPropValue(actualAttributeNode, actualAttributeScope);
28
- const actualAttributeValueResolved = VAR.toResolved(actualAttributeValue).value;
29
- return match(actualAttributeValueResolved).with(P.string, identity).with({ [actualAttributeName]: P.select(P.string) }, identity).otherwise(() => _);
32
+ if (attributeNode == null) return [name2, name2];
33
+ const polymorphicPropValue = VAR.toResolved(JSX.getAttributeStaticValue(attributeNode, initialScope)).value;
34
+ if (typeof polymorphicPropValue === "string") {
35
+ return [name2, polymorphicPropValue];
36
+ }
37
+ return [name2, name2];
30
38
  }
31
- var createRule = createRuleForPlugin("dom");
32
39
 
33
40
  // src/rules/no-dangerously-set-innerhtml.ts
34
41
  var RULE_NAME = "no-dangerously-set-innerhtml";
@@ -49,14 +56,19 @@ var no_dangerously_set_innerhtml_default = createRule({
49
56
  },
50
57
  name: RULE_NAME,
51
58
  create(context) {
59
+ if (!context.sourceCode.text.includes("dangerouslySetInnerHTML")) return {};
52
60
  return {
53
61
  JSXElement(node) {
54
62
  const attributes = node.openingElement.attributes;
55
- const prop = JSX3.getProp("dangerouslySetInnerHTML", context.sourceCode.getScope(node), attributes);
56
- if (prop === _) return;
63
+ const attribute = JSX.getAttributeNode(
64
+ "dangerouslySetInnerHTML",
65
+ context.sourceCode.getScope(node),
66
+ attributes
67
+ );
68
+ if (attribute == null) return;
57
69
  context.report({
58
70
  messageId: "noDangerouslySetInnerhtml",
59
- node: prop
71
+ node: attribute
60
72
  });
61
73
  }
62
74
  };
@@ -81,13 +93,13 @@ var no_dangerously_set_innerhtml_with_children_default = createRule({
81
93
  },
82
94
  name: RULE_NAME2,
83
95
  create(context) {
96
+ if (!context.sourceCode.text.includes("dangerouslySetInnerHTML")) return {};
84
97
  return {
85
98
  JSXElement(node) {
86
99
  const attributes = node.openingElement.attributes;
87
100
  const initialScope = context.sourceCode.getScope(node);
88
- const hasChildren = hasChildrenWithin(node) || JSX3.hasProp("children", initialScope, attributes);
89
- const hasDangerouslySetInnerHTML = JSX3.hasProp("dangerouslySetInnerHTML", initialScope, attributes);
90
- if (hasChildren && hasDangerouslySetInnerHTML) {
101
+ const hasChildren = hasChildrenWithin(node) || JSX.hasAttribute("children", initialScope, attributes);
102
+ if (hasChildren && JSX.hasAttribute("dangerouslySetInnerHTML", initialScope, attributes)) {
91
103
  context.report({
92
104
  messageId: "noDangerouslySetInnerhtmlWithChildren",
93
105
  node
@@ -99,7 +111,7 @@ var no_dangerously_set_innerhtml_with_children_default = createRule({
99
111
  defaultOptions: []
100
112
  });
101
113
  function hasChildrenWithin(node) {
102
- return node.children.length > 0 && node.children[0] != null && !JSX3.isLineBreak(node.children[0]);
114
+ return node.children.length > 0 && node.children[0] != null && !JSX.isLineBreak(node.children[0]);
103
115
  }
104
116
  var RULE_NAME3 = "no-find-dom-node";
105
117
  var RULE_FEATURES3 = [
@@ -119,6 +131,7 @@ var no_find_dom_node_default = createRule({
119
131
  },
120
132
  name: RULE_NAME3,
121
133
  create(context) {
134
+ if (!context.sourceCode.text.includes("findDOMNode")) return {};
122
135
  return {
123
136
  CallExpression(node) {
124
137
  const { callee } = node;
@@ -158,26 +171,39 @@ var no_missing_button_type_default = createRule({
158
171
  name: RULE_NAME4,
159
172
  create(context) {
160
173
  const settings = getSettingsFromContext(context);
174
+ const polymorphicPropName = settings.polymorphicPropName;
161
175
  const additionalComponents = settings.additionalComponents.filter((c) => c.as === "button");
162
176
  return {
163
177
  JSXElement(node) {
164
- const [name2, representName] = getElementNameAndRepresentName(
178
+ const [elementNameOnJsx, elementNameOnDom] = getElementNameOnJsxAndDom(
165
179
  node.openingElement,
166
180
  context,
167
- settings.polymorphicPropName,
168
- settings.additionalComponents
181
+ polymorphicPropName,
182
+ additionalComponents
169
183
  );
170
- if (representName !== "button") return;
171
- const getPropValue3 = (propName) => {
172
- return getAttributeStringValue(
173
- propName,
174
- node,
175
- context,
176
- getAdditionalAttributes(name2, additionalComponents)
177
- );
178
- };
179
- const prop = getPropValue3("type");
180
- if (typeof prop !== "string") {
184
+ if (elementNameOnDom !== "button") return;
185
+ const elementScope = context.sourceCode.getScope(node);
186
+ const customComponent = findCustomComponent(elementNameOnJsx, additionalComponents);
187
+ const customComponentProp = findCustomComponentProp("type", customComponent?.attributes ?? []);
188
+ const propNameOnJsx = customComponentProp?.name ?? "type";
189
+ const attributeNode = JSX.getAttributeNode(
190
+ propNameOnJsx,
191
+ elementScope,
192
+ node.openingElement.attributes
193
+ );
194
+ if (attributeNode != null) {
195
+ const attributeScope = context.sourceCode.getScope(attributeNode);
196
+ const attributeStaticValue = JSX.getAttributeStaticValue(attributeNode, attributeScope);
197
+ const attributeStringValue = JSX.toResolvedAttributeValue(propNameOnJsx, attributeStaticValue);
198
+ if (typeof attributeStringValue !== "string") {
199
+ context.report({
200
+ messageId: "noMissingButtonType",
201
+ node: attributeNode
202
+ });
203
+ }
204
+ return;
205
+ }
206
+ if (typeof customComponentProp?.defaultValue !== "string") {
181
207
  context.report({
182
208
  messageId: "noMissingButtonType",
183
209
  node
@@ -210,6 +236,9 @@ var validTypes = [
210
236
  "allow-top-navigation-by-user-activation",
211
237
  "allow-top-navigation-to-custom-protocols"
212
238
  ];
239
+ function hasValidSandBox(value) {
240
+ return typeof value === "string" && value.split(" ").every((value2) => validTypes.some((valid) => valid === value2));
241
+ }
213
242
  var no_missing_iframe_sandbox_default = createRule({
214
243
  meta: {
215
244
  type: "problem",
@@ -225,37 +254,41 @@ var no_missing_iframe_sandbox_default = createRule({
225
254
  name: RULE_NAME5,
226
255
  create(context) {
227
256
  const settings = getSettingsFromContext(context);
257
+ const polymorphicPropName = settings.polymorphicPropName;
228
258
  const additionalComponents = settings.additionalComponents.filter((c) => c.as === "iframe");
229
259
  return {
230
260
  JSXElement(node) {
231
- const [name2, representName] = getElementNameAndRepresentName(
261
+ const [elementNameOnJsx, elementNameOnDom] = getElementNameOnJsxAndDom(
232
262
  node.openingElement,
233
263
  context,
234
- settings.polymorphicPropName,
235
- settings.additionalComponents
264
+ polymorphicPropName,
265
+ additionalComponents
236
266
  );
237
- if (representName !== "iframe") return;
238
- const getPropValue3 = (propName) => {
239
- return getAttributeStringValue(
240
- propName,
241
- node,
242
- context,
243
- getAdditionalAttributes(name2, additionalComponents)
244
- );
245
- };
246
- const sandboxValue = getPropValue3("sandbox");
247
- if (sandboxValue === _) {
267
+ if (elementNameOnDom !== "iframe") return;
268
+ const elementScope = context.sourceCode.getScope(node);
269
+ const customComponent = findCustomComponent(elementNameOnJsx, additionalComponents);
270
+ const customComponentProp = findCustomComponentProp("sandbox", customComponent?.attributes ?? []);
271
+ const propNameOnJsx = customComponentProp?.name ?? "sandbox";
272
+ const attributeNode = JSX.getAttributeNode(
273
+ propNameOnJsx,
274
+ elementScope,
275
+ node.openingElement.attributes
276
+ );
277
+ if (attributeNode != null) {
278
+ const attributeScope = context.sourceCode.getScope(attributeNode);
279
+ const attributeStaticValue = JSX.getAttributeStaticValue(attributeNode, attributeScope);
280
+ const attributeStringValue = JSX.toResolvedAttributeValue(propNameOnJsx, attributeStaticValue);
281
+ if (hasValidSandBox(attributeStringValue)) return;
248
282
  context.report({
249
283
  messageId: "noMissingIframeSandbox",
250
- node: node.openingElement
284
+ node: attributeNode
251
285
  });
252
286
  return;
253
287
  }
254
- const values = sandboxValue.split(" ");
255
- if (!values.every((value) => validTypes.some((validType) => validType === value))) {
288
+ if (!hasValidSandBox(customComponentProp?.defaultValue)) {
256
289
  context.report({
257
290
  messageId: "noMissingIframeSandbox",
258
- node: node.openingElement
291
+ node
259
292
  });
260
293
  }
261
294
  }
@@ -283,7 +316,7 @@ var no_namespace_default = createRule({
283
316
  create(context) {
284
317
  return {
285
318
  JSXOpeningElement(node) {
286
- const name2 = JSX3.getElementName(node);
319
+ const name2 = JSX.getElementName(node);
287
320
  if (typeof name2 !== "string" || !name2.includes(":")) {
288
321
  return;
289
322
  }
@@ -375,11 +408,11 @@ var no_script_url_default = createRule({
375
408
  if (node.name.type !== AST_NODE_TYPES.JSXIdentifier || node.value == null) {
376
409
  return;
377
410
  }
378
- const propScope = context.sourceCode.getScope(node);
379
- const propValue = JSX3.getPropValue(node, propScope);
380
- const propValueResolved = VAR.toResolved(propValue).value;
381
- if (typeof propValueResolved !== "string") return;
382
- if (RE_JAVASCRIPT_PROTOCOL.test(propValueResolved)) {
411
+ const attributeScope = context.sourceCode.getScope(node);
412
+ const attributeValue = JSX.getAttributeStaticValue(node, attributeScope);
413
+ const attributeValueResolved = VAR.toResolved(attributeValue).value;
414
+ if (typeof attributeValueResolved !== "string") return;
415
+ if (RE_JAVASCRIPT_PROTOCOL.test(attributeValueResolved)) {
383
416
  context.report({
384
417
  messageId: "noScriptUrl",
385
418
  node: node.value
@@ -1451,9 +1484,15 @@ var RULE_NAME10 = "no-unsafe-iframe-sandbox";
1451
1484
  var RULE_FEATURES9 = [
1452
1485
  "CHK"
1453
1486
  ];
1454
- var unsafeCombinations = [
1487
+ var unsafeSandboxValues = [
1455
1488
  ["allow-scripts", "allow-same-origin"]
1456
1489
  ];
1490
+ function hasNoneOrSafeSandbox(value) {
1491
+ if (value == null) return true;
1492
+ return !unsafeSandboxValues.some((values) => {
1493
+ return values.every((v) => value.includes(v));
1494
+ });
1495
+ }
1457
1496
  var no_unsafe_iframe_sandbox_default = createRule({
1458
1497
  meta: {
1459
1498
  type: "problem",
@@ -1469,31 +1508,41 @@ var no_unsafe_iframe_sandbox_default = createRule({
1469
1508
  name: RULE_NAME10,
1470
1509
  create(context) {
1471
1510
  const settings = getSettingsFromContext(context);
1511
+ const polymorphicPropName = settings.polymorphicPropName;
1472
1512
  const additionalComponents = settings.additionalComponents.filter((c) => c.as === "iframe");
1473
1513
  return {
1474
1514
  JSXElement(node) {
1475
- const [name2, representName] = getElementNameAndRepresentName(
1515
+ const [elementNameOnJsx, elementNameOnDom] = getElementNameOnJsxAndDom(
1476
1516
  node.openingElement,
1477
1517
  context,
1478
- settings.polymorphicPropName,
1479
- settings.additionalComponents
1518
+ polymorphicPropName,
1519
+ additionalComponents
1480
1520
  );
1481
- if (representName !== "iframe") return;
1482
- const getPropValue3 = (propName) => {
1483
- return getAttributeStringValue(
1484
- propName,
1485
- node,
1486
- context,
1487
- getAdditionalAttributes(name2, additionalComponents)
1488
- );
1489
- };
1490
- const sandboxValue = getPropValue3("sandbox");
1491
- if (sandboxValue === _) return;
1492
- const values = sandboxValue.split(" ");
1493
- if (unsafeCombinations.some((unsafes) => unsafes.every((x) => values.includes(x)))) {
1521
+ if (elementNameOnDom !== "iframe") return;
1522
+ const elementScope = context.sourceCode.getScope(node);
1523
+ const customComponent = findCustomComponent(elementNameOnJsx, additionalComponents);
1524
+ const customComponentProp = findCustomComponentProp("sandbox", customComponent?.attributes ?? []);
1525
+ const propNameOnJsx = customComponentProp?.name ?? "sandbox";
1526
+ const attributeNode = JSX.getAttributeNode(
1527
+ propNameOnJsx,
1528
+ elementScope,
1529
+ node.openingElement.attributes
1530
+ );
1531
+ if (attributeNode != null) {
1532
+ const attributeScope = context.sourceCode.getScope(attributeNode);
1533
+ const attributeStaticValue = JSX.getAttributeStaticValue(attributeNode, attributeScope);
1534
+ const attributeStringValue = JSX.toResolvedAttributeValue(propNameOnJsx, attributeStaticValue);
1535
+ if (hasNoneOrSafeSandbox(attributeStringValue)) return;
1536
+ context.report({
1537
+ messageId: "noUnsafeIframeSandbox",
1538
+ node: attributeNode
1539
+ });
1540
+ return;
1541
+ }
1542
+ if (!hasNoneOrSafeSandbox(customComponentProp?.defaultValue)) {
1494
1543
  context.report({
1495
1544
  messageId: "noUnsafeIframeSandbox",
1496
- node: node.openingElement
1545
+ node
1497
1546
  });
1498
1547
  }
1499
1548
  }
@@ -1506,11 +1555,11 @@ var RULE_FEATURES10 = [
1506
1555
  "CHK"
1507
1556
  ];
1508
1557
  function isExternalLinkLike(value) {
1509
- if (value === _) return false;
1558
+ if (value == null) return false;
1510
1559
  return value.startsWith("https://") || /^(?:\w+:|\/\/)/u.test(value);
1511
1560
  }
1512
1561
  function isSafeRel(value) {
1513
- if (value === _) return false;
1562
+ if (value == null) return false;
1514
1563
  return value === "noreferrer" || /\bnoreferrer\b/u.test(value);
1515
1564
  }
1516
1565
  var no_unsafe_target_blank_default = createRule({
@@ -1528,36 +1577,45 @@ var no_unsafe_target_blank_default = createRule({
1528
1577
  name: RULE_NAME11,
1529
1578
  create(context) {
1530
1579
  const settings = getSettingsFromContext(context);
1580
+ const polymorphicPropName = settings.polymorphicPropName;
1531
1581
  const additionalComponents = settings.additionalComponents.filter((c) => c.as === "a");
1532
1582
  return {
1533
1583
  JSXElement(node) {
1534
- const [name2, representName] = getElementNameAndRepresentName(
1584
+ const [elementNameOnJsx, elementNameOnDom] = getElementNameOnJsxAndDom(
1535
1585
  node.openingElement,
1536
1586
  context,
1537
- settings.polymorphicPropName,
1538
- settings.additionalComponents
1587
+ polymorphicPropName,
1588
+ additionalComponents
1539
1589
  );
1540
- if (representName !== "a") return;
1541
- const getPropValue3 = (propName) => {
1542
- return getAttributeStringValue(
1543
- propName,
1544
- node,
1545
- context,
1546
- getAdditionalAttributes(name2, additionalComponents)
1590
+ if (elementNameOnDom !== "a") return;
1591
+ const elementScope = context.sourceCode.getScope(node);
1592
+ const customComponent = findCustomComponent(elementNameOnJsx, additionalComponents);
1593
+ const getAttributeValue = (name2) => {
1594
+ const customComponentProp = findCustomComponentProp(name2, customComponent?.attributes ?? []);
1595
+ const propNameOnJsx = customComponentProp?.name ?? name2;
1596
+ const attributeNode = JSX.getAttributeNode(
1597
+ propNameOnJsx,
1598
+ elementScope,
1599
+ node.openingElement.attributes
1547
1600
  );
1601
+ if (attributeNode == null) return customComponentProp?.defaultValue;
1602
+ const attributeScope = context.sourceCode.getScope(attributeNode);
1603
+ const attributeStaticValue = JSX.getAttributeStaticValue(attributeNode, attributeScope);
1604
+ return JSX.toResolvedAttributeValue(propNameOnJsx, attributeStaticValue);
1548
1605
  };
1549
- if (getPropValue3("target") !== "_blank") {
1606
+ if (getAttributeValue("target") !== "_blank") {
1550
1607
  return;
1551
1608
  }
1552
- if (!isExternalLinkLike(getPropValue3("href"))) {
1609
+ if (!isExternalLinkLike(getAttributeValue("href"))) {
1553
1610
  return;
1554
1611
  }
1555
- if (!isSafeRel(getPropValue3("rel"))) {
1556
- context.report({
1557
- messageId: "noUnsafeTargetBlank",
1558
- node
1559
- });
1612
+ if (isSafeRel(getAttributeValue("rel"))) {
1613
+ return;
1560
1614
  }
1615
+ context.report({
1616
+ messageId: "noUnsafeTargetBlank",
1617
+ node
1618
+ });
1561
1619
  }
1562
1620
  };
1563
1621
  },
@@ -1601,7 +1659,7 @@ var no_void_elements_with_children_default = createRule({
1601
1659
  create(context) {
1602
1660
  return {
1603
1661
  JSXElement(node) {
1604
- const elementName = JSX3.getElementName(node.openingElement);
1662
+ const elementName = JSX.getElementName(node.openingElement);
1605
1663
  if (elementName.length === 0 || !voidElements.has(elementName)) {
1606
1664
  return;
1607
1665
  }
@@ -1616,8 +1674,8 @@ var no_void_elements_with_children_default = createRule({
1616
1674
  }
1617
1675
  const { attributes } = node.openingElement;
1618
1676
  const initialScope = context.sourceCode.getScope(node);
1619
- const hasAttribute = (name2) => JSX3.findPropInAttributes(name2, initialScope, attributes) !== _;
1620
- if (hasAttribute("children") || hasAttribute("dangerouslySetInnerHTML")) {
1677
+ const hasAttribute3 = (name2) => JSX.hasAttribute(name2, initialScope, attributes);
1678
+ if (hasAttribute3("children") || hasAttribute3("dangerouslySetInnerHTML")) {
1621
1679
  context.report({
1622
1680
  messageId: "noVoidElementsWithChildren",
1623
1681
  node,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-react-dom",
3
- "version": "1.24.0-next.0",
3
+ "version": "1.24.0-next.11",
4
4
  "description": "ESLint React's ESLint plugin for React DOM related rules.",
5
5
  "keywords": [
6
6
  "react",
@@ -41,23 +41,22 @@
41
41
  "./package.json"
42
42
  ],
43
43
  "dependencies": {
44
- "@typescript-eslint/scope-manager": "^8.19.1",
45
- "@typescript-eslint/types": "^8.19.1",
46
- "@typescript-eslint/utils": "^8.19.1",
44
+ "@typescript-eslint/scope-manager": "^8.20.0",
45
+ "@typescript-eslint/types": "^8.20.0",
46
+ "@typescript-eslint/utils": "^8.20.0",
47
47
  "compare-versions": "^6.1.1",
48
48
  "string-ts": "^2.2.0",
49
49
  "ts-pattern": "^5.6.0",
50
- "@eslint-react/ast": "1.24.0-next.0",
51
- "@eslint-react/core": "1.24.0-next.0",
52
- "@eslint-react/eff": "1.24.0-next.0",
53
- "@eslint-react/jsx": "1.24.0-next.0",
54
- "@eslint-react/types": "1.24.0-next.0",
55
- "@eslint-react/var": "1.24.0-next.0",
56
- "@eslint-react/shared": "1.24.0-next.0"
50
+ "@eslint-react/ast": "1.24.0-next.11",
51
+ "@eslint-react/eff": "1.24.0-next.11",
52
+ "@eslint-react/jsx": "1.24.0-next.11",
53
+ "@eslint-react/var": "1.24.0-next.11",
54
+ "@eslint-react/core": "1.24.0-next.11",
55
+ "@eslint-react/shared": "1.24.0-next.11"
57
56
  },
58
57
  "devDependencies": {
59
- "@types/react": "^19.0.4",
60
- "@types/react-dom": "^19.0.2",
58
+ "@types/react": "^19.0.7",
59
+ "@types/react-dom": "^19.0.3",
61
60
  "tsup": "^8.3.5",
62
61
  "@workspace/configs": "0.0.0"
63
62
  },