| 423 | if (docsContent) { |
| 424 | // Add copy buttons to code blocks (handles both Rouge-highlighted and plain code) |
| 425 | const addCopyButtons = () => { |
| 426 | // Find all code elements, but process them intelligently to avoid duplicates |
| 427 | const allCodeElements = docsContent.querySelectorAll("pre > code"); |
| 428 | |
| 429 | allCodeElements.forEach((codeEl) => { |
| 430 | // Skip if this code element is already inside a .docs-code-block wrapper |
| 431 | if (codeEl.closest(".docs-code-block")) return; |
| 432 | |
| 433 | // Check if this is inside a Rouge .highlight block |
| 434 | const highlightEl = codeEl.closest(".highlight"); |
| 435 | const containerEl = highlightEl || codeEl.parentElement; // Use .highlight if present, otherwise use pre |
| 436 | const pre = codeEl.parentElement; |
| 437 | |
| 438 | // Skip if container is already enhanced |
| 439 | if (containerEl.dataset.copyEnhanced === "true") return; |
| 440 | |
| 441 | containerEl.dataset.copyEnhanced = "true"; |
| 442 | const wrapper = document.createElement("div"); |
| 443 | wrapper.className = "docs-code-block"; |
| 444 | |
| 445 | containerEl.parentNode.insertBefore(wrapper, containerEl); |
| 446 | wrapper.appendChild(containerEl); |
| 447 | |
| 448 | const button = document.createElement("button"); |
| 449 | button.type = "button"; |
| 450 | button.className = "docs-code-copy-btn"; |
| 451 | button.setAttribute("aria-label", "Copy code to clipboard"); |
| 452 | button.textContent = "Copy"; |
| 453 | |
| 454 | button.addEventListener("click", async () => { |
| 455 | const text = codeEl.innerText || codeEl.textContent || ""; |
| 456 | try { |
| 457 | await navigator.clipboard.writeText(text); |
| 458 | button.classList.add("copied"); |
| 459 | button.textContent = "Copied"; |
| 460 | window.setTimeout(() => { |
| 461 | button.classList.remove("copied"); |
| 462 | button.textContent = "Copy"; |
| 463 | }, 1500); |
| 464 | } catch (e) { |
| 465 | // eslint-disable-next-line no-console |
| 466 | console.error("Failed to copy code", e); |
| 467 | } |
| 468 | }); |
| 469 | |
| 470 | wrapper.appendChild(button); |
| 471 | }); |
| 472 | }; |
| 473 | |
| 474 | // Add anchor links to headings with IDs |
| 475 | const addHeadingAnchors = () => { |