Something went wrong. Try again.
A simple self-host service providing API keys for tightly scoped alterations to your atproto records blinkers.dev
Something went wrong. Try again.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152// Shiki's HTML (svelte.config.js's highlight.highlighter hook) is plain,// static markup with no interactivity of its own — the copy button and its// click handling only exist once this runs client-side. Called from// docs/+layout.svelte's afterNavigate, since the layout persists across// docs navigations and wouldn't otherwise see a later page's code blocks.const COPY_ICON = `<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.3" aria-hidden="true"> <rect x="5.5" y="5.5" width="8" height="8" rx="1.3"></rect> <path d="M3.8 10.2h-1a1 1 0 0 1-1-1v-6a1 1 0 0 1 1-1h6a1 1 0 0 1 1 1v1"></path></svg>`;
export function wireCodeCopyButtons() { for (const pre of document.querySelectorAll<HTMLPreElement>("pre.shiki")) { // afterNavigate can fire for a same-page hash-only navigation too, where // this pre is the exact same DOM node as last time — skip it rather // than stack a second button on top of the first. if (pre.querySelector(":scope > .copy-button")) continue;
const code = pre.querySelector("code"); if (!code) continue;
const button = document.createElement("button"); button.type = "button"; button.className = "copy-button"; button.setAttribute("aria-label", "Copy code"); button.innerHTML = COPY_ICON; pre.appendChild(button);
// One listener on the block itself, not the button — a click on the // button bubbles up to it too, so "click anywhere on the code block" // and "click the button" both take this one path. pre.addEventListener("click", () => { // A click that ends a manual text-selection drag (e.g. selecting one // line to copy by hand) still fires a click event on mouseup — skip // the whole-block copy then, rather than clobber a selection the // reader just deliberately made with the button's own click handler. const selection = window.getSelection(); if (selection && !selection.isCollapsed && pre.contains(selection.anchorNode)) { return; }
// Both `?.`s matter: navigator.clipboard is absent entirely on an // insecure origin, and writeText itself can still reject (a denied // permission) even when it exists. Either way, there's nothing more // useful to do client-side than leave the text selectable as-is — // the click feedback below runs regardless. navigator.clipboard?.writeText(code.textContent ?? "")?.catch(() => {}); button.classList.add("copied"); setTimeout(() => button.classList.remove("copied"), 500); }); }}