Skip to content

Keep Markdown footnote links inside the preview - #3586

Open
danielbachhuber wants to merge 3 commits into
get-bb:mainfrom
danielbachhuber:fix-markdown-in-page-anchors
Open

danielbachhuber wants to merge 3 commits into
get-bb:mainfrom
danielbachhuber:fix-markdown-in-page-anchors

Conversation

@danielbachhuber

Copy link
Copy Markdown
Contributor

What was wrong

Markdown footnote references use #user-content-fn-… links, but MarkdownAnchor applied target="_blank" to every link. Fragment links therefore opened the app URL with a hash in a new browser window instead of staying in the preview. MarkdownListItem also dropped the footnote id, leaving the reference with no rendered destination.

What changed

apps/app/src/components/ui/markdown-preview.tsx now handles # links as in-preview navigation: it prevents default navigation, finds the matching id inside the closest [data-markdown-preview], and scrolls it into view at block: "start". It does not add target or rel to fragment links. Broken fragments also remain in the preview rather than opening a browser window.

MarkdownListItem now forwards id to its <li>, preserving the footnote destination without changing the existing handling of other list-item props. Scoping the lookup to the preview keeps footnote ids from colliding when the same Markdown renders in more than one preview at once. #3395 remains out of scope: it concerns external links in the file preview and is not fixed here.

Implementation details

The destination search iterates [id] elements instead of building a CSS id selector, so ids need no CSS escaping. Back-reference links use the same path, though the new test covers only the forward footnote reference. A sticky header in a scroll container can still cover a destination because scrolling uses block: "start".

How you verified

apps/app/src/components/ui/markdown-preview.test.tsx adds a two-preview footnote test. It confirms the first preview's reference has no target, prevents its default action, does not call linkRouting.onOpenLink, and calls scrollIntoView once on #user-content-fn-ode in that preview only. The test failed before the change because _blank was present, then still failed after the anchor change alone because the dropped list-item id left scrollIntoView uncalled. It passes after both changes.

  • pnpm exec turbo run typecheck --filter=@bb/app passes.
  • pnpm exec turbo run test --filter=@bb/app runs 4,448 passing tests, but src/components/thread/terminal/ThreadTerminalView.test.ts fails while importing @xterm/xterm Platform.ts with Cannot read properties of undefined (reading 'indexOf'). The same failure occurs with this diff reverted, so it is pre-existing and unrelated.
  • Prettier check passes on both changed files.

The behavior has not been checked in the running desktop app or iOS Safari; verification is limited to jsdom.

🤖 Generated with Claude Code

AGENT GENERATED

danielbachhuber and others added 3 commits September 12, 2026 06:36
Fragment links no longer open a new window; clicking one scrolls to the
matching id within the same preview. MarkdownListItem now forwards the
footnote id so the destination exists.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- markdown-preview.test.tsx: the only marked conflict, and it was adjacency
  in the import block. This branch added `onTestFinished` to the vitest
  import; main added `highlightMarkdownCode` on the next line. Both imports
  stay.
- markdown-preview.tsx merged cleanly and needed no follow-up. Main's
  changes there came from the incremental streaming render (get-bb#3591) and the
  timeline lightbox work (get-bb#3489, get-bb#3596); none of them touch `MarkdownAnchor`
  or `MarkdownListItem`, so the fragment-link handling and the forwarded
  `<li id>` survive as written.
- The incremental renderer does not undercut this fix. It treats
  `footnoteDefinition` and `footnoteReference` as global constructs
  (markdown-incremental-pieces.ts), so a message with footnotes is not split
  across pieces, and every piece renders inside the same
  `[data-markdown-preview]` root the destination lookup scopes to.
- markdown-preview.test.tsx: this branch's footnote-scroll test and main's
  "keeps a rewritten link mounted across unrelated preview rerenders" test
  (get-bb#4096) were both appended after the same test, which is what conflicted.
  Both are kept.
- markdown-preview.tsx merged cleanly. Main's only change there is a Prettier
  reformat of MarkdownImageProps; the fragment handling already routes
  through rewrittenHref, so localhost rewriting does not affect footnotes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant