Skip to content

feat: expandable diff context in code review#247

Merged
backnotprop merged 3 commits intomainfrom
feat/expandable-diff-context
Mar 8, 2026
Merged

feat: expandable diff context in code review#247
backnotprop merged 3 commits intomainfrom
feat/expandable-diff-context

Conversation

@backnotprop
Copy link
Owner

Summary

  • Switches from PatchDiff to FileDiff component from @pierre/diffs to enable GitHub-style expandable context between diff hunks
  • Adds /api/file-content server endpoint that serves old/new file content based on the active diff type (uncommitted, staged, last-commit, branch, worktree)
  • Client fetches file contents on file switch, augments the parsed FileDiffMetadata with oldLines/newLines, unlocking the library's built-in expansion UI
  • Updates @pierre/diffs from 1.0.4 → 1.0.11 (scroll sync fix for unified mode, no breaking changes)

Closes #243

Test plan

  • bun run dev:review — demo mode renders identically (no expansion, graceful fallback since /api/file-content 404s)
  • bun run build:hook && ~/.local/bin/plannotator review from a repo with changes:
    • Hunk separators show "N unmodified lines" with expand buttons on hover
    • Click expand up/down/both — context lines appear with syntax highlighting
    • File with multiple scattered hunks — separators appear between each pair
    • Switch diff types (uncommitted → last-commit → branch) — expansion works across types
    • New/untracked files — expansion only downward (no old version)
    • Annotations still work: hover +, line selection, inline annotations render correctly
    • Split and unified views both work with expansion
    • j/k file navigation unaffected

🤖 Generated with Claude Code

backnotprop and others added 2 commits March 7, 2026 18:39
Switch from PatchDiff to FileDiff component from @pierre/diffs to enable
GitHub-style "show more lines" buttons between hunks. The library handles
all expansion UI when provided full file contents via oldLines/newLines.

- Add /api/file-content endpoint to serve old/new file content per diff type
- Add getFileContentsForDiff() helper with ref mapping for all diff types
- Parse patch client-side via getSingularPatch(), augment with file contents
- Update @pierre/diffs from 1.0.4 to 1.0.11 (scroll sync fix, no breaking changes)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…tents

The previous approach spread file content arrays onto a partial-mode
FileDiffMetadata, causing hunk index mismatches and Shiki decoration
errors. Now uses processFile() to re-parse the patch with oldFile/newFile
so hunk indices are computed against the full file (isPartial: false),
which is required for expansion to work correctly.

Also fixes a flash error on file switch by tagging fileContents with the
filePath they were fetched for, preventing stale contents from being
paired with the wrong patch during the render before useEffect fires.

- Upgrade @pierre/diffs from ^1.0.x to ^1.1.0-beta.19 in all workspaces
- Add test fixtures for disjoint hunks, deleted/renamed/new files

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@backnotprop
Copy link
Owner Author

Code review

No issues found. Checked for bugs and CLAUDE.md compliance.

🤖 Generated with Claude Code

- If this code review was useful, please react with 👍. Otherwise, react with 👎.

- Add AbortController to file-content fetch effect to cancel in-flight
  requests when switching files
- Reject path traversal (.. or absolute paths) on /api/file-content
- Document /api/file-content endpoint in CLAUDE.md

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@backnotprop backnotprop merged commit 472e17b into main Mar 8, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FR] Ability to show more lines of diff context during Code Review

1 participant