Skip to content

feat(mdviewer): blockquote toggle and nest/unnest with Tab#2875

Merged
abose merged 4 commits intomainfrom
ai
Apr 30, 2026
Merged

feat(mdviewer): blockquote toggle and nest/unnest with Tab#2875
abose merged 4 commits intomainfrom
ai

Conversation

@abose
Copy link
Copy Markdown
Member

@abose abose commented Apr 30, 2026

Quote toolbar button now lifts only the cursor's paragraph out of a blockquote (splitting it so neighboring quoted lines stay quoted), instead of unwrapping the whole blockquote.

Tab/Shift+Tab inside a blockquote nest deeper / lift one level. Lists and tables are checked first so their existing Tab behavior is unchanged.

Normalize blockquotes that contain loose text (no block wrapper) by wrapping their contents in

before manipulation, and handle the case where the cursor's anchorNode is the blockquote element itself (which happens right after execCommand wraps a paragraph) by resolving to the correct child via anchorOffset. Without this, the toggle stops working after an unquote → re-quote sequence.

abose added 4 commits April 30, 2026 09:23
Quote toolbar button now lifts only the cursor's paragraph out of a
blockquote (splitting it so neighboring quoted lines stay quoted),
instead of unwrapping the whole blockquote.

Tab/Shift+Tab inside a blockquote nest deeper / lift one level. Lists
and tables are checked first so their existing Tab behavior is
unchanged.

Normalize blockquotes that contain loose text (no block wrapper) by
wrapping their contents in <p> before manipulation, and handle the case
where the cursor's anchorNode is the blockquote element itself (which
happens right after execCommand wraps a paragraph) by resolving to the
correct child via anchorOffset. Without this, the toggle stops working
after an unquote → re-quote sequence.
Selecting/clicking/editing in the md viewer caused the iframe to scroll
itself to a stale line, and undo/redo plus backspace caused visible
scroll jumps. Root cause was missing suppression on both sides of the
sync bridge:

- The iframe side: viewer-initiated events that can cause CM to scroll
  (selection sync, cursor-line sync, click-to-focus) didn't mark the
  iframe as the scroll origin, so CM's resulting scroll-handler echo
  came back through MDVIEWR_SCROLL_TO_LINE and re-scrolled the iframe.
  Centralize the flag in sendToParent for all such events, and drop the
  editMode-only requirement from the guard so design mode is covered too.

- The CM side: cm.replaceRange (in _applyDiffToEditor), cm.scrollTo (in
  _scrollCMToLine), and cm.undo()/cm.redo() can each trigger an async
  CM scroll that echoes back to the iframe. Wrap each in
  _scrollSyncFromIframe = true with a 200ms clear so CM's scroll handler
  ignores them.
@abose abose merged commit bf53d83 into main Apr 30, 2026
9 of 18 checks passed
@abose abose deleted the ai branch April 30, 2026 09:15
@sonarqubecloud
Copy link
Copy Markdown

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