oxlint-plugin-react-doctor 0.2.5 → 0.2.6

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.d.ts CHANGED
@@ -529,26 +529,6 @@ declare const REACT_DOCTOR_RULES: readonly [{
529
529
  readonly recommendation?: string;
530
530
  readonly create: (context: RuleContext) => RuleVisitors;
531
531
  };
532
- }, {
533
- readonly key: "react-doctor/design-no-bold-heading";
534
- readonly id: "design-no-bold-heading";
535
- readonly source: "react-doctor";
536
- readonly originallyExternal: false;
537
- readonly framework: "global";
538
- readonly category: "Architecture";
539
- readonly severity: "warn";
540
- readonly rule: {
541
- readonly framework: "global";
542
- readonly category: "Architecture";
543
- readonly id: string;
544
- readonly severity: RuleSeverity;
545
- readonly requires?: ReadonlyArray<string>;
546
- readonly disabledBy?: ReadonlyArray<string>;
547
- readonly tags?: ReadonlyArray<string>;
548
- readonly defaultEnabled?: boolean;
549
- readonly recommendation?: string;
550
- readonly create: (context: RuleContext) => RuleVisitors;
551
- };
552
532
  }, {
553
533
  readonly key: "react-doctor/design-no-em-dash-in-jsx-text";
554
534
  readonly id: "design-no-em-dash-in-jsx-text";
@@ -6315,26 +6295,6 @@ declare const RULES: readonly [{
6315
6295
  readonly recommendation?: string;
6316
6296
  readonly create: (context: RuleContext) => RuleVisitors;
6317
6297
  };
6318
- }, {
6319
- readonly key: "react-doctor/design-no-bold-heading";
6320
- readonly id: "design-no-bold-heading";
6321
- readonly source: "react-doctor";
6322
- readonly originallyExternal: false;
6323
- readonly framework: "global";
6324
- readonly category: "Architecture";
6325
- readonly severity: "warn";
6326
- readonly rule: {
6327
- readonly framework: "global";
6328
- readonly category: "Architecture";
6329
- readonly id: string;
6330
- readonly severity: RuleSeverity;
6331
- readonly requires?: ReadonlyArray<string>;
6332
- readonly disabledBy?: ReadonlyArray<string>;
6333
- readonly tags?: ReadonlyArray<string>;
6334
- readonly defaultEnabled?: boolean;
6335
- readonly recommendation?: string;
6336
- readonly create: (context: RuleContext) => RuleVisitors;
6337
- };
6338
6298
  }, {
6339
6299
  readonly key: "react-doctor/design-no-em-dash-in-jsx-text";
6340
6300
  readonly id: "design-no-em-dash-in-jsx-text";
package/dist/index.js CHANGED
@@ -3527,19 +3527,6 @@ const controlHasAssociatedLabel = defineRule({
3527
3527
  }
3528
3528
  });
3529
3529
  const LONG_TRANSITION_DURATION_THRESHOLD_MS = 1e3;
3530
- const HEADING_TAG_NAMES = new Set([
3531
- "h1",
3532
- "h2",
3533
- "h3",
3534
- "h4",
3535
- "h5",
3536
- "h6"
3537
- ]);
3538
- const HEAVY_HEADING_TAILWIND_WEIGHTS = new Set([
3539
- "font-bold",
3540
- "font-extrabold",
3541
- "font-black"
3542
- ]);
3543
3530
  const VAGUE_BUTTON_LABELS = new Set([
3544
3531
  "continue",
3545
3532
  "submit",
@@ -3609,85 +3596,6 @@ const getOpeningElementTagName = (openingElement) => {
3609
3596
  return null;
3610
3597
  };
3611
3598
  //#endregion
3612
- //#region src/plugin/rules/react-ui/utils/get-class-name-literal.ts
3613
- const getClassNameLiteral = (classAttribute) => {
3614
- if (!isNodeOfType(classAttribute, "JSXAttribute")) return null;
3615
- if (!classAttribute.value) return null;
3616
- if (isNodeOfType(classAttribute.value, "Literal") && typeof classAttribute.value.value === "string") return classAttribute.value.value;
3617
- if (isNodeOfType(classAttribute.value, "JSXExpressionContainer")) {
3618
- const expression = classAttribute.value.expression;
3619
- if (isNodeOfType(expression, "Literal") && typeof expression.value === "string") return expression.value;
3620
- if (isNodeOfType(expression, "TemplateLiteral") && expression.quasis?.length === 1) return expression.quasis[0].value?.raw ?? null;
3621
- }
3622
- return null;
3623
- };
3624
- //#endregion
3625
- //#region src/plugin/rules/react-ui/no-bold-heading.ts
3626
- const getInlineStyleObjectExpression = (jsxAttribute) => {
3627
- if (!isNodeOfType(jsxAttribute, "JSXAttribute")) return null;
3628
- if (!isNodeOfType(jsxAttribute.name, "JSXIdentifier") || jsxAttribute.name.name !== "style") return null;
3629
- if (!isNodeOfType(jsxAttribute.value, "JSXExpressionContainer")) return null;
3630
- const expression = jsxAttribute.value.expression;
3631
- if (!isNodeOfType(expression, "ObjectExpression")) return null;
3632
- return expression;
3633
- };
3634
- const getStylePropertyKeyName = (objectProperty) => {
3635
- if (!isNodeOfType(objectProperty, "Property")) return null;
3636
- if (isNodeOfType(objectProperty.key, "Identifier")) return objectProperty.key.name;
3637
- if (isNodeOfType(objectProperty.key, "Literal") && typeof objectProperty.key.value === "string") return objectProperty.key.value;
3638
- return null;
3639
- };
3640
- const getStylePropertyNumericValue = (objectProperty) => {
3641
- if (!isNodeOfType(objectProperty, "Property")) return null;
3642
- const valueNode = objectProperty.value;
3643
- if (!valueNode) return null;
3644
- if (isNodeOfType(valueNode, "Literal") && typeof valueNode.value === "number") return valueNode.value;
3645
- if (isNodeOfType(valueNode, "Literal") && typeof valueNode.value === "string") {
3646
- const parsed = parseFloat(valueNode.value);
3647
- return Number.isFinite(parsed) ? parsed : null;
3648
- }
3649
- return null;
3650
- };
3651
- const noBoldHeading = defineRule({
3652
- id: "design-no-bold-heading",
3653
- tags: ["design", "test-noise"],
3654
- severity: "warn",
3655
- category: "Architecture",
3656
- recommendation: "Use `font-semibold` (600) or `font-medium` (500) on headings — 700+ crushes letter counter shapes at display sizes",
3657
- create: (context) => ({ JSXOpeningElement(openingNode) {
3658
- const tagName = getOpeningElementTagName(openingNode);
3659
- if (!tagName || !HEADING_TAG_NAMES.has(tagName)) return;
3660
- const classAttribute = findJsxAttribute(openingNode.attributes ?? [], "className");
3661
- if (classAttribute) {
3662
- const classNameLiteral = getClassNameLiteral(classAttribute);
3663
- if (classNameLiteral) {
3664
- for (const tailwindWeightToken of HEAVY_HEADING_TAILWIND_WEIGHTS) if (new RegExp(`(?:^|\\s)${tailwindWeightToken}(?:$|\\s|:)`).test(classNameLiteral)) {
3665
- context.report({
3666
- node: classAttribute,
3667
- message: `${tailwindWeightToken} on <${tagName}> crushes counter shapes at display sizes — use font-semibold (600) or font-medium (500)`
3668
- });
3669
- return;
3670
- }
3671
- }
3672
- }
3673
- const styleAttribute = findJsxAttribute(openingNode.attributes ?? [], "style");
3674
- if (!styleAttribute) return;
3675
- const styleObject = getInlineStyleObjectExpression(styleAttribute);
3676
- if (!styleObject) return;
3677
- for (const objectProperty of styleObject.properties ?? []) {
3678
- if (getStylePropertyKeyName(objectProperty) !== "fontWeight") continue;
3679
- const numericWeight = getStylePropertyNumericValue(objectProperty);
3680
- if (numericWeight !== null && numericWeight >= 700) {
3681
- context.report({
3682
- node: objectProperty,
3683
- message: `fontWeight: ${numericWeight} on <${tagName}> crushes counter shapes at display sizes — use 500 or 600`
3684
- });
3685
- return;
3686
- }
3687
- }
3688
- } })
3689
- });
3690
- //#endregion
3691
3599
  //#region src/plugin/rules/react-ui/utils/is-inside-excluded-typography-ancestor.ts
3692
3600
  const isInsideExcludedTypographyAncestor = (jsxTextNode) => {
3693
3601
  let cursor = jsxTextNode.parent;
@@ -3721,6 +3629,19 @@ const noEmDashInJsxText = defineRule({
3721
3629
  } })
3722
3630
  });
3723
3631
  //#endregion
3632
+ //#region src/plugin/rules/react-ui/utils/get-class-name-literal.ts
3633
+ const getClassNameLiteral = (classAttribute) => {
3634
+ if (!isNodeOfType(classAttribute, "JSXAttribute")) return null;
3635
+ if (!classAttribute.value) return null;
3636
+ if (isNodeOfType(classAttribute.value, "Literal") && typeof classAttribute.value.value === "string") return classAttribute.value.value;
3637
+ if (isNodeOfType(classAttribute.value, "JSXExpressionContainer")) {
3638
+ const expression = classAttribute.value.expression;
3639
+ if (isNodeOfType(expression, "Literal") && typeof expression.value === "string") return expression.value;
3640
+ if (isNodeOfType(expression, "TemplateLiteral") && expression.quasis?.length === 1) return expression.quasis[0].value?.raw ?? null;
3641
+ }
3642
+ return null;
3643
+ };
3644
+ //#endregion
3724
3645
  //#region src/plugin/rules/react-ui/utils/collect-axis-shorthand-pairs.ts
3725
3646
  const collectAxisShorthandPairs = (classNameValue, horizontalPattern, verticalPattern) => {
3726
3647
  const horizontalValues = /* @__PURE__ */ new Set();
@@ -29881,20 +29802,6 @@ const reactDoctorRules = [
29881
29802
  category: "Accessibility"
29882
29803
  }
29883
29804
  },
29884
- {
29885
- key: "react-doctor/design-no-bold-heading",
29886
- id: "design-no-bold-heading",
29887
- source: "react-doctor",
29888
- originallyExternal: false,
29889
- framework: "global",
29890
- category: "Architecture",
29891
- severity: "warn",
29892
- rule: {
29893
- ...noBoldHeading,
29894
- framework: "global",
29895
- category: "Architecture"
29896
- }
29897
- },
29898
29805
  {
29899
29806
  key: "react-doctor/design-no-em-dash-in-jsx-text",
29900
29807
  id: "design-no-em-dash-in-jsx-text",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oxlint-plugin-react-doctor",
3
- "version": "0.2.5",
3
+ "version": "0.2.6",
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",