Skip to content

desktop: external markdown links ([label](url)) inside a journal are not clickable #86

@vmesel

Description

@vmesel

Problem

In the desktop client you cannot click links that exist inside a journal (or any page). External markdown links — [label](https://…) — render as styled text but are completely inert: clicking them does nothing. There is no way to follow a URL you wrote in a block.

To be precise about scope (verified in the code):

Link type Desktop today
[[page ref]] ✅ navigates (onRefClickopenRef)
#tag ✅ navigates (same path)
((block ref)) / !((embed)) ✅ renders/expands
[label](https://…) external link not clickable — nothing happens

So the gap is specifically external URLs. The renderer even admits it in a comment:

// MarkdownInline.tsx
// - `[label](url)` links (non-clickable for now, would need the Tauri opener plugin)

Why it's broken (root cause)

The token pipeline is fine — outl_md::inline tokenizes [text](url) into a Link { text, url } variant and it reaches the frontend with the href populated (InlineToken { kind: "link", value, href }). The break is everything after tokenization, on the desktop:

  1. No click handler. In crates/outl-frontend-shared/src/markdown/MarkdownInline.tsx, the link case renders a plain <span> with no onClick (unlike ref and tag, which both call props.onRefClick / props.onTagClick). The href field is never read.
  2. No callback. BlockCallbacks in crates/outl-desktop/src/components/BlockRow.tsx has onRefClick / onTagClick but no onLinkClick.
  3. No Tauri capability / plugin. crates/outl-desktop/src-tauri/Cargo.toml has neither tauri-plugin-opener nor tauri-plugin-shell, and capabilities/default.json grants no opener:* / shell:* permission. So even with a handler there is no sanctioned way to open a URL in the system browser.
  4. No backend command. There is no Tauri command that opens an external URL.

Expected behavior

Clicking an external [label](url) link inside a journal/page on the desktop should open the URL in the user's default browser (modifier-click could open in background — nice-to-have, not required).

Suggested fix

  • Add tauri-plugin-opener (the modern replacement for the shell-open API) to src-tauri, register it, and grant opener:allow-open-url (scoped to http/https/mailto) in capabilities/default.json.
  • Add an onLinkClick(href) prop threaded from OutlineViewBlockRow<MarkdownInline />, wired to a small wrapper that calls the opener.
  • Wire the link token in MarkdownInline.tsx to call it (with cursor-pointer + the existing link styling), guarding against non-http(s)/mailto schemes.

Notes / parity

The TUI also doesn't open external links today (ref_at_cursor has no Link variant), so this is a desktop-first feature — but it should be designed so the "open a URL" capability can be shared rather than reimplemented per client if the TUI/mobile later want it. The [[ref]] / #tag navigation already works on both and is out of scope here.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions