Files
expressjs.com/js/copycode.js
shubham oulkar 100dc75ebf Add Copy btn on install command (#1846)
* add copy btn on install command

* remove CCS

* add padding

* remove $ sign from copied install command

---------

Co-authored-by: Sebastian Beltran <bjohansebas@gmail.com>
2025-04-26 11:18:13 -05:00

60 lines
1.7 KiB
JavaScript

const codeBlocks = document.querySelectorAll("pre:has(code)");
codeBlocks.forEach((block) => {
// Only add button if browser supports Clipboard API
if (!navigator.clipboard) return;
const button = createCopyButton();
block.appendChild(button);
block.setAttribute("tabindex", 0); // Add keyboard a11y for <pre></pre>
button.addEventListener("click", async () => {
await copyCode(block, button);
});
});
function createCopyButton() {
const button = document.createElement("button");
setButtonAttributes(button, {
type: "button", // button doesn't act as a submit button
title: "copy code",
"aria-label": "click to copy code",
});
return button;
}
function setButtonAttributes(button, attributes) {
for (const [key, value] of Object.entries(attributes)) {
button.setAttribute(key, value);
}
}
async function copyCode(block, button) {
const code = block.querySelector("code");
let text = code.innerText;
// remove "$" and space if exists at the beginning of the code
text = text.replace(/^\$\s?/,"");
try {
await navigator.clipboard.writeText(text);
updateButtonState(button, "copied", "code is copied!");
} catch {
updateButtonState(button, "failed", "failed!");
}
}
function updateButtonState(button, statusClass, ariaLabel) {
button.setAttribute("aria-live", "polite");
button.setAttribute("aria-label", ariaLabel);
button.classList.add(statusClass);
// Clear any existing timer
if (button.dataset.timerId) clearTimeout(Number(button.dataset.timerId));
const timer = setTimeout(() => {
button.classList.remove(statusClass);
button.setAttribute("aria-label", "click to copy code");
}, 1000);
button.dataset.timerId = timer;
}