Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
2 tasks
Reproduce: 1. Open an editable diff with a marker close to the lower-right edge of the visible code viewport. 2. Hover the marker until its message popup opens. 3. Scroll the editor while keeping the popup open. Before this change, the marker popup keeps the side chosen at hover time and its horizontal clamp is based on the code column rather than the visible scroll viewport, so it can stay clipped or overflow the edge. Marker popups duplicated the selection-action placement branch, and the shared popover manager only treated selection-action as the active popover. Route marker popups through PopoverManager.choosePlacement, track hysteresis state per popover kind, and expose viewport left/right bounds to the shared popover CSS clamp.
1. Open an editable file with a marker on a long line. 2. Scroll the code pane horizontally until the marked text sits near the sticky line-number gutter. 3. Hover the marked text. Before this change, the shared popover left clamp could use only the horizontal scroll viewport plus padding, so marker and selection popovers could overlap the sticky gutter after horizontal scroll. Include the current gutter width in the scrolled left clamp and cover the marker case in the browser fixture.
1. Open the diffs editor with a line containing `変数\tvalue`. 2. Place the caret after `value`, select across the tab, or enable wrapping near the tab stop. 3. Observe the caret, selection block, or wrap decision drift left because the tab after `変数` is measured from two logical columns instead of the glyphs' rendered width. Measure tabs by accumulating rendered pixel width between tab characters and advancing to the next pixel tab stop. Keep the ASCII column fast path for plain ASCII text, and remove the stale tab-to- spaces expansion helper. Add coverage with a fake canvas where CJK glyphs are 2ch wide, including the case where `変数` lands exactly on a tab stop and the tab advances a full stop.
* feat(diffs): Add edit-session region skeleton for diff hunks While an editor is attached to a FileDiff, hunk updates now preserve the current hunk structure instead of recomputing it per keystroke: each hunk is a frozen region, edits re-diff only the region they land in, a fully reverted region persists as a context-only hunk, edits spanning regions merge them, and edits inside an unchanged gap synthesize a new region. The real recompute runs once on genuine session exit, so post-session state is unchanged. This is groundwork for edit mode preserving collapsed unchanged regions; with expandUnchanged still forced during editing, rendering behavior is unchanged. Details: - New pure module `utils/editSessionHunks.ts` holds the region math (window mapping, region re-diff with zero context, expansion-key remapping, exit recompute) built on the exported updateDiffHunks helpers. - Line-count edit passes run updateRenderCache with dense, stale indexed dirty lines before applyDocumentChange. A new explicit `lineCountChangeInFlight` flag threads from the editor through the host so the session path defers hunk work to the document rebuild, which scans a per-session line snapshot instead of the contaminated live array. Deferred background-tokenize passes keep running region updates from their (current) changed indexes. - A same-line-count gap edit changes the rendered row set, which the debounced refresh cannot express; the host escalates to a deferred full re-render, and VirtualizedFileDiff also invalidates its layout caches. - The editor detach closure now reports whether it is a virtualized recycle or a genuine session end. Session hunks and a dirty marker on the shared FileDiffMetadata survive recycling; CodeView finishes sessions whose instance was already released, and FileDiff.render self-heals session-shaped metadata reused after a teardown. * feat(diffs): Make the editor DOM layer collapse-aware Prepare the editor for diffs whose collapsed unchanged regions stay collapsed during editing: rendered rows can then be a sparse subset of document lines, which several editor code paths assumed were dense. With expansion still forced during editing, behavior is unchanged. - New visibility oracle: `isAdditionLineRenderable` in virtualDiffLayout derives from hunks plus expansion state (the same inputs as iterateOverDiff), exposed to the editor as the optional `DiffsEditableComponent.isLineRenderable`. FileDiff implements it; plain files leave it unset and every line stays renderable. - `#rerender` filters dirty lines through the oracle, scans the row patch loop from child index 0 (a sparse row can sit at a smaller index than its dense position, and overshooting appended duplicate rows), and only creates new rows beyond the last rendered row. - `#applyChange` only widens the render window toward a caret whose line can actually gain a row; `#scrollToLine` refuses to park its retry state on a collapsed line, which previously became a non-terminating scroll loop against separator geometry. - `__syncRenderView` stamps hunk separator rows contenteditable=false in both diff styles, alongside annotation and deleted rows. - `FileDiff.syncRenderViewToEditor` converts the stored render range (rendered-row units for the windowed AST pipeline) into the document-line units the editor consumes; the two only coincide while everything renders. The RenderRange type documents both readings. * feat(diffs): Add fold-skip caret motion and reveal-on-jump for collapsed regions Give the editor code-fold semantics over a diff's collapsed unchanged regions, ahead of edit mode keeping them collapsed: - Arrow up/down (and shift-extended selection) skip over a collapsed region atomically to the nearest renderable line, staying put when nothing renders in that direction. The skip target comes from a single hunk-metadata walk (getNearestRenderableAdditionLine), not a per-line probe across the gap. - Jumps that must land inside a collapsed region — setSelections, search-match navigation, cmd+d/find-next, cmd+Home/End, undo/redo caret restores — expand the region minimally first via the new `revealLine` host API: one deterministic bump from the nearest gap edge sized to reach the target plus the normal expansion step, routed through expandHunk so CodeView's deferred expansion staging applies. Search counts still include hidden matches; navigating to one reveals it. - VirtualizedFileDiff's line-visibility oracle now accounts for staged pendingExpansions so the caret-scroll retry can park while a reveal waits for the next layout consume. Behavior is unchanged while editing still forces expandUnchanged. * feat(diffs): Keep hunk separator expansion interactive during editing Separator expand buttons keep working while an editor is attached: their pointer wiring was already independent of the edit-mode gutter lockdown and only unreachable because no separators rendered during editing. With collapse live mid-session, a click reveals the gap, the revealed context lines are immediately editable (a gap edit synthesizes a session region), and the expansion re-render rebuilds its AST from diff.additionLines — which the session paths keep current every pass, so live edits survive the render-cache clear. Covered by jsdom tests on the standalone collapse-during-edit vector: a real separator button click mid-edit, then typing and undoing inside the newly revealed context. * feat(diffs): Stop forcing expandUnchanged while editing a diff Entering edit mode on a diff no longer expands every collapsed unchanged region. Collapsed regions stay collapsed: the caret skips over them like code folds, jumps that must land inside one expand it minimally, separator expand buttons keep working, and the layout no longer jumps when editing starts or ends. Edits re-diff within the current hunk regions and a genuine session end restores the normal recompute (all built up in the preceding commits). - Editor.edit drops expandUnchanged from its option normalization — from the destructuring too, so the setOptions fallback (which replaces options wholesale) can no longer strip a host's own expandUnchanged when another forced option triggers it. - CodeView's edit-forced option facade stops serving expandUnchanged: true for edited diff items; the key rejoins the plain pass-through options. - The React contentEditable option merge stops injecting expandUnchanged: true. - Editors need full file contents, so attaching to a partial diff now triggers loadDiffFiles hydration directly (previously the forced expansion render did it as a side effect). - The genuine session-end recompute now drives layout invalidation explicitly (estimated-height reset plus a virtualizer height reconcile); the expandUnchanged option flip that used to invalidate layout at exit is gone. CodeView applies the same invalidation when it reaps a session whose instance was released. - Docs: the Editor guide describes the fold behavior, and the demo SSR preloads drop the baked-in expandUnchanged (mockData.generated.ts regenerated). * feat(diffs): Preserve expansion state best-effort across session exit Expanding collapsed context while editing (separator clicks or reveal-on-jump) no longer resets when the session ends: expanded gap edges are snapshotted as old-side line ranges before the exit recompute — old-side coordinates are the ones edits cannot move — and remapped onto the recomputed hunks afterward. A preserved range that still touches a gap's start or end edge restores that edge's expansion; ranges whose gap disappeared just collapse. The exit flow consolidates into FileDiff.completeEditSession (marker-guarded, idempotent), shared by the live editor-detach path and CodeView's reap of sessions whose instance virtualization already released. The virtualized escalation now reports the layout change to its virtualizer so item tops re-derive from the changed heights. * test(diffs): Add browser E2E coverage for editing with collapsed regions New edit-collapsed fixture: a 60-line diff whose unchanged gap collapses, driven in both split and unified view (the unified content column rebuilds via innerHTML on edits, a named regression risk). Cases: the gap stays collapsed on edit entry, a reverted hunk persists as context until session exit and then collapses away, arrow keys fold-skip the gap, search navigation reveals a hidden match, a separator expand click mid-edit keeps the viewport and accepts typing into the revealed context, a programmatic replace into the gap materializes a rendered hunk without scrolling, and undo/redo round-trip with collapse live. * Add a new HTML editable example to /playground This is useful for different types of diff editing scenarios * feat(diffs): semantic diffs, at home Basically an attempt at doing better line matching on stuff * review(fix): Fix the arrow keys issue brought up by codex * fix(bug): Fix a strange edge cases with diffs that include intermixed blank lines Unclear if this will create some knock on effects that make it harder to manage in the future...
* [diffs/edit] Add missed commands * fix * fix LANGUAGE_COMMENT_CONFIGS
* [diffs/edit] docs: Add "Compared with Monaco Editor and CodeMirror" section * Small content updates * fix(docs): Prerender the edit mode demo on the server Load the Editor docs page: the live edit mode demo starts blank and its highlighted code only pops in once the client attaches the editor, so the surface visibly flashes after the page loads. The demo rendered <File> with no prerendered HTML, so the server only emitted an empty container and all highlighting happened client side. Preload the demo file with preloadFile and hydrate <File> from the resulting prerenderedHTML instead. The preload options mirror the state the editor enforces in contentEditable mode (token transformer on; gutter, line selection, and hover off) so the SSR markup matches the post-attach render and doesn't re-highlight. The demo now ships highlighted in the initial HTML. * Remove comparison, add paragraph near top for purpose --------- Co-authored-by: Mark Otto <markdotto@gmail.com>
fix issue with selection action, add another selection action for edges
* [diffs/edit] Add legacy-editor test suites harvested from monaco and CodeMirror Ports behavioral edge-case scenarios from microsoft/vscode (MIT) and CodeMirror 6 (MIT) test suites into two new bun:test suites under packages/diffs/test/. 139 tests, including 22 test.failing entries that encode real bugs found during the port (frozen EditStack entries vs non-history edits, undo coalescing, surrogate-pair edit boundaries, CRLF line metadata, and others). Test-only change; fixes land separately. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * [diffs/edit] Add atom-legacy-tests suite Third legacy-editor harvest, from atom/text-buffer and atom/superstring (both MIT): 56 tests covering search/replace semantics (regex capture expansion, zero-width-match termination, replace-past-own-output, anchored patterns on CRLF), selection remapping under partial-overlap replacements, soft-wrap boundary behavior, history invariant fuzzing, and malformed-position handling. Includes 8 test.failing entries encoding newly found bugs, the worst being: an edit with a NaN position component silently replaces the entire document, and soft-wrap vertical caret motion can land inside a surrogate pair. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * [diffs/edit] Guard ICU-dependent word-segmentation pins with skipIf Intl.Segmenter's isWordLike classification varies across ICU builds (underscore joining, bare-digit and Han word-ness differ between engines/platforms). Two segmenter-side expansion pins now probe the runtime's segmentation of their own fixture and skip visibly on divergent ICUs instead of failing. Both tests still execute on our dev and CI environments, which agree with the pinned segmentation. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * [diffs/edit] Extend ICU skipIf guards to all segmenter-side CJK pins Completes the previous commit: the Chinese, Japanese, and Latin-Katakana double-click expansion pins depend on the same ICU-variable isWordLike classification (dictionary-based CJK segmentation is the most engine-dependent of all), so they get the same runtime probe treatment via a shared wordLikeSegments helper. Delete-word tests are untouched — the regex classifier is deterministic. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * [diffs/edit] Consolidate editor-derived tests into the main suite Per team feedback: the three editor-named test directories are gone and all 195 tests now live in the existing per-domain files (editorPieceTable, editorTextDocument, editorApplyEdits, editorEditStack, editorSelection, editorSearchPanel, editorWrapCaretPosition). Migration was audited name-by-name before deletion: every test present exactly once, all 30 test.failing known-bug pins and 5 ICU skipIf guards preserved. Comments no longer reference other editors; the conventions, known-bug inventory, coverage-gap additions, and a single provenance note moved into test/README.md. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * [diffs/edit] Pin block-indent blank-line bug as test.failing resolveIndentEdits inserts the indent unit at column 0 of every line a multi-line selection touches, including empty and whitespace-only lines, injecting trailing whitespace on lines the user never typed on. Outdent round-trips it away, bounding the damage to the indented state. Brings the pinned known-bug count to 31. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * [diffs/edit] Drop the wiped-region graceful-undo pin We don't model programmatic edits as a class distinct from local edits, so the scenario's premise (a dead history entry after an untracked edit replaced its region) doesn't match the intended design. The remaining five history-across-untracked-edits pins stand; pinned known-bug count returns to 30. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * [diffs/edit] Reframe history-mixing pins around programmatic==local equivalence Design decision: edits applied with updateHistory=false are not a semantic class distinct from local edits — a mixed sequence must behave exactly like the same sequence applied all-tracked. The old pins asserted rebasing semantics (untracked edits surviving undo); all are flipped to equivalence assertions whose expected values mirror an all-tracked reference run: undo-to-exhaustion restores the original text, redo-to-exhaustion the final text. The wiped-region test returns under the new model, and the coalescing-across-an-untracked-edit pin flipped from passing to failing because its outcome also deviates from the all-tracked timeline. Cluster: 7 failing pins; suite total 32. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * sick --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…ion (#986) Math.min/max pass NaN straight through and fractional indexes break the integer-keyed line-offset lookup, so a NaN (or fractional) line/character resolved to a NaN offset and the degenerate edit range swallowed the entire document — an insert with one malformed component silently erased everything else. normalizePosition now sanitizes before clamping: NaN and -Infinity act as 0, fractions floor, +Infinity clamps to the max. Every position-taking API funnels through it (offsetAt, resolveEdit), so all edit paths are covered. Flips the two malformed-position pins to permanent regression tests with exact expectations; pinned known-bug count drops to 30. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* Refactor edit resolution logic to improve surrogate pair handling * fix codex
* [diffs/edit] Fix soft-wrap vertical caret motion * fix
* Rename popup to popover to be more consistent * fix codex * fix e2e testing --------- Co-authored-by: Je Xia <i@jex.me>
* fix typo * fix editStack coalescing bugs.
* fix(diffs): Keep editor active line separate from selected lines Moving the caret in edit mode reused the selected-lines state, which could replace an existing line selection and disturb its callbacks or gutter utility. Track the editor active line independently and derive one visual highlight where selected lines take precedence. Preserve both states across diff row refreshes so each retains its latest value. * fix(diffs): Preserve interactions in edit mode Entering Edit mode with line selection, gutter utilities, or hover highlighting enabled currently turns those interactions off and clears selected lines. Preserve the configured interaction options while enabling only the token transformer required by the editor. Keep editor active-line styling separate from selected-line styling, protect gutter utility gestures from editor selection handlers, and exercise the behavior across playground views. * docs(diffs): Remove obsolete editor option overrides Update editor documentation and live examples to stop disabling gutter utilities, line selection, and hover highlighting in edit mode. Keep useTokenTransformer enabled in prerendered examples because the editor still requires it, and refresh the generated homepage fixture. * fix(diffs): Keep text and line selections independent Dragging a gutter utility now updates the line range and selection lifecycle even when ordinary line selection is disabled. Ordinary gutter drags remain disabled, and callbacks retain the completed gesture range when utility code changes the current selection. Preserve editor text selections during gutter-owned gestures and render the cursor line independently from selected diff lines. Retry incomplete renders, avoid rewriting unchanged ranges, and keep both states visible across supported themes. * docs(diffs): Document gutter utility selection callbacks Clarify that gutter utility gestures emit selection lifecycle callbacks even when ordinary line selection is disabled. * fix(docs): Respect editor active lines in Agent UI Added and deleted gutter numbers kept their base colors on the editor cursor line because the Agent UI override excluded the obsolete `data-active` attribute. Exclude `data-editor-active-line` instead and update the generated demo snapshot so the editor active-line styling can apply. * Fix playground with new selection states * fix(diffs): Compose editor active lines with diff states Select a line in edit mode and move the cursor onto it: the theme current-line background can obscure the selection and addition or deletion color. Resolve decoration, diff, selection, editor active, and hover colors as ordered layers. Derive active emphasis from the resolved semantic color, retain theme borders as a fallback cue, and prevent gutter numbers from receiving the selection mix twice. * fix(diffs): Flush line state after virtualized rerenders Edit inside a collapsed diff region, then move the caret or update the line selection: virtualized views can keep showing the previous line state after rebuilding their rows. Flush deferred selected and active-line writes after virtualized managers bind to the rebuilt DOM, and cover the region-changing render path.
* [diffs/edit] improve picectable performance 50 latency in milliseconds; two warmups and nine measured samples per workload. Lower is better. | Workload | Baseline | Round 1 | Round 2 | Round 3 | Improvement | |---|---:|---:|---:|---:|---:| | Construct large document | 0.549 | 0.503 | 0.548 | 0.501 | +8.7% | | Sequential typing | 1.649 | 1.547 | 1.706 | 1.555 | +5.7% | | Scattered inserts | 3.726 | 3.481 | 3.120 | 3.406 | +8.6% | | Append after fragmentation | 1.003 | 0.995 | 0.629 | 0.784 | +21.9% | | Batch replacements | 3.302 | 3.139 | 3.042 | 3.254 | +1.5% | | Position round-trips | 11.630 | 11.497 | 10.759 | 12.414 | −6.7% | | Fragmented slices | 1.721 | 1.467 | 1.586 | 1.688 | +1.9% | | Whole-word search | 7.783 | 7.355 | 7.464 | 2.081 | +73.3% | | **Combined p50** | **31.364** | **29.983** | **28.854** | **25.683** | **+18.1%** | * another improvement * another improvement
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
* First follow up task An attempt to ensure the edited diff better matches the fully parsed diff at the end. It's not perfect, and I think it can still break in certain ways, but I think it's a bit better. Will need more testing. I am a little worried about this code, it touches a lot of things, but it does appear to fix things... It's one of those things that I don't fully understand, which scares me a little. * [diffs] Normalize zero-count hunk sides in merge conflict parser createHunkBuilder seeds each side's start as "next line to consume" (lines.length + 1), but getHunkSideStartBoundary assumes the unified N,0 convention where a zero-count side's start names the line the hunk applies after. A whole-file conflict with an empty side (no context anywhere) finalized with that start unnormalized, inventing a phantom collapsedBefore row and inflating split/unified totals by one. Normalize each zero-count side down by one in finalizeActiveHunk so emitted hunks match what parsePatchFiles produces from real git patches (headers now read +0,0/-0,0 like git). Also corrects the benchmark checksum documented in the file header, which was stale before this branch (the parser output hasn't changed: parent, HEAD, and this fix all produce 31314920). Addresses codex review feedback on #978. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * Quick sidequest to help prevent UnresolvedFile's from being editable * [diffs/edit] Fix stale highlighting after edit-session line-count edits The cached per-line addition HAST is looked up by line index, but applyDocumentChange only truncated/appended it — a mid-document insert or delete never shifted the surviving entries, so rows hidden behind collapsed context rendered another line's stale tokens once the edit session ended and they became visible (a duplicated line in the diff). - realignAdditionHastLines shifts the cached entries to their new indexes on a line-count edit (common prefix/suffix preserved, the changed window plain-filled for the editor's next tokenize pass). - refreshHighlightedResult re-highlights the final diff in the background at genuine session exit, so plain-filled and shifted lines regain color. The current result keeps rendering until the fresh one lands, so no interim paint drops highlighting (no un-highlighted flash). Called from completeEditSession and the self-heal backstop. - applyDocumentChange now throws on a partial diff instead of half-applying the line rewrite, matching updateRenderCache's guard. Adds regression tests covering the realign shift and the exit re-highlight restoring colors without an interim un-highlighted render. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * [diffs] Keep bottom-of-run anchor when a blank slide stops at a hunk edge slideBlankBoundaryBlocksUp moves a pure blank insert/delete to the top of its blank run so the change anchors to the content above it (the caret line after an Enter). When the run outruns the diff context, the slide was instead stopped by the hunk's leading edge — a context-window cut, not the run's top — parking the block at an arbitrary mid-run position that abuts a hunk separator and anchors to nothing. Make the slide all-or-nothing: skip it when it would consume the hunk's entire leading context, keeping the diff library's bottom-of-run anchor, which sits against the content below the run (and matches what plain git diff shows for the same files). Slides that come to rest beneath in-hunk content are unchanged. The rule runs inside the shared canonical parse, so mid-session and exit renderings agree by construction. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * PR feedback fix * Fix playground to not force initial re-renders * Defensive diffs fix for initialization highlighting flash * Fix commenting in playground * only use server rendered code on initial render * Actually server render the query string params * Fix css hydration bug with annotations --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Used to track editor beta versions. Will be periodically rebased on main.