Skip to content

fix(composer): make toolbar formatting undoable with Ctrl+Z - #178

Open
palmoni5 wants to merge 1 commit into
NodeBB:masterfrom
palmoni5:fix/formatting-undo
Open

fix(composer): make toolbar formatting undoable with Ctrl+Z#178
palmoni5 wants to merge 1 commit into
NodeBB:masterfrom
palmoni5:fix/formatting-undo

Conversation

@palmoni5

@palmoni5 palmoni5 commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Problem

None of the composer toolbar actions (bold, italic, code, link, list, …) can be undone with Ctrl/Cmd+Z. The three text-insertion helpers in static/lib/composer/controls.js replace the entire textarea value via $textarea.val(...), which is not recorded in the browser's undo stack. In Chromium-based browsers it also discards the undo history of everything typed before the click, so the user has to remove the inserted markup by hand.

Fix

Add a small replaceRange(textarea, start, end, text) helper and route insertIntoTextarea, replaceSelectionInTextareaWith and wrapSelectionInTextareaWith through it. It selects the target range and uses document.execCommand('insertText'), which browsers treat as a regular user edit and push onto the undo stack. If the command is unavailable or reports failure it falls back to setRangeText, and finally to a plain value assignment, so behaviour is unchanged where native insertion is not supported.

The action:composer.* hooks and the return value of wrapSelectionInTextareaWith are untouched, so callers in core and nodebb-plugin-markdown need no changes.

Testing

Verified the new helper in isolation in Chromium: wrap a selection in backticks, then insert ** at the start, then undo twice — the textarea returns to its exact original value at each step (hello worldhello `world`**hello `world` → back to hello `world` → back to hello world). ESLint passes.

The formatting helpers (insertIntoTextarea, replaceSelectionInTextareaWith,
wrapSelectionInTextareaWith) replaced the whole textarea value via
$textarea.val(), which bypasses the browser's undo stack. Clicking a toolbar
button (bold, code, link...) could therefore not be reverted with Ctrl/Cmd+Z,
and in some browsers also wiped the undo history of the text typed before it.

Route all three through a shared replaceRange() helper that uses
document.execCommand('insertText') so the change is recorded as a regular
edit, with setRangeText / direct value assignment as fallbacks.
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