eslint-plugin-react-dom 2.0.5-beta.1 → 2.0.5-beta.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.
Files changed (2) hide show
  1. package/dist/index.js +49 -58
  2. package/package.json +8 -8
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-beta.1";
50
+ var version = "2.0.5-beta.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.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
  }
@@ -129,7 +129,7 @@ var no_dangerously_set_innerhtml_with_children_default = createRule({
129
129
  description: "Disallow `dangerouslySetInnerHTML` and `children` at the same time.",
130
130
  [Symbol.for("rule_features")]: RULE_FEATURES$15
131
131
  },
132
- messages: { noDangerouslySetInnerhtmlWithChildren: "A DOM component cannot use both 'children' and 'dangerouslySetInnerHTML'." },
132
+ messages: { noDangerouslySetInnerhtmlWithChildren: "A DOM component cannot use both children and 'dangerouslySetInnerHTML'." },
133
133
  schema: []
134
134
  },
135
135
  name: RULE_NAME$16,
@@ -146,24 +146,16 @@ function isSignificantChildren(node) {
146
146
  if (!isJsxText(node)) return true;
147
147
  return !(node.raw.trim() === "" && node.raw.includes("\n"));
148
148
  }
149
- /**
150
- * Checks if a JSX element has children, either through the `children` prop or as JSX children.
151
- * @param context The rule context.
152
- * @param node The JSX element to check.
153
- * @returns `true` if the element has children, `false` otherwise.
154
- */
155
- function hasChildren(context, node) {
156
- if (getJsxAttribute(context, node.openingElement.attributes, context.sourceCode.getScope(node))("children") != null) return true;
157
- return node.children.some(isSignificantChildren);
158
- }
159
149
  function create$16(context) {
160
150
  if (!context.sourceCode.text.includes(DSIH)) return {};
161
151
  return { JSXElement(node) {
162
- const DSIHAttr = getJsxAttribute(context, node.openingElement.attributes, context.sourceCode.getScope(node))(DSIH);
163
- if (DSIHAttr == null) return;
164
- if (hasChildren(context, node)) context.report({
152
+ const findJsxAttribute = getJsxAttribute(context, node);
153
+ if (findJsxAttribute(DSIH) == null) return;
154
+ const childrenPropOrNode = findJsxAttribute("children") ?? node.children.find(isSignificantChildren);
155
+ if (childrenPropOrNode == null) return;
156
+ context.report({
165
157
  messageId: "noDangerouslySetInnerhtmlWithChildren",
166
- node: DSIHAttr
158
+ node: childrenPropOrNode
167
159
  });
168
160
  } };
169
161
  }
@@ -349,7 +341,7 @@ function create$12(context) {
349
341
  const resolver = createJsxElementResolver(context);
350
342
  return { JSXElement(node) {
351
343
  if (resolver.resolve(node).domElementType !== "button") return;
352
- if (getJsxAttribute(context, node.openingElement.attributes, context.sourceCode.getScope(node))("type") != null) return;
344
+ if (getJsxAttribute(context, node)("type") != null) return;
353
345
  context.report({
354
346
  messageId: "noMissingButtonType",
355
347
  node: node.openingElement,
@@ -370,14 +362,14 @@ var no_missing_iframe_sandbox_default = createRule({
370
362
  meta: {
371
363
  type: "problem",
372
364
  docs: {
373
- description: "Enforces explicit `sandbox` attribute for `iframe` elements.",
365
+ description: "Enforces explicit `sandbox` prop for `iframe` elements.",
374
366
  [Symbol.for("rule_features")]: RULE_FEATURES$10
375
367
  },
376
368
  fixable: "code",
377
369
  hasSuggestions: true,
378
370
  messages: {
379
- addIframeSandbox: "Add 'sandbox' attribute with value '{{value}}'.",
380
- 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."
381
373
  },
382
374
  schema: []
383
375
  },
@@ -390,8 +382,8 @@ function create$11(context) {
390
382
  return { JSXElement(node) {
391
383
  const { domElementType } = resolver.resolve(node);
392
384
  if (domElementType !== "iframe") return;
393
- const sandboxAttr = getJsxAttribute(context, node.openingElement.attributes, context.sourceCode.getScope(node))("sandbox");
394
- if (sandboxAttr == null) {
385
+ const sandboxProp = getJsxAttribute(context, node)("sandbox");
386
+ if (sandboxProp == null) {
395
387
  context.report({
396
388
  messageId: "noMissingIframeSandbox",
397
389
  node: node.openingElement,
@@ -405,17 +397,17 @@ function create$11(context) {
405
397
  });
406
398
  return;
407
399
  }
408
- const sandboxValue = resolveJsxAttributeValue(context, sandboxAttr);
400
+ const sandboxValue = resolveJsxAttributeValue(context, sandboxProp);
409
401
  if (typeof sandboxValue.toStatic("sandbox") === "string") return;
410
402
  context.report({
411
403
  messageId: "noMissingIframeSandbox",
412
- node: sandboxValue.node ?? sandboxAttr,
404
+ node: sandboxValue.node ?? sandboxProp,
413
405
  suggest: [{
414
406
  messageId: "addIframeSandbox",
415
407
  data: { value: "" },
416
408
  fix(fixer) {
417
409
  if (sandboxValue.kind.startsWith("spread")) return null;
418
- return fixer.replaceText(sandboxAttr, `sandbox=""`);
410
+ return fixer.replaceText(sandboxProp, `sandbox=""`);
419
411
  }
420
412
  }]
421
413
  });
@@ -633,12 +625,12 @@ var no_string_style_prop_default = createRule({
633
625
  function create$6(context) {
634
626
  return { JSXElement(node) {
635
627
  if (!isJsxHostElement(context, node)) return;
636
- const styleAttr = getJsxAttribute(context, node.openingElement.attributes, context.sourceCode.getScope(node))("style");
637
- if (styleAttr == null) return;
638
- const styleValue = resolveJsxAttributeValue(context, styleAttr);
628
+ const styleProp = getJsxAttribute(context, node)("style");
629
+ if (styleProp == null) return;
630
+ const styleValue = resolveJsxAttributeValue(context, styleProp);
639
631
  if (typeof styleValue.toStatic() === "string") context.report({
640
632
  messageId: "noStringStyleProp",
641
- node: styleValue.node ?? styleAttr
633
+ node: styleValue.node ?? styleProp
642
634
  });
643
635
  } };
644
636
  }
@@ -1809,13 +1801,13 @@ function create$4(context) {
1809
1801
  const resolver = createJsxElementResolver(context);
1810
1802
  return { JSXElement(node) {
1811
1803
  if (resolver.resolve(node).domElementType !== "iframe") return;
1812
- const sandboxAttr = getJsxAttribute(context, node.openingElement.attributes, context.sourceCode.getScope(node))("sandbox");
1813
- if (sandboxAttr == null) return;
1814
- const sandboxValue = resolveJsxAttributeValue(context, sandboxAttr);
1804
+ const sandboxProp = getJsxAttribute(context, node)("sandbox");
1805
+ if (sandboxProp == null) return;
1806
+ const sandboxValue = resolveJsxAttributeValue(context, sandboxProp);
1815
1807
  const sandboxValueStatic = sandboxValue.toStatic("sandbox");
1816
1808
  if (isUnsafeSandboxCombination(sandboxValueStatic)) context.report({
1817
1809
  messageId: "noUnsafeIframeSandbox",
1818
- node: sandboxValue.node ?? sandboxAttr
1810
+ node: sandboxValue.node ?? sandboxProp
1819
1811
  });
1820
1812
  } };
1821
1813
  }
@@ -1835,9 +1827,9 @@ function isExternalLinkLike(value) {
1835
1827
  return value.startsWith("https://") || /^(?:\w+:|\/\/)/u.test(value);
1836
1828
  }
1837
1829
  /**
1838
- * Checks if a rel attribute value contains the necessary security attributes.
1830
+ * Checks if a rel prop value contains the necessary security attributes.
1839
1831
  * At minimum, it should contain "noreferrer".
1840
- * @param value - The rel attribute value to check
1832
+ * @param value - The rel prop value to check
1841
1833
  * @returns Whether the rel value is considered secure
1842
1834
  */
1843
1835
  function isSafeRel(value) {
@@ -1868,16 +1860,16 @@ function create$3(context) {
1868
1860
  return { JSXElement(node) {
1869
1861
  const { domElementType } = resolver.resolve(node);
1870
1862
  if (domElementType !== "a") return;
1871
- const findAttribute = getJsxAttribute(context, node.openingElement.attributes, context.sourceCode.getScope(node));
1872
- const targetAttribute = findAttribute("target");
1873
- if (targetAttribute == null) return;
1874
- if (resolveJsxAttributeValue(context, targetAttribute).toStatic("target") !== "_blank") return;
1875
- const hrefAttribute = findAttribute("href");
1876
- if (hrefAttribute == null) return;
1877
- const hrefAttributeValue = resolveJsxAttributeValue(context, hrefAttribute).toStatic("href");
1878
- if (!isExternalLinkLike(hrefAttributeValue)) return;
1879
- const relAttribute = findAttribute("rel");
1880
- if (relAttribute == null) {
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) {
1881
1873
  context.report({
1882
1874
  messageId: "noUnsafeTargetBlank",
1883
1875
  node: node.openingElement,
@@ -1890,15 +1882,15 @@ function create$3(context) {
1890
1882
  });
1891
1883
  return;
1892
1884
  }
1893
- const relAttributeValue = resolveJsxAttributeValue(context, relAttribute).toStatic("rel");
1894
- if (isSafeRel(relAttributeValue)) return;
1885
+ const relValue = resolveJsxAttributeValue(context, relProp).toStatic("rel");
1886
+ if (isSafeRel(relValue)) return;
1895
1887
  context.report({
1896
1888
  messageId: "noUnsafeTargetBlank",
1897
- node: relAttribute,
1889
+ node: relProp,
1898
1890
  suggest: [{
1899
1891
  messageId: "addRelNoreferrerNoopener",
1900
1892
  fix(fixer) {
1901
- return fixer.replaceText(relAttribute, `rel="noreferrer noopener"`);
1893
+ return fixer.replaceText(relProp, `rel="noreferrer noopener"`);
1902
1894
  }
1903
1895
  }]
1904
1896
  });
@@ -2013,10 +2005,9 @@ function create$1(context) {
2013
2005
  return { JSXElement(node) {
2014
2006
  const { domElementType: elementName } = resolver.resolve(node);
2015
2007
  if (!voidElements.has(elementName)) return;
2016
- const { attributes } = node.openingElement;
2017
- const initialScope = context.sourceCode.getScope(node);
2018
- const hasChildrenProp = hasJsxAttribute(context, "children", attributes, initialScope);
2019
- 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;
2020
2011
  if (node.children.length > 0 || hasChildrenProp || hasDangerouslySetInnerHTML) context.report({
2021
2012
  messageId: "noVoidElementsWithChildren",
2022
2013
  node,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-react-dom",
3
- "version": "2.0.5-beta.1",
3
+ "version": "2.0.5-beta.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/ast": "2.0.5-beta.1",
45
- "@eslint-react/eff": "2.0.5-beta.1",
46
- "@eslint-react/core": "2.0.5-beta.1",
47
- "@eslint-react/shared": "2.0.5-beta.1",
48
- "@eslint-react/kit": "2.0.5-beta.1",
49
- "@eslint-react/var": "2.0.5-beta.1"
44
+ "@eslint-react/ast": "2.0.5-beta.3",
45
+ "@eslint-react/core": "2.0.5-beta.3",
46
+ "@eslint-react/eff": "2.0.5-beta.3",
47
+ "@eslint-react/kit": "2.0.5-beta.3",
48
+ "@eslint-react/shared": "2.0.5-beta.3",
49
+ "@eslint-react/var": "2.0.5-beta.3"
50
50
  },
51
51
  "devDependencies": {
52
52
  "@types/react": "^19.1.16",
@@ -56,7 +56,7 @@
56
56
  },
57
57
  "peerDependencies": {
58
58
  "eslint": "^9.36.0",
59
- "typescript": "^5.9.2"
59
+ "typescript": "^5.9.3"
60
60
  },
61
61
  "engines": {
62
62
  "node": ">=20.19.0"