Skip to content

[Repo Assist] fix: Markdown.ToMd preserves unresolved IndirectLink in reference notation#1153

Draft
github-actions[bot] wants to merge 2 commits intomainfrom
repo-assist/fix-indirect-link-tomd-2026-04-08-5585c8dbf5e94cc8
Draft

[Repo Assist] fix: Markdown.ToMd preserves unresolved IndirectLink in reference notation#1153
github-actions[bot] wants to merge 2 commits intomainfrom
repo-assist/fix-indirect-link-tomd-2026-04-08-5585c8dbf5e94cc8

Conversation

@github-actions
Copy link
Copy Markdown
Contributor

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

🤖 This PR was created by Repo Assist, an automated AI assistant.

Summary

Fixes a bug in Markdown.ToMd where a reference-style link whose definition is absent from the document would serialise as invalid Markdown.

Before (broken): [link text]([unknown-key]) — the raw [key] string used as a URL
After (correct): [link text][unknown-key] — proper reference-link notation

Root Cause

In MarkdownUtils.formatSpan, the IndirectLink cases were written as a three-way OR pattern:

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

In the fallthrough arm (IndirectLink(body, link, _, _)), link binds to position 2 of IndirectLink — the original field — which contains the raw key text including brackets (e.g. "[unknown-key]"). Using that as the URL produced [text]([unknown-key]), which is broken Markdown.

Fix

Split the fallthrough into its own arm and use the correct key field (position 3 — the clean key string):

| IndirectLink(body, _, LookupKey ctx.Links (link, _), _)
| DirectLink(body, link, _, _) -> "[" + formatSpans ctx body + "](" + link + ")"
// Unresolved reference link: emit [text][key] to preserve the reference notation
| IndirectLink(body, _, key, _) -> "[" + formatSpans ctx body + "][" + key + "]"

The corresponding IndirectImage fallthrough was already correct (it used key from position 3), so no change was needed there.

Tests Added

  • ToMd preserves unresolved indirect link in reference notation — verifies the broken [text]([ form no longer appears
  • ToMd resolves indirect link when reference is present — verifies the resolved case still emits a direct link form

Test Status

✅ Build: 0 warnings, 0 errors
FSharp.Markdown.Tests: 283/283 passed (including 2 new tests)

Trade-offs

None. This is a pure correctness fix. The resolved-link behaviour (when a [key]: url definition is present) is unchanged.

Note: this change touches the same region as #1150 (DirectLink title fix); when both are eventually merged, the merge will be trivial to resolve.

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

…ation

When a document contains a reference-style link whose key is not defined
in the link dictionary (e.g. '[text][key]' with no '[key]: url' definition),
the previous code emitted '[text]([key])' — treating the raw '[key]' string
(including brackets) as the URL, producing broken Markdown.

Root cause: the three-way OR pattern
  IndirectLink(resolved) | DirectLink | IndirectLink(fallthrough)
bound 'link' to the 'original' field (position 2) of IndirectLink for the
fallthrough arm. 'original' is the raw key text with surrounding brackets
(e.g. '[unknown-key]'), not a URL.

Fix: split the fallthrough into a dedicated pattern arm that uses the
'key' field (position 3 — the clean key string without brackets) and emits
the correct '[text][key]' reference notation.

Added 2 tests:
- unresolved indirect link emits [text][key]
- resolved indirect link (reference present) resolves to direct form

All 283 Markdown tests pass.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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.

0 participants