From a223376006ecf4c8b1a9c71a0039ed83ba02aa85 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Thu, 18 Jun 2026 09:54:08 +0000 Subject: [PATCH 1/2] Add copy current URL as markdown link on artifact toolbar 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 --- src/components/viewer-shell.tsx | 57 +++++++++++++++++++++++++++++++++ src/lib/markdown-link.ts | 14 ++++++++ tests/e2e/viewer.spec.ts | 27 +++++++++++++++- tests/markdown-link.test.ts | 20 ++++++++++++ 4 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 src/lib/markdown-link.ts create mode 100644 tests/markdown-link.test.ts diff --git a/src/components/viewer-shell.tsx b/src/components/viewer-shell.tsx index ca4eb83..b440937 100644 --- a/src/components/viewer-shell.tsx +++ b/src/components/viewer-shell.tsx @@ -13,6 +13,7 @@ import { Copy, Download, Eye, + Link2, FileCode2, FileDiff, FileJson2, @@ -41,6 +42,7 @@ import { type PayloadEnvelope, } from "@/lib/payload/schema"; import { copyTextToClipboard } from "@/lib/copy-text"; +import { formatMarkdownLink } from "@/lib/markdown-link"; import { cn } from "@/lib/utils"; import { LinkCreator } from "@/components/home/link-creator"; import { ArtifactSelector } from "@/components/viewer/artifact-selector"; @@ -260,10 +262,12 @@ export function ViewerShell() { const [hash, setHash] = useState(""); const [rendererReady, setRendererReady] = useState(true); const [artifactCopyState, setArtifactCopyState] = useState<"idle" | "copied" | "failed">("idle"); + const [markdownLinkCopyState, setMarkdownLinkCopyState] = useState<"idle" | "copied" | "failed">("idle"); const [viewMode, setViewMode] = useState<"rendered" | "raw">("rendered"); const activeArtifactRef = useRef(null); /** Incremented on each copy click so stale async completions cannot overwrite state from a newer request. */ const artifactCopyTokenRef = useRef(0); + const markdownLinkCopyTokenRef = useRef(0); /** True when the current hash originated from a server-injected payload (self-hosted UUID mode). */ const injectedPayloadRef = useRef(false); @@ -354,6 +358,7 @@ export function ViewerShell() { useEffect(() => { setArtifactCopyState("idle"); + setMarkdownLinkCopyState("idle"); setViewMode("rendered"); }, [activeArtifact?.id]); @@ -371,6 +376,20 @@ export function ViewerShell() { }; }, [artifactCopyState]); + useEffect(() => { + if (markdownLinkCopyState !== "copied" && markdownLinkCopyState !== "failed") { + return; + } + + const timer = window.setTimeout(() => { + setMarkdownLinkCopyState("idle"); + }, 2000); + + return () => { + window.clearTimeout(timer); + }; + }, [markdownLinkCopyState]); + const setFragmentHash = useCallback((nextHash: string) => { if (window.location.hash === nextHash) { return; @@ -423,6 +442,32 @@ export function ViewerShell() { } }, []); + const handleCopyMarkdownLink = useCallback(async () => { + const artifact = activeArtifactRef.current; + if (!artifact) { + return; + } + + const requestArtifactId = artifact.id; + const requestToken = ++markdownLinkCopyTokenRef.current; + const label = getArtifactHeading(artifact); + const href = window.location.href; + const markdownLink = formatMarkdownLink(label, href); + + try { + await copyTextToClipboard(markdownLink); + if (activeArtifactRef.current?.id !== requestArtifactId || markdownLinkCopyTokenRef.current !== requestToken) { + return; + } + setMarkdownLinkCopyState("copied"); + } catch { + if (activeArtifactRef.current?.id !== requestArtifactId || markdownLinkCopyTokenRef.current !== requestToken) { + return; + } + setMarkdownLinkCopyState("failed"); + } + }, []); + const handleArtifactDownload = useCallback(() => { if (!activeArtifact) { return; @@ -526,6 +571,18 @@ export function ViewerShell() { {artifactCopyState === "copied" ? : } {artifactCopyState === "copied" ? "Copied" : artifactCopyState === "failed" ? "Copy failed" : "Copy"} + {markdownArtifact && viewMode === "rendered" ? (