Markdown preview: repo-relative links open the target file
Plan — make a repo-relative Markdown link open the linked file in the Code tab (mirroring how relative images already resolve) instead of booting a bogus app SPA in a new browser tab.
Plan of record · branch md-preview-rellink · issue #1161 · shipped in
#1190
What a user sees
In the Code tab’s rendered Markdown preview, a repo-relative link — say
[the limitations doc](packages/solid-markdown/LIMITATIONS.md) — should open
that file in the Code tab, the way it does on GitHub. Today it opens a new
browser tab at the app origin (http://localhost:5173/packages/…/LIMITATIONS.md),
which just boots a fresh kolu SPA at a route that means nothing. The linked file
never opens.
Relative images already do the right thing — a README’s 
renders the real image through the per-terminal file route. Relative links
have no equivalent. This plan gives them one.
Shape of the fix — wire links the way images are wired
The change reuses an existing seam rather than inventing one. Relative images are
resolved by a host callback that the preview component already accepts; links get
a parallel callback, and clicks route through the same front door every other
“open this file in the Code tab” producer uses (terminal path:line links, the
right-click Open path menu).
Three layers move, each a thin pass-through — the shape mirrors the image path exactly:
| Layer | Today (images) | Added (links) |
|---|---|---|
@kolu/solid-markdown | accepts resolveImageSrc; rewrites <img> src | tags scheme-less anchors, intercepts their click, calls a new optional onNavigateRelative(path) host callback |
@kolu/solid-fileview renderer | threads resolveImageSrc | threads the new link callback |
right-panel/BrowseFileDispatcher | resolves image src vs the doc’s dir | resolves the href vs the doc’s dir, then calls openInCodeTab |
Why route through the existing front door
openInCodeTab is the single producer-side entry point for “show this file in the
Code tab.” Reusing it means relative links inherit, for free, the behaviour the
team already debugged for terminal links:
- A href that resolves to any repo file opens it — not just other Markdown.
- A href that resolves to nothing in the repo surfaces a toast (the front door’s existing miss path), which is strictly better than a bogus new tab.
- Desktop uncollapse / mobile drawer / re-click-after-collapse all already work.
The alternative — teaching the preview to navigate on its own — would duplicate that front-door logic and re-open bugs (#1161’s sibling: the production effect-ordering elision the front door was built to sidestep). Rejected.
Trade-offs & scope
- Fragments on a relative path (
LIMITATIONS.md#known-issues) — the path opens; scrolling to the heading inside the freshly-opened doc is out of scope for this fix (a future follow-up, tracked as a known limitation). - No host callback wired (compact/inline Markdown slots, or a future embedder that doesn’t pass it) — the scheme-less anchor simply doesn’t navigate rather than opening a bogus tab. Document-variant preview always wires it.
LIMITATIONS.md— the package’s known-limitation note that documents today’s broken behaviour is removed (or its entry retired) once this lands, since the limitation no longer holds.
Test gap to close
This is a bug fix, so the reproducing test comes first (red → green):
- New scenario — render a doc with a repo-relative link, click it, assert the target file opens in the Code tab’s browse view and that the app origin was never navigated. This is the failing test that captures #1161.
- Correct the existing scenario — a scheme-less anchor is no longer expected
to carry
target=_blank; it’s expected to be tagged for interception. The unsafe-scheme (javascript:) and genuine-external assertions stay. - Unit — the factored-out Markdown-relative-path resolver gets table tests
shared in spirit with the image resolver’s cases (doc-dir relative,
root-absolute,
..-escape rejected, percent-decode).