Skip to content

fix(editor): block cross-boundary edits before they reach the server - #676

Open
weprintmoney wants to merge 1 commit into
derive-to:mainfrom
weprintmoney:fix/bug7-editor-boundary-precheck
Open

fix(editor): block cross-boundary edits before they reach the server#676
weprintmoney wants to merge 1 commit into
derive-to:mainfrom
weprintmoney:fix/bug7-editor-boundary-precheck

Conversation

@weprintmoney

@weprintmoney weprintmoney commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

What a user experiences today

Open an artifact in the visual editor, select text that crosses a paragraph or
inline-element boundary (a heading into the next paragraph, a word that spans an
<em> chip), and the editor accepts the selection — it even shows "1 unsaved
change." But when you save, the server refuses: "the selection crosses formatting
or element boundaries in the source — edit a smaller run of plain text, or open
the source editor."

For a non-technical reviewer who can't see markup, this message has no actionable
interpretation. And "Edit 1 of 2 failed" leaves it unclear whether the other edit
applied.

Value

  • No more false progress: the selection is blocked at arm time with plain
    language ("that selection crosses an element boundary — try selecting within a
    single paragraph"), not after the user has finished composing their change.
  • Correct partial-edit reporting: because the server never sees the bad edit,
    it can no longer report ambiguous "Edit N of M failed" mixed outcomes for that
    slot.
  • Zero behavior change for valid edits: the check is purely additive — edits
    that stay within a single block continue to work exactly as before.

Technical root cause and fix

The anchor client's setEditMode entered edit mode on any selection, including
ones that span multiple editContainerFor blocks. The server's boundary check
only fires at save time.

Fix: in setEditMode's fromSelection branch
(packages/core/src/anchor-client.ts), detect when the selection's start and end
nodes belong to different edit containers. When they do:

  1. Exit edit mode immediately (setEditMode(false)).
  2. Post an edit-blocked event with reason: "cross-boundary".

use-inline-edit.ts already listens for edit-blocked and surfaces a toast from
BLOCKED_COPY. Added a "cross-boundary" entry to that map with a human-readable
explanation, and exported the map so it can be unit-tested.

The anchor client is a compiled bundle; node scripts/build-anchor-client.mjs was
run after the source change and node scripts/check-anchor-client.mjs confirmed
the bundle is in sync.

Test plan

  • Open a markdown artifact → visual editor → select text spanning two
    paragraphs → confirm toast fires immediately (no "1 unsaved change" flash).
  • Same test with a selection inside a single paragraph → confirm edit proceeds
    normally.
  • pnpm test in apps/webuse-inline-edit.test.ts asserts
    BLOCKED_COPY["cross-boundary"] is defined and contains "boundary".
  • node scripts/check-anchor-client.mjs exits 0.

View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

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.

1 participant