Skip to content

[Repo Assist] fix: Markdown.ToMd preserves DirectLink and DirectImage titles#1150

Open
github-actions[bot] wants to merge 2 commits intomainfrom
repo-assist/fix-tomd-link-title-2026-04-07-256d700bda470a34
Open

[Repo Assist] fix: Markdown.ToMd preserves DirectLink and DirectImage titles#1150
github-actions[bot] wants to merge 2 commits intomainfrom
repo-assist/fix-tomd-link-title-2026-04-07-256d700bda470a34

Conversation

@github-actions
Copy link
Copy Markdown
Contributor

@github-actions github-actions bot commented Apr 7, 2026

🤖 This is an automated PR from Repo Assist.

Root Cause

Markdown.ToMd serialised DirectLink and DirectImage spans by grouping them in an F# OR-pattern that used a wildcard for the title field:

// Before
| IndirectLink(body, _, LookupKey ctx.Links (link, _), _)
| DirectLink(body, link, _, _)          // ← title discarded
| IndirectLink(body, link, _, _) -> "[" + formatSpans ctx body + "](" + link + ")"

| DirectImage(body, link, _, _) -> sprintf "![%s](%s)" body link   // ← title discarded

A Markdown fragment such as [text](url "My Title") would round-trip as [text](url), silently losing the title attribute.

Fix

Give DirectLink and DirectImage their own match branches so the optional title can be emitted in CommonMark form ("title"):

// After
| DirectLink(body, link, title, _) ->
    let t = title |> Option.map (fun t -> sprintf " \"%s\"" (t.Replace("\"", "\\\""))) |> Option.defaultValue ""
    "[" + formatSpans ctx body + "](" + link + t + ")"

| DirectImage(body, link, title, _) ->
    let t = title |> Option.map (fun t -> sprintf " \"%s\"" (t.Replace("\"", "\\\""))) |> Option.defaultValue ""
    sprintf "![%s](%s)" body (link + t)

The title value is escaped to handle embedded double-quote characters per CommonMark spec.

Changes

File Change
src/FSharp.Formatting.Markdown/MarkdownUtils.fs Separate DirectLink/DirectImage from OR-pattern; emit title when present
tests/FSharp.Markdown.Tests/Markdown.fs Three new round-trip tests: link-with-title, link-without-title (regression), image-with-title
RELEASE_NOTES.md Changelog entry under [Unreleased] / Fixed

Test Status

  • dotnet build FSharp.Formatting.sln --configuration Release — 0 warnings, 0 errors
  • dotnet test tests/FSharp.Markdown.Tests --configuration Release --no-build284/284 passed (includes 3 new tests)
  • dotnet fantomas … --check — formatting verified

Generated by Repo Assist ·

To install this agentic workflow, run

gh aw add githubnext/agentics/workflows/repo-assist.md

Generated by 🌈 Repo Assist, see workflow run. Learn more.

To install this agentic workflow, run

gh aw add githubnext/agentics/workflows/repo-assist.md@e1ecf341a90b7bc2021e77c58685d7e269e20b99

When serialising a document with ToMd, link and image titles were
silently dropped.  A Markdown fragment such as

    [text](url "My Title")

would round-trip as

    [text](url)

because the `DirectLink` / `DirectImage` formatSpan cases matched the
title field with a wildcard.

Fix: give DirectLink and DirectImage their own branches so the optional
title can be appended in CommonMark form (  \"title\").

Three new round-trip tests cover:
  - DirectLink with title
  - DirectLink without title (unchanged behaviour)
  - DirectImage with title

All 284 Markdown tests pass.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@dsyme dsyme marked this pull request as ready for review April 7, 2026 17:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants