Skip to content

markdown_preview: Support anchor link for headings#53184

Merged
smitbarmase merged 17 commits intozed-industries:mainfrom
dongdong867:feat/support-heading-links-in-markdown
Apr 9, 2026
Merged

markdown_preview: Support anchor link for headings#53184
smitbarmase merged 17 commits intozed-industries:mainfrom
dongdong867:feat/support-heading-links-in-markdown

Conversation

@dongdong867
Copy link
Copy Markdown
Contributor

@dongdong867 dongdong867 commented Apr 5, 2026

What does this PR did

  • Generate GitHub-flavored heading slugs for markdown headings
  • Handle [label](#heading) same-document anchor links that scroll the preview and editor to the target heading
  • Handle [label](./file.md#heading) cross-file anchor links that open the file, scroll the preview, and move the editor cursor to the heading
markdown_heading_linking.mov

What to test

  • Create a markdown file with [Go to section](#section-name) links, verify clicking scrolls preview and editor
  • Create two markdown files with cross-file links like [See other](./other.md#heading), verify file opens and preview scrolls to heading
  • Verify duplicate headings produce correct slugs (heading, heading-1)
  • Verify external URLs (https://...) are unaffected

Self-Review Checklist:

  • I've reviewed my own diff for quality, security, and reliability
  • Unsafe blocks (if any) have justifying comments
  • The content is consistent with the UI/UX checklist
  • Tests cover the new/changed behavior
  • Performance impact has been considered and is acceptable

Closes #18699

Release Notes:

  • Added support for anchor links for headings in Markdown Preview.
@cla-bot cla-bot Bot added the cla-signed The user has signed the Contributor License Agreement label Apr 5, 2026
@zed-community-bot zed-community-bot Bot added the guild Pull requests by someone in Zed Guild. NOTE: the label application is automated via github actions label Apr 5, 2026
@zed-codeowner-coordinator zed-codeowner-coordinator Bot requested review from a team, nathansobo and osiewicz and removed request for a team April 5, 2026 07:12
@zelenenka zelenenka assigned smitbarmase and unassigned osiewicz Apr 7, 2026
@zelenenka zelenenka requested review from smitbarmase and removed request for nathansobo and osiewicz April 7, 2026 08:54
Copy link
Copy Markdown
Member

@smitbarmase smitbarmase left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I added a few suggestions.

Comment thread crates/markdown/src/markdown.rs Outdated
Comment thread crates/markdown/src/markdown.rs Outdated
Comment thread crates/markdown/src/markdown.rs Outdated
Comment thread crates/markdown/src/markdown.rs Outdated
Comment thread crates/markdown/src/markdown.rs Outdated
Move generate_heading_slug(), slug deduplication, and heading slug
storage from MarkdownElementBuilder (render-time) to the parser
(parse-time). Slugs are now stored as HashMap<SharedString, usize>
on ParsedMarkdownData for O(1) lookup instead of Vec with O(N) scan.
When clicking a cross-file anchor link like [text](./file.md#heading),
the editor cursor now moves to the heading position in addition to
the preview scrolling. Uses a pending slug that resolves once the
target file's parse completes.
Keep both pending_heading_scroll (ours) and search_highlights (upstream).
@smitbarmase
Copy link
Copy Markdown
Member

Thanks, taking a look.

Copy link
Copy Markdown
Member

@smitbarmase smitbarmase left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I made a few fixes on top of your commits before merging:

Have you tested it? I don't think the cross-file anchor scroll (./file.md#heading) was ever working. It was trying to scroll the current preview while opening a target editor, so the heading would never resolve. There was a bunch of dead code around this that just added complexity, so I cleaned it up. We can introduce cross-file scroll later.

I also removed the scroll logic from render. We should not handle state mutations there, it's unreliable and wrong. Render should purely be used for rendering. I moved it to a window.defer call in handle_url_click instead, which is a more deterministic way to handle it.

For separation of concern, I removed the # fragment handling from MarkdownElement. Any URL can have a # in it, so stripping it and treating it as an anchor at the shared markdown level is a bug. I fixed that handling and moved into markdown preview itself.

We now also do parsing for heading slug only for markdown preview.

Thanks again for working on this!

@smitbarmase smitbarmase merged commit b150663 into zed-industries:main Apr 9, 2026
31 checks passed
@dongdong867 dongdong867 deleted the feat/support-heading-links-in-markdown branch April 9, 2026 16:20
AzureZee added a commit to AzureZee/gpuix that referenced this pull request Apr 10, 2026
AzureZee added a commit to AzureZee/gpuix that referenced this pull request Apr 10, 2026
piper-of-dawn pushed a commit to piper-of-dawn/zed that referenced this pull request Apr 25, 2026
)

## What does this PR did

- Generate [GitHub-flavored heading
slugs](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#section-links)
for markdown headings
- Handle `[label](#heading)` same-document anchor links that scroll the
preview and editor to the target heading
- Handle `[label](./file.md#heading)` cross-file anchor links that open
the file, scroll the preview, and move the editor cursor to the heading


https://github.com/user-attachments/assets/ecc468bf-bed0-4543-a988-703025a61bf8

## What to test

- [ ] Create a markdown file with `[Go to section](#section-name)`
links, verify clicking scrolls preview and editor
- [ ] Create two markdown files with cross-file links like `[See
other](./other.md#heading)`, verify file opens and preview scrolls to
heading
- [ ] Verify duplicate headings produce correct slugs (`heading`,
`heading-1`)
- [ ] Verify external URLs (`https://...`) are unaffected

Self-Review Checklist:

- [x] I've reviewed my own diff for quality, security, and reliability
- [ ] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [x] Tests cover the new/changed behavior
- [ ] Performance impact has been considered and is acceptable

Closes zed-industries#18699

Release Notes:

- Added support for anchor links for headings in Markdown Preview.

---------

Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
@mendeza
Copy link
Copy Markdown

mendeza commented Apr 27, 2026

Thanks @dongdong867

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

Labels

cla-signed The user has signed the Contributor License Agreement guild Pull requests by someone in Zed Guild. NOTE: the label application is automated via github actions

6 participants