mirror of
https://github.com/PerpetualSoftware/pad.git
synced 2026-10-26 06:19:49 +00:00
8d910dc20a
* fix(editor): bold, italic and strike always serialize to markdown that reads back (BUG-3583) CommonMark lets a `**` / `*` / `~~` run open only where it is left-flanking and close only where it is right-flanking. A mark whose text starts with punctuation after a letter, or ends with punctuation before a letter, has no delimiter that can do both. Measured on the headless editor with the editor's own parser: every such case lost its mark on reload. tiptap-markdown slides an unflankable delimiter inward (the punctuation silently loses the mark), and skips that for a mark at output offset 0, so a bold run starting a block went out as `**Hello.**World` and read back as literal asterisks. flankingMarks.ts replaces bold, italic and strike (and re-adds code and underline, keeping StarterKit's mark order) in the body editor, the materializer (htmlProseExtensions, so parity holds) and the comment editor: - each run is written with its delimiter and, when it closes, tested against the characters actually around it with markdown-it's scanDelims; a run that cannot flank is rewritten to <strong>/<em>/<s>, which parse back to the same mark (html: true) and render through renderMarkdown's allow-list; - tiptap-markdown's sliding is switched off for these marks only (a guarded patch on prosemirror-markdown's base markString); - a textblock whose output could still mis-pair (a run ending in punctuation before a letter, or merged same-character runs) is parsed back and compared per character; on a mismatch it is re-rendered with the HTML form. Code needs nothing (measured). Fuzz (6000 paragraphs of letters, punctuation and spaces under overlapping marks, links and hard breaks, in paragraphs, quotes and list items): marks lost 0 (old serializer 211-228 per 1500); text altered 0-1 (old 163-172, the rest a pre-existing line-start escaping gap); output changed where the old one already round-tripped: 3 per 1500, all one whitespace placement. Serialization time on 500 paragraphs: equal to main for ordinary prose; the extra parse runs only on the textblocks that can fail. Corpus: a block with the failing shapes is added to the materializer parity generator; corpus.json regenerated; Go materialize tests pass on the new bundle. New e2e: typed bold "Hello." + "World" is stored as <strong>Hello.</strong>World; on main it is stored as **Hello.**World. (A reload of an open tab does not show the defect on main: it re-seeds from the op-log. The stored body is what readers and a pruned editor see.) Claude-Session: https://claude.ai/code/session_01FAVXA5mJ5BNhKmv95jxQkQ * fix(web): backlink snippets drop inline tags; every reader of an HTML mark pinned (BUG-3583) The lead's check before GO: the fix stores runs markdown delimiters cannot express as inline HTML, so every other reader of items.content must show it as formatting or plain text, never literal tags. - Share pages and their collection views: renderMarkdown's allow-list renders <strong>/<em>/<s> (e2e). - The editor seeding from the body (after an op-log prune): bold (e2e). - Search palette snippets: already stripped tags (e2e pins it). - Backlink snippets showed the raw slice, so `<strong>` appeared literally, and the slice could cut a tag in two (`…g>Hello.`). Tags and cut fragments are now dropped. Red on main in the new e2e, green here. - Email/notification templates carry no item content; the workspace and artifact exports hand out the raw body, where inline HTML is valid CommonMark/GFM; nothing syncs bodies to GitHub (read from the code). Claude-Session: https://claude.ai/code/session_01FAVXA5mJ5BNhKmv95jxQkQ