Repository navigation
Description
Summary
EnrichedMarkdownTextInput completes unclosed delimiters before parsing (**bold → **bold**) with three separate copies of the same loop: InputRemend.ts (web), InputRemend.kt (Android), ENRMInputRemend.mm (iOS). They have already drifted (web never got the #798 flanking check), and they share bugs that have to be fixed three times. All three parsers already reach the C++ core, so the completion step can live there once.
Bugs in today's loop
| Input | Android / iOS (with #798 flanking) | Web (no flanking) |
|---|---|---|
**a *b*** (toolbar: bold a b, italic b) |
**a *b****** |
**a *b********* |
***a* b** |
***a* b***** |
***a* b******** |
`a*b` c (delimiter inside a code span) |
`a*b` c`*` |
same |
snake_case is fine, 2 * 3 |
ok | …fine_, 2 * 3* |
Where the display is rebuilt from the completed string (Android, web), these extra characters show up as literal text: the toolbar case re-imports as a b****** on web. iOS rebuilds the display from the original string and drops them (see #799).
Causes:
- A
***closer that does not match the*on top of the stack is pushed (or ignored) instead of closing*and then**. The output is also not idempotent: completing**rebase *interactive***again appends more asterisks. - Delimiters inside a code span are counted.
Proposal
One small function in packages/core/cpp, roughly today's algorithm plus:
- the md4c-style opener check from fix: input default values serialization #798 (
isEmphasisOpener, intraword_never opens) for*,_,~~; */_runs close by length, popping several stack entries (***closes*then**), so completion is idempotent;- a backtick run skips to the matching equal-length run; an unmatched run is still closed.
Wiring:
- Android and web: a
Md4cFlagsfield that makesMD4CParser.cppcomplete the input before parsing (no new JNI method or wasm export, no second string copy into wasm). - iOS:
ENRMInputParser.mmcalls the C++ function directly (it already compiles the core). - Delete
InputRemend.ts,InputRemend.kt,ENRMInputRemend.mm; move their tests to core ctest cases plus one parse-level test per platform.
This also removes a web import hot spot: completeMarkdown is the largest JS import cost today (3.7–4.8 ms per 63 KB); in C++ it runs inside the wasm parse call.
Related
- Align Android input display reconstruction with iOS (and drop the remend flanking heuristic) #799: rebuild the display from the original string on Android (as iOS does). Together with this issue, over-completion stops leaking on every platform; Align Android input display reconstruction with iOS (and drop the remend flanking heuristic) #799 alone would also allow dropping the flanking check.
- feat(core): C++ markdown repair module for streaming #830: core
MarkdownRepair(remend port) for streaming. It fixes the cases above but is not usable for the input as is: its link handling drops or rewrites text (TextOnlydrops a truncated link,Protocolinsertsstreamdown:incomplete-link, which would be serialized back), and with links off[**stable](https://git-scmgets its**inside the URL. An "editor" profile there could replace this function later.
Out of scope
Escaping plain text in the serializer (5 * 2, a || b round trips).
Activity