Summary
#255 offers the escape gesture only where a conversion exists, and today that is one inline link and one image. Text the file escaped to keep emphasis, strong, strikethrough, inline code, a heading marker, or a list marker literal shows no escape at all, because a backslash whose deletion changes nothing is the silent gesture #245 blocked #255 on.
So for every form but a link, removing an unwanted escape still means deleting the run and retyping it, which is the problem #238 was opened to solve. This issue supplies the missing half: the conversion those runs need before the gesture can be offered on them.
Measured against 621866a8: *not emphasis* saves as \*not emphasis\* and # not a heading as \# not a heading, but findLiteralSourceCommit returns nothing at either escape, because findLinkNodeBounds matches node.type === "link" and nothing else.
Expected behavior
A caret arriving at a character the file will escape projects the escape for every supported form, not only a link. Deleting the backslash converts the run to the syntax it describes, and Undo reverses it like any other document change.
Nothing is stored to make this work. The escape stays derived from the text and the serializer's safety check, as #245 settled and #255 implements.
Related context
Done when
Notes
Implementation direction
The mechanism is a generalization of findLiteralLinkSourceCommit in src/features/editor/utils/sourceProjectionLinkAdapter.ts: parse the block's text and replace the matched run with whatever it now spells, rather than matching one mdast type. The two families behave differently enough to be worth separating before starting.
- Inline marks rehydrate as marks over text that stays in place, rather than as a replacement node. The commit has to reconcile with marks the run already carries, and
isPlainTextRange, which every literal-source commit is gated on today, rejects any marked range outright.
- Block markers —
#, -, >, and an ordered-list marker — change the block's type rather than its inline content, so they sit outside the projection engine's inline commit path entirely. They may deserve their own issue rather than a shared one.
Blocked in practice by #271: until precise escaping reaches inside a mark, a run nested in one would project an escape that does not match what the file writes, which is the failure mode this whole line of work exists to avoid.
Out of scope
Summary
#255 offers the escape gesture only where a conversion exists, and today that is one inline link and one image. Text the file escaped to keep emphasis, strong, strikethrough, inline code, a heading marker, or a list marker literal shows no escape at all, because a backslash whose deletion changes nothing is the silent gesture #245 blocked #255 on.
So for every form but a link, removing an unwanted escape still means deleting the run and retyping it, which is the problem #238 was opened to solve. This issue supplies the missing half: the conversion those runs need before the gesture can be offered on them.
Measured against
621866a8:*not emphasis*saves as\*not emphasis\*and# not a headingas\# not a heading, butfindLiteralSourceCommitreturns nothing at either escape, becausefindLinkNodeBoundsmatchesnode.type === "link"and nothing else.Expected behavior
A caret arriving at a character the file will escape projects the escape for every supported form, not only a link. Deleting the backslash converts the run to the syntax it describes, and
Undoreverses it like any other document change.Nothing is stored to make this work. The escape stays derived from the text and the serializer's safety check, as #245 settled and #255 implements.
Related context
Outcomesection of How a Markdown escape should be represented in the editor #245,docs/specification.mdInline Content,docs/architecture.mdSource ProjectionDone when
Undoreverses each conversion, and a run left alone stays literal across a save and reopen.docs/specification.mdInline Content describes the widened rule.Notes
Implementation direction
The mechanism is a generalization of
findLiteralLinkSourceCommitinsrc/features/editor/utils/sourceProjectionLinkAdapter.ts: parse the block's text and replace the matched run with whatever it now spells, rather than matching one mdast type. The two families behave differently enough to be worth separating before starting.isPlainTextRange, which every literal-source commit is gated on today, rejects any marked range outright.#,-,>, and an ordered-list marker — change the block's type rather than its inline content, so they sit outside the projection engine's inline commit path entirely. They may deserve their own issue rather than a shared one.Blocked in practice by #271: until precise escaping reaches inside a mark, a run nested in one would project an escape that does not match what the file writes, which is the failure mode this whole line of work exists to avoid.
Out of scope
src/features/editor/plugins/markerPresentation.tsas the cheaper answer if that is wanted.