Skip to content

markdown_preview: Refactor to use shared markdown crate#52008

Merged
smitbarmase merged 12 commits intomainfrom
markdown-preview-refactor
Mar 26, 2026
Merged

markdown_preview: Refactor to use shared markdown crate#52008
smitbarmase merged 12 commits intomainfrom
markdown-preview-refactor

Conversation

@smitbarmase
Copy link
Copy Markdown
Member

@smitbarmase smitbarmase commented Mar 20, 2026

We now use the parser and renderer from the markdown crate for Markdown Preview, instead of maintaining two separate code paths.

How it works:

markdown_preview_view.rs is now a consumer of MarkdownElement. It acts as a thin wrapper, handling things like resolving URL clicks and image URLs, which can vary between consumers. It also handles syncing the editor selection with the active block in the preview. The APIs for this are provided by MarkdownElement.

All the heavy lifting like parsing HTML, rendering block markers on hover, handling the active block, etc. is done by MarkdownElement. Everything is opt-in. For example, markdown in the Agent Panel can choose not to enable block marker rendering or HTML parsing, while Markdown Preview opts into those features.

Final outcome:

For Markdown Preview View:

  • Added:

    • Selection support in the preview
  • Stays:

    • Syncing between editor and preview
    • Autoscroll
    • Hover and active block markers
    • Checkbox toggling
    • Image rendering
    • Mermaid rendering

For the markdown crate:

  • No changes for existing consumers like the Agent Panel
  • Consumers can now opt into:
    • HTML rendering
    • Block marker rendering
    • Click event handling
    • Custom image resolvers
    • Mermaid rendering

Release Notes:

  • N/A

@cla-bot cla-bot Bot added the cla-signed The user has signed the Contributor License Agreement label Mar 20, 2026
@zed-community-bot zed-community-bot Bot added the staff Pull requests authored by a current member of Zed staff label Mar 20, 2026
@zed-codeowner-coordinator zed-codeowner-coordinator Bot requested review from a team, Anthony-Eid and osiewicz and removed request for a team March 20, 2026 11:56
mac9sb pushed a commit to mac9sb/zed that referenced this pull request Mar 23, 2026
Merge the markdown preview refactor (PR zed-industries#52008) which replaces the custom
markdown_elements/markdown_parser/markdown_renderer modules with the shared
markdown crate. Port the navigation features (link click behavior settings,
back/forward nav history, navigate-to-markdown-file) to work with the new
MarkdownElement API.
@smitbarmase smitbarmase force-pushed the markdown-preview-refactor branch from 8752ef7 to 774f03a Compare March 24, 2026 08:31
@github-actions
Copy link
Copy Markdown

📏 PR Size: 8278 lines changed (Size XL)

Please note: this PR exceeds the 400 LOC soft limit.

  • Consider splitting into separate PRs if the changes are separable
  • Ensure the PR description includes a guided tour in the "How to Review" section so reviewers know where to start

@smitbarmase smitbarmase force-pushed the markdown-preview-refactor branch from 1ab80cc to d423928 Compare March 24, 2026 22:41
@smitbarmase smitbarmase force-pushed the markdown-preview-refactor branch from d423928 to 6798ec4 Compare March 26, 2026 06:03
@smitbarmase smitbarmase merged commit 9efe3c5 into main Mar 26, 2026
31 checks passed
@smitbarmase smitbarmase deleted the markdown-preview-refactor branch March 26, 2026 06:57
@balcsida
Copy link
Copy Markdown

Closes #16727

@luapmartin
Copy link
Copy Markdown

@smitbarmase thanks a lot, also wondering how hard it would be adding markdown preview mode search (Find) support too?

cppcoffee pushed a commit to cppcoffee/zed that referenced this pull request Apr 24, 2026
Closes zed-industries#53587

Follow-up to zed-industries#50595.

[zed-industries#50595](zed-industries#50595) added
display-only checkboxes when `[x]` / `[X]` / `[ ]` appears as the sole
content of a markdown table cell. That PR called out interactivity as a
later step — this PR delivers it.


https://github.com/user-attachments/assets/c666ee4c-7e31-4450-ab33-c07c82949818

## What this does

When a consumer of `MarkdownElement` supplies an `on_checkbox_toggle`
callback, table-cell checkboxes now invoke it on click with the source
range of the `[x]` / `[ ]` marker and the new checked state. This
mirrors the existing list-item checkbox path.

For markdown preview (`markdown_preview_view.rs`) the callback is
already wired to edit the source buffer, so clicking a checkbox in a
previewed `.md` file now flips `[x]` to `[ ]` and back in the file, the
same as it already did for list checkboxes.

## How it works

`replace_pending_checkbox` previously took the cell's outer source range
and always built a visualization-only checkbox. It now takes the
optional toggle callback instead, and reconstructs the marker's exact
source range from `pending_line.source_mappings` — pulldown-cmark emits
`[x]` in a table cell as three separate `Text` events, so the per-chunk
mappings are needed to recover the 3-character range to rewrite. If a
callback was supplied, the checkbox attaches an `on_click` that invokes
it with that range and `!checked`; otherwise it falls back to the prior
visualization-only rendering.

Two free helpers (`source_range_for_rendered` /
`source_index_for_rendered`) were extracted so the mapping logic is
unit-testable.

## Scope

One file: `crates/markdown/src/markdown.rs`. No changes to
`markdown_preview` — since zed-industries#52008 it renders through the shared
`MarkdownElement`, so its existing `on_checkbox_toggle` wiring picks up
table checkboxes for free.

## Relation to zed-industries#53587

[zed-industries#53587](zed-industries#53587) reports
that markdown checkboxes in the **agent panel** can't be clicked. This
PR is a necessary piece of that fix — without it, even if the agent
panel wired `on_checkbox_toggle`, its table checkboxes would stay inert.
It does not fully close zed-industries#53587 on its own: the agent panel's
`MarkdownElement` instances in `conversation_view.rs` / `thread_view.rs`
don't currently wire `on_checkbox_toggle`, and wiring it there requires
deciding how clicks should mutate the in-memory agent response (no
source file to edit into). That's a follow-up.

## Test plan

**Unit tests** (2 new, both in `crates/markdown/src/markdown.rs`):
- `test_table_checkbox_marker_source_range` — walks parser events for a
table with checkboxes, replays what the builder accumulates, and asserts
the reconstructed source range slices to exactly `[x]` / `[ ]` in the
original markdown (including a padded-whitespace case).
- `test_source_range_for_rendered_handles_split_chunks` — pins the
mapping helper against the three-chunk layout pulldown-cmark produces.

**Automated**:
- [x] `cargo test -p markdown` — 46 tests pass (44 existing + 2 new)
- [x] `cargo test -p markdown_preview` — 3 tests pass
- [x] `./script/clippy -p markdown` — clean

**Manual** (against a preview of a markdown file with checkbox tables):
- [x] Click a checked `[x]` table cell — it becomes `[ ]` in the source
and rerenders as unchecked
- [x] Click an unchecked `[ ]` — becomes `[x]`
- [x] Uppercase `[X]` toggles on click (replacement writes `[x]` / `[
]`, matching the list-item behaviour)
- [x] Padded-whitespace cells still target just the three marker
characters
- [x] Multiple checkbox columns in one table all independently clickable
- [x] Alignment variants (left/center/right) behave the same
- [x] Non-checkbox table text unaffected
- [x] List-item checkboxes continue to work (regression)

Release Notes:

- Made table-cell markdown checkboxes clickable in markdown preview,
matching list-item checkbox behavior

Co-authored-by: Lukas Wirth <lukas@zed.dev>
piper-of-dawn pushed a commit to piper-of-dawn/zed that referenced this pull request Apr 25, 2026
…es#52008)

We now use the parser and renderer from the `markdown` crate for
Markdown Preview, instead of maintaining two separate code paths.

How it works:

`markdown_preview_view.rs` is now a consumer of `MarkdownElement`. It
acts as a thin wrapper, handling things like resolving URL clicks and
image URLs, which can vary between consumers. It also handles syncing
the editor selection with the active block in the preview. The APIs for
this are provided by `MarkdownElement`.

All the heavy lifting like parsing HTML, rendering block markers on
hover, handling the active block, etc. is done by `MarkdownElement`.
Everything is opt-in. For example, markdown in the Agent Panel can
choose not to enable block marker rendering or HTML parsing, while
Markdown Preview opts into those features.

Final outcome:

For Markdown Preview View:

- Added:
  - Selection support in the preview

- Stays:
  - Syncing between editor and preview
  - Autoscroll
  - Hover and active block markers
  - Checkbox toggling
  - Image rendering
  - Mermaid rendering

For the `markdown` crate:

- No changes for existing consumers like the Agent Panel
- Consumers can now opt into:
  - HTML rendering
  - Block marker rendering
  - Click event handling
  - Custom image resolvers
  - Mermaid rendering

Release Notes:

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

Labels

area:preview/markdown cla-signed The user has signed the Contributor License Agreement large-pr staff Pull requests authored by a current member of Zed staff

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants