eslint-plugin-react-x 3.0.0-beta.69 → 3.0.0-beta.70

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 +35 -41
  2. package/package.json +6 -6
package/dist/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { DEFAULT_ESLINT_REACT_SETTINGS, IMPURE_CTORS, IMPURE_FUNCS, WEBSITE_URL, defineRuleListener, getSettingsFromContext, report, toRegExp } from "@eslint-react/shared";
2
2
  import * as ast from "@eslint-react/ast";
3
3
  import * as core from "@eslint-react/core";
4
+ import { JsxEmit, JsxInspector } from "@eslint-react/core";
4
5
  import { ESLintUtils } from "@typescript-eslint/utils";
5
6
  import { P, isMatching, match } from "ts-pattern";
6
7
  import ts from "typescript";
@@ -147,7 +148,7 @@ const rules$7 = {
147
148
  //#endregion
148
149
  //#region package.json
149
150
  var name$6 = "eslint-plugin-react-x";
150
- var version = "3.0.0-beta.69";
151
+ var version = "3.0.0-beta.70";
151
152
 
152
153
  //#endregion
153
154
  //#region src/utils/create-rule.ts
@@ -1540,11 +1541,8 @@ var jsx_key_before_spread_default = createRule({
1540
1541
  defaultOptions: []
1541
1542
  });
1542
1543
  function create$59(context) {
1543
- const { jsx } = {
1544
- ...core.getJsxConfigFromContext(context),
1545
- ...core.getJsxConfigFromAnnotation(context)
1546
- };
1547
- if (jsx !== core.JsxEmit.ReactJSX && jsx !== core.JsxEmit.ReactJSXDev) return {};
1544
+ const { jsx } = JsxInspector.from(context).jsxConfig;
1545
+ if (jsx !== JsxEmit.ReactJSX && jsx !== JsxEmit.ReactJSXDev) return {};
1548
1546
  return defineRuleListener({ JSXOpeningElement(node) {
1549
1547
  let firstSpreadPropIndex = null;
1550
1548
  for (const [index, prop] of node.attributes.entries()) {
@@ -1649,9 +1647,10 @@ var jsx_shorthand_boolean_default = createRule({
1649
1647
  });
1650
1648
  function create$56(context) {
1651
1649
  const policy = context.options[0] ?? defaultOptions$4[0];
1650
+ const jsx = JsxInspector.from(context);
1652
1651
  return defineRuleListener({ JSXAttribute(node) {
1653
1652
  const { value } = node;
1654
- const propName = core.getJsxAttributeName(context, node);
1653
+ const propName = jsx.getAttributeName(node);
1655
1654
  switch (true) {
1656
1655
  case policy === 1 && value?.type === AST_NODE_TYPES.JSXExpressionContainer && value.expression.type === AST_NODE_TYPES.Literal && value.expression.value === true:
1657
1656
  context.report({
@@ -1695,13 +1694,10 @@ var jsx_shorthand_fragment_default = createRule({
1695
1694
  });
1696
1695
  function create$55(context) {
1697
1696
  const policy = context.options[0] ?? defaultOptions$3[0];
1698
- const jsxConfig = {
1699
- ...core.getJsxConfigFromContext(context),
1700
- ...core.getJsxConfigFromAnnotation(context)
1701
- };
1702
- const { jsxFragmentFactory } = jsxConfig;
1697
+ const jsx = JsxInspector.from(context);
1698
+ const { jsxFragmentFactory } = jsx.jsxConfig;
1703
1699
  return match(policy).with(1, () => defineRuleListener({ JSXElement(node) {
1704
- if (!core.isJsxFragmentElement(context, node, jsxConfig)) return;
1700
+ if (!jsx.isFragmentElement(node)) return;
1705
1701
  if (node.openingElement.attributes.length > 0) return;
1706
1702
  context.report({
1707
1703
  data: { message: "Use fragment shorthand syntax instead of 'Fragment' component." },
@@ -1741,11 +1737,8 @@ var jsx_uses_react_default = createRule({
1741
1737
  defaultOptions: []
1742
1738
  });
1743
1739
  function create$54(context) {
1744
- const { jsx, jsxFactory, jsxFragmentFactory } = {
1745
- ...core.getJsxConfigFromContext(context),
1746
- ...core.getJsxConfigFromAnnotation(context)
1747
- };
1748
- if (jsx === core.JsxEmit.ReactJSX || jsx === core.JsxEmit.ReactJSXDev) return {};
1740
+ const { jsx, jsxFactory, jsxFragmentFactory } = JsxInspector.from(context).jsxConfig;
1741
+ if (jsx === JsxEmit.ReactJSX || jsx === JsxEmit.ReactJSXDev) return {};
1749
1742
  function handleJsxElement(node) {
1750
1743
  context.sourceCode.markVariableAsUsed(jsxFactory, node);
1751
1744
  debugReport(context, node, jsxFactory);
@@ -2110,8 +2103,9 @@ var no_children_prop_default = createRule({
2110
2103
  defaultOptions: []
2111
2104
  });
2112
2105
  function create$46(context) {
2106
+ const jsx = JsxInspector.from(context);
2113
2107
  return defineRuleListener({ JSXElement(node) {
2114
- const childrenProp = core.getJsxAttribute(context, node)("children");
2108
+ const childrenProp = jsx.findAttribute(node, "children");
2115
2109
  if (childrenProp != null) context.report({
2116
2110
  messageId: "default",
2117
2111
  node: childrenProp
@@ -2316,8 +2310,9 @@ function create$39(context) {
2316
2310
  if (!context.sourceCode.text.includes("Provider")) return {};
2317
2311
  const { version } = getSettingsFromContext(context);
2318
2312
  if (compare(version, "19.0.0", "<")) return {};
2313
+ const jsx = JsxInspector.from(context);
2319
2314
  return defineRuleListener({ JSXElement(node) {
2320
- const parts = core.getJsxElementType(context, node).split(".");
2315
+ const parts = jsx.getElementType(node).split(".");
2321
2316
  const selfName = parts.pop();
2322
2317
  const contextFullName = parts.join(".");
2323
2318
  const contextSelfName = parts.pop();
@@ -2797,9 +2792,10 @@ var no_missing_key_default = createRule({
2797
2792
  defaultOptions: []
2798
2793
  });
2799
2794
  function create$30(ctx) {
2795
+ const jsx = JsxInspector.from(ctx);
2800
2796
  let inChildrenToArray = false;
2801
2797
  function check(node) {
2802
- if (node.type === AST_NODE_TYPES.JSXElement) return core.getJsxAttribute(ctx, node)("key") == null ? {
2798
+ if (node.type === AST_NODE_TYPES.JSXElement) return !jsx.hasAttribute(node, "key") ? {
2803
2799
  messageId: "default",
2804
2800
  node
2805
2801
  } : null;
@@ -2834,7 +2830,7 @@ function create$30(ctx) {
2834
2830
  const elements = node.elements.filter(ast.is(AST_NODE_TYPES.JSXElement));
2835
2831
  if (elements.length === 0) return;
2836
2832
  const scope = ctx.sourceCode.getScope(node);
2837
- for (const el of elements) if (core.getJsxAttribute(ctx, el, scope)("key") == null) ctx.report({
2833
+ for (const el of elements) if (!jsx.hasAttribute(el, "key", scope)) ctx.report({
2838
2834
  messageId: "default",
2839
2835
  node: el
2840
2836
  });
@@ -3002,7 +2998,7 @@ function create$28(context) {
3002
2998
  * @returns `true` if the node is inside JSX attribute value
3003
2999
  */
3004
3000
  function isInsideJSXAttributeValue(node) {
3005
- return node.parent.type === AST_NODE_TYPES.JSXAttribute || core.findParentJsxAttribute(node, (n) => n.value?.type === AST_NODE_TYPES.JSXExpressionContainer) != null;
3001
+ return node.parent.type === AST_NODE_TYPES.JSXAttribute || JsxInspector.findParentAttribute(node, (n) => n.value?.type === AST_NODE_TYPES.JSXExpressionContainer) != null;
3006
3002
  }
3007
3003
  /**
3008
3004
  * Check whether a given node is declared inside a class component's render block
@@ -3495,9 +3491,10 @@ function create$16(context) {
3495
3491
  const isReact18OrBelow = compare(version, "19.0.0", "<");
3496
3492
  const { ctx, visitor } = core.useComponentCollector(context);
3497
3493
  const constructions = /* @__PURE__ */ new WeakMap();
3494
+ const jsx = JsxInspector.from(context);
3498
3495
  return defineRuleListener(visitor, {
3499
3496
  JSXOpeningElement(node) {
3500
- const selfName = core.getJsxElementType(context, node.parent).split(".").at(-1);
3497
+ const selfName = jsx.getElementType(node.parent).split(".").at(-1);
3501
3498
  if (selfName == null) return;
3502
3499
  if (!isContextName(selfName, isReact18OrBelow)) return;
3503
3500
  const functionEntry = ctx.getCurrentEntry();
@@ -4047,15 +4044,12 @@ var no_useless_fragment_default = createRule({
4047
4044
  });
4048
4045
  function create$10(context, [option]) {
4049
4046
  const { allowEmptyFragment = false, allowExpressions = true } = option;
4050
- const jsxConfig = {
4051
- ...core.getJsxConfigFromContext(context),
4052
- ...core.getJsxConfigFromAnnotation(context)
4053
- };
4047
+ const jsx = JsxInspector.from(context);
4054
4048
  /**
4055
4049
  * Check if a fragment node is useless and should be reported
4056
4050
  */
4057
4051
  function checkNode(context, node) {
4058
- if (core.isJsxHostElement(context, node.parent)) context.report({
4052
+ if (jsx.isHostElement(node.parent)) context.report({
4059
4053
  data: { reason: "placed inside a host component" },
4060
4054
  fix: getFix(context, node),
4061
4055
  messageId: "default",
@@ -4073,7 +4067,7 @@ function create$10(context, [option]) {
4073
4067
  }
4074
4068
  const isChildElement = ast.isOneOf([AST_NODE_TYPES.JSXElement, AST_NODE_TYPES.JSXFragment])(node.parent);
4075
4069
  switch (true) {
4076
- case allowExpressions && !isChildElement && node.children.length === 1 && core.isJsxText(node.children.at(0) ?? null): return;
4070
+ case allowExpressions && !isChildElement && node.children.length === 1 && JsxInspector.isJsxText(node.children.at(0) ?? null): return;
4077
4071
  case !allowExpressions && isChildElement:
4078
4072
  context.report({
4079
4073
  data: { reason: "contains less than two children" },
@@ -4113,15 +4107,15 @@ function create$10(context, [option]) {
4113
4107
  * Check if it's safe to automatically fix the fragment
4114
4108
  */
4115
4109
  function canFix(context, node) {
4116
- if (node.parent.type === AST_NODE_TYPES.JSXElement || node.parent.type === AST_NODE_TYPES.JSXFragment) return core.isJsxHostElement(context, node.parent);
4110
+ if (node.parent.type === AST_NODE_TYPES.JSXElement || node.parent.type === AST_NODE_TYPES.JSXFragment) return jsx.isHostElement(node.parent);
4117
4111
  if (node.children.length === 0) return false;
4118
- return !node.children.some((child) => core.isJsxText(child) && !isWhiteSpace(child) || ast.is(AST_NODE_TYPES.JSXExpressionContainer)(child));
4112
+ return !node.children.some((child) => JsxInspector.isJsxText(child) && !isWhiteSpace(child) || ast.is(AST_NODE_TYPES.JSXExpressionContainer)(child));
4119
4113
  }
4120
4114
  return defineRuleListener({
4121
4115
  JSXElement(node) {
4122
- if (!core.isJsxFragmentElement(context, node, jsxConfig)) return;
4123
- if (core.getJsxAttribute(context, node)("key") != null) return;
4124
- if (core.getJsxAttribute(context, node)("ref") != null) return;
4116
+ if (!jsx.isFragmentElement(node)) return;
4117
+ if (jsx.hasAttribute(node, "key")) return;
4118
+ if (jsx.hasAttribute(node, "ref")) return;
4125
4119
  checkNode(context, node);
4126
4120
  },
4127
4121
  JSXFragment(node) {
@@ -4139,7 +4133,7 @@ function isWhiteSpace(node) {
4139
4133
  * Check if a node is padding spaces (whitespace with line breaks)
4140
4134
  */
4141
4135
  function isPaddingSpaces(node) {
4142
- return core.isJsxText(node) && isWhiteSpace(node) && node.raw.includes("\n");
4136
+ return JsxInspector.isJsxText(node) && isWhiteSpace(node) && node.raw.includes("\n");
4143
4137
  }
4144
4138
  /**
4145
4139
  * Trim whitespace like React would in JSX
@@ -7213,12 +7207,12 @@ function create(context) {
7213
7207
  if (controlledProp == null) continue;
7214
7208
  if (!attributes.has(controlledProp)) continue;
7215
7209
  context.report({
7216
- node: attrNode,
7217
- messageId: "noControlledAndUncontrolledTogether",
7218
7210
  data: {
7219
7211
  controlled: controlledProp,
7220
7212
  uncontrolled: propName
7221
- }
7213
+ },
7214
+ messageId: "noControlledAndUncontrolledTogether",
7215
+ node: attrNode
7222
7216
  });
7223
7217
  }
7224
7218
  } });
@@ -7466,10 +7460,10 @@ const settings = { ...settings$1 };
7466
7460
  const finalPlugin = {
7467
7461
  ...plugin,
7468
7462
  configs: {
7469
- ["disable-experimental"]: disable_experimental_exports,
7470
- ["disable-type-checked"]: disable_type_checked_exports,
7471
7463
  ["disable-conflict-eslint-plugin-react"]: disable_conflict_eslint_plugin_react_exports,
7472
7464
  ["disable-conflict-eslint-plugin-react-hooks"]: disable_conflict_eslint_plugin_react_hooks_exports,
7465
+ ["disable-experimental"]: disable_experimental_exports,
7466
+ ["disable-type-checked"]: disable_type_checked_exports,
7473
7467
  ["recommended"]: recommended_exports,
7474
7468
  ["recommended-type-checked"]: recommended_type_checked_exports,
7475
7469
  ["recommended-typescript"]: recommended_typescript_exports,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-react-x",
3
- "version": "3.0.0-beta.69",
3
+ "version": "3.0.0-beta.70",
4
4
  "description": "A set of composable ESLint rules for libraries and frameworks that use React as a UI runtime.",
5
5
  "keywords": [
6
6
  "react",
@@ -45,11 +45,11 @@
45
45
  "string-ts": "^2.3.1",
46
46
  "ts-api-utils": "^2.4.0",
47
47
  "ts-pattern": "^5.9.0",
48
- "@eslint-react/ast": "3.0.0-beta.69",
49
- "@eslint-react/core": "3.0.0-beta.69",
50
- "@eslint-react/eff": "3.0.0-beta.69",
51
- "@eslint-react/shared": "3.0.0-beta.69",
52
- "@eslint-react/var": "3.0.0-beta.69"
48
+ "@eslint-react/ast": "3.0.0-beta.70",
49
+ "@eslint-react/core": "3.0.0-beta.70",
50
+ "@eslint-react/shared": "3.0.0-beta.70",
51
+ "@eslint-react/eff": "3.0.0-beta.70",
52
+ "@eslint-react/var": "3.0.0-beta.70"
53
53
  },
54
54
  "devDependencies": {
55
55
  "@types/react": "^19.2.14",