Repository navigation
Make character formatting and link removal undoable - #39
Merged
Merged
Conversation
Bold/italic/underline/strikethrough/sub/superscript/clear-formatting commands, Ctrl+B/I/U, the font family/size dropdowns and the text/highlight colour pickers called FormattingEngine/FontFormattingEngine directly, so none of them could be undone. ApplyStyleAction existed but only took a fixed transform (the toggles decide on/off from the current runs), restored the paragraph style on undo, and paired snapshots with block indices by position, restoring the wrong paragraph when a table sat inside the range. ApplyStyleAction now also wraps any formatting operation, snapshots each paragraph with its block index, restores only the inlines on undo, and merges split runs after applying. EditorContext.ApplyCharacterFormatting pushes one ApplyStyleAction for a non-empty selection (keeping the selection on the same text) and leaves a collapsed selection to the engines' pending style, which is not recorded. The commands, keyboard shortcuts and MAUI dropdowns/pickers all go through it. HyperlinkEngine.RemoveHyperlink now keeps the link's runs and their styles instead of one plain run, and RemoveHyperlinkCommand pushes a new RemoveHyperlinkAction that snapshots the paragraph so undo restores the link. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0197tHRWhTiagB1MTsDuPkoa
There was a problem hiding this comment.
🟡 Changes recommended
Snapshot restoration breaks earlier insertion undo actions and loses supported inline content.
2 open issues
What changed in this PR
Adds undo support for character formatting and hyperlink removal across editor commands, keyboard shortcuts, and MAUI controls.
Changes:
- Records selected-text formatting as one undo step while preserving selection.
- Makes hyperlink removal undoable and preserves styled text.
- Adds regression tests and updates documentation.
| File | Description |
|---|---|
| tests/MintedTextEditor.Core.Tests/CharacterFormatUndoTests.cs | Tests formatting and hyperlink undo behavior. |
| src/MintedTextEditor.Maui/MintedEditorView.cs | Routes font and colour pickers through undo. |
| src/MintedTextEditor.Core/Input/EditorInputController.cs | Records keyboard formatting actions. |
| src/MintedTextEditor.Core/Formatting/HyperlinkEngine.cs | Preserves formatting when removing links. |
| src/MintedTextEditor.Core/Editing/UndoableActions.cs | Extends formatting snapshots and adds link-removal undo. |
| src/MintedTextEditor.Core/Commands/HyperlinkCommands.cs | Makes link removal undoable. |
| src/MintedTextEditor.Core/Commands/FormattingCommands.cs | Uses undo-aware formatting. |
| src/MintedTextEditor.Core/Commands/FontCommands.cs | Adds undo-aware font and colour commands. |
| src/MintedTextEditor.Core/Commands/EditorContext.cs | Centralizes undo-aware character formatting. |
| docs/images-hyperlinks.md | Documents undoable link removal. |
| docs/formatting.md | Explains formatting undo integration. |
| docs/architecture.md | Clarifies snapshot-based restoration. |
| CHANGELOG.md | Records the undo improvements. |
Review effort: Balanced
# Conflicts: # CHANGELOG.md
…napshots SnapshotHelper rebuilt every inline from copied data on restore, so undo steps recorded earlier that hold the original objects (InsertHyperlinkAction, InsertImageAction) could no longer find them: insert a link, remove or format it, undo twice, and the link stayed. Snapshots also turned LineBreak into a "\n" text run and kept only TextRun children of hyperlinks. Adopt the identity-preserving SnapshotHelper from PR #28 (housekeeping/hyperlink-display-text) verbatim so the two PRs merge cleanly: snapshots keep each original inline (and paragraph) with its state, restore puts the same objects back, line breaks and other inline types are kept as themselves, and hyperlink children are captured recursively. The inline-only restore used by ApplyStyleAction and RemoveHyperlinkAction is now a small ApplyStyleAction.RestoreInlines wrapper outside SnapshotHelper. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0197tHRWhTiagB1MTsDuPkoa
# Conflicts: # CHANGELOG.md # docs/architecture.md # docs/formatting.md # src/MintedTextEditor.Core/Editing/UndoableActions.cs # src/MintedTextEditor.Maui/MintedEditorView.cs
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.


Summary
Character formatting (bold, italic, underline, strikethrough, sub/superscript, font family/size, text/highlight colour) and hyperlink removal can now each be undone as one step.
ApplyStyleActiongains a constructor that wraps any formatting operation. It saves each affected paragraph with its index and restores only the inline runs, so a table inside the range and later paragraph formatting are left alone. Runs it split are merged on undo.EditorContext.ApplyCharacterFormatting: with a selection, it records one undo step and keeps the same text selected. With no selection, it only sets the pending style and records nothing. All formatting commands, Ctrl+B/I/U, and the MAUI font/colour pickers go through it.HyperlinkEngine.RemoveHyperlinkkeeps the link text's styled runs. The newRemoveHyperlinkActionrestores the URL, title and formatted text on undo.formatting.md,images-hyperlinks.md,architecture.md. CHANGELOG entry under Unreleased → Fixed.Tests
31 new cases in
CharacterFormatUndoTests.cs:Results: Core 825 passed, SkiaSharp 29 passed, Release build with 0 warnings, and the MAUI compile check is clean.
Not in this PR
ApplyTextStyleskips tables. This is unchanged from before.Generated by Claude Code