feat(files): smarter bullet delete/indent and untitled-file title sync - #5971
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
PR SummaryMedium Risk Overview Serialize/load fixes stop a Setext corruption bug by stripping only hazardous nested empty list markers in Untitled files ( Reviewed by Cursor Bugbot for commit eae98df. Configure here. |
Greptile SummaryThis PR improves markdown-file editing behavior.
Confidence Score: 4/5The PR appears safe to merge, with the previously documented bounded concurrent auto-rename behavior still present. Two collaborators editing the leading heading during the same untitled window can still submit ordinary rename requests from stale local metadata, allowing the later request to determine the filename; no additional eligible failure was identified. Files Needing Attention: apps/sim/app/workspace/[workspaceId]/files/files.tsx; apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/rich-markdown-editor/rich-markdown-editor.tsx
|
| Filename | Overview |
|---|---|
| apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/rich-markdown-editor/keymap.ts | Adds context-aware list-item clearing and outdenting behavior for Backspace and Enter. |
| apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/rich-markdown-editor/markdown-fidelity.ts | Filters nested empty list-item marker lines during markdown post-processing to preserve round-trip structure. |
| apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/rich-markdown-editor/markdown-parse.ts | Refines markdown parsing and empty-block reconstruction behavior. |
| apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/rich-markdown-editor/rich-markdown-editor.tsx | Debounces leading-heading extraction for locally edited untitled markdown documents. |
| apps/sim/app/workspace/[workspaceId]/files/files.tsx | Wires heading-derived title callbacks into file rename handling and centralizes untitled-name generation. |
| apps/sim/app/workspace/[workspaceId]/files/untitled-title.ts | Adds helpers for recognizing untitled names and deriving unique markdown filenames. |
Reviews (11): Last reviewed commit: "docs(files): correct EMPTY_PARAGRAPH_SPA..." | Re-trigger Greptile
8a904f1 to
c2357d6
Compare
…llet heading corruption Backspace at the start of a list item now outdents a nested item or clears a top-level item to a paragraph in place instead of deleting the row and jumping the caret to the previous block; Enter on an empty nested item outdents. Empty non-trailing top-level items still collapse cleanly since they cannot round-trip as a lifted paragraph. Also strips nested empty list-item marker lines on serialize: a nested empty bullet re-parsed as a Setext heading underline, silently turning its parent line into an H2 and dropping the bullet. Top-level empty items are preserved.
While a file is still named untitled(.md), typing a leading heading auto-renames the file after it (debounced), and renaming the file first seeds a leading H1 from the new name. One-shot: coupling stops once the file has a real name, and the heading seed always prepends so existing content is never clobbered.
c2357d6 to
b5b30f6
Compare
…ck items on Backspace Addresses review findings on the list Backspace logic: - Emptiness now uses the caret block's content.size (counts inline images/mentions), not textContent, so a bullet holding only a non-text atom is no longer treated as empty and deleted. - An empty first block whose item has sibling blocks removes only that block instead of lifting the whole item out of the list.
|
@cursor review |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 2d39f67. Configure here.
…me during editor load The parent captures the file name at mount (before content/session finish loading) and passes it as the transition baseline, so a rename that lands in the loading window is still seen as an untitled to named transition and the leading heading seed is not skipped.
|
@cursor review |
Removes the effect that inserted a leading H1 when an untitled file was renamed. On the collaborative Files page every open client observed the untitled-to-named transition and inserted into the shared doc, producing duplicate headings; it could also re-insert a heading a user had just deleted while a rename was in flight. Seeding document content from an async rename transition is the wrong model on a shared editor. The primary direction — typing a leading heading renames a still-untitled file — is unaffected (it never mutates the doc).
|
@cursor review |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit f9b2f9b. Configure here.
|
@cursor review |
…Enter/Backspace symmetry - markdown-parse: EMPTY_PARAGRAPH_SPACING/NON_CHUNKABLE tested the raw body, but a classic \r-only file (blank lines are \r) would miss the \n-anchored guard and still be chunked, dropping empties. Normalize line endings once up front so the routing guards, the chunker, and the parser all see the same \n. +CRLF/CR test cases. - keymap: Enter on an empty first block of a multi-block item now removes only that block (removeEmptyWrappedBlock) instead of exiting the list, mirroring the Backspace hasSiblingBlocks case — the trailing check no longer swallows multi-block items. +test.
|
@cursor review |
… rename, over-strip) A 4-agent independent audit (UX vs inkeep + SOTA, cleanliness, adversarial correctness) surfaced these: - HIGH regression: files ending in a blank line opened READ-ONLY. The empty-paragraph routing preserved a TRAILING empty paragraph, but postProcess collapses trailing newlines → serialize/parse non-idempotent → isRoundTripSafe flipped the file read-only. A trailing empty paragraph can't be serialized stably, so parseMarkdownToDoc now strips trailing empty paragraphs and the guard no longer routes on trailing blanks. Interior/leading empties are unaffected. +regression tests. - Medium: the debounced untitled→filename rename fired on remote Yjs edits too, so every peer renamed and could rename from a not-yet-synced heading. Gate on isChangeOrigin (local edits only; false for non-collab surfaces). - Medium: stripEmptyListItemLines over-stripped a nested empty item that follows a same-indent sibling (a real placeholder the parser keeps). Narrowed to the actual Setext hazard — an empty item DIRECTLY under a shallower parent line — matching the function's own docstring intent. Probe-verified. +test. - Low: corrected untitled-title.ts docstring that described a reverse name→heading coupling removed during review.
|
@cursor review |
The isChangeOrigin gate cleared the debounce timer BEFORE bailing on a remote update, so a peer's edit arriving within the 600ms window cancelled the local user's pending rename. Bail on isChangeOrigin first, before touching the timer; only local edits clear/reschedule it.
|
@cursor review |
|
@cursor review |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 29176a9. Configure here.
…-strip The stacked trailing-empty-paragraph strip made the older comment overstate a correctness necessity it no longer owns, mislabel trailing runs of 2+ blanks, and advertise dead CRLF handling. Reword to match what the code actually does.
|
@cursor review |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit eae98df. Configure here.
Summary
Two files-module improvements to the markdown editor. Based on
realtime-rooms(notstaging) so it integrates directly with the live co-editing work and lands together with it — the only overlap was additive prop wiring infiles.tsx/file-viewer.tsx/rich-markdown-editor.tsx, resolved here so that branch inherits these fixes conflict-free.Bullet delete/indent + round-trip fix (
improvement)-) serialized directly under a parent's text and re-parsed as a Setext heading underline, silently turning the parent line into an H2 and dropping the bullet. Serialize now strips nested empty list-item lines only; top-level empty items (placeholders, imported blanks) are preserved and round-trip faithfully.Untitled file → filename sync (
feat)untitled(.md), typing a leading heading auto-renames the file after it (debounced 600ms). One-shot: coupling stops once the file has a real name.Test Coverage
Round-trip-verified unit tests for every list Backspace/Enter branch and every
stripEmptyListItemLinesrule, plus the untitled→filename derivation helpers. New/updated:keymap.test.ts,markdown-fidelity.test.ts,untitled-title.test.ts,title-heading.test.ts. Full files-feature + editor-consumer suite: 652 tests pass on the rebasedrealtime-roomsbase. Typecheck + Biome clean.Review
Greptile 5/5. Cursor Bugbot findings across rounds — all resolved:
isEmptycounted only text, so a bullet holding an inline atom could be deleted → now uses the caret block'scontent.size.Test plan
realtime-roomsbase