eslint-plugin-react-dom 1.24.0-beta.1 → 1.24.0-beta.18

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