eslint-plugin-react-dom 1.24.0-next.8 → 1.24.0
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 +155 -103
- package/dist/index.mjs +154 -101
- package/package.json +8 -8
package/dist/index.js
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
var eff = require('@eslint-react/eff');
|
|
3
|
+
var JSX = require('@eslint-react/jsx');
|
|
5
4
|
var shared = require('@eslint-react/shared');
|
|
6
5
|
var types = require('@typescript-eslint/types');
|
|
7
|
-
var core = require('@eslint-react/core');
|
|
8
6
|
var AST = require('@eslint-react/ast');
|
|
9
|
-
var VAR = require('@eslint-react/var');
|
|
10
7
|
var compareVersions = require('compare-versions');
|
|
8
|
+
var eff = require('@eslint-react/eff');
|
|
11
9
|
|
|
12
10
|
function _interopNamespace(e) {
|
|
13
11
|
if (e && e.__esModule) return e;
|
|
@@ -27,47 +25,40 @@ function _interopNamespace(e) {
|
|
|
27
25
|
return Object.freeze(n);
|
|
28
26
|
}
|
|
29
27
|
|
|
30
|
-
var
|
|
28
|
+
var JSX__namespace = /*#__PURE__*/_interopNamespace(JSX);
|
|
31
29
|
var AST__namespace = /*#__PURE__*/_interopNamespace(AST);
|
|
32
|
-
var VAR__namespace = /*#__PURE__*/_interopNamespace(VAR);
|
|
33
30
|
|
|
34
31
|
// package.json
|
|
35
32
|
var name = "eslint-plugin-react-dom";
|
|
36
|
-
var version = "1.24.0
|
|
37
|
-
|
|
38
|
-
|
|
33
|
+
var version = "1.24.0";
|
|
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
39
|
}
|
|
40
|
-
function
|
|
41
|
-
|
|
42
|
-
return {
|
|
43
|
-
name: settings?.name ?? name2,
|
|
44
|
-
controlled: settings?.controlled ?? false,
|
|
45
|
-
defaultValue: settings?.defaultValue
|
|
46
|
-
};
|
|
40
|
+
function findCustomComponentProp(name2, props) {
|
|
41
|
+
return props.findLast((a) => a.as === name2);
|
|
47
42
|
}
|
|
48
|
-
function
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
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
|
|
55
54
|
);
|
|
56
|
-
if (attributeNode == null)
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
};
|
|
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];
|
|
61
59
|
}
|
|
62
|
-
|
|
63
|
-
const attributeValue = JSX3__namespace.getAttributeStringValue(
|
|
64
|
-
attributeNameOnElement,
|
|
65
|
-
attributeNode,
|
|
66
|
-
attributeScope
|
|
67
|
-
);
|
|
68
|
-
return { attributeNode, attributeValue };
|
|
60
|
+
return [name2, name2];
|
|
69
61
|
}
|
|
70
|
-
var createRule = shared.createRuleForPlugin("dom");
|
|
71
62
|
|
|
72
63
|
// src/rules/no-dangerously-set-innerhtml.ts
|
|
73
64
|
var RULE_NAME = "no-dangerously-set-innerhtml";
|
|
@@ -92,10 +83,10 @@ var no_dangerously_set_innerhtml_default = createRule({
|
|
|
92
83
|
return {
|
|
93
84
|
JSXElement(node) {
|
|
94
85
|
const attributes = node.openingElement.attributes;
|
|
95
|
-
const attribute =
|
|
86
|
+
const attribute = JSX__namespace.getAttribute(
|
|
96
87
|
"dangerouslySetInnerHTML",
|
|
97
|
-
|
|
98
|
-
|
|
88
|
+
attributes,
|
|
89
|
+
context.sourceCode.getScope(node)
|
|
99
90
|
);
|
|
100
91
|
if (attribute == null) return;
|
|
101
92
|
context.report({
|
|
@@ -130,8 +121,8 @@ var no_dangerously_set_innerhtml_with_children_default = createRule({
|
|
|
130
121
|
JSXElement(node) {
|
|
131
122
|
const attributes = node.openingElement.attributes;
|
|
132
123
|
const initialScope = context.sourceCode.getScope(node);
|
|
133
|
-
const hasChildren = hasChildrenWithin(node) ||
|
|
134
|
-
if (hasChildren &&
|
|
124
|
+
const hasChildren = hasChildrenWithin(node) || JSX__namespace.hasAttribute("children", attributes, initialScope);
|
|
125
|
+
if (hasChildren && JSX__namespace.hasAttribute("dangerouslySetInnerHTML", attributes, initialScope)) {
|
|
135
126
|
context.report({
|
|
136
127
|
messageId: "noDangerouslySetInnerhtmlWithChildren",
|
|
137
128
|
node
|
|
@@ -143,7 +134,7 @@ var no_dangerously_set_innerhtml_with_children_default = createRule({
|
|
|
143
134
|
defaultOptions: []
|
|
144
135
|
});
|
|
145
136
|
function hasChildrenWithin(node) {
|
|
146
|
-
return node.children.length > 0 && node.children[0] != null && !
|
|
137
|
+
return node.children.length > 0 && node.children[0] != null && !JSX__namespace.isLineBreak(node.children[0]);
|
|
147
138
|
}
|
|
148
139
|
var RULE_NAME3 = "no-find-dom-node";
|
|
149
140
|
var RULE_FEATURES3 = [
|
|
@@ -207,23 +198,37 @@ var no_missing_button_type_default = createRule({
|
|
|
207
198
|
const additionalComponents = settings.additionalComponents.filter((c) => c.as === "button");
|
|
208
199
|
return {
|
|
209
200
|
JSXElement(node) {
|
|
210
|
-
const [elementNameOnJsx,
|
|
211
|
-
node
|
|
201
|
+
const [elementNameOnJsx, elementNameOnDom] = getElementNameOnJsxAndDom(
|
|
202
|
+
node,
|
|
212
203
|
context,
|
|
213
204
|
polymorphicPropName,
|
|
214
205
|
additionalComponents
|
|
215
206
|
);
|
|
216
|
-
if (
|
|
217
|
-
const
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
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
|
|
222
216
|
);
|
|
223
|
-
if (
|
|
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") {
|
|
224
229
|
context.report({
|
|
225
230
|
messageId: "noMissingButtonType",
|
|
226
|
-
node
|
|
231
|
+
node
|
|
227
232
|
});
|
|
228
233
|
}
|
|
229
234
|
}
|
|
@@ -253,6 +258,9 @@ var validTypes = [
|
|
|
253
258
|
"allow-top-navigation-by-user-activation",
|
|
254
259
|
"allow-top-navigation-to-custom-protocols"
|
|
255
260
|
];
|
|
261
|
+
function hasValidSandBox(value) {
|
|
262
|
+
return typeof value === "string" && value.split(" ").every((value2) => validTypes.some((valid) => valid === value2));
|
|
263
|
+
}
|
|
256
264
|
var no_missing_iframe_sandbox_default = createRule({
|
|
257
265
|
meta: {
|
|
258
266
|
type: "problem",
|
|
@@ -272,25 +280,38 @@ var no_missing_iframe_sandbox_default = createRule({
|
|
|
272
280
|
const additionalComponents = settings.additionalComponents.filter((c) => c.as === "iframe");
|
|
273
281
|
return {
|
|
274
282
|
JSXElement(node) {
|
|
275
|
-
const [elementNameOnJsx,
|
|
276
|
-
node
|
|
283
|
+
const [elementNameOnJsx, elementNameOnDom] = getElementNameOnJsxAndDom(
|
|
284
|
+
node,
|
|
277
285
|
context,
|
|
278
286
|
polymorphicPropName,
|
|
279
287
|
additionalComponents
|
|
280
288
|
);
|
|
281
|
-
if (
|
|
282
|
-
const
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
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
|
|
287
298
|
);
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
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;
|
|
303
|
+
context.report({
|
|
304
|
+
messageId: "noMissingIframeSandbox",
|
|
305
|
+
node: attributeNode
|
|
306
|
+
});
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
if (!hasValidSandBox(customComponentProp?.defaultValue)) {
|
|
310
|
+
context.report({
|
|
311
|
+
messageId: "noMissingIframeSandbox",
|
|
312
|
+
node
|
|
313
|
+
});
|
|
314
|
+
}
|
|
294
315
|
}
|
|
295
316
|
};
|
|
296
317
|
},
|
|
@@ -315,14 +336,14 @@ var no_namespace_default = createRule({
|
|
|
315
336
|
name: RULE_NAME6,
|
|
316
337
|
create(context) {
|
|
317
338
|
return {
|
|
318
|
-
|
|
319
|
-
const name2 =
|
|
339
|
+
JSXElement(node) {
|
|
340
|
+
const name2 = JSX__namespace.getElementName(node);
|
|
320
341
|
if (typeof name2 !== "string" || !name2.includes(":")) {
|
|
321
342
|
return;
|
|
322
343
|
}
|
|
323
344
|
context.report({
|
|
324
345
|
messageId: "noNamespace",
|
|
325
|
-
node,
|
|
346
|
+
node: node.openingElement.name,
|
|
326
347
|
data: {
|
|
327
348
|
name: name2
|
|
328
349
|
}
|
|
@@ -409,10 +430,10 @@ var no_script_url_default = createRule({
|
|
|
409
430
|
return;
|
|
410
431
|
}
|
|
411
432
|
const attributeScope = context.sourceCode.getScope(node);
|
|
412
|
-
const
|
|
413
|
-
const
|
|
414
|
-
if (typeof
|
|
415
|
-
if (shared.RE_JAVASCRIPT_PROTOCOL.test(
|
|
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)) {
|
|
416
437
|
context.report({
|
|
417
438
|
messageId: "noScriptUrl",
|
|
418
439
|
node: node.value
|
|
@@ -1484,9 +1505,15 @@ var RULE_NAME10 = "no-unsafe-iframe-sandbox";
|
|
|
1484
1505
|
var RULE_FEATURES9 = [
|
|
1485
1506
|
"CHK"
|
|
1486
1507
|
];
|
|
1487
|
-
var
|
|
1508
|
+
var unsafeSandboxValues = [
|
|
1488
1509
|
["allow-scripts", "allow-same-origin"]
|
|
1489
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
|
+
}
|
|
1490
1517
|
var no_unsafe_iframe_sandbox_default = createRule({
|
|
1491
1518
|
meta: {
|
|
1492
1519
|
type: "problem",
|
|
@@ -1506,25 +1533,40 @@ var no_unsafe_iframe_sandbox_default = createRule({
|
|
|
1506
1533
|
const additionalComponents = settings.additionalComponents.filter((c) => c.as === "iframe");
|
|
1507
1534
|
return {
|
|
1508
1535
|
JSXElement(node) {
|
|
1509
|
-
const [elementNameOnJsx,
|
|
1510
|
-
node
|
|
1536
|
+
const [elementNameOnJsx, elementNameOnDom] = getElementNameOnJsxAndDom(
|
|
1537
|
+
node,
|
|
1511
1538
|
context,
|
|
1512
1539
|
polymorphicPropName,
|
|
1513
1540
|
additionalComponents
|
|
1514
1541
|
);
|
|
1515
|
-
if (
|
|
1516
|
-
const
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
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
|
|
1521
1551
|
);
|
|
1522
|
-
if (
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
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)) {
|
|
1565
|
+
context.report({
|
|
1566
|
+
messageId: "noUnsafeIframeSandbox",
|
|
1567
|
+
node
|
|
1568
|
+
});
|
|
1569
|
+
}
|
|
1528
1570
|
}
|
|
1529
1571
|
};
|
|
1530
1572
|
},
|
|
@@ -1561,28 +1603,38 @@ var no_unsafe_target_blank_default = createRule({
|
|
|
1561
1603
|
const additionalComponents = settings.additionalComponents.filter((c) => c.as === "a");
|
|
1562
1604
|
return {
|
|
1563
1605
|
JSXElement(node) {
|
|
1564
|
-
const [elementNameOnJsx,
|
|
1565
|
-
node
|
|
1606
|
+
const [elementNameOnJsx, elementNameOnDom] = getElementNameOnJsxAndDom(
|
|
1607
|
+
node,
|
|
1566
1608
|
context,
|
|
1567
1609
|
polymorphicPropName,
|
|
1568
1610
|
additionalComponents
|
|
1569
1611
|
);
|
|
1570
|
-
if (
|
|
1571
|
-
const
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
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
|
|
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._;
|
|
1578
1630
|
};
|
|
1579
|
-
if (
|
|
1631
|
+
if (getAttributeStringValue("target") !== "_blank") {
|
|
1580
1632
|
return;
|
|
1581
1633
|
}
|
|
1582
|
-
if (!isExternalLinkLike(
|
|
1634
|
+
if (!isExternalLinkLike(getAttributeStringValue("href"))) {
|
|
1583
1635
|
return;
|
|
1584
1636
|
}
|
|
1585
|
-
if (isSafeRel(
|
|
1637
|
+
if (isSafeRel(getAttributeStringValue("rel"))) {
|
|
1586
1638
|
return;
|
|
1587
1639
|
}
|
|
1588
1640
|
context.report({
|
|
@@ -1632,7 +1684,7 @@ var no_void_elements_with_children_default = createRule({
|
|
|
1632
1684
|
create(context) {
|
|
1633
1685
|
return {
|
|
1634
1686
|
JSXElement(node) {
|
|
1635
|
-
const elementName =
|
|
1687
|
+
const elementName = JSX__namespace.getElementName(node);
|
|
1636
1688
|
if (elementName.length === 0 || !voidElements.has(elementName)) {
|
|
1637
1689
|
return;
|
|
1638
1690
|
}
|
|
@@ -1647,7 +1699,7 @@ var no_void_elements_with_children_default = createRule({
|
|
|
1647
1699
|
}
|
|
1648
1700
|
const { attributes } = node.openingElement;
|
|
1649
1701
|
const initialScope = context.sourceCode.getScope(node);
|
|
1650
|
-
const hasAttribute3 = (name2) =>
|
|
1702
|
+
const hasAttribute3 = (name2) => JSX__namespace.hasAttribute(name2, attributes, initialScope);
|
|
1651
1703
|
if (hasAttribute3("children") || hasAttribute3("dangerouslySetInnerHTML")) {
|
|
1652
1704
|
context.report({
|
|
1653
1705
|
messageId: "noVoidElementsWithChildren",
|
package/dist/index.mjs
CHANGED
|
@@ -1,49 +1,41 @@
|
|
|
1
|
-
import * as
|
|
2
|
-
import { _ } from '@eslint-react/eff';
|
|
1
|
+
import * as JSX from '@eslint-react/jsx';
|
|
3
2
|
import { createRuleForPlugin, getSettingsFromContext, RE_JAVASCRIPT_PROTOCOL } from '@eslint-react/shared';
|
|
4
3
|
import { AST_NODE_TYPES } from '@typescript-eslint/types';
|
|
5
|
-
import { getElementNameOnJsxAndHtml } from '@eslint-react/core';
|
|
6
4
|
import * as AST from '@eslint-react/ast';
|
|
7
|
-
import * as VAR from '@eslint-react/var';
|
|
8
5
|
import { compare } from 'compare-versions';
|
|
6
|
+
import { _ } from '@eslint-react/eff';
|
|
9
7
|
|
|
10
8
|
// package.json
|
|
11
9
|
var name = "eslint-plugin-react-dom";
|
|
12
|
-
var version = "1.24.0
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
var version = "1.24.0";
|
|
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));
|
|
15
16
|
}
|
|
16
|
-
function
|
|
17
|
-
|
|
18
|
-
return {
|
|
19
|
-
name: settings?.name ?? name2,
|
|
20
|
-
controlled: settings?.controlled ?? false,
|
|
21
|
-
defaultValue: settings?.defaultValue
|
|
22
|
-
};
|
|
17
|
+
function findCustomComponentProp(name2, props) {
|
|
18
|
+
return props.findLast((a) => a.as === name2);
|
|
23
19
|
}
|
|
24
|
-
function
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
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
|
|
31
31
|
);
|
|
32
|
-
if (attributeNode == null)
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
};
|
|
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];
|
|
37
36
|
}
|
|
38
|
-
|
|
39
|
-
const attributeValue = JSX3.getAttributeStringValue(
|
|
40
|
-
attributeNameOnElement,
|
|
41
|
-
attributeNode,
|
|
42
|
-
attributeScope
|
|
43
|
-
);
|
|
44
|
-
return { attributeNode, attributeValue };
|
|
37
|
+
return [name2, name2];
|
|
45
38
|
}
|
|
46
|
-
var createRule = createRuleForPlugin("dom");
|
|
47
39
|
|
|
48
40
|
// src/rules/no-dangerously-set-innerhtml.ts
|
|
49
41
|
var RULE_NAME = "no-dangerously-set-innerhtml";
|
|
@@ -68,10 +60,10 @@ var no_dangerously_set_innerhtml_default = createRule({
|
|
|
68
60
|
return {
|
|
69
61
|
JSXElement(node) {
|
|
70
62
|
const attributes = node.openingElement.attributes;
|
|
71
|
-
const attribute =
|
|
63
|
+
const attribute = JSX.getAttribute(
|
|
72
64
|
"dangerouslySetInnerHTML",
|
|
73
|
-
|
|
74
|
-
|
|
65
|
+
attributes,
|
|
66
|
+
context.sourceCode.getScope(node)
|
|
75
67
|
);
|
|
76
68
|
if (attribute == null) return;
|
|
77
69
|
context.report({
|
|
@@ -106,8 +98,8 @@ var no_dangerously_set_innerhtml_with_children_default = createRule({
|
|
|
106
98
|
JSXElement(node) {
|
|
107
99
|
const attributes = node.openingElement.attributes;
|
|
108
100
|
const initialScope = context.sourceCode.getScope(node);
|
|
109
|
-
const hasChildren = hasChildrenWithin(node) ||
|
|
110
|
-
if (hasChildren &&
|
|
101
|
+
const hasChildren = hasChildrenWithin(node) || JSX.hasAttribute("children", attributes, initialScope);
|
|
102
|
+
if (hasChildren && JSX.hasAttribute("dangerouslySetInnerHTML", attributes, initialScope)) {
|
|
111
103
|
context.report({
|
|
112
104
|
messageId: "noDangerouslySetInnerhtmlWithChildren",
|
|
113
105
|
node
|
|
@@ -119,7 +111,7 @@ var no_dangerously_set_innerhtml_with_children_default = createRule({
|
|
|
119
111
|
defaultOptions: []
|
|
120
112
|
});
|
|
121
113
|
function hasChildrenWithin(node) {
|
|
122
|
-
return node.children.length > 0 && node.children[0] != null && !
|
|
114
|
+
return node.children.length > 0 && node.children[0] != null && !JSX.isLineBreak(node.children[0]);
|
|
123
115
|
}
|
|
124
116
|
var RULE_NAME3 = "no-find-dom-node";
|
|
125
117
|
var RULE_FEATURES3 = [
|
|
@@ -183,23 +175,37 @@ var no_missing_button_type_default = createRule({
|
|
|
183
175
|
const additionalComponents = settings.additionalComponents.filter((c) => c.as === "button");
|
|
184
176
|
return {
|
|
185
177
|
JSXElement(node) {
|
|
186
|
-
const [elementNameOnJsx,
|
|
187
|
-
node
|
|
178
|
+
const [elementNameOnJsx, elementNameOnDom] = getElementNameOnJsxAndDom(
|
|
179
|
+
node,
|
|
188
180
|
context,
|
|
189
181
|
polymorphicPropName,
|
|
190
182
|
additionalComponents
|
|
191
183
|
);
|
|
192
|
-
if (
|
|
193
|
-
const
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
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
|
|
198
193
|
);
|
|
199
|
-
if (
|
|
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") {
|
|
200
206
|
context.report({
|
|
201
207
|
messageId: "noMissingButtonType",
|
|
202
|
-
node
|
|
208
|
+
node
|
|
203
209
|
});
|
|
204
210
|
}
|
|
205
211
|
}
|
|
@@ -229,6 +235,9 @@ var validTypes = [
|
|
|
229
235
|
"allow-top-navigation-by-user-activation",
|
|
230
236
|
"allow-top-navigation-to-custom-protocols"
|
|
231
237
|
];
|
|
238
|
+
function hasValidSandBox(value) {
|
|
239
|
+
return typeof value === "string" && value.split(" ").every((value2) => validTypes.some((valid) => valid === value2));
|
|
240
|
+
}
|
|
232
241
|
var no_missing_iframe_sandbox_default = createRule({
|
|
233
242
|
meta: {
|
|
234
243
|
type: "problem",
|
|
@@ -248,25 +257,38 @@ var no_missing_iframe_sandbox_default = createRule({
|
|
|
248
257
|
const additionalComponents = settings.additionalComponents.filter((c) => c.as === "iframe");
|
|
249
258
|
return {
|
|
250
259
|
JSXElement(node) {
|
|
251
|
-
const [elementNameOnJsx,
|
|
252
|
-
node
|
|
260
|
+
const [elementNameOnJsx, elementNameOnDom] = getElementNameOnJsxAndDom(
|
|
261
|
+
node,
|
|
253
262
|
context,
|
|
254
263
|
polymorphicPropName,
|
|
255
264
|
additionalComponents
|
|
256
265
|
);
|
|
257
|
-
if (
|
|
258
|
-
const
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
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
|
|
263
275
|
);
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
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;
|
|
280
|
+
context.report({
|
|
281
|
+
messageId: "noMissingIframeSandbox",
|
|
282
|
+
node: attributeNode
|
|
283
|
+
});
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
if (!hasValidSandBox(customComponentProp?.defaultValue)) {
|
|
287
|
+
context.report({
|
|
288
|
+
messageId: "noMissingIframeSandbox",
|
|
289
|
+
node
|
|
290
|
+
});
|
|
291
|
+
}
|
|
270
292
|
}
|
|
271
293
|
};
|
|
272
294
|
},
|
|
@@ -291,14 +313,14 @@ var no_namespace_default = createRule({
|
|
|
291
313
|
name: RULE_NAME6,
|
|
292
314
|
create(context) {
|
|
293
315
|
return {
|
|
294
|
-
|
|
295
|
-
const name2 =
|
|
316
|
+
JSXElement(node) {
|
|
317
|
+
const name2 = JSX.getElementName(node);
|
|
296
318
|
if (typeof name2 !== "string" || !name2.includes(":")) {
|
|
297
319
|
return;
|
|
298
320
|
}
|
|
299
321
|
context.report({
|
|
300
322
|
messageId: "noNamespace",
|
|
301
|
-
node,
|
|
323
|
+
node: node.openingElement.name,
|
|
302
324
|
data: {
|
|
303
325
|
name: name2
|
|
304
326
|
}
|
|
@@ -385,10 +407,10 @@ var no_script_url_default = createRule({
|
|
|
385
407
|
return;
|
|
386
408
|
}
|
|
387
409
|
const attributeScope = context.sourceCode.getScope(node);
|
|
388
|
-
const
|
|
389
|
-
const
|
|
390
|
-
if (typeof
|
|
391
|
-
if (RE_JAVASCRIPT_PROTOCOL.test(
|
|
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)) {
|
|
392
414
|
context.report({
|
|
393
415
|
messageId: "noScriptUrl",
|
|
394
416
|
node: node.value
|
|
@@ -1460,9 +1482,15 @@ var RULE_NAME10 = "no-unsafe-iframe-sandbox";
|
|
|
1460
1482
|
var RULE_FEATURES9 = [
|
|
1461
1483
|
"CHK"
|
|
1462
1484
|
];
|
|
1463
|
-
var
|
|
1485
|
+
var unsafeSandboxValues = [
|
|
1464
1486
|
["allow-scripts", "allow-same-origin"]
|
|
1465
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
|
+
}
|
|
1466
1494
|
var no_unsafe_iframe_sandbox_default = createRule({
|
|
1467
1495
|
meta: {
|
|
1468
1496
|
type: "problem",
|
|
@@ -1482,25 +1510,40 @@ var no_unsafe_iframe_sandbox_default = createRule({
|
|
|
1482
1510
|
const additionalComponents = settings.additionalComponents.filter((c) => c.as === "iframe");
|
|
1483
1511
|
return {
|
|
1484
1512
|
JSXElement(node) {
|
|
1485
|
-
const [elementNameOnJsx,
|
|
1486
|
-
node
|
|
1513
|
+
const [elementNameOnJsx, elementNameOnDom] = getElementNameOnJsxAndDom(
|
|
1514
|
+
node,
|
|
1487
1515
|
context,
|
|
1488
1516
|
polymorphicPropName,
|
|
1489
1517
|
additionalComponents
|
|
1490
1518
|
);
|
|
1491
|
-
if (
|
|
1492
|
-
const
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
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
|
|
1497
1528
|
);
|
|
1498
|
-
if (
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
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)) {
|
|
1542
|
+
context.report({
|
|
1543
|
+
messageId: "noUnsafeIframeSandbox",
|
|
1544
|
+
node
|
|
1545
|
+
});
|
|
1546
|
+
}
|
|
1504
1547
|
}
|
|
1505
1548
|
};
|
|
1506
1549
|
},
|
|
@@ -1537,28 +1580,38 @@ var no_unsafe_target_blank_default = createRule({
|
|
|
1537
1580
|
const additionalComponents = settings.additionalComponents.filter((c) => c.as === "a");
|
|
1538
1581
|
return {
|
|
1539
1582
|
JSXElement(node) {
|
|
1540
|
-
const [elementNameOnJsx,
|
|
1541
|
-
node
|
|
1583
|
+
const [elementNameOnJsx, elementNameOnDom] = getElementNameOnJsxAndDom(
|
|
1584
|
+
node,
|
|
1542
1585
|
context,
|
|
1543
1586
|
polymorphicPropName,
|
|
1544
1587
|
additionalComponents
|
|
1545
1588
|
);
|
|
1546
|
-
if (
|
|
1547
|
-
const
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
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
|
|
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 _;
|
|
1554
1607
|
};
|
|
1555
|
-
if (
|
|
1608
|
+
if (getAttributeStringValue("target") !== "_blank") {
|
|
1556
1609
|
return;
|
|
1557
1610
|
}
|
|
1558
|
-
if (!isExternalLinkLike(
|
|
1611
|
+
if (!isExternalLinkLike(getAttributeStringValue("href"))) {
|
|
1559
1612
|
return;
|
|
1560
1613
|
}
|
|
1561
|
-
if (isSafeRel(
|
|
1614
|
+
if (isSafeRel(getAttributeStringValue("rel"))) {
|
|
1562
1615
|
return;
|
|
1563
1616
|
}
|
|
1564
1617
|
context.report({
|
|
@@ -1608,7 +1661,7 @@ var no_void_elements_with_children_default = createRule({
|
|
|
1608
1661
|
create(context) {
|
|
1609
1662
|
return {
|
|
1610
1663
|
JSXElement(node) {
|
|
1611
|
-
const elementName =
|
|
1664
|
+
const elementName = JSX.getElementName(node);
|
|
1612
1665
|
if (elementName.length === 0 || !voidElements.has(elementName)) {
|
|
1613
1666
|
return;
|
|
1614
1667
|
}
|
|
@@ -1623,7 +1676,7 @@ var no_void_elements_with_children_default = createRule({
|
|
|
1623
1676
|
}
|
|
1624
1677
|
const { attributes } = node.openingElement;
|
|
1625
1678
|
const initialScope = context.sourceCode.getScope(node);
|
|
1626
|
-
const hasAttribute3 = (name2) =>
|
|
1679
|
+
const hasAttribute3 = (name2) => JSX.hasAttribute(name2, attributes, initialScope);
|
|
1627
1680
|
if (hasAttribute3("children") || hasAttribute3("dangerouslySetInnerHTML")) {
|
|
1628
1681
|
context.report({
|
|
1629
1682
|
messageId: "noVoidElementsWithChildren",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-react-dom",
|
|
3
|
-
"version": "1.24.0
|
|
3
|
+
"version": "1.24.0",
|
|
4
4
|
"description": "ESLint React's ESLint plugin for React DOM related rules.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -46,13 +46,13 @@
|
|
|
46
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.
|
|
50
|
-
"@eslint-react/
|
|
51
|
-
"@eslint-react/
|
|
52
|
-
"@eslint-react/eff": "1.24.0
|
|
53
|
-
"@eslint-react/
|
|
54
|
-
"@eslint-react/
|
|
55
|
-
"@eslint-react/var": "1.24.0
|
|
49
|
+
"ts-pattern": "^5.6.1",
|
|
50
|
+
"@eslint-react/ast": "1.24.0",
|
|
51
|
+
"@eslint-react/core": "1.24.0",
|
|
52
|
+
"@eslint-react/eff": "1.24.0",
|
|
53
|
+
"@eslint-react/shared": "1.24.0",
|
|
54
|
+
"@eslint-react/jsx": "1.24.0",
|
|
55
|
+
"@eslint-react/var": "1.24.0"
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|
|
58
58
|
"@types/react": "^19.0.7",
|