const successIcon = ` `; const errorIcon = ` `; const copyIcon = ` `; // Function to change icons after copying const changeIcon = (button, isSuccess) => { button.innerHTML = isSuccess ? successIcon : errorIcon; setTimeout(() => { button.innerHTML = copyIcon; // Reset to copy icon }, 2000); }; // Function to get code text from tables, skipping line numbers const getCodeFromTable = (codeBlock) => { return [...codeBlock.querySelectorAll("tr")] .map((row) => row.querySelector("td:last-child")?.innerText ?? "") .join(""); }; // Function to get code text from non-table blocks const getNonTableCode = (codeBlock) => { return codeBlock.textContent.trim(); }; document.addEventListener("DOMContentLoaded", function () { // Select all `pre` elements containing `code` document.querySelectorAll("pre code").forEach((codeBlock) => { const pre = codeBlock.parentNode; pre.style.position = "relative"; // Ensure parent `pre` can contain absolute elements // Create and append the copy button const copyBtn = document.createElement("button"); copyBtn.className = "clipboard-button"; copyBtn.innerHTML = copyIcon; copyBtn.setAttribute("aria-label", "Copy code to clipboard"); pre.appendChild(copyBtn); // Create and append the language label const langClass = codeBlock.className.match(/language-(\w+)/); const lang = langClass ? langClass[1].toUpperCase() : "TEXT"; const label = document.createElement("span"); label.className = "code-label label-" + lang.toLowerCase(); label.textContent = lang; pre.appendChild(label); // Attach event listener to copy button copyBtn.addEventListener("click", async () => { const codeToCopy = codeBlock.textContent.trim(); // Get the code content try { await navigator.clipboard.writeText(codeToCopy); changeIcon(copyBtn, true); // Show success icon } catch (error) { console.error("Failed to copy text: ", error); changeIcon(copyBtn, false); // Show error icon } }); let ticking = false; pre.addEventListener("scroll", () => { if (!ticking) { window.requestAnimationFrame(() => { copyBtn.style.right = `-${pre.scrollLeft}px`; // Ensure button stays on the right label.style.left = `${pre.scrollLeft}px`; // Ensure label stays on the left ticking = false; }); ticking = true; } }); }); });