oxlint-plugin-react-doctor 0.2.18-dev.4dc48d7 → 0.2.18-dev.67be206

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 +104 -78
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -3954,6 +3954,7 @@ const noEmDashInJsxText = defineRule({
3954
3954
  title: "Em dash in JSX text",
3955
3955
  tags: ["design", "test-noise"],
3956
3956
  severity: "warn",
3957
+ defaultEnabled: false,
3957
3958
  category: "Architecture",
3958
3959
  recommendation: "Replace em dashes in UI text with commas, colons, semicolons, or parentheses so the copy reads less like AI output.",
3959
3960
  create: (context) => ({ JSXText(jsxTextNode) {
@@ -4000,6 +4001,7 @@ const noRedundantPaddingAxes = defineRule({
4000
4001
  title: "Redundant padding axes",
4001
4002
  tags: ["design", "test-noise"],
4002
4003
  severity: "warn",
4004
+ defaultEnabled: false,
4003
4005
  category: "Architecture",
4004
4006
  recommendation: "Collapse `px-N py-N` to `p-N` when both sides match. Keep them split only when one side changes at a breakpoint (`py-2 md:py-3`).",
4005
4007
  create: (context) => ({ JSXAttribute(jsxAttribute) {
@@ -4023,6 +4025,7 @@ const noRedundantSizeAxes = defineRule({
4023
4025
  requires: ["tailwind:3.4"],
4024
4026
  tags: ["design", "test-noise"],
4025
4027
  severity: "warn",
4028
+ defaultEnabled: false,
4026
4029
  category: "Architecture",
4027
4030
  recommendation: "Collapse `w-N h-N` to `size-N` (Tailwind v3.4+) when both sides match.",
4028
4031
  create: (context) => ({ JSXAttribute(jsxAttribute) {
@@ -4046,6 +4049,7 @@ const noSpaceOnFlexChildren = defineRule({
4046
4049
  title: "space-* utility on flex children",
4047
4050
  tags: ["design", "test-noise"],
4048
4051
  severity: "warn",
4052
+ defaultEnabled: false,
4049
4053
  category: "Architecture",
4050
4054
  recommendation: "Use `gap-*` on the flex or grid parent. `space-x-*` and `space-y-*` leave gaps when a child is hidden, miss spacing on wrapped lines, and don't flip in right-to-left layouts.",
4051
4055
  create: (context) => ({ JSXAttribute(jsxAttribute) {
@@ -4079,6 +4083,7 @@ const noThreePeriodEllipsis = defineRule({
4079
4083
  title: "Three dots instead of ellipsis",
4080
4084
  tags: ["design", "test-noise"],
4081
4085
  severity: "warn",
4086
+ defaultEnabled: false,
4082
4087
  category: "Architecture",
4083
4088
  recommendation: "Use the real ellipsis \"…\" (or `…`) instead of three dots. Good for labels like \"Rename…\" and \"Loading…\".",
4084
4089
  create: (context) => ({ JSXText(jsxTextNode) {
@@ -4138,6 +4143,7 @@ const noVagueButtonLabel = defineRule({
4138
4143
  title: "Vague button label",
4139
4144
  tags: ["design", "test-noise"],
4140
4145
  severity: "warn",
4146
+ defaultEnabled: false,
4141
4147
  recommendation: "Name the action: \"Save changes\" instead of \"Continue\", \"Send invite\" instead of \"Submit\". The label is the button's accessible name.",
4142
4148
  create: (context) => ({ JSXElement(jsxElementNode) {
4143
4149
  const tagName = getOpeningElementTagName(jsxElementNode.openingElement);
@@ -11808,6 +11814,7 @@ const jsxPascalCase = defineRule({
11808
11814
  id: "jsx-pascal-case",
11809
11815
  title: "Component name not PascalCase",
11810
11816
  severity: "warn",
11817
+ defaultEnabled: false,
11811
11818
  tags: ["test-noise"],
11812
11819
  recommendation: "Rename custom JSX components to PascalCase.",
11813
11820
  category: "Architecture",
@@ -14266,6 +14273,7 @@ const noArrayIndexKey = defineRule({
14266
14273
  id: "no-array-index-key",
14267
14274
  title: "Array index used as a key",
14268
14275
  severity: "warn",
14276
+ defaultEnabled: false,
14269
14277
  recommendation: "Use a stable `key` from your data instead of the array index.",
14270
14278
  category: "Performance",
14271
14279
  create: (context) => ({
@@ -14778,6 +14786,37 @@ const isSetterIdentifier = (name) => SETTER_PATTERN.test(name);
14778
14786
  //#region src/plugin/utils/is-setter-call.ts
14779
14787
  const isSetterCall = (node) => isNodeOfType(node, "CallExpression") && isNodeOfType(node.callee, "Identifier") && isSetterIdentifier(node.callee.name);
14780
14788
  //#endregion
14789
+ //#region src/plugin/utils/is-hook-binding-in-scope.ts
14790
+ const isHookBindingInScope = (node, query) => {
14791
+ const { bindingName, hookName, destructureIndex } = query;
14792
+ let cursor = node;
14793
+ while (cursor) {
14794
+ if (isNodeOfType(cursor, "BlockStatement") || isNodeOfType(cursor, "Program")) for (const statement of cursor.body ?? []) {
14795
+ if (!isNodeOfType(statement, "VariableDeclaration")) continue;
14796
+ for (const declarator of statement.declarations ?? []) {
14797
+ if (!isNodeOfType(declarator.init, "CallExpression")) continue;
14798
+ if (!isHookCall$1(declarator.init, hookName)) continue;
14799
+ if (destructureIndex !== void 0) {
14800
+ if (!isNodeOfType(declarator.id, "ArrayPattern")) continue;
14801
+ const elements = declarator.id.elements ?? [];
14802
+ if (elements.length <= destructureIndex) continue;
14803
+ const element = elements[destructureIndex];
14804
+ if (isNodeOfType(element, "Identifier") && element.name === bindingName) return true;
14805
+ } else if (isNodeOfType(declarator.id, "Identifier") && declarator.id.name === bindingName) return true;
14806
+ }
14807
+ }
14808
+ cursor = cursor.parent ?? null;
14809
+ }
14810
+ return false;
14811
+ };
14812
+ //#endregion
14813
+ //#region src/plugin/utils/is-use-state-setter-in-scope.ts
14814
+ const isUseStateSetterInScope = (node, setterName) => isHookBindingInScope(node, {
14815
+ bindingName: setterName,
14816
+ hookName: "useState",
14817
+ destructureIndex: 1
14818
+ });
14819
+ //#endregion
14781
14820
  //#region src/plugin/rules/state-and-effects/no-cascading-set-state.ts
14782
14821
  const isAsyncFunctionLike = (node) => {
14783
14822
  if (isNodeOfType(node, "ArrowFunctionExpression") || isNodeOfType(node, "FunctionExpression") || isNodeOfType(node, "FunctionDeclaration")) return Boolean(node.async);
@@ -14819,7 +14858,7 @@ const countMaxPathSetStateCalls = (node) => {
14819
14858
  const finallyCount = node.finalizer ? countMaxPathSetStateCalls(node.finalizer) : 0;
14820
14859
  return Math.max(tryCount, catchCount) + finallyCount;
14821
14860
  }
14822
- if (isSetterCall(node)) {
14861
+ if (isNodeOfType(node, "CallExpression") && isSetterCall(node) && isNodeOfType(node.callee, "Identifier") && isUseStateSetterInScope(node, node.callee.name)) {
14823
14862
  let nestedSettersInArgs = 0;
14824
14863
  for (const argument of node.arguments ?? []) nestedSettersInArgs += countMaxPathSetStateCalls(argument);
14825
14864
  return 1 + nestedSettersInArgs;
@@ -15405,6 +15444,7 @@ const noDarkModeGlow = defineRule({
15405
15444
  title: "Colored glow on dark background",
15406
15445
  tags: ["design", "test-noise"],
15407
15446
  severity: "warn",
15447
+ defaultEnabled: false,
15408
15448
  recommendation: "Use a subtle `box-shadow` in neutral colors for depth, or a faint `border`. Colored glows on dark backgrounds look overdone.",
15409
15449
  create: (context) => ({ JSXAttribute(node) {
15410
15450
  const expression = getInlineStyleExpression(node);
@@ -15439,6 +15479,7 @@ const noDefaultProps = defineRule({
15439
15479
  requires: ["react:19"],
15440
15480
  tags: ["test-noise"],
15441
15481
  severity: "warn",
15482
+ defaultEnabled: false,
15442
15483
  recommendation: "React 19 drops `Component.defaultProps` for function components. Set the defaults in the destructured props instead: `function Foo({ size = \"md\", variant = \"primary\" })` instead of `Foo.defaultProps = { size: \"md\", variant: \"primary\" }`.",
15443
15484
  create: (context) => ({ AssignmentExpression(node) {
15444
15485
  if (node.operator !== "=") return;
@@ -15618,7 +15659,11 @@ const noDerivedStateEffect = defineRule({
15618
15659
  if (statements.length === 0) return;
15619
15660
  if (!statements.every((statement) => {
15620
15661
  if (!isNodeOfType(statement, "ExpressionStatement")) return false;
15621
- return isSetterCall(statement.expression);
15662
+ const expression = statement.expression;
15663
+ if (!isSetterCall(expression)) return false;
15664
+ if (!isNodeOfType(expression, "CallExpression")) return false;
15665
+ if (!isNodeOfType(expression.callee, "Identifier")) return false;
15666
+ return isUseStateSetterInScope(expression, expression.callee.name);
15622
15667
  })) return;
15623
15668
  let allArgumentsDeriveFromDeps = true;
15624
15669
  let hasAnyDependencyReference = false;
@@ -17611,6 +17656,7 @@ const noGenericHandlerNames = defineRule({
17611
17656
  id: "no-generic-handler-names",
17612
17657
  title: "Vague event handler name",
17613
17658
  severity: "warn",
17659
+ defaultEnabled: false,
17614
17660
  tags: ["test-noise"],
17615
17661
  recommendation: "Rename it to say what it does. For example `handleSubmit` could be `saveUserProfile`, and `handleClick` could be `toggleSidebar`.",
17616
17662
  create: (context) => ({ JSXAttribute(node) {
@@ -17812,6 +17858,7 @@ const noGradientText = defineRule({
17812
17858
  title: "Gradient text is hard to read",
17813
17859
  tags: ["design", "test-noise"],
17814
17860
  severity: "warn",
17861
+ defaultEnabled: false,
17815
17862
  recommendation: "Use a solid text color so it stays readable. For emphasis, change the weight, size, or color instead of using a gradient.",
17816
17863
  create: (context) => ({
17817
17864
  JSXAttribute(node) {
@@ -18098,6 +18145,7 @@ const noJustifiedText = defineRule({
18098
18145
  title: "Justified text without hyphens",
18099
18146
  tags: ["test-noise"],
18100
18147
  severity: "warn",
18148
+ defaultEnabled: false,
18101
18149
  category: "Accessibility",
18102
18150
  recommendation: "Use `text-align: left` for body text. If you must justify, add `hyphens: auto` and `overflow-wrap: break-word`.",
18103
18151
  create: (context) => ({ JSXAttribute(node) {
@@ -20345,6 +20393,7 @@ const noPropTypes = defineRule({
20345
20393
  requires: ["react:19"],
20346
20394
  tags: ["test-noise"],
20347
20395
  severity: "warn",
20396
+ defaultEnabled: false,
20348
20397
  recommendation: "React 19 ignores `Component.propTypes`, so invalid props pass silently. Describe props with TypeScript types and add real runtime checks (or schema parsing) only where data can actually be wrong. Only runs on React 19+ projects.",
20349
20398
  create: (context) => ({
20350
20399
  AssignmentExpression(node) {
@@ -20373,6 +20422,7 @@ const noPureBlackBackground = defineRule({
20373
20422
  title: "Pure black background",
20374
20423
  tags: ["design", "test-noise"],
20375
20424
  severity: "warn",
20425
+ defaultEnabled: false,
20376
20426
  recommendation: "Nudge the background slightly toward your brand color, like `#0a0a0f` or Tailwind's `bg-gray-950`. Pure black looks harsh on modern screens.",
20377
20427
  create: (context) => ({
20378
20428
  JSXAttribute(node) {
@@ -21802,6 +21852,7 @@ const noSideTabBorder = defineRule({
21802
21852
  title: "Thick one-sided border",
21803
21853
  tags: ["design", "test-noise"],
21804
21854
  severity: "warn",
21855
+ defaultEnabled: false,
21805
21856
  recommendation: "Use a softer accent like an inset box-shadow, a background, or a thin border-bottom instead of a thick one-sided border.",
21806
21857
  create: (context) => ({
21807
21858
  JSXAttribute(node) {
@@ -23680,15 +23731,46 @@ const noUsememoSimpleExpression = defineRule({
23680
23731
  });
23681
23732
  //#endregion
23682
23733
  //#region src/plugin/rules/design/no-wide-letter-spacing.ts
23734
+ const getJsxAttributeStringValue = (attributeValue) => {
23735
+ if (!attributeValue) return null;
23736
+ if (isNodeOfType(attributeValue, "Literal") && typeof attributeValue.value === "string") return attributeValue.value;
23737
+ if (isNodeOfType(attributeValue, "JSXExpressionContainer")) {
23738
+ const expression = attributeValue.expression;
23739
+ if (isNodeOfType(expression, "Literal") && typeof expression.value === "string") return expression.value;
23740
+ }
23741
+ return null;
23742
+ };
23743
+ const isTruthyBooleanJsxAttribute = (attributeValue) => {
23744
+ if (attributeValue === null) return true;
23745
+ if (isNodeOfType(attributeValue, "JSXExpressionContainer")) {
23746
+ const expression = attributeValue.expression;
23747
+ return isNodeOfType(expression, "Literal") && expression.value === true;
23748
+ }
23749
+ return false;
23750
+ };
23751
+ const hasUppercaseSiblingProp = (styleAttribute) => {
23752
+ const openingElement = styleAttribute.parent;
23753
+ if (!openingElement || !isNodeOfType(openingElement, "JSXOpeningElement")) return false;
23754
+ for (const attribute of openingElement.attributes ?? []) {
23755
+ if (!isNodeOfType(attribute, "JSXAttribute")) continue;
23756
+ if (!isNodeOfType(attribute.name, "JSXIdentifier")) continue;
23757
+ const attributeName = attribute.name.name;
23758
+ if (attributeName === "uppercase" && isTruthyBooleanJsxAttribute(attribute.value)) return true;
23759
+ if (attributeName === "textTransform" && getJsxAttributeStringValue(attribute.value) === "uppercase") return true;
23760
+ }
23761
+ return false;
23762
+ };
23683
23763
  const noWideLetterSpacing = defineRule({
23684
23764
  id: "no-wide-letter-spacing",
23685
23765
  title: "Wide letter spacing on body text",
23686
23766
  severity: "warn",
23767
+ defaultEnabled: false,
23687
23768
  tags: ["test-noise"],
23688
23769
  recommendation: "Save wide letter-spacing (over 0.05em) for short uppercase labels, nav items, and buttons, not body text.",
23689
23770
  create: (context) => ({ JSXAttribute(node) {
23690
23771
  const expression = getInlineStyleExpression(node);
23691
23772
  if (!expression) return;
23773
+ if (hasUppercaseSiblingProp(node)) return;
23692
23774
  let isUppercase = false;
23693
23775
  let letterSpacingProperty = null;
23694
23776
  let letterSpacingEm = null;
@@ -23766,6 +23848,7 @@ const noZIndex9999 = defineRule({
23766
23848
  title: "Excessively high z-index",
23767
23849
  tags: ["test-noise"],
23768
23850
  severity: "warn",
23851
+ defaultEnabled: false,
23769
23852
  recommendation: "Pick a small z-index scale, like dropdown 10, modal 20, toast 30. To layer something on top, use `isolation: isolate` instead of bigger numbers.",
23770
23853
  create: (context) => ({
23771
23854
  JSXAttribute(node) {
@@ -24541,6 +24624,7 @@ const preferEs6Class = defineRule({
24541
24624
  id: "prefer-es6-class",
24542
24625
  title: "createClass instead of ES6 class",
24543
24626
  severity: "warn",
24627
+ defaultEnabled: false,
24544
24628
  recommendation: "Pick one component style for the whole codebase: `class extends React.Component` (default) or `createReactClass` (legacy).",
24545
24629
  category: "Architecture",
24546
24630
  create: (context) => {
@@ -24851,6 +24935,7 @@ const preferModuleScopeStaticValue = defineRule({
24851
24935
  tags: ["test-noise"],
24852
24936
  severity: "warn",
24853
24937
  category: "Architecture",
24938
+ disabledBy: ["react-compiler"],
24854
24939
  recommendation: "Move the value above the component, at the top of the file. It doesn't use local state, so rebuilding it each update is wasted and makes it look new every time.",
24855
24940
  create: (context) => ({ VariableDeclarator(node) {
24856
24941
  if (!isNodeOfType(node.id, "Identifier")) return;
@@ -25918,7 +26003,9 @@ const renderingHydrationNoFlicker = defineRule({
25918
26003
  const bodyStatements = isNodeOfType(callback.body, "BlockStatement") ? callback.body.body : [callback.body];
25919
26004
  if (!bodyStatements || bodyStatements.length !== 1) return;
25920
26005
  const soleStatement = bodyStatements[0];
25921
- if (isNodeOfType(soleStatement, "ExpressionStatement") && isSetterCall(soleStatement.expression)) context.report({
26006
+ if (!isNodeOfType(soleStatement, "ExpressionStatement")) return;
26007
+ const expression = soleStatement.expression;
26008
+ if (isSetterCall(expression) && isNodeOfType(expression, "CallExpression") && isNodeOfType(expression.callee, "Identifier") && isUseStateSetterInScope(expression, expression.callee.name)) context.report({
25922
26009
  node,
25923
26010
  message: "This flashes for your users because useEffect(setState, []) runs after the first paint, so use useSyncExternalStore, or add suppressHydrationWarning"
25924
26011
  });
@@ -26441,6 +26528,7 @@ const rerenderFunctionalSetstate = defineRule({
26441
26528
  if (!isSetterCall(node)) return;
26442
26529
  if (!node.arguments?.length) return;
26443
26530
  if (!isNodeOfType(node.callee, "Identifier")) return;
26531
+ if (!isUseStateSetterInScope(node, node.callee.name)) return;
26444
26532
  const calleeName = node.callee.name;
26445
26533
  const argument = node.arguments[0];
26446
26534
  const expectedStateName = deriveStateVariableName(calleeName);
@@ -26775,7 +26863,7 @@ const handlerCallsSetState = (handler) => {
26775
26863
  let setStateCall = null;
26776
26864
  walkAst(handler.body, (child) => {
26777
26865
  if (setStateCall) return;
26778
- if (isNodeOfType(child, "CallExpression") && isNodeOfType(child.callee, "Identifier") && /^set[A-Z]/.test(child.callee.name)) setStateCall = child;
26866
+ if (isNodeOfType(child, "CallExpression") && isNodeOfType(child.callee, "Identifier") && /^set[A-Z]/.test(child.callee.name) && isUseStateSetterInScope(child, child.callee.name)) setStateCall = child;
26779
26867
  });
26780
26868
  return setStateCall;
26781
26869
  };
@@ -26807,76 +26895,22 @@ const rerenderTransitionsScroll = defineRule({
26807
26895
  } })
26808
26896
  });
26809
26897
  //#endregion
26898
+ //#region src/plugin/utils/define-retired-rule.ts
26899
+ const defineRetiredRule = (rule) => defineRule({
26900
+ ...rule,
26901
+ defaultEnabled: false,
26902
+ lifecycle: "retired",
26903
+ create: () => ({})
26904
+ });
26905
+ //#endregion
26810
26906
  //#region src/plugin/rules/react-native/rn-animate-layout-property.ts
26811
- const REANIMATED_LAYOUT_KEYS = new Set([
26812
- "width",
26813
- "height",
26814
- "top",
26815
- "left",
26816
- "right",
26817
- "bottom",
26818
- "minWidth",
26819
- "minHeight",
26820
- "maxWidth",
26821
- "maxHeight",
26822
- "margin",
26823
- "marginTop",
26824
- "marginBottom",
26825
- "marginLeft",
26826
- "marginRight",
26827
- "marginHorizontal",
26828
- "marginVertical",
26829
- "padding",
26830
- "paddingTop",
26831
- "paddingBottom",
26832
- "paddingLeft",
26833
- "paddingRight",
26834
- "paddingHorizontal",
26835
- "paddingVertical",
26836
- "flex",
26837
- "flexBasis",
26838
- "flexGrow",
26839
- "flexShrink",
26840
- "borderWidth",
26841
- "borderTopWidth",
26842
- "borderBottomWidth",
26843
- "borderLeftWidth",
26844
- "borderRightWidth",
26845
- "fontSize",
26846
- "lineHeight",
26847
- "letterSpacing"
26848
- ]);
26849
- const findReturnedObject = (callback) => {
26850
- if (!isNodeOfType(callback, "ArrowFunctionExpression") && !isNodeOfType(callback, "FunctionExpression")) return null;
26851
- const body = callback.body;
26852
- if (isNodeOfType(body, "ObjectExpression")) return body;
26853
- if (!isNodeOfType(body, "BlockStatement")) return null;
26854
- for (const stmt of body.body ?? []) if (isNodeOfType(stmt, "ReturnStatement") && isNodeOfType(stmt.argument, "ObjectExpression")) return stmt.argument;
26855
- return null;
26856
- };
26857
- const rnAnimateLayoutProperty = defineRule({
26907
+ const rnAnimateLayoutProperty = defineRetiredRule({
26858
26908
  id: "rn-animate-layout-property",
26859
26909
  title: "Animating a layout property",
26860
26910
  tags: ["test-noise"],
26861
26911
  requires: ["react-native"],
26862
- severity: "error",
26863
- recommendation: "Animating size or position props runs on the JS thread and can stutter. Animate `transform: [{ translateX/Y }, { scale }]` or `opacity` instead, which run on the GPU.",
26864
- create: (context) => ({ CallExpression(node) {
26865
- if (!isNodeOfType(node.callee, "Identifier") || node.callee.name !== "useAnimatedStyle") return;
26866
- const callback = node.arguments?.[0];
26867
- if (!callback) return;
26868
- const returnedObject = findReturnedObject(callback);
26869
- if (!returnedObject) return;
26870
- for (const property of returnedObject.properties ?? []) {
26871
- if (!isNodeOfType(property, "Property")) continue;
26872
- if (!isNodeOfType(property.key, "Identifier")) continue;
26873
- if (!REANIMATED_LAYOUT_KEYS.has(property.key.name)) continue;
26874
- context.report({
26875
- node: property,
26876
- message: `Your users see stutter when useAnimatedStyle animates "${property.key.name}" on the layout thread.`
26877
- });
26878
- }
26879
- } })
26912
+ severity: "warn",
26913
+ recommendation: "Reanimated useAnimatedStyle runs on the UI thread; layout-affecting properties driven by animation helpers, interpolate, or shared values are valid."
26880
26914
  });
26881
26915
  //#endregion
26882
26916
  //#region src/plugin/rules/react-native/rn-animation-reaction-as-derived.ts
@@ -28077,7 +28111,7 @@ const findSetStateInBody = (body) => {
28077
28111
  let setStateCallNode = null;
28078
28112
  walkAst(body, (child) => {
28079
28113
  if (setStateCallNode) return;
28080
- if (isNodeOfType(child, "CallExpression") && isNodeOfType(child.callee, "Identifier") && SET_STATE_PATTERN.test(child.callee.name)) setStateCallNode = child;
28114
+ if (isNodeOfType(child, "CallExpression") && isNodeOfType(child.callee, "Identifier") && SET_STATE_PATTERN.test(child.callee.name) && isUseStateSetterInScope(child, child.callee.name)) setStateCallNode = child;
28081
28115
  });
28082
28116
  return setStateCallNode;
28083
28117
  };
@@ -28203,14 +28237,6 @@ const rnNoSingleElementStyleArray = defineRule({
28203
28237
  } })
28204
28238
  });
28205
28239
  //#endregion
28206
- //#region src/plugin/utils/define-retired-rule.ts
28207
- const defineRetiredRule = (rule) => defineRule({
28208
- ...rule,
28209
- defaultEnabled: false,
28210
- lifecycle: "retired",
28211
- create: () => ({})
28212
- });
28213
- //#endregion
28214
28240
  //#region src/plugin/rules/react-native/rn-prefer-content-inset-adjustment.ts
28215
28241
  const rnPreferContentInsetAdjustment = defineRetiredRule({
28216
28242
  id: "rn-prefer-content-inset-adjustment",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oxlint-plugin-react-doctor",
3
- "version": "0.2.18-dev.4dc48d7",
3
+ "version": "0.2.18-dev.67be206",
4
4
  "description": "oxlint plugin for React Doctor: diagnose React codebases for security, performance, correctness, accessibility, bundle-size, and architecture issues",
5
5
  "keywords": [
6
6
  "accessibility",