You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
id(web): prosemirror_to_markdown keeps only the first text node of a code_block — multi-node blocks are truncated on save #882
A code block whose ProseMirror content is split into more than one text node — which editors produce legitimately, e.g. after collaborative merges, paste operations, or syntax-token boundaries in the client — silently loses every node after the first on save.
fn b() {} is deleted with no error. (The single-node form the codec's own parser produces works, which is why the existing tests — e.g. test_pm_to_md_table-era code-block tests — never caught this: the loss only appears once a real editor or a collab peer splits the text.)
Why it matters
This is the save path for the id web editor, and id is a collaborative system: a code block edited by multiple peers is exactly the content most likely to arrive as several text nodes. Saving silently truncates the block to its first node — data loss in the same codec family as #872/#873/#879/#880/#881, but a distinct arm (code_block in json_to_ast).
Suggested fix
Concatenate the text of all children of the code block (skipping/handling non-text children the same way the first-child code does today — i.e. treat a missing text as empty rather than aborting), e.g.:
let content = json["content"].as_array().map_or(String::new(), |arr| {
arr.iter().filter_map(|n| n["text"].as_str()).collect()});
and keep the existing format!("{content}\n") literal construction.
Acceptance criteria
Regression test: a code_block with two or more text children round-trips with all text present, in order.
Single-node and empty code blocks behave exactly as before.
Existing web::markdown tests still pass (cargo test --features web --lib web::markdown::).
Verification note from the filer (new-issue-creator): this issue was re-verified in a corrected probe run on main 45c817e and genuinely reproduces.
Context: the original run's interim probe deliveries in this environment proved unreliable (a sibling issue filed the same run, #879, did not reproduce on re-check and has been closed as invalid). So all four filings from that run were re-run properly — crate compiled with a stub web/dist/manifest.json in place (the clone otherwise fails to compile the rust-embed Assets derive), probe log preserved by the filer.
For this issue the re-run shows exactly the reported behaviour: a code_block with text nodes "fn a() {}\n" and "fn b() {}" emits only fn a() {} (plus the usual trailing blank line before the closing fence). The second node is dropped, as filed.
Activity
dezren39 commentedon Oct 25, 2026
Verification note from the filer (new-issue-creator): this issue was re-verified in a corrected probe run on main 45c817e and genuinely reproduces.
Context: the original run's interim probe deliveries in this environment proved unreliable (a sibling issue filed the same run, #879, did not reproduce on re-check and has been closed as invalid). So all four filings from that run were re-run properly — crate compiled with a stub
web/dist/manifest.jsonin place (the clone otherwise fails to compile the rust-embedAssetsderive), probe log preserved by the filer.For this issue the re-run shows exactly the reported behaviour: a
code_blockwith text nodes"fn a() {}\n"and"fn b() {}"emits onlyfn a() {}(plus the usual trailing blank line before the closing fence). The second node is dropped, as filed.fix(id-web): codec round-trip — linked images, table alignment, multi…