eslint-plugin-react-dom 2.0.5-next.2 → 2.0.5-next.3
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 +46 -47
- package/package.json +7 -7
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { DEFAULT_ESLINT_REACT_SETTINGS, getConfigAdapters, getDocsUrl, getSettingsFromContext } from "@eslint-react/shared";
|
|
2
|
-
import { getJsxAttribute, getJsxElementType,
|
|
2
|
+
import { getJsxAttribute, getJsxElementType, isJsxHostElement, isJsxText, resolveJsxAttributeValue } from "@eslint-react/core";
|
|
3
3
|
import { ESLintUtils } from "@typescript-eslint/utils";
|
|
4
4
|
import { AST_NODE_TYPES } from "@typescript-eslint/types";
|
|
5
5
|
import { compare } from "compare-versions";
|
|
@@ -47,7 +47,7 @@ const settings = { "react-x": DEFAULT_ESLINT_REACT_SETTINGS };
|
|
|
47
47
|
//#endregion
|
|
48
48
|
//#region package.json
|
|
49
49
|
var name = "eslint-plugin-react-dom";
|
|
50
|
-
var version = "2.0.5-next.
|
|
50
|
+
var version = "2.0.5-next.3";
|
|
51
51
|
|
|
52
52
|
//#endregion
|
|
53
53
|
//#region src/utils/create-jsx-element-resolver.ts
|
|
@@ -71,7 +71,7 @@ function createJsxElementResolver(context) {
|
|
|
71
71
|
jsxElementType: elementName
|
|
72
72
|
};
|
|
73
73
|
if (elementName === elementName.toLowerCase() || polymorphicPropName == null) return result;
|
|
74
|
-
const polymorphicProp = getJsxAttribute(context, node
|
|
74
|
+
const polymorphicProp = getJsxAttribute(context, node)(polymorphicPropName);
|
|
75
75
|
if (polymorphicProp != null) {
|
|
76
76
|
const staticValue = resolveJsxAttributeValue(context, polymorphicProp).toStatic(polymorphicPropName);
|
|
77
77
|
if (typeof staticValue === "string") return {
|
|
@@ -109,11 +109,11 @@ var no_dangerously_set_innerhtml_default = createRule({
|
|
|
109
109
|
function create$17(context) {
|
|
110
110
|
if (!context.sourceCode.text.includes(DSIH$1)) return {};
|
|
111
111
|
return { JSXElement(node) {
|
|
112
|
-
const
|
|
113
|
-
if (
|
|
112
|
+
const dsihProp = getJsxAttribute(context, node)(DSIH$1);
|
|
113
|
+
if (dsihProp == null) return;
|
|
114
114
|
context.report({
|
|
115
115
|
messageId: "noDangerouslySetInnerhtml",
|
|
116
|
-
node:
|
|
116
|
+
node: dsihProp
|
|
117
117
|
});
|
|
118
118
|
} };
|
|
119
119
|
}
|
|
@@ -149,13 +149,13 @@ function isSignificantChildren(node) {
|
|
|
149
149
|
function create$16(context) {
|
|
150
150
|
if (!context.sourceCode.text.includes(DSIH)) return {};
|
|
151
151
|
return { JSXElement(node) {
|
|
152
|
-
const findJsxAttribute = getJsxAttribute(context, node
|
|
152
|
+
const findJsxAttribute = getJsxAttribute(context, node);
|
|
153
153
|
if (findJsxAttribute(DSIH) == null) return;
|
|
154
|
-
const
|
|
155
|
-
if (
|
|
154
|
+
const childrenPropOrNode = findJsxAttribute("children") ?? node.children.find(isSignificantChildren);
|
|
155
|
+
if (childrenPropOrNode == null) return;
|
|
156
156
|
context.report({
|
|
157
157
|
messageId: "noDangerouslySetInnerhtmlWithChildren",
|
|
158
|
-
node:
|
|
158
|
+
node: childrenPropOrNode
|
|
159
159
|
});
|
|
160
160
|
} };
|
|
161
161
|
}
|
|
@@ -341,7 +341,7 @@ function create$12(context) {
|
|
|
341
341
|
const resolver = createJsxElementResolver(context);
|
|
342
342
|
return { JSXElement(node) {
|
|
343
343
|
if (resolver.resolve(node).domElementType !== "button") return;
|
|
344
|
-
if (getJsxAttribute(context, node
|
|
344
|
+
if (getJsxAttribute(context, node)("type") != null) return;
|
|
345
345
|
context.report({
|
|
346
346
|
messageId: "noMissingButtonType",
|
|
347
347
|
node: node.openingElement,
|
|
@@ -362,14 +362,14 @@ var no_missing_iframe_sandbox_default = createRule({
|
|
|
362
362
|
meta: {
|
|
363
363
|
type: "problem",
|
|
364
364
|
docs: {
|
|
365
|
-
description: "Enforces explicit `sandbox`
|
|
365
|
+
description: "Enforces explicit `sandbox` prop for `iframe` elements.",
|
|
366
366
|
[Symbol.for("rule_features")]: RULE_FEATURES$10
|
|
367
367
|
},
|
|
368
368
|
fixable: "code",
|
|
369
369
|
hasSuggestions: true,
|
|
370
370
|
messages: {
|
|
371
|
-
addIframeSandbox: "Add 'sandbox'
|
|
372
|
-
noMissingIframeSandbox: "Add missing 'sandbox'
|
|
371
|
+
addIframeSandbox: "Add 'sandbox' prop with value '{{value}}'.",
|
|
372
|
+
noMissingIframeSandbox: "Add missing 'sandbox' prop on 'iframe' component."
|
|
373
373
|
},
|
|
374
374
|
schema: []
|
|
375
375
|
},
|
|
@@ -382,8 +382,8 @@ function create$11(context) {
|
|
|
382
382
|
return { JSXElement(node) {
|
|
383
383
|
const { domElementType } = resolver.resolve(node);
|
|
384
384
|
if (domElementType !== "iframe") return;
|
|
385
|
-
const
|
|
386
|
-
if (
|
|
385
|
+
const sandboxProp = getJsxAttribute(context, node)("sandbox");
|
|
386
|
+
if (sandboxProp == null) {
|
|
387
387
|
context.report({
|
|
388
388
|
messageId: "noMissingIframeSandbox",
|
|
389
389
|
node: node.openingElement,
|
|
@@ -397,17 +397,17 @@ function create$11(context) {
|
|
|
397
397
|
});
|
|
398
398
|
return;
|
|
399
399
|
}
|
|
400
|
-
const sandboxValue = resolveJsxAttributeValue(context,
|
|
400
|
+
const sandboxValue = resolveJsxAttributeValue(context, sandboxProp);
|
|
401
401
|
if (typeof sandboxValue.toStatic("sandbox") === "string") return;
|
|
402
402
|
context.report({
|
|
403
403
|
messageId: "noMissingIframeSandbox",
|
|
404
|
-
node: sandboxValue.node ??
|
|
404
|
+
node: sandboxValue.node ?? sandboxProp,
|
|
405
405
|
suggest: [{
|
|
406
406
|
messageId: "addIframeSandbox",
|
|
407
407
|
data: { value: "" },
|
|
408
408
|
fix(fixer) {
|
|
409
409
|
if (sandboxValue.kind.startsWith("spread")) return null;
|
|
410
|
-
return fixer.replaceText(
|
|
410
|
+
return fixer.replaceText(sandboxProp, `sandbox=""`);
|
|
411
411
|
}
|
|
412
412
|
}]
|
|
413
413
|
});
|
|
@@ -625,12 +625,12 @@ var no_string_style_prop_default = createRule({
|
|
|
625
625
|
function create$6(context) {
|
|
626
626
|
return { JSXElement(node) {
|
|
627
627
|
if (!isJsxHostElement(context, node)) return;
|
|
628
|
-
const
|
|
629
|
-
if (
|
|
630
|
-
const styleValue = resolveJsxAttributeValue(context,
|
|
628
|
+
const styleProp = getJsxAttribute(context, node)("style");
|
|
629
|
+
if (styleProp == null) return;
|
|
630
|
+
const styleValue = resolveJsxAttributeValue(context, styleProp);
|
|
631
631
|
if (typeof styleValue.toStatic() === "string") context.report({
|
|
632
632
|
messageId: "noStringStyleProp",
|
|
633
|
-
node: styleValue.node ??
|
|
633
|
+
node: styleValue.node ?? styleProp
|
|
634
634
|
});
|
|
635
635
|
} };
|
|
636
636
|
}
|
|
@@ -1801,13 +1801,13 @@ function create$4(context) {
|
|
|
1801
1801
|
const resolver = createJsxElementResolver(context);
|
|
1802
1802
|
return { JSXElement(node) {
|
|
1803
1803
|
if (resolver.resolve(node).domElementType !== "iframe") return;
|
|
1804
|
-
const
|
|
1805
|
-
if (
|
|
1806
|
-
const sandboxValue = resolveJsxAttributeValue(context,
|
|
1804
|
+
const sandboxProp = getJsxAttribute(context, node)("sandbox");
|
|
1805
|
+
if (sandboxProp == null) return;
|
|
1806
|
+
const sandboxValue = resolveJsxAttributeValue(context, sandboxProp);
|
|
1807
1807
|
const sandboxValueStatic = sandboxValue.toStatic("sandbox");
|
|
1808
1808
|
if (isUnsafeSandboxCombination(sandboxValueStatic)) context.report({
|
|
1809
1809
|
messageId: "noUnsafeIframeSandbox",
|
|
1810
|
-
node: sandboxValue.node ??
|
|
1810
|
+
node: sandboxValue.node ?? sandboxProp
|
|
1811
1811
|
});
|
|
1812
1812
|
} };
|
|
1813
1813
|
}
|
|
@@ -1827,9 +1827,9 @@ function isExternalLinkLike(value) {
|
|
|
1827
1827
|
return value.startsWith("https://") || /^(?:\w+:|\/\/)/u.test(value);
|
|
1828
1828
|
}
|
|
1829
1829
|
/**
|
|
1830
|
-
* Checks if a rel
|
|
1830
|
+
* Checks if a rel prop value contains the necessary security attributes.
|
|
1831
1831
|
* At minimum, it should contain "noreferrer".
|
|
1832
|
-
* @param value - The rel
|
|
1832
|
+
* @param value - The rel prop value to check
|
|
1833
1833
|
* @returns Whether the rel value is considered secure
|
|
1834
1834
|
*/
|
|
1835
1835
|
function isSafeRel(value) {
|
|
@@ -1860,16 +1860,16 @@ function create$3(context) {
|
|
|
1860
1860
|
return { JSXElement(node) {
|
|
1861
1861
|
const { domElementType } = resolver.resolve(node);
|
|
1862
1862
|
if (domElementType !== "a") return;
|
|
1863
|
-
const findAttribute = getJsxAttribute(context, node
|
|
1864
|
-
const
|
|
1865
|
-
if (
|
|
1866
|
-
if (resolveJsxAttributeValue(context,
|
|
1867
|
-
const
|
|
1868
|
-
if (
|
|
1869
|
-
const
|
|
1870
|
-
if (!isExternalLinkLike(
|
|
1871
|
-
const
|
|
1872
|
-
if (
|
|
1863
|
+
const findAttribute = getJsxAttribute(context, node);
|
|
1864
|
+
const targetProp = findAttribute("target");
|
|
1865
|
+
if (targetProp == null) return;
|
|
1866
|
+
if (resolveJsxAttributeValue(context, targetProp).toStatic("target") !== "_blank") return;
|
|
1867
|
+
const hrefProp = findAttribute("href");
|
|
1868
|
+
if (hrefProp == null) return;
|
|
1869
|
+
const hrefValue = resolveJsxAttributeValue(context, hrefProp).toStatic("href");
|
|
1870
|
+
if (!isExternalLinkLike(hrefValue)) return;
|
|
1871
|
+
const relProp = findAttribute("rel");
|
|
1872
|
+
if (relProp == null) {
|
|
1873
1873
|
context.report({
|
|
1874
1874
|
messageId: "noUnsafeTargetBlank",
|
|
1875
1875
|
node: node.openingElement,
|
|
@@ -1882,15 +1882,15 @@ function create$3(context) {
|
|
|
1882
1882
|
});
|
|
1883
1883
|
return;
|
|
1884
1884
|
}
|
|
1885
|
-
const
|
|
1886
|
-
if (isSafeRel(
|
|
1885
|
+
const relValue = resolveJsxAttributeValue(context, relProp).toStatic("rel");
|
|
1886
|
+
if (isSafeRel(relValue)) return;
|
|
1887
1887
|
context.report({
|
|
1888
1888
|
messageId: "noUnsafeTargetBlank",
|
|
1889
|
-
node:
|
|
1889
|
+
node: relProp,
|
|
1890
1890
|
suggest: [{
|
|
1891
1891
|
messageId: "addRelNoreferrerNoopener",
|
|
1892
1892
|
fix(fixer) {
|
|
1893
|
-
return fixer.replaceText(
|
|
1893
|
+
return fixer.replaceText(relProp, `rel="noreferrer noopener"`);
|
|
1894
1894
|
}
|
|
1895
1895
|
}]
|
|
1896
1896
|
});
|
|
@@ -2005,10 +2005,9 @@ function create$1(context) {
|
|
|
2005
2005
|
return { JSXElement(node) {
|
|
2006
2006
|
const { domElementType: elementName } = resolver.resolve(node);
|
|
2007
2007
|
if (!voidElements.has(elementName)) return;
|
|
2008
|
-
const
|
|
2009
|
-
const
|
|
2010
|
-
const
|
|
2011
|
-
const hasDangerouslySetInnerHTML = hasJsxAttribute(context, "dangerouslySetInnerHTML", attributes, initialScope);
|
|
2008
|
+
const findJsxAttribute = getJsxAttribute(context, node);
|
|
2009
|
+
const hasChildrenProp = findJsxAttribute("children") != null;
|
|
2010
|
+
const hasDangerouslySetInnerHTML = findJsxAttribute("dangerouslySetInnerHTML") != null;
|
|
2012
2011
|
if (node.children.length > 0 || hasChildrenProp || hasDangerouslySetInnerHTML) context.report({
|
|
2013
2012
|
messageId: "noVoidElementsWithChildren",
|
|
2014
2013
|
node,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-react-dom",
|
|
3
|
-
"version": "2.0.5-next.
|
|
3
|
+
"version": "2.0.5-next.3",
|
|
4
4
|
"description": "ESLint React's ESLint plugin for React DOM related rules.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -41,12 +41,12 @@
|
|
|
41
41
|
"compare-versions": "^6.1.1",
|
|
42
42
|
"string-ts": "^2.2.1",
|
|
43
43
|
"ts-pattern": "^5.8.0",
|
|
44
|
-
"@eslint-react/
|
|
45
|
-
"@eslint-react/
|
|
46
|
-
"@eslint-react/
|
|
47
|
-
"@eslint-react/
|
|
48
|
-
"@eslint-react/
|
|
49
|
-
"@eslint-react/
|
|
44
|
+
"@eslint-react/ast": "2.0.5-next.3",
|
|
45
|
+
"@eslint-react/core": "2.0.5-next.3",
|
|
46
|
+
"@eslint-react/eff": "2.0.5-next.3",
|
|
47
|
+
"@eslint-react/kit": "2.0.5-next.3",
|
|
48
|
+
"@eslint-react/var": "2.0.5-next.3",
|
|
49
|
+
"@eslint-react/shared": "2.0.5-next.3"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
52
|
"@types/react": "^19.1.16",
|