Skip to content

Commit 10bd788

Browse files
fix: address multiple GitHub issues (#117, #113, #119, #106) (#120)
* fix: detect namespace hook calls (React.useState, React.useEffect) in all rules Fixes #117: isHookCall now handles MemberExpression callee types (e.g. React.useEffect, React.useState) in addition to plain Identifier callee types. This fixes silent misses in no-derived-state-effect, no-fetch-in-effect, no-cascading-set-state, no-effect-event-handler, rerender-functional-setstate, rendering-hydration-no-flicker, and the countSetStateCalls helper. Co-authored-by: Aiden Bai <aidenybai@users.noreply.github.com> * fix: remove unsupported jsx-a11y/no-noninteractive-element-interactions rule Fixes #113, #119: This rule does not exist in the bundled oxlint binary, causing 'Failed to parse oxlint configuration file' errors and score suppression on all scans. Co-authored-by: Aiden Bai <aidenybai@users.noreply.github.com> * feat: add --no flag to skip prompts and always run full scan Fixes #106: Adds -n/--no flag that skips all interactive prompts (like --yes) but specifically declines the diff-only scan prompt, ensuring a full project scan runs. Useful for CI agents that cannot interact with TTY prompts. Co-authored-by: Aiden Bai <aidenybai@users.noreply.github.com> * test: add namespace hook detection tests (React.useEffect, React.useState, etc.) Adds 13 tests verifying that all rules correctly detect namespace-style hook calls (import * as React; React.useEffect, React.useState, etc.). Covers: no-derived-state-effect, no-fetch-in-effect, no-cascading-set-state, no-effect-event-handler, no-derived-useState, rerender-lazy-state-init, rerender-functional-setstate, rerender-dependencies, rendering-hydration-no-flicker, no-usememo-simple-expression, prefer-useReducer, plus a regression guard for direct-import fixtures. Relates to #117. Co-authored-by: Aiden Bai <aidenybai@users.noreply.github.com> * test: add edge case tests for project discovery and catalog resolution Adds tests for: - peerDependencies-only with catalog reference resolution - Catalog reference to nonexistent catalog name (fallback to default) - Empty pnpm-workspace.yaml handling - Malformed package.json in workspace subdirectories - Nonexistent root directory for discoverReactSubprojects - File entries mixed with directory entries in project root Relates to #101, #87, #105, #71. Co-authored-by: Aiden Bai <aidenybai@users.noreply.github.com> * fix: handle malformed JSON in workspace package.json files gracefully readPackageJson now catches SyntaxError from malformed JSON and returns an empty object instead of crashing. This prevents workspace discovery from aborting when a subdirectory has an invalid package.json. Previously, a broken package.json in any workspace subdirectory would crash the entire scan with an unhandled SyntaxError. Co-authored-by: Aiden Bai <aidenybai@users.noreply.github.com> * feat: add customRulesOnly config to disable builtin react/jsx-a11y rules Fixes #109: Teams with existing ESLint setups can now set customRulesOnly: true in react-doctor.config.json to only run react-doctor/* custom rules, skipping the bundled react/, jsx-a11y/, react-perf, and react-compiler rules. This avoids rule duplication for projects that already lint with eslint-plugin-react, eslint-plugin-jsx-a11y, etc. Co-authored-by: Aiden Bai <aidenybai@users.noreply.github.com> * feat: inherit config from ancestor directories for monorepo support Fixes #73: loadConfig now walks up the directory tree to find react-doctor.config.json or package.json reactDoctor key from ancestor directories. This means a single config at the monorepo root applies to all workspace packages without needing to duplicate the config in each package. Co-authored-by: Aiden Bai <aidenybai@users.noreply.github.com> * feat: add --annotations flag for GitHub Actions annotation output Fixes #81: The --annotations flag outputs diagnostics in GitHub Actions annotation format (::error / ::warning) so they appear as inline annotations on PR diffs. Example: ::error file=src/App.tsx,line=42,title=react-doctor/no-fetch-in-effect::fetch() inside useEffect Co-authored-by: Aiden Bai <aidenybai@users.noreply.github.com> * refactor: remove Ami integration Removes all Ami-related code: - --ami flag, --fix flag, fix subcommand, install-ami subcommand - Ami detection, installation, deeplinks, and open-URL helpers - Fix prompt (maybePromptFix) with Ami banners - Skill installation prompt (maybePromptSkillInstall) - fetchEstimatedScore and EstimatedScoreResult - AMI_WEBSITE_URL, AMI_INSTALL_URL, AMI_RELEASES_URL, OPEN_BASE_URL, ESTIMATE_SCORE_API_URL, ERROR_ESTIMATED_FIX_RATE, WARNING_ESTIMATED_FIX_RATE - skill-prompt.ts utility CLI bundle reduced by ~39KB (324KB → 285KB). Co-authored-by: Aiden Bai <aidenybai@users.noreply.github.com> * chore: remove .ami directory and all remaining Ami references - Delete .ami/ directory (42 skill/config files) - Delete packages/website/src/app/open/ (Ami redirect page) - Remove Ami references from README.md, share page, install-skill route, llms.txt, and install-skill.sh - Zero Ami references remain in the codebase Co-authored-by: Aiden Bai <aidenybai@users.noreply.github.com> * chore: move .ami/skills to .agents/skills Relocates all skill files from the deleted .ami/ directory into .agents/skills/ and removes .agents from .gitignore so they are tracked in version control. Co-authored-by: Aiden Bai <aidenybai@users.noreply.github.com> * fix: recognize custom text components in rn-no-raw-text rule Fixes #93: The rn-no-raw-text rule now recognizes a much wider set of text-handling components: 1. Expanded built-in names: Typography, Paragraph, Span, H1-H6 2. Keyword matching instead of suffix-only: any component whose name contains Text, Title, Label, Heading, Caption, Subtitle, Typography, Paragraph, Description, or Body is treated as text-handling (e.g. StyledText, BodyText, CustomLabel, MyTypography) 3. New textComponents config option: users can specify arbitrary component names in react-doctor.config.json that should be treated as text-handling: { "textComponents": ["MyCustomComp", "NativeWindText"] } Diagnostics inside these components are filtered out post-lint. Co-authored-by: Aiden Bai <aidenybai@users.noreply.github.com> * chore: upgrade dependencies - oxlint: 1.47.0 → 1.59.0 (fixes SIGABRT crashes on large projects #84/#77) - oxfmt: 0.32.0 → 0.44.0 - typescript: 5.9.3 → 6.0.2 - vitest: 4.0.18 → 4.1.4 - tsdown: 0.20.3 → 0.21.7 - knip: 5.83.1 → 6.3.1 Co-authored-by: Aiden Bai <aidenybai@users.noreply.github.com> * fix: add file count limit per oxlint batch to prevent OOM crashes Mitigates #84/#77: Adds OXLINT_MAX_FILES_PER_BATCH (500) to cap the number of files per oxlint invocation. Combined with the oxlint upgrade from 1.47 to 1.59, this prevents SIGABRT/OOM crashes on large projects with 100+ source files. Co-authored-by: Aiden Bai <aidenybai@users.noreply.github.com> * feat: add --staged flag for pre-commit hook scanning Fixes #115: The --staged flag scans only files in the git index (staged with git add). It materializes staged content to a temp directory so oxlint reads the exact index version, not the working tree version. This is critical for pre-commit hooks where the working tree may differ from what's being committed. Usage: npx react-doctor . --staged --fail-on error For lint-staged: "*.{tsx,jsx}": "npx react-doctor . --staged --fail-on error" Co-authored-by: Aiden Bai <aidenybai@users.noreply.github.com> * refactor: code review fixes per AGENTS.md rules - DRY: Extract shared createFileLinesCache in filter-diagnostics.ts - DRY: Extract resolveFailOnLevel in cli.ts (was duplicated in staged and normal paths) - DRY: Reuse exported getCalleeName from helpers.ts instead of duplicating in state-and-effects.ts and performance.ts - Magic number: Move maxBuffer 10MB to GIT_SHOW_MAX_BUFFER_BYTES constant - Variable naming: prevLine → previousLine, tagName → fullTagName, leafName → leafTagName, configFiles → projectConfigFilenames - Remove .pop()! non-null assertion in favor of .at(-1) with fallback Co-authored-by: Aiden Bai <aidenybai@users.noreply.github.com> * fix: prevent shell injection in staged file content reading Replace execSync with string interpolation with spawnSync using an args array. File paths with shell metacharacters (quotes, semicolons, etc.) in their names are now passed safely without shell interpretation. Co-authored-by: Aiden Bai <aidenybai@users.noreply.github.com> * fix: pass resolved config to staged scan to preserve ancestor inheritance The staged scan materializes files to /tmp, where loadConfig's ancestor traversal would never find a monorepo root's config. Now the CLI resolves config from the real project directory first and passes it via the new configOverride ScanOption, so customRulesOnly, share, ignore rules, and textComponents all apply correctly during --staged scans. Co-authored-by: Aiden Bai <aidenybai@users.noreply.github.com> --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Aiden Bai <aidenybai@users.noreply.github.com>
1 parent 66e1318 commit 10bd788

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

75 files changed

+1632
-1236
lines changed

.ami/skills/remotion-best-practices/rules/animations.md renamed to .agents/skills/remotion-best-practices/rules/animations.md

.ami/skills/remotion-best-practices/rules/assets/charts-bar-chart.tsx renamed to .agents/skills/remotion-best-practices/rules/assets/charts-bar-chart.tsx

File renamed without changes.

.ami/skills/remotion-best-practices/rules/assets/text-animations-typewriter.tsx renamed to .agents/skills/remotion-best-practices/rules/assets/text-animations-typewriter.tsx

File renamed without changes.

.ami/skills/remotion-best-practices/rules/assets/text-animations-word-highlight.tsx renamed to .agents/skills/remotion-best-practices/rules/assets/text-animations-word-highlight.tsx

File renamed without changes.

.ami/skills/remotion-best-practices/rules/audio-visualization.md renamed to .agents/skills/remotion-best-practices/rules/audio-visualization.md

0 commit comments

Comments
 (0)