feat(docs): add markdown copy button to page headings

This commit is contained in:
Dax Raad 2026-08-25 00:48:39 -04:00
parent f2ff93a5b7
commit 442bc92a21
2 changed files with 44 additions and 1 deletions

View file

@ -54,7 +54,15 @@ const canonical = new URL(Astro.url.pathname, "https://opencode.ai").href
</aside>
<main id="docs-content">
<article class="prose" data-pagefind-body data-pagefind-meta={`title:${Astro.props.title}`}>
<h1>{Astro.props.title}</h1>
<h1>
{Astro.props.title}
<button type="button" aria-label="Copy page as Markdown" data-copy-markdown data-pagefind-ignore>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" aria-hidden="true">
<rect x="8" y="8" width="13" height="13" rx="2" />
<path d="M16 8V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h3" />
</svg>
</button>
</h1>
<slot />
</article>
</main>
@ -81,5 +89,21 @@ const canonical = new URL(Astro.url.pathname, "https://opencode.ai").href
addHeadingAnchors()
document.addEventListener("astro:page-load", addHeadingAnchors)
</script>
<script>
document.addEventListener("click", async (event) => {
if (!(event.target instanceof Element)) return
const button = event.target.closest<HTMLButtonElement>("[data-copy-markdown]")
if (!button) return
const response = await fetch(window.location.href, { headers: { Accept: "text/markdown" } })
if (!response.ok) return
await navigator.clipboard.writeText(await response.text())
button.dataset.copied = "true"
button.setAttribute("aria-label", "Copied")
window.setTimeout(() => {
delete button.dataset.copied
button.setAttribute("aria-label", "Copy page as Markdown")
}, 1500)
})
</script>
</body>
</html>

View file

@ -788,7 +788,11 @@ main {
}
.prose h1 {
display: flex;
margin: 0 0 3rem;
align-items: center;
justify-content: space-between;
gap: 1rem;
font-size: 1.875rem;
line-height: 1.2;
}
@ -993,6 +997,21 @@ main {
font-size: 0.75rem;
}
.prose h1 button {
display: inline-flex;
padding: 0;
flex-shrink: 0;
cursor: pointer;
border: 0;
background: transparent;
color: var(--muted);
}
.prose h1 button:hover,
.prose h1 button[data-copied] {
color: var(--foreground);
}
.search-dialog {
width: min(42rem, calc(100% - 2rem));
max-height: min(36rem, calc(100vh - 4rem));