eslint-plugin-react-dom 1.24.0-beta.3 → 1.24.0-beta.8
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 +115 -108
- package/dist/index.mjs +116 -109
- package/package.json +11 -12
package/dist/index.js
CHANGED
|
@@ -2,12 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
var JSX3 = require('@eslint-react/jsx');
|
|
4
4
|
var eff = require('@eslint-react/eff');
|
|
5
|
-
var VAR = require('@eslint-react/var');
|
|
6
|
-
var tsPattern = require('ts-pattern');
|
|
7
5
|
var shared = require('@eslint-react/shared');
|
|
8
6
|
var types = require('@typescript-eslint/types');
|
|
9
7
|
var core = require('@eslint-react/core');
|
|
10
8
|
var AST = require('@eslint-react/ast');
|
|
9
|
+
var VAR = require('@eslint-react/var');
|
|
11
10
|
var compareVersions = require('compare-versions');
|
|
12
11
|
|
|
13
12
|
function _interopNamespace(e) {
|
|
@@ -29,28 +28,44 @@ function _interopNamespace(e) {
|
|
|
29
28
|
}
|
|
30
29
|
|
|
31
30
|
var JSX3__namespace = /*#__PURE__*/_interopNamespace(JSX3);
|
|
32
|
-
var VAR__namespace = /*#__PURE__*/_interopNamespace(VAR);
|
|
33
31
|
var AST__namespace = /*#__PURE__*/_interopNamespace(AST);
|
|
32
|
+
var VAR__namespace = /*#__PURE__*/_interopNamespace(VAR);
|
|
34
33
|
|
|
35
34
|
// package.json
|
|
36
35
|
var name = "eslint-plugin-react-dom";
|
|
37
|
-
var version = "1.24.0-beta.
|
|
38
|
-
function getAdditionalAttributes(
|
|
39
|
-
return additionalComponents.findLast((c) => c.name ===
|
|
36
|
+
var version = "1.24.0-beta.8";
|
|
37
|
+
function getAdditionalAttributes(componentName, additionalComponents) {
|
|
38
|
+
return additionalComponents.findLast((c) => c.name === componentName || c.re.test(componentName))?.attributes ?? [];
|
|
40
39
|
}
|
|
41
|
-
function
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
40
|
+
function getAttributeMetaData(name2, attributes) {
|
|
41
|
+
const settings = attributes.findLast((a) => a.as === name2);
|
|
42
|
+
return {
|
|
43
|
+
name: settings?.name ?? name2,
|
|
44
|
+
controlled: settings?.controlled ?? false,
|
|
45
|
+
defaultValue: settings?.defaultValue
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
function getAttributeNodeAndStringValue(name2, element, context, additionalAttributes) {
|
|
49
|
+
const attributeMetaData = getAttributeMetaData(name2, additionalAttributes);
|
|
50
|
+
const attributeNameOnElement = attributeMetaData.name;
|
|
51
|
+
const attributeNode = JSX3__namespace.getAttributeNode(
|
|
52
|
+
attributeNameOnElement,
|
|
46
53
|
context.sourceCode.getScope(element),
|
|
47
54
|
element.openingElement.attributes
|
|
48
55
|
);
|
|
49
|
-
if (
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
56
|
+
if (attributeNode == null) {
|
|
57
|
+
return {
|
|
58
|
+
attributeNode: eff._,
|
|
59
|
+
attributeValue: attributeMetaData.defaultValue
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
const attributeScope = context.sourceCode.getScope(attributeNode);
|
|
63
|
+
const attributeValue = JSX3__namespace.getAttributeStringValue(
|
|
64
|
+
attributeNameOnElement,
|
|
65
|
+
attributeNode,
|
|
66
|
+
attributeScope
|
|
67
|
+
);
|
|
68
|
+
return { attributeNode, attributeValue };
|
|
54
69
|
}
|
|
55
70
|
var createRule = shared.createRuleForPlugin("dom");
|
|
56
71
|
|
|
@@ -73,14 +88,19 @@ var no_dangerously_set_innerhtml_default = createRule({
|
|
|
73
88
|
},
|
|
74
89
|
name: RULE_NAME,
|
|
75
90
|
create(context) {
|
|
91
|
+
if (!context.sourceCode.text.includes("dangerouslySetInnerHTML")) return {};
|
|
76
92
|
return {
|
|
77
93
|
JSXElement(node) {
|
|
78
94
|
const attributes = node.openingElement.attributes;
|
|
79
|
-
const
|
|
80
|
-
|
|
95
|
+
const attribute = JSX3__namespace.getAttributeNode(
|
|
96
|
+
"dangerouslySetInnerHTML",
|
|
97
|
+
context.sourceCode.getScope(node),
|
|
98
|
+
attributes
|
|
99
|
+
);
|
|
100
|
+
if (attribute == null) return;
|
|
81
101
|
context.report({
|
|
82
102
|
messageId: "noDangerouslySetInnerhtml",
|
|
83
|
-
node:
|
|
103
|
+
node: attribute
|
|
84
104
|
});
|
|
85
105
|
}
|
|
86
106
|
};
|
|
@@ -105,13 +125,13 @@ var no_dangerously_set_innerhtml_with_children_default = createRule({
|
|
|
105
125
|
},
|
|
106
126
|
name: RULE_NAME2,
|
|
107
127
|
create(context) {
|
|
128
|
+
if (!context.sourceCode.text.includes("dangerouslySetInnerHTML")) return {};
|
|
108
129
|
return {
|
|
109
130
|
JSXElement(node) {
|
|
110
131
|
const attributes = node.openingElement.attributes;
|
|
111
132
|
const initialScope = context.sourceCode.getScope(node);
|
|
112
|
-
const hasChildren = hasChildrenWithin(node) || JSX3__namespace.
|
|
113
|
-
|
|
114
|
-
if (hasChildren && hasDangerouslySetInnerHTML) {
|
|
133
|
+
const hasChildren = hasChildrenWithin(node) || JSX3__namespace.hasAttribute("children", initialScope, attributes);
|
|
134
|
+
if (hasChildren && JSX3__namespace.hasAttribute("dangerouslySetInnerHTML", initialScope, attributes)) {
|
|
115
135
|
context.report({
|
|
116
136
|
messageId: "noDangerouslySetInnerhtmlWithChildren",
|
|
117
137
|
node
|
|
@@ -143,6 +163,7 @@ var no_find_dom_node_default = createRule({
|
|
|
143
163
|
},
|
|
144
164
|
name: RULE_NAME3,
|
|
145
165
|
create(context) {
|
|
166
|
+
if (!context.sourceCode.text.includes("findDOMNode")) return {};
|
|
146
167
|
return {
|
|
147
168
|
CallExpression(node) {
|
|
148
169
|
const { callee } = node;
|
|
@@ -182,29 +203,27 @@ var no_missing_button_type_default = createRule({
|
|
|
182
203
|
name: RULE_NAME4,
|
|
183
204
|
create(context) {
|
|
184
205
|
const settings = shared.getSettingsFromContext(context);
|
|
206
|
+
const polymorphicPropName = settings.polymorphicPropName;
|
|
185
207
|
const additionalComponents = settings.additionalComponents.filter((c) => c.as === "button");
|
|
186
208
|
return {
|
|
187
209
|
JSXElement(node) {
|
|
188
|
-
const [
|
|
210
|
+
const [elementNameOnJsx, elementNameOnHtml] = core.getElementNameOnJsxAndHtml(
|
|
189
211
|
node.openingElement,
|
|
190
212
|
context,
|
|
191
|
-
|
|
192
|
-
|
|
213
|
+
polymorphicPropName,
|
|
214
|
+
additionalComponents
|
|
193
215
|
);
|
|
194
|
-
if (
|
|
195
|
-
const
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
};
|
|
203
|
-
const prop = getPropValue3("type");
|
|
204
|
-
if (typeof prop !== "string") {
|
|
216
|
+
if (elementNameOnHtml !== "button") return;
|
|
217
|
+
const { attributeNode, attributeValue } = getAttributeNodeAndStringValue(
|
|
218
|
+
"type",
|
|
219
|
+
node,
|
|
220
|
+
context,
|
|
221
|
+
getAdditionalAttributes(elementNameOnJsx, additionalComponents)
|
|
222
|
+
);
|
|
223
|
+
if (typeof attributeValue !== "string") {
|
|
205
224
|
context.report({
|
|
206
225
|
messageId: "noMissingButtonType",
|
|
207
|
-
node
|
|
226
|
+
node: attributeNode ?? node
|
|
208
227
|
});
|
|
209
228
|
}
|
|
210
229
|
}
|
|
@@ -249,39 +268,29 @@ var no_missing_iframe_sandbox_default = createRule({
|
|
|
249
268
|
name: RULE_NAME5,
|
|
250
269
|
create(context) {
|
|
251
270
|
const settings = shared.getSettingsFromContext(context);
|
|
271
|
+
const polymorphicPropName = settings.polymorphicPropName;
|
|
252
272
|
const additionalComponents = settings.additionalComponents.filter((c) => c.as === "iframe");
|
|
253
273
|
return {
|
|
254
274
|
JSXElement(node) {
|
|
255
|
-
const [
|
|
275
|
+
const [elementNameOnJsx, elementNameOnHtml] = core.getElementNameOnJsxAndHtml(
|
|
256
276
|
node.openingElement,
|
|
257
277
|
context,
|
|
258
|
-
|
|
259
|
-
|
|
278
|
+
polymorphicPropName,
|
|
279
|
+
additionalComponents
|
|
260
280
|
);
|
|
261
|
-
if (
|
|
262
|
-
const
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
node: node.openingElement
|
|
275
|
-
});
|
|
276
|
-
return;
|
|
277
|
-
}
|
|
278
|
-
const values = sandboxValue.split(" ");
|
|
279
|
-
if (!values.every((value) => validTypes.some((validType) => validType === value))) {
|
|
280
|
-
context.report({
|
|
281
|
-
messageId: "noMissingIframeSandbox",
|
|
282
|
-
node: node.openingElement
|
|
283
|
-
});
|
|
284
|
-
}
|
|
281
|
+
if (elementNameOnHtml !== "iframe") return;
|
|
282
|
+
const { attributeNode, attributeValue } = getAttributeNodeAndStringValue(
|
|
283
|
+
"sandbox",
|
|
284
|
+
node,
|
|
285
|
+
context,
|
|
286
|
+
getAdditionalAttributes(elementNameOnJsx, additionalComponents)
|
|
287
|
+
);
|
|
288
|
+
const hasValidSandboxValue = typeof attributeValue === "string" && attributeValue.split(" ").every((value) => validTypes.some((valid) => valid === value));
|
|
289
|
+
if (hasValidSandboxValue) return;
|
|
290
|
+
context.report({
|
|
291
|
+
messageId: "noMissingIframeSandbox",
|
|
292
|
+
node: attributeNode ?? node.openingElement
|
|
293
|
+
});
|
|
285
294
|
}
|
|
286
295
|
};
|
|
287
296
|
},
|
|
@@ -399,11 +408,11 @@ var no_script_url_default = createRule({
|
|
|
399
408
|
if (node.name.type !== types.AST_NODE_TYPES.JSXIdentifier || node.value == null) {
|
|
400
409
|
return;
|
|
401
410
|
}
|
|
402
|
-
const
|
|
403
|
-
const
|
|
404
|
-
const
|
|
405
|
-
if (typeof
|
|
406
|
-
if (shared.RE_JAVASCRIPT_PROTOCOL.test(
|
|
411
|
+
const attributeScope = context.sourceCode.getScope(node);
|
|
412
|
+
const attributeValue = JSX3__namespace.getAttributeStaticValue(node, attributeScope);
|
|
413
|
+
const attributeValueResolved = VAR__namespace.toResolved(attributeValue).value;
|
|
414
|
+
if (typeof attributeValueResolved !== "string") return;
|
|
415
|
+
if (shared.RE_JAVASCRIPT_PROTOCOL.test(attributeValueResolved)) {
|
|
407
416
|
context.report({
|
|
408
417
|
messageId: "noScriptUrl",
|
|
409
418
|
node: node.value
|
|
@@ -1493,33 +1502,29 @@ var no_unsafe_iframe_sandbox_default = createRule({
|
|
|
1493
1502
|
name: RULE_NAME10,
|
|
1494
1503
|
create(context) {
|
|
1495
1504
|
const settings = shared.getSettingsFromContext(context);
|
|
1505
|
+
const polymorphicPropName = settings.polymorphicPropName;
|
|
1496
1506
|
const additionalComponents = settings.additionalComponents.filter((c) => c.as === "iframe");
|
|
1497
1507
|
return {
|
|
1498
1508
|
JSXElement(node) {
|
|
1499
|
-
const [
|
|
1509
|
+
const [elementNameOnJsx, elementNameOnHtml] = core.getElementNameOnJsxAndHtml(
|
|
1500
1510
|
node.openingElement,
|
|
1501
1511
|
context,
|
|
1502
|
-
|
|
1503
|
-
|
|
1512
|
+
polymorphicPropName,
|
|
1513
|
+
additionalComponents
|
|
1504
1514
|
);
|
|
1505
|
-
if (
|
|
1506
|
-
const
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
context.report({
|
|
1519
|
-
messageId: "noUnsafeIframeSandbox",
|
|
1520
|
-
node: node.openingElement
|
|
1521
|
-
});
|
|
1522
|
-
}
|
|
1515
|
+
if (elementNameOnHtml !== "iframe") return;
|
|
1516
|
+
const { attributeNode, attributeValue } = getAttributeNodeAndStringValue(
|
|
1517
|
+
"sandbox",
|
|
1518
|
+
node,
|
|
1519
|
+
context,
|
|
1520
|
+
getAdditionalAttributes(elementNameOnJsx, additionalComponents)
|
|
1521
|
+
);
|
|
1522
|
+
if (attributeValue == null) return;
|
|
1523
|
+
if (!unsafeCombinations.some((c) => c.every((v) => attributeValue.includes(v)))) return;
|
|
1524
|
+
context.report({
|
|
1525
|
+
messageId: "noUnsafeIframeSandbox",
|
|
1526
|
+
node: attributeNode ?? node.openingElement
|
|
1527
|
+
});
|
|
1523
1528
|
}
|
|
1524
1529
|
};
|
|
1525
1530
|
},
|
|
@@ -1552,36 +1557,38 @@ var no_unsafe_target_blank_default = createRule({
|
|
|
1552
1557
|
name: RULE_NAME11,
|
|
1553
1558
|
create(context) {
|
|
1554
1559
|
const settings = shared.getSettingsFromContext(context);
|
|
1560
|
+
const polymorphicPropName = settings.polymorphicPropName;
|
|
1555
1561
|
const additionalComponents = settings.additionalComponents.filter((c) => c.as === "a");
|
|
1556
1562
|
return {
|
|
1557
1563
|
JSXElement(node) {
|
|
1558
|
-
const [
|
|
1564
|
+
const [elementNameOnJsx, elementNameOnHtml] = core.getElementNameOnJsxAndHtml(
|
|
1559
1565
|
node.openingElement,
|
|
1560
1566
|
context,
|
|
1561
|
-
|
|
1562
|
-
|
|
1567
|
+
polymorphicPropName,
|
|
1568
|
+
additionalComponents
|
|
1563
1569
|
);
|
|
1564
|
-
if (
|
|
1565
|
-
const
|
|
1566
|
-
return
|
|
1567
|
-
|
|
1570
|
+
if (elementNameOnHtml !== "a") return;
|
|
1571
|
+
const getAttributeValue = (name2) => {
|
|
1572
|
+
return getAttributeNodeAndStringValue(
|
|
1573
|
+
name2,
|
|
1568
1574
|
node,
|
|
1569
1575
|
context,
|
|
1570
|
-
getAdditionalAttributes(
|
|
1571
|
-
);
|
|
1576
|
+
getAdditionalAttributes(elementNameOnJsx, additionalComponents)
|
|
1577
|
+
).attributeValue;
|
|
1572
1578
|
};
|
|
1573
|
-
if (
|
|
1579
|
+
if (getAttributeValue("target") !== "_blank") {
|
|
1574
1580
|
return;
|
|
1575
1581
|
}
|
|
1576
|
-
if (!isExternalLinkLike(
|
|
1582
|
+
if (!isExternalLinkLike(getAttributeValue("href"))) {
|
|
1577
1583
|
return;
|
|
1578
1584
|
}
|
|
1579
|
-
if (
|
|
1580
|
-
|
|
1581
|
-
messageId: "noUnsafeTargetBlank",
|
|
1582
|
-
node
|
|
1583
|
-
});
|
|
1585
|
+
if (isSafeRel(getAttributeValue("rel"))) {
|
|
1586
|
+
return;
|
|
1584
1587
|
}
|
|
1588
|
+
context.report({
|
|
1589
|
+
messageId: "noUnsafeTargetBlank",
|
|
1590
|
+
node
|
|
1591
|
+
});
|
|
1585
1592
|
}
|
|
1586
1593
|
};
|
|
1587
1594
|
},
|
|
@@ -1640,8 +1647,8 @@ var no_void_elements_with_children_default = createRule({
|
|
|
1640
1647
|
}
|
|
1641
1648
|
const { attributes } = node.openingElement;
|
|
1642
1649
|
const initialScope = context.sourceCode.getScope(node);
|
|
1643
|
-
const
|
|
1644
|
-
if (
|
|
1650
|
+
const hasAttribute3 = (name2) => JSX3__namespace.hasAttribute(name2, initialScope, attributes);
|
|
1651
|
+
if (hasAttribute3("children") || hasAttribute3("dangerouslySetInnerHTML")) {
|
|
1645
1652
|
context.report({
|
|
1646
1653
|
messageId: "noVoidElementsWithChildren",
|
|
1647
1654
|
node,
|
package/dist/index.mjs
CHANGED
|
@@ -1,32 +1,47 @@
|
|
|
1
1
|
import * as JSX3 from '@eslint-react/jsx';
|
|
2
|
-
import {
|
|
3
|
-
import * as VAR from '@eslint-react/var';
|
|
4
|
-
import { match, P } from 'ts-pattern';
|
|
2
|
+
import { _ } from '@eslint-react/eff';
|
|
5
3
|
import { createRuleForPlugin, getSettingsFromContext, RE_JAVASCRIPT_PROTOCOL } from '@eslint-react/shared';
|
|
6
4
|
import { AST_NODE_TYPES } from '@typescript-eslint/types';
|
|
7
|
-
import {
|
|
5
|
+
import { getElementNameOnJsxAndHtml } from '@eslint-react/core';
|
|
8
6
|
import * as AST from '@eslint-react/ast';
|
|
7
|
+
import * as VAR from '@eslint-react/var';
|
|
9
8
|
import { compare } from 'compare-versions';
|
|
10
9
|
|
|
11
10
|
// package.json
|
|
12
11
|
var name = "eslint-plugin-react-dom";
|
|
13
|
-
var version = "1.24.0-beta.
|
|
14
|
-
function getAdditionalAttributes(
|
|
15
|
-
return additionalComponents.findLast((c) => c.name ===
|
|
12
|
+
var version = "1.24.0-beta.8";
|
|
13
|
+
function getAdditionalAttributes(componentName, additionalComponents) {
|
|
14
|
+
return additionalComponents.findLast((c) => c.name === componentName || c.re.test(componentName))?.attributes ?? [];
|
|
15
|
+
}
|
|
16
|
+
function getAttributeMetaData(name2, attributes) {
|
|
17
|
+
const settings = attributes.findLast((a) => a.as === name2);
|
|
18
|
+
return {
|
|
19
|
+
name: settings?.name ?? name2,
|
|
20
|
+
controlled: settings?.controlled ?? false,
|
|
21
|
+
defaultValue: settings?.defaultValue
|
|
22
|
+
};
|
|
16
23
|
}
|
|
17
|
-
function
|
|
18
|
-
const
|
|
19
|
-
const
|
|
20
|
-
const
|
|
21
|
-
|
|
24
|
+
function getAttributeNodeAndStringValue(name2, element, context, additionalAttributes) {
|
|
25
|
+
const attributeMetaData = getAttributeMetaData(name2, additionalAttributes);
|
|
26
|
+
const attributeNameOnElement = attributeMetaData.name;
|
|
27
|
+
const attributeNode = JSX3.getAttributeNode(
|
|
28
|
+
attributeNameOnElement,
|
|
22
29
|
context.sourceCode.getScope(element),
|
|
23
30
|
element.openingElement.attributes
|
|
24
31
|
);
|
|
25
|
-
if (
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
32
|
+
if (attributeNode == null) {
|
|
33
|
+
return {
|
|
34
|
+
attributeNode: _,
|
|
35
|
+
attributeValue: attributeMetaData.defaultValue
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
const attributeScope = context.sourceCode.getScope(attributeNode);
|
|
39
|
+
const attributeValue = JSX3.getAttributeStringValue(
|
|
40
|
+
attributeNameOnElement,
|
|
41
|
+
attributeNode,
|
|
42
|
+
attributeScope
|
|
43
|
+
);
|
|
44
|
+
return { attributeNode, attributeValue };
|
|
30
45
|
}
|
|
31
46
|
var createRule = createRuleForPlugin("dom");
|
|
32
47
|
|
|
@@ -49,14 +64,19 @@ var no_dangerously_set_innerhtml_default = createRule({
|
|
|
49
64
|
},
|
|
50
65
|
name: RULE_NAME,
|
|
51
66
|
create(context) {
|
|
67
|
+
if (!context.sourceCode.text.includes("dangerouslySetInnerHTML")) return {};
|
|
52
68
|
return {
|
|
53
69
|
JSXElement(node) {
|
|
54
70
|
const attributes = node.openingElement.attributes;
|
|
55
|
-
const
|
|
56
|
-
|
|
71
|
+
const attribute = JSX3.getAttributeNode(
|
|
72
|
+
"dangerouslySetInnerHTML",
|
|
73
|
+
context.sourceCode.getScope(node),
|
|
74
|
+
attributes
|
|
75
|
+
);
|
|
76
|
+
if (attribute == null) return;
|
|
57
77
|
context.report({
|
|
58
78
|
messageId: "noDangerouslySetInnerhtml",
|
|
59
|
-
node:
|
|
79
|
+
node: attribute
|
|
60
80
|
});
|
|
61
81
|
}
|
|
62
82
|
};
|
|
@@ -81,13 +101,13 @@ var no_dangerously_set_innerhtml_with_children_default = createRule({
|
|
|
81
101
|
},
|
|
82
102
|
name: RULE_NAME2,
|
|
83
103
|
create(context) {
|
|
104
|
+
if (!context.sourceCode.text.includes("dangerouslySetInnerHTML")) return {};
|
|
84
105
|
return {
|
|
85
106
|
JSXElement(node) {
|
|
86
107
|
const attributes = node.openingElement.attributes;
|
|
87
108
|
const initialScope = context.sourceCode.getScope(node);
|
|
88
|
-
const hasChildren = hasChildrenWithin(node) || JSX3.
|
|
89
|
-
|
|
90
|
-
if (hasChildren && hasDangerouslySetInnerHTML) {
|
|
109
|
+
const hasChildren = hasChildrenWithin(node) || JSX3.hasAttribute("children", initialScope, attributes);
|
|
110
|
+
if (hasChildren && JSX3.hasAttribute("dangerouslySetInnerHTML", initialScope, attributes)) {
|
|
91
111
|
context.report({
|
|
92
112
|
messageId: "noDangerouslySetInnerhtmlWithChildren",
|
|
93
113
|
node
|
|
@@ -119,6 +139,7 @@ var no_find_dom_node_default = createRule({
|
|
|
119
139
|
},
|
|
120
140
|
name: RULE_NAME3,
|
|
121
141
|
create(context) {
|
|
142
|
+
if (!context.sourceCode.text.includes("findDOMNode")) return {};
|
|
122
143
|
return {
|
|
123
144
|
CallExpression(node) {
|
|
124
145
|
const { callee } = node;
|
|
@@ -158,29 +179,27 @@ var no_missing_button_type_default = createRule({
|
|
|
158
179
|
name: RULE_NAME4,
|
|
159
180
|
create(context) {
|
|
160
181
|
const settings = getSettingsFromContext(context);
|
|
182
|
+
const polymorphicPropName = settings.polymorphicPropName;
|
|
161
183
|
const additionalComponents = settings.additionalComponents.filter((c) => c.as === "button");
|
|
162
184
|
return {
|
|
163
185
|
JSXElement(node) {
|
|
164
|
-
const [
|
|
186
|
+
const [elementNameOnJsx, elementNameOnHtml] = getElementNameOnJsxAndHtml(
|
|
165
187
|
node.openingElement,
|
|
166
188
|
context,
|
|
167
|
-
|
|
168
|
-
|
|
189
|
+
polymorphicPropName,
|
|
190
|
+
additionalComponents
|
|
169
191
|
);
|
|
170
|
-
if (
|
|
171
|
-
const
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
};
|
|
179
|
-
const prop = getPropValue3("type");
|
|
180
|
-
if (typeof prop !== "string") {
|
|
192
|
+
if (elementNameOnHtml !== "button") return;
|
|
193
|
+
const { attributeNode, attributeValue } = getAttributeNodeAndStringValue(
|
|
194
|
+
"type",
|
|
195
|
+
node,
|
|
196
|
+
context,
|
|
197
|
+
getAdditionalAttributes(elementNameOnJsx, additionalComponents)
|
|
198
|
+
);
|
|
199
|
+
if (typeof attributeValue !== "string") {
|
|
181
200
|
context.report({
|
|
182
201
|
messageId: "noMissingButtonType",
|
|
183
|
-
node
|
|
202
|
+
node: attributeNode ?? node
|
|
184
203
|
});
|
|
185
204
|
}
|
|
186
205
|
}
|
|
@@ -225,39 +244,29 @@ var no_missing_iframe_sandbox_default = createRule({
|
|
|
225
244
|
name: RULE_NAME5,
|
|
226
245
|
create(context) {
|
|
227
246
|
const settings = getSettingsFromContext(context);
|
|
247
|
+
const polymorphicPropName = settings.polymorphicPropName;
|
|
228
248
|
const additionalComponents = settings.additionalComponents.filter((c) => c.as === "iframe");
|
|
229
249
|
return {
|
|
230
250
|
JSXElement(node) {
|
|
231
|
-
const [
|
|
251
|
+
const [elementNameOnJsx, elementNameOnHtml] = getElementNameOnJsxAndHtml(
|
|
232
252
|
node.openingElement,
|
|
233
253
|
context,
|
|
234
|
-
|
|
235
|
-
|
|
254
|
+
polymorphicPropName,
|
|
255
|
+
additionalComponents
|
|
236
256
|
);
|
|
237
|
-
if (
|
|
238
|
-
const
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
node: node.openingElement
|
|
251
|
-
});
|
|
252
|
-
return;
|
|
253
|
-
}
|
|
254
|
-
const values = sandboxValue.split(" ");
|
|
255
|
-
if (!values.every((value) => validTypes.some((validType) => validType === value))) {
|
|
256
|
-
context.report({
|
|
257
|
-
messageId: "noMissingIframeSandbox",
|
|
258
|
-
node: node.openingElement
|
|
259
|
-
});
|
|
260
|
-
}
|
|
257
|
+
if (elementNameOnHtml !== "iframe") return;
|
|
258
|
+
const { attributeNode, attributeValue } = getAttributeNodeAndStringValue(
|
|
259
|
+
"sandbox",
|
|
260
|
+
node,
|
|
261
|
+
context,
|
|
262
|
+
getAdditionalAttributes(elementNameOnJsx, additionalComponents)
|
|
263
|
+
);
|
|
264
|
+
const hasValidSandboxValue = typeof attributeValue === "string" && attributeValue.split(" ").every((value) => validTypes.some((valid) => valid === value));
|
|
265
|
+
if (hasValidSandboxValue) return;
|
|
266
|
+
context.report({
|
|
267
|
+
messageId: "noMissingIframeSandbox",
|
|
268
|
+
node: attributeNode ?? node.openingElement
|
|
269
|
+
});
|
|
261
270
|
}
|
|
262
271
|
};
|
|
263
272
|
},
|
|
@@ -375,11 +384,11 @@ var no_script_url_default = createRule({
|
|
|
375
384
|
if (node.name.type !== AST_NODE_TYPES.JSXIdentifier || node.value == null) {
|
|
376
385
|
return;
|
|
377
386
|
}
|
|
378
|
-
const
|
|
379
|
-
const
|
|
380
|
-
const
|
|
381
|
-
if (typeof
|
|
382
|
-
if (RE_JAVASCRIPT_PROTOCOL.test(
|
|
387
|
+
const attributeScope = context.sourceCode.getScope(node);
|
|
388
|
+
const attributeValue = JSX3.getAttributeStaticValue(node, attributeScope);
|
|
389
|
+
const attributeValueResolved = VAR.toResolved(attributeValue).value;
|
|
390
|
+
if (typeof attributeValueResolved !== "string") return;
|
|
391
|
+
if (RE_JAVASCRIPT_PROTOCOL.test(attributeValueResolved)) {
|
|
383
392
|
context.report({
|
|
384
393
|
messageId: "noScriptUrl",
|
|
385
394
|
node: node.value
|
|
@@ -1469,33 +1478,29 @@ var no_unsafe_iframe_sandbox_default = createRule({
|
|
|
1469
1478
|
name: RULE_NAME10,
|
|
1470
1479
|
create(context) {
|
|
1471
1480
|
const settings = getSettingsFromContext(context);
|
|
1481
|
+
const polymorphicPropName = settings.polymorphicPropName;
|
|
1472
1482
|
const additionalComponents = settings.additionalComponents.filter((c) => c.as === "iframe");
|
|
1473
1483
|
return {
|
|
1474
1484
|
JSXElement(node) {
|
|
1475
|
-
const [
|
|
1485
|
+
const [elementNameOnJsx, elementNameOnHtml] = getElementNameOnJsxAndHtml(
|
|
1476
1486
|
node.openingElement,
|
|
1477
1487
|
context,
|
|
1478
|
-
|
|
1479
|
-
|
|
1488
|
+
polymorphicPropName,
|
|
1489
|
+
additionalComponents
|
|
1480
1490
|
);
|
|
1481
|
-
if (
|
|
1482
|
-
const
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
context.report({
|
|
1495
|
-
messageId: "noUnsafeIframeSandbox",
|
|
1496
|
-
node: node.openingElement
|
|
1497
|
-
});
|
|
1498
|
-
}
|
|
1491
|
+
if (elementNameOnHtml !== "iframe") return;
|
|
1492
|
+
const { attributeNode, attributeValue } = getAttributeNodeAndStringValue(
|
|
1493
|
+
"sandbox",
|
|
1494
|
+
node,
|
|
1495
|
+
context,
|
|
1496
|
+
getAdditionalAttributes(elementNameOnJsx, additionalComponents)
|
|
1497
|
+
);
|
|
1498
|
+
if (attributeValue == null) return;
|
|
1499
|
+
if (!unsafeCombinations.some((c) => c.every((v) => attributeValue.includes(v)))) return;
|
|
1500
|
+
context.report({
|
|
1501
|
+
messageId: "noUnsafeIframeSandbox",
|
|
1502
|
+
node: attributeNode ?? node.openingElement
|
|
1503
|
+
});
|
|
1499
1504
|
}
|
|
1500
1505
|
};
|
|
1501
1506
|
},
|
|
@@ -1528,36 +1533,38 @@ var no_unsafe_target_blank_default = createRule({
|
|
|
1528
1533
|
name: RULE_NAME11,
|
|
1529
1534
|
create(context) {
|
|
1530
1535
|
const settings = getSettingsFromContext(context);
|
|
1536
|
+
const polymorphicPropName = settings.polymorphicPropName;
|
|
1531
1537
|
const additionalComponents = settings.additionalComponents.filter((c) => c.as === "a");
|
|
1532
1538
|
return {
|
|
1533
1539
|
JSXElement(node) {
|
|
1534
|
-
const [
|
|
1540
|
+
const [elementNameOnJsx, elementNameOnHtml] = getElementNameOnJsxAndHtml(
|
|
1535
1541
|
node.openingElement,
|
|
1536
1542
|
context,
|
|
1537
|
-
|
|
1538
|
-
|
|
1543
|
+
polymorphicPropName,
|
|
1544
|
+
additionalComponents
|
|
1539
1545
|
);
|
|
1540
|
-
if (
|
|
1541
|
-
const
|
|
1542
|
-
return
|
|
1543
|
-
|
|
1546
|
+
if (elementNameOnHtml !== "a") return;
|
|
1547
|
+
const getAttributeValue = (name2) => {
|
|
1548
|
+
return getAttributeNodeAndStringValue(
|
|
1549
|
+
name2,
|
|
1544
1550
|
node,
|
|
1545
1551
|
context,
|
|
1546
|
-
getAdditionalAttributes(
|
|
1547
|
-
);
|
|
1552
|
+
getAdditionalAttributes(elementNameOnJsx, additionalComponents)
|
|
1553
|
+
).attributeValue;
|
|
1548
1554
|
};
|
|
1549
|
-
if (
|
|
1555
|
+
if (getAttributeValue("target") !== "_blank") {
|
|
1550
1556
|
return;
|
|
1551
1557
|
}
|
|
1552
|
-
if (!isExternalLinkLike(
|
|
1558
|
+
if (!isExternalLinkLike(getAttributeValue("href"))) {
|
|
1553
1559
|
return;
|
|
1554
1560
|
}
|
|
1555
|
-
if (
|
|
1556
|
-
|
|
1557
|
-
messageId: "noUnsafeTargetBlank",
|
|
1558
|
-
node
|
|
1559
|
-
});
|
|
1561
|
+
if (isSafeRel(getAttributeValue("rel"))) {
|
|
1562
|
+
return;
|
|
1560
1563
|
}
|
|
1564
|
+
context.report({
|
|
1565
|
+
messageId: "noUnsafeTargetBlank",
|
|
1566
|
+
node
|
|
1567
|
+
});
|
|
1561
1568
|
}
|
|
1562
1569
|
};
|
|
1563
1570
|
},
|
|
@@ -1616,8 +1623,8 @@ var no_void_elements_with_children_default = createRule({
|
|
|
1616
1623
|
}
|
|
1617
1624
|
const { attributes } = node.openingElement;
|
|
1618
1625
|
const initialScope = context.sourceCode.getScope(node);
|
|
1619
|
-
const
|
|
1620
|
-
if (
|
|
1626
|
+
const hasAttribute3 = (name2) => JSX3.hasAttribute(name2, initialScope, attributes);
|
|
1627
|
+
if (hasAttribute3("children") || hasAttribute3("dangerouslySetInnerHTML")) {
|
|
1621
1628
|
context.report({
|
|
1622
1629
|
messageId: "noVoidElementsWithChildren",
|
|
1623
1630
|
node,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-react-dom",
|
|
3
|
-
"version": "1.24.0-beta.
|
|
3
|
+
"version": "1.24.0-beta.8",
|
|
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.
|
|
45
|
-
"@typescript-eslint/types": "^8.
|
|
46
|
-
"@typescript-eslint/utils": "^8.
|
|
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-beta.
|
|
51
|
-
"@eslint-react/
|
|
52
|
-
"@eslint-react/
|
|
53
|
-
"@eslint-react/
|
|
54
|
-
"@eslint-react/
|
|
55
|
-
"@eslint-react/shared": "1.24.0-beta.
|
|
56
|
-
"@eslint-react/var": "1.24.0-beta.3"
|
|
50
|
+
"@eslint-react/ast": "1.24.0-beta.8",
|
|
51
|
+
"@eslint-react/jsx": "1.24.0-beta.8",
|
|
52
|
+
"@eslint-react/eff": "1.24.0-beta.8",
|
|
53
|
+
"@eslint-react/var": "1.24.0-beta.8",
|
|
54
|
+
"@eslint-react/core": "1.24.0-beta.8",
|
|
55
|
+
"@eslint-react/shared": "1.24.0-beta.8"
|
|
57
56
|
},
|
|
58
57
|
"devDependencies": {
|
|
59
|
-
"@types/react": "^19.0.
|
|
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"
|