feat(rich-text): preserve ordered list markers when unindenting out of a list - #1415
Merged
Merged
Conversation
…f a list Typing a number followed by a dot and a space (e.g. the German date `17. Juli`) converts the paragraph into an ordered list via the automatic input rule, swallowing the typed number into the list's `start` attribute. Unindenting the item with `Shift-Tab` then dropped the number entirely, making it impossible to recover the original text. `RichTextListItem` now extends the built-in `ListItem` extension so that when `Shift-Tab` lifts an item out of an ordered list (rather than unindenting it into a parent list), the rendered marker is re-inserted as literal text at the start of the lifted paragraph, preserving exactly what was on screen. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
✅ Deploy Preview for doist-typist ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
doistbot
reviewed
Jul 14, 2026
doistbot
left a comment
Member
There was a problem hiding this comment.
This PR adds a RichTextListItem extension that preserves ordered-list markers as literal text when Shift-Tab lifts an item out of a list — a nice fix for the date-at-start-of-line problem.
I also included a few optional follow-up notes in the details below.
Optional follow-up notes (3)
src/extensions/rich-text/rich-text-list-item.ts:63: The
editor.can().liftListItem(itemTypeName)guard at this line dry-runs the lift command's transaction logic to check feasibility, theneditor.chain().liftListItem(itemTypeName)at line 75 runs the same logic again to actually apply it. The chain already handles failure — ifliftListItemreturns false, the chain returns false and the fallbackthis.editor.commands.liftListItem(this.name)on line 99 fires correctly. The guard adds no safety benefit (the lift happens before marker insertion, so there's no risk of partial execution) and doubles the lift computation on every Shift-Tab that reaches this path. Remove lines 63–65.src/extensions/rich-text/rich-text-list-item.test.ts:83: The describe block name says "when
Shift-Tabdoes not lift the item out of a list," but the bullet-list test inside it (line 84) does lift the item out — it goes from<ul><li>to plain<p>. The describe name is only accurate for the nested ordered list test. Consider renaming to something likewhen marker preservation is not applicableorwhenShift-Tabfalls back to the default behavior.src/extensions/rich-text/rich-text-list-item.test.ts:47: The non-empty selection guard in
liftOutOfOrderedListPreservingMarker(line 27 ofrich-text-list-item.ts) is a deliberate safety behavior — it prevents ambiguous marker insertion when lifting a multi-item range — but no test covers it. Every test usescreateEditorWithCaretAfter, which always creates a collapsed selection. A test that selects across two ordered-list items (e.g. viaeditor.commands.setTextSelection(from, to)) and asserts that Shift-Tab lifts without inserting a stray marker would protect against someone removing the guard. The existing harness makes this straightforward to add.
rfgamaral
reviewed
Jul 27, 2026
rfgamaral
reviewed
Jul 27, 2026
rfgamaral
reviewed
Jul 27, 2026
rfgamaral
left a comment
Member
There was a problem hiding this comment.
@henningmu Looks good to me, left a few comments that I think are worth addressing, but non-blocking.
Contributor
Author
|
Addressed both comments. Thanks, Ricardo 🙌 |
rfgamaral
approved these changes
Jul 29, 2026
doist-release-bot Bot
pushed a commit
that referenced
this pull request
Jul 29, 2026
## [16.2.0](v16.1.0...v16.2.0) (2026-07-29) ### Features * **rich-text:** preserve ordered list markers when unindenting out of a list ([#1415](#1415)) ([4408c72](4408c72))
|
🎉 This PR is included in version 16.2.0 🎉 The release is available on: Your semantic-release bot 📦🚀 |
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.
Overview
Typing a number followed by a dot and a space at the start of a paragraph (e.g. the German date
17. Juli) triggers the ordered-list input rule, which swallows the typed number into the list'sstartattribute.Shift-Tabto undo the list conversion, removed the number entirely (17. Juli→Juli), with no way to recover it. This made it effectively impossible to start a line with such a date.This PR adds a
RichTextListItemextension (mirroring theRichTextOrderedList/RichTextBulletListpattern) that replaces the stockListIteminRichTextKit. It only customizesShift-Tab: when the lift takes the item out of an ordered list (as opposed to unindenting it into a parent list), the rendered marker is re-inserted as literal text at the start of the lifted paragraph — soShift-Tabnever destroys visible content.17. Juli+Shift-Tab→Juli17. Juli+Shift-Tab→17. JuliImplementation notes:
Bullet lists are intentionally left untouched: the number is user-meaningful data, a bullet is not.
Related: Doist/Issues#20622
PR Checklist
Test plan
Rich-text → Defaultstory17. Juliat the start of an empty line (converts to an ordered list starting at 17)Shift-Tab17. Julias plain textTab/Shift-Tabinside nested and bullet lists