eslint-plugin-react-dom 2.0.5-next.2 → 2.0.5-next.4

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 (2) hide show
  1. package/dist/index.js +64 -57
  2. 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, hasJsxAttribute, isJsxHostElement, isJsxText, resolveJsxAttributeValue } from "@eslint-react/core";
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.2";
50
+ var version = "2.0.5-next.4";
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.openingElement.attributes, context.sourceCode.getScope(node))(polymorphicPropName);
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 attr = getJsxAttribute(context, node.openingElement.attributes, context.sourceCode.getScope(node))(DSIH$1);
113
- if (attr == null) return;
112
+ const dsihProp = getJsxAttribute(context, node)(DSIH$1);
113
+ if (dsihProp == null) return;
114
114
  context.report({
115
115
  messageId: "noDangerouslySetInnerhtml",
116
- node: attr
116
+ node: dsihProp
117
117
  });
118
118
  } };
119
119
  }
@@ -138,9 +138,9 @@ var no_dangerously_set_innerhtml_with_children_default = createRule({
138
138
  });
139
139
  const DSIH = "dangerouslySetInnerHTML";
140
140
  /**
141
- * Checks if a JSX child node is considered significant (i.e., not just whitespace for formatting).
142
- * @param node The JSX child node to check.
143
- * @returns `true` if the node is significant, `false` otherwise.
141
+ * Checks if a JSX child node is considered significant (i.e., not just whitespace for formatting)
142
+ * @param node The JSX child node to check
143
+ * @returns `true` if the node is significant, `false` otherwise
144
144
  */
145
145
  function isSignificantChildren(node) {
146
146
  if (!isJsxText(node)) return true;
@@ -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.openingElement.attributes, context.sourceCode.getScope(node));
152
+ const findJsxAttribute = getJsxAttribute(context, node);
153
153
  if (findJsxAttribute(DSIH) == null) return;
154
- const children = findJsxAttribute("children") ?? node.children.find(isSignificantChildren);
155
- if (children == null) return;
154
+ const childrenPropOrNode = findJsxAttribute("children") ?? node.children.find(isSignificantChildren);
155
+ if (childrenPropOrNode == null) return;
156
156
  context.report({
157
157
  messageId: "noDangerouslySetInnerhtmlWithChildren",
158
- node: children
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.openingElement.attributes, context.sourceCode.getScope(node))("type") != null) return;
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` attribute for `iframe` elements.",
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' attribute with value '{{value}}'.",
372
- noMissingIframeSandbox: "Add missing 'sandbox' attribute on 'iframe' component."
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 sandboxAttr = getJsxAttribute(context, node.openingElement.attributes, context.sourceCode.getScope(node))("sandbox");
386
- if (sandboxAttr == null) {
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, sandboxAttr);
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 ?? sandboxAttr,
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(sandboxAttr, `sandbox=""`);
410
+ return fixer.replaceText(sandboxProp, `sandbox=""`);
411
411
  }
412
412
  }]
413
413
  });
@@ -504,6 +504,12 @@ function create$9(context) {
504
504
  }
505
505
  };
506
506
  }
507
+ /**
508
+ * Provides a fixer function to replace `render(app, container)` with `createRoot(container).render(app)`
509
+ * @param context The rule context
510
+ * @param node The `CallExpression` node to fix
511
+ * @returns A fixer function or null if the fix cannot be applied
512
+ */
507
513
  function getFix$1(context, node) {
508
514
  const getText$1 = (n) => context.sourceCode.getText(n);
509
515
  return (fixer) => {
@@ -625,12 +631,12 @@ var no_string_style_prop_default = createRule({
625
631
  function create$6(context) {
626
632
  return { JSXElement(node) {
627
633
  if (!isJsxHostElement(context, node)) return;
628
- const styleAttr = getJsxAttribute(context, node.openingElement.attributes, context.sourceCode.getScope(node))("style");
629
- if (styleAttr == null) return;
630
- const styleValue = resolveJsxAttributeValue(context, styleAttr);
634
+ const styleProp = getJsxAttribute(context, node)("style");
635
+ if (styleProp == null) return;
636
+ const styleValue = resolveJsxAttributeValue(context, styleProp);
631
637
  if (typeof styleValue.toStatic() === "string") context.report({
632
638
  messageId: "noStringStyleProp",
633
- node: styleValue.node ?? styleAttr
639
+ node: styleValue.node ?? styleProp
634
640
  });
635
641
  } };
636
642
  }
@@ -1775,9 +1781,11 @@ const RULE_NAME$4 = "no-unsafe-iframe-sandbox";
1775
1781
  const RULE_FEATURES$4 = [];
1776
1782
  const UNSAFE_SANDBOX_VALUES = ["allow-scripts", "allow-same-origin"];
1777
1783
  /**
1778
- * Checks if the sandbox attribute value contains an unsafe combination.
1779
- * @param value The value of the sandbox attribute.
1780
- * @returns `true` if the value is a string and contains an unsafe combination, `false` otherwise.
1784
+ * Checks if the sandbox attribute value contains an unsafe combination
1785
+ * An iframe with both "allow-scripts" and "allow-same-origin" can remove its sandbox attribute,
1786
+ * making it as insecure as an iframe without any sandboxing
1787
+ * @param value The value of the sandbox attribute
1788
+ * @returns `true` if the value is a string and contains an unsafe combination, `false` otherwise
1781
1789
  */
1782
1790
  function isUnsafeSandboxCombination(value) {
1783
1791
  if (typeof value !== "string") return false;
@@ -1801,13 +1809,13 @@ function create$4(context) {
1801
1809
  const resolver = createJsxElementResolver(context);
1802
1810
  return { JSXElement(node) {
1803
1811
  if (resolver.resolve(node).domElementType !== "iframe") return;
1804
- const sandboxAttr = getJsxAttribute(context, node.openingElement.attributes, context.sourceCode.getScope(node))("sandbox");
1805
- if (sandboxAttr == null) return;
1806
- const sandboxValue = resolveJsxAttributeValue(context, sandboxAttr);
1812
+ const sandboxProp = getJsxAttribute(context, node)("sandbox");
1813
+ if (sandboxProp == null) return;
1814
+ const sandboxValue = resolveJsxAttributeValue(context, sandboxProp);
1807
1815
  const sandboxValueStatic = sandboxValue.toStatic("sandbox");
1808
1816
  if (isUnsafeSandboxCombination(sandboxValueStatic)) context.report({
1809
1817
  messageId: "noUnsafeIframeSandbox",
1810
- node: sandboxValue.node ?? sandboxAttr
1818
+ node: sandboxValue.node ?? sandboxProp
1811
1819
  });
1812
1820
  } };
1813
1821
  }
@@ -1827,9 +1835,9 @@ function isExternalLinkLike(value) {
1827
1835
  return value.startsWith("https://") || /^(?:\w+:|\/\/)/u.test(value);
1828
1836
  }
1829
1837
  /**
1830
- * Checks if a rel attribute value contains the necessary security attributes.
1838
+ * Checks if a rel prop value contains the necessary security attributes.
1831
1839
  * At minimum, it should contain "noreferrer".
1832
- * @param value - The rel attribute value to check
1840
+ * @param value - The rel prop value to check
1833
1841
  * @returns Whether the rel value is considered secure
1834
1842
  */
1835
1843
  function isSafeRel(value) {
@@ -1860,16 +1868,16 @@ function create$3(context) {
1860
1868
  return { JSXElement(node) {
1861
1869
  const { domElementType } = resolver.resolve(node);
1862
1870
  if (domElementType !== "a") return;
1863
- const findAttribute = getJsxAttribute(context, node.openingElement.attributes, context.sourceCode.getScope(node));
1864
- const targetAttribute = findAttribute("target");
1865
- if (targetAttribute == null) return;
1866
- if (resolveJsxAttributeValue(context, targetAttribute).toStatic("target") !== "_blank") return;
1867
- const hrefAttribute = findAttribute("href");
1868
- if (hrefAttribute == null) return;
1869
- const hrefAttributeValue = resolveJsxAttributeValue(context, hrefAttribute).toStatic("href");
1870
- if (!isExternalLinkLike(hrefAttributeValue)) return;
1871
- const relAttribute = findAttribute("rel");
1872
- if (relAttribute == null) {
1871
+ const findAttribute = getJsxAttribute(context, node);
1872
+ const targetProp = findAttribute("target");
1873
+ if (targetProp == null) return;
1874
+ if (resolveJsxAttributeValue(context, targetProp).toStatic("target") !== "_blank") return;
1875
+ const hrefProp = findAttribute("href");
1876
+ if (hrefProp == null) return;
1877
+ const hrefValue = resolveJsxAttributeValue(context, hrefProp).toStatic("href");
1878
+ if (!isExternalLinkLike(hrefValue)) return;
1879
+ const relProp = findAttribute("rel");
1880
+ if (relProp == null) {
1873
1881
  context.report({
1874
1882
  messageId: "noUnsafeTargetBlank",
1875
1883
  node: node.openingElement,
@@ -1882,15 +1890,15 @@ function create$3(context) {
1882
1890
  });
1883
1891
  return;
1884
1892
  }
1885
- const relAttributeValue = resolveJsxAttributeValue(context, relAttribute).toStatic("rel");
1886
- if (isSafeRel(relAttributeValue)) return;
1893
+ const relValue = resolveJsxAttributeValue(context, relProp).toStatic("rel");
1894
+ if (isSafeRel(relValue)) return;
1887
1895
  context.report({
1888
1896
  messageId: "noUnsafeTargetBlank",
1889
- node: relAttribute,
1897
+ node: relProp,
1890
1898
  suggest: [{
1891
1899
  messageId: "addRelNoreferrerNoopener",
1892
1900
  fix(fixer) {
1893
- return fixer.replaceText(relAttribute, `rel="noreferrer noopener"`);
1901
+ return fixer.replaceText(relProp, `rel="noreferrer noopener"`);
1894
1902
  }
1895
1903
  }]
1896
1904
  });
@@ -1993,7 +2001,7 @@ var no_void_elements_with_children_default = createRule({
1993
2001
  description: "Disallow `children` in void DOM elements.",
1994
2002
  [Symbol.for("rule_features")]: RULE_FEATURES$1
1995
2003
  },
1996
- messages: { noVoidElementsWithChildren: "'{{element}}' is a void element tag and must not have children." },
2004
+ messages: { noVoidElementsWithChildren: "'{{elementType}}' is a void element tag and must not have children." },
1997
2005
  schema: []
1998
2006
  },
1999
2007
  name: RULE_NAME$1,
@@ -2003,16 +2011,15 @@ var no_void_elements_with_children_default = createRule({
2003
2011
  function create$1(context) {
2004
2012
  const resolver = createJsxElementResolver(context);
2005
2013
  return { JSXElement(node) {
2006
- const { domElementType: elementName } = resolver.resolve(node);
2007
- if (!voidElements.has(elementName)) return;
2008
- const { attributes } = node.openingElement;
2009
- const initialScope = context.sourceCode.getScope(node);
2010
- const hasChildrenProp = hasJsxAttribute(context, "children", attributes, initialScope);
2011
- const hasDangerouslySetInnerHTML = hasJsxAttribute(context, "dangerouslySetInnerHTML", attributes, initialScope);
2014
+ const { domElementType } = resolver.resolve(node);
2015
+ if (!voidElements.has(domElementType)) return;
2016
+ const findJsxAttribute = getJsxAttribute(context, node);
2017
+ const hasChildrenProp = findJsxAttribute("children") != null;
2018
+ const hasDangerouslySetInnerHTML = findJsxAttribute("dangerouslySetInnerHTML") != null;
2012
2019
  if (node.children.length > 0 || hasChildrenProp || hasDangerouslySetInnerHTML) context.report({
2013
2020
  messageId: "noVoidElementsWithChildren",
2014
2021
  node,
2015
- data: { element: elementName }
2022
+ data: { elementType: domElementType }
2016
2023
  });
2017
2024
  } };
2018
2025
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-react-dom",
3
- "version": "2.0.5-next.2",
3
+ "version": "2.0.5-next.4",
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/core": "2.0.5-next.2",
45
- "@eslint-react/kit": "2.0.5-next.2",
46
- "@eslint-react/shared": "2.0.5-next.2",
47
- "@eslint-react/var": "2.0.5-next.2",
48
- "@eslint-react/ast": "2.0.5-next.2",
49
- "@eslint-react/eff": "2.0.5-next.2"
44
+ "@eslint-react/ast": "2.0.5-next.4",
45
+ "@eslint-react/core": "2.0.5-next.4",
46
+ "@eslint-react/kit": "2.0.5-next.4",
47
+ "@eslint-react/eff": "2.0.5-next.4",
48
+ "@eslint-react/shared": "2.0.5-next.4",
49
+ "@eslint-react/var": "2.0.5-next.4"
50
50
  },
51
51
  "devDependencies": {
52
52
  "@types/react": "^19.1.16",