Repository navigation
Description
Summary
In pkgs/id's web markdown codec, a mark that wraps an image (emphasis, strong, strikethrough) is silently lost. When the mark wraps only an image, it disappears entirely; when it wraps text plus an image, the saved markdown splits the mark around the image and leaks literal   HTML entities into the file.
Evidence (verified this run on main 37418e56)
Probe: verbatim copy of pkgs/id/src/web/markdown.rs in a standalone crate (comrak 0.56.0), hidden_files/probe-2026-10-27-creator-a4/out4.log:
| Input | Saved output |
|---|---|
** |
 — emphasis gone |
**** |
 — strong gone |
~~~~ |
 — strikethrough gone |
*[](https://e.com)* |
[](https://e.com) — link survives, emphasis gone |
*text  tail* |
*text ** tail* — one emphasis span becomes two, with literal   entities in the saved file, and the image is no longer inside either span's text (re-parse gives the same split PM, so it is stable corruption, not a fixpoint error) |
**text  tail** |
**text **** tail** — same for strong |
- ** item |
-  item — same loss inside list items |
Control: *text only* round-trips exactly. The parsed ProseMirror for ** is a bare image node with no marks at all ({"type":"image","attrs":{"alt":"alt","src":"/x.png"}}).
Root cause
- Parse direction: the
NodeValue::Imagearm inconvert_node(pkgs/id/src/web/markdown.rs:354-393) receives the surrounding marks inactive_marksbut only carries thelinkmark forward, copying it into the image node'slinkHref/linkTitleattrs (the id(web): linked images [](href) lose their link in the markdown ↔ ProseMirror codec — save strips the href #880 precedent).em/strong/strikethroughmarks inactive_marksare ignored, and the emitted image node has no representation for them. - Save direction: the
"image"arm ofjson_to_ast(pkgs/id/src/web/markdown.rs:1308-1360) and the post-processing wrap (:1503-1519) only know how to re-wrap an image in aLinknode fromlinkHref; there is no equivalent for emphasis/strong/strikethrough, and the marked text runs on either side of the image are emitted as separate mark-wrapper nodes, whose boundary spaces comrak escapes as .
Why it matters
Italic/bold captions and callouts that include an inline image are ordinary markdown (common in notes imported from other tools, which id syncs as plain files). Today such a document loses its formatting on the first open→save, and the mixed text+image case additionally writes   entities into the user's file — visible garbage in any other editor. The loss is silent: no error, and the result is a stable fixpoint, so nothing downstream notices.
Acceptance criteria
-
**,****,~~~~and the linked-image form*[](href)*round-trip with the mark preserved (exact markdown or an equivalent form that re-parses to the same marked structure, with no mark loss). -
*text  tail*(and the strong/strikethrough equivalents) save as a single emphasis span containing the image, with no or other HTML entities introduced into the saved markdown. - The representation chosen is coherent with the existing id(web): linked images [](href) lose their link in the markdown ↔ ProseMirror codec — save strips the href #880
linkHref/linkTitlepattern for wrapping an image, and the editor either renders it or the limitation is explicitly documented in the issue's resolution. - Regression tests in
pkgs/id/src/web/markdown.rscover image-only and mixed text+image mark spans in both directions; existingweb::markdowntests still pass.
Related: #880 (linked images carried via attrs — the pattern to extend), #1045 (unknown marks dropped on save — a different, text-node policy question), #968 (mark re-nesting for text runs).
Activity
developing-today commentedon Oct 27, 2026
CODE-498
dezren39 commentedon Oct 27, 2026
🤖 Agent note · state: filed
dezren39 commentedon Oct 27, 2026
🤖 Agent note · picked up
25 remaining items
dezren39 commentedon Oct 28, 2026
Queue task 1477 parked on CI again (Lane B): PR #1630 stands at 31 SUCCESS / 0 FAILURE with only the aggregate 'nix flake check' job still QUEUED (runner stall #1599). Resume = merge PR #1630 when the aggregate flips green, then complete fixed_merged.
dezren39 commentedon Oct 28, 2026
🤖 Agent note · picked up
fix(id): carry emphasis/strong/strikethrough marks wrapping images th…
dezren39 commentedon Oct 28, 2026
🤖 Agent note · done