Repository navigation
Description
Bug
In the id web editor's markdown ↔ ProseMirror codec (pkgs/id/src/web/markdown.rs), a table cell that contains more than one paragraph is fused into a single run of text on save — the paragraphs are concatenated with no separator at all, so words merge:
ProseMirror document (editor/collab-originated; a user pressing Enter inside a cell produces exactly this shape):
{"type":"table_cell","content":[
{"type":"paragraph","content":[{"type":"text","text":"first"}]},
{"type":"paragraph","content":[{"type":"text","text":"second"}]}
]}Saved markdown cell: | firstsecond | — "first" and "second" have become one word. Reparsing that output yields the single text node firstsecond; the paragraph boundary is unrecoverable.
Root cause (verified in code)
json_to_ast's table-cell special case (markdown.rs, the table_header/table_cell branch after the main match, ~:1080-1098 on main 3b9d159) unwraps each paragraph in the cell and appends its inline children directly to the cell node, in sequence, with nothing inserted between paragraphs. The markdown parse direction never produces multi-paragraph cells (GFM table cells are inline-only), so this only fires for editor-authored or collab-merged documents — which is precisely the population the unwrap special case exists to serve (its own comment: "ProseMirror wraps cell content in paragraphs, so we unwrap them here").
Verified repro (this run, main 3b9d159)
Standalone verbatim-codec probe (evidence log: goal hidden_files/probe-2026-10-26-1415/out4.log, case cell-two-paras):
- Input PM: header
h, one data cell with paragraphsfirstandsecond(JSON in the log). prosemirror_to_markdown→"| h |\n| --- |\n| firstsecond |\n".- Reparse → cell text is the single node
firstsecond;SAMEPM: false.
Why it matters
Silent content corruption (word fusion) on save for anyone who puts a line break / second paragraph in a table cell in the editor — the same codec data-loss family as #996/#997, in the save direction's cell handling rather than the parse direction.
Suggested fix
In the cell unwrap loop, insert a separator between consecutive paragraphs — a single space is the least-surprise choice for a GFM cell (a literal newline cannot appear in a table row, and <br> would change rendering semantics); alternatively join with a space text node via append_inline_child so mark handling stays consistent. Whichever separator is chosen, pin it with a test so the behaviour is deliberate rather than accidental.
Acceptance criteria
- A table cell with two paragraphs saves with a separator between them (no word fusion) and reparses to text containing both words as separate words.
- Single-paragraph cells (the common case, and everything the markdown parse direction produces) save byte-identically to today.
- A cell with three paragraphs, and a header cell with two paragraphs, behave the same way.
- Existing
web::markdowntable tests pass.
Activity
developing-today commentedon Oct 26, 2026
CODE-174
dezren39 commentedon Oct 26, 2026
🤖 Agent note · filed
hidden_files/probe-2026-10-26-1415/out4.log, casecell-two-paras): an editor-originated table cell with two paragraphs saves asfirstsecond—json_to_ast's cell unwrap loop inserts no separator between paragraphs. Enqueued as a triage packet to repo-health-code-pilot.dezren39 commentedon Oct 31, 2026
🤖 Agent note · picked up
dezren39 commentedon Oct 31, 2026
🤖 Agent note · done