Skip to content

Add copy current URL as markdown link on artifact page - #68

Merged
baanish merged 2 commits into
mainfrom
cursor/copy-markdown-link-3c0d
Jun 18, 2026
Merged

Add copy current URL as markdown link on artifact page#68
baanish merged 2 commits into
mainfrom
cursor/copy-markdown-link-3c0d

Conversation

@baanish

@baanish baanish commented Jun 18, 2026

Copy link
Copy Markdown
Owner

Summary

Adds a Markdown link action to the artifact toolbar that copies the current page URL formatted as a markdown inline link, e.g. [viewer-shell.tsx](https://example.com/#agent-render=...).

The link label uses the same heading text shown for the active artifact (title → filename → id), with bracket escaping so labels containing [ or ] remain valid markdown.

Changes

  • New formatMarkdownLink() helper in src/lib/markdown-link.ts
  • New Markdown link toolbar button on the artifact page (next to Copy)
  • Unit tests for link formatting
  • E2E test verifying clipboard output

Test plan

  • npm run lint
  • npm run typecheck
  • npm run test -- tests/markdown-link.test.ts
  • npm run test:e2e -- tests/e2e/viewer.spec.ts -g "markdown link"
Open in Web Open in Cursor 

Summary by CodeRabbit

  • New Features
    • Added one-click copying of a Markdown-formatted link for the currently active artifact to the clipboard.
    • Extended the artifact toolbar with a new “Markdown link” button that shows success/failure feedback.
  • Bug Fixes
    • Improved async copy UI handling to avoid stale “copied”/“failed” states.
  • Tests
    • Added end-to-end coverage for Markdown link copying.
    • Added unit tests for Markdown link formatting, including label escaping and safe destination handling.

Introduce a Markdown link toolbar action that copies the current page
URL formatted as [artifact title](url), with bracket escaping in labels.
Includes unit tests for link formatting and an e2e test for the copy flow.

Co-authored-by: Aanish Bhirud <baanish@users.noreply.github.com>
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jun 18, 2026

Copy link
Copy Markdown

Deploying agent-render with  Cloudflare Pages  Cloudflare Pages

Latest commit: faa606b
Status: ✅  Deploy successful!
Preview URL: https://3779a3bd.agent-render.pages.dev
Branch Preview URL: https://cursor-copy-markdown-link-3c.agent-render.pages.dev

View logs

@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8f0760a6-0574-4ff7-b9f6-e47fa63c7144

📥 Commits

Reviewing files that changed from the base of the PR and between a223376 and faa606b.

📒 Files selected for processing (2)
  • src/lib/markdown-link.ts
  • tests/markdown-link.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/markdown-link.test.ts

📝 Walkthrough

Walkthrough

Adds a formatMarkdownLink utility in src/lib/markdown-link.ts that safely escapes label characters and formats destination URLs for inline Markdown links. ViewerShell is extended with a new markdownLinkCopyState with a token guard, a handleCopyMarkdownLink callback, and a toolbar button. Unit tests and a new E2E test cover the full behavior.

Changes

Markdown Link Copy Feature

Layer / File(s) Summary
formatMarkdownLink utility and unit tests
src/lib/markdown-link.ts, tests/markdown-link.test.ts
Adds private escapeMarkdownLinkLabel (escapes \, [, ]) and formatMarkdownDestination (wraps unsafe URLs in angle brackets and percent-encodes angle brackets). Exported formatMarkdownLink(label, href) combines these with trimmed-label and empty-label fallback logic. Unit tests assert standard formatting, bracket escaping, blank-label URL fallback, and special destination handling.
ViewerShell state, handler, toolbar button, and E2E tests
src/components/viewer-shell.tsx, tests/e2e/viewer.spec.ts
Imports Link2 icon and formatMarkdownLink; adds markdownLinkCopyState with a dedicated token ref for stale-update prevention; extends artifact-change reset and adds a 2-second auto-clear useEffect; implements handleCopyMarkdownLink that builds, copies, and updates state; renders the "Markdown link" toolbar button with state-driven labels. Existing artifact-copy E2E test adjusted to target the first "Copied" button; new E2E test verifies the "Markdown link" button click stores and displays the expected [viewer-shell.tsx](<current href>) format.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

  • baanish/agent-render#13: Introduced the base artifact clipboard copy flow in ViewerShell using the same guarded copy state and token-ref pattern that this PR extends for the Markdown link button.

Poem

🐇 Hop hop, a link takes shape,
Brackets escaped, no chance to break,
[label](url) — tidy and neat,
One toolbar click, the copy's complete.
The rabbit grins at markdown made sweet! 🔗

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Add copy current URL as markdown link on artifact page' accurately and concisely describes the main feature being added: the ability to copy the current page URL as a markdown-formatted link on the artifact page.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch cursor/copy-markdown-link-3c0d

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@baanish
baanish marked this pull request as ready for review June 18, 2026 09:58
@kilo-code-bot

kilo-code-bot Bot commented Jun 18, 2026

Copy link
Copy Markdown

Code Review Summary

Status: 1 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 1
SUGGESTION 0
Issue Details (click to expand)

WARNING

File Line Issue
src/lib/markdown-link.ts 13 href is inserted into the markdown destination without escaping ) or backslashes, so links with those characters can be rendered incorrectly or truncated by markdown parsers.
Files Reviewed (4 files)
  • src/components/viewer-shell.tsx - 0 issues
  • src/lib/markdown-link.ts - 1 issue
  • tests/e2e/viewer.spec.ts - 0 issues
  • tests/markdown-link.test.ts - 0 issues
Previous Review Summary (commit a223376)

Current summary above is authoritative. Previous snapshots are kept for context only.

Previous review (commit a223376)

Status: 1 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 1
SUGGESTION 0
Issue Details (click to expand)

WARNING

File Line Issue
src/lib/markdown-link.ts 13 href is inserted into the markdown destination without escaping ) or backslashes, so links with those characters can be rendered incorrectly or truncated by markdown parsers.
Files Reviewed (4 files)
  • src/components/viewer-shell.tsx - 0 issues
  • src/lib/markdown-link.ts - 1 issue
  • tests/e2e/viewer.spec.ts - 0 issues
  • tests/markdown-link.test.ts - 0 issues

Reviewed by gpt-5.4-mini-2026-03-17 · 131,214 tokens

Comment thread src/lib/markdown-link.ts Outdated
*/
export function formatMarkdownLink(label: string, href: string): string {
const trimmedLabel = label.trim() || href;
return `[${escapeMarkdownLinkLabel(trimmedLabel)}](${href})`;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

WARNING: href is inserted into the markdown destination without escaping ) or backslashes, so links with those characters can be rendered incorrectly or truncated by markdown parsers.

Escaping the destination before formatting the link would make the helper safe for arbitrary URLs.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

@greptile-apps

greptile-apps Bot commented Jun 18, 2026

Copy link
Copy Markdown

Greptile Summary

Adds a "Markdown link" toolbar button that copies the current artifact URL formatted as a CommonMark inline link, using the artifact heading as the label with proper bracket and backslash escaping.

  • src/lib/markdown-link.ts — new pure helper with formatMarkdownLink; handles label escaping, parenthesis-containing URLs via angle-bracket wrapping, and blank-label fallback.
  • src/components/viewer-shell.tsx — new button and state/effect pair that mirrors the existing copy button pattern (token guard, 2 s auto-reset).
  • Unit and E2E tests cover the key formatting cases and the clipboard integration.

Confidence Score: 5/5

Safe to merge — new functionality is additive and isolated, with no changes to the fragment transport or existing toolbar actions.

The new handler closely follows the existing copy-button pattern, the markdown escaping logic is correct, and both unit and E2E tests cover the expected scenarios. The only gap is a stale description in AGENTS.md.

AGENTS.md — the toolbar capability description should be updated to mention the new action.

Important Files Changed

Filename Overview
src/lib/markdown-link.ts New helper; escaping logic for label and destination is correct per CommonMark. JSDoc present on the exported function.
src/components/viewer-shell.tsx New "Markdown link" button added to artifact toolbar, following the same token-guard + timer-reset pattern as the existing copy button.
tests/markdown-link.test.ts Unit tests cover standard links, bracket escaping, blank-label fallback, parens in URL, and angle-bracket wrapping with encoded inner brackets.
tests/e2e/viewer.spec.ts E2E test for the markdown link action stubs clipboard and verifies the formatted output; existing copy test correctly updated to use .first() now that two "Copied" buttons can coexist.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant User
    participant Button as Markdown Link Button
    participant Handler as handleCopyMarkdownLink
    participant Lib as formatMarkdownLink
    participant Clipboard as copyTextToClipboard

    User->>Button: click
    Button->>Handler: invoke
    Handler->>Handler: read activeArtifactRef + increment token
    Handler->>Handler: getArtifactHeading(artifact)
    Handler->>Handler: window.location.href
    Handler->>Lib: formatMarkdownLink(label, href)
    Lib->>Lib: escapeMarkdownLinkLabel(label)
    Lib->>Lib: formatMarkdownDestination(href)
    Lib-->>Handler: "[label](url)"
    Handler->>Clipboard: copyTextToClipboard(markdownLink)
    alt success
        Clipboard-->>Handler: resolved
        Handler->>Button: setMarkdownLinkCopyState("copied")
        Note over Button: shows Check icon + "Copied" for 2s
    else failure
        Clipboard-->>Handler: rejected
        Handler->>Button: setMarkdownLinkCopyState("failed")
        Note over Button: shows "Copy failed" for 2s
    end
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant User
    participant Button as Markdown Link Button
    participant Handler as handleCopyMarkdownLink
    participant Lib as formatMarkdownLink
    participant Clipboard as copyTextToClipboard

    User->>Button: click
    Button->>Handler: invoke
    Handler->>Handler: read activeArtifactRef + increment token
    Handler->>Handler: getArtifactHeading(artifact)
    Handler->>Handler: window.location.href
    Handler->>Lib: formatMarkdownLink(label, href)
    Lib->>Lib: escapeMarkdownLinkLabel(label)
    Lib->>Lib: formatMarkdownDestination(href)
    Lib-->>Handler: "[label](url)"
    Handler->>Clipboard: copyTextToClipboard(markdownLink)
    alt success
        Clipboard-->>Handler: resolved
        Handler->>Button: setMarkdownLinkCopyState("copied")
        Note over Button: shows Check icon + "Copied" for 2s
    else failure
        Clipboard-->>Handler: rejected
        Handler->>Button: setMarkdownLinkCopyState("failed")
        Note over Button: shows "Copy failed" for 2s
    end
Loading

Reviews (2): Last reviewed commit: "Wrap markdown link destinations that con..." | Re-trigger Greptile

Comment on lines +17 to +20
it("falls back to the URL when the label is blank", () => {
expect(formatMarkdownLink(" ", "https://example.com/")).toBe("[https://example.com/](https://example.com/)");
});
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Missing test case for backslash escaping in the label. escapeMarkdownLinkLabel escapes \\\ before handling brackets; without a test for this path a regression (e.g. dropping the first .replace) would go undetected, and artifact filenames from Windows paths can legitimately contain backslashes.

Suggested change
it("falls back to the URL when the label is blank", () => {
expect(formatMarkdownLink(" ", "https://example.com/")).toBe("[https://example.com/](https://example.com/)");
});
});
it("falls back to the URL when the label is blank", () => {
expect(formatMarkdownLink(" ", "https://example.com/")).toBe("[https://example.com/](https://example.com/)");
});
it("escapes backslashes in the label", () => {
expect(formatMarkdownLink("path\\to\\file", "https://example.com/")).toBe(
"[path\\\\to\\\\file](https://example.com/)",
);
});
});

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Fix in Codex

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a223376006

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/lib/markdown-link.ts Outdated
*/
export function formatMarkdownLink(label: string, href: string): string {
const trimmedLabel = label.trim() || href;
return `[${escapeMarkdownLinkLabel(trimmedLabel)}](${href})`;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Escape markdown link destinations

When users copy a link for a supported arx/arx2 fragment that uses the base76 wire form, the fragment payload can contain literal ) characters; inserting window.location.href directly between ( and ) makes Markdown close the destination at the first such character, so the pasted link is truncated and no longer decodes. Escape or wrap the destination, e.g. use an angle-bracket destination with any required escaping, before copying it.

Useful? React with 👍 / 👎.

URLs with literal ) characters (e.g. arx base76 fragments) can truncate
markdown link destinations. Angle-bracket wrapping keeps the full href
intact; nested < and > are percent-encoded.

Co-authored-by: Aanish Bhirud <baanish@users.noreply.github.com>
@baanish
baanish merged commit 4a33a96 into main Jun 18, 2026
10 checks passed
baanish added a commit that referenced this pull request Jun 19, 2026
Integrates the copy-current-URL-as-markdown-link feature (PR #68) into the
refactored ArtifactStage toolbar so #67's bundle-splitting is preserved.
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.

2 participants