Files
termi-blog/frontend/src/components/CodeCopyButton.astro

62 lines
2.2 KiB
Plaintext

---
// Code Block Copy Button Component
// Adds copy functionality to all code blocks
---
<script is:inline>
(function() {
function initCodeCopy() {
const codeBlocks = document.querySelectorAll('pre code');
codeBlocks.forEach(code => {
const pre = code.parentElement;
if (!pre || pre.classList.contains('code-copy-enabled')) return;
pre.classList.add('code-copy-enabled', 'relative', 'group');
// Create copy button
const button = document.createElement('button');
button.className = 'absolute top-2 right-2 px-2 py-1 text-xs rounded bg-[var(--terminal-bg)] text-[var(--text-secondary)] opacity-0 group-hover:opacity-100 transition-opacity border border-[var(--border-color)] hover:border-[var(--primary)] hover:text-[var(--primary)]';
button.innerHTML = '<i class="fas fa-copy mr-1"></i>复制';
button.addEventListener('click', async () => {
try {
await navigator.clipboard.writeText(code.textContent || '');
button.innerHTML = '<i class="fas fa-check mr-1"></i>已复制';
button.classList.add('text-[var(--success)]');
setTimeout(() => {
button.innerHTML = '<i class="fas fa-copy mr-1"></i>复制';
button.classList.remove('text-[var(--success)]');
}, 2000);
} catch (err) {
button.innerHTML = '<i class="fas fa-times mr-1"></i>失败';
button.classList.add('text-[var(--error)]');
setTimeout(() => {
button.innerHTML = '<i class="fas fa-copy mr-1"></i>复制';
button.classList.remove('text-[var(--error)]');
}, 2000);
}
});
pre.appendChild(button);
});
}
// Initialize on DOM ready
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initCodeCopy);
} else {
initCodeCopy();
}
// Re-initialize after dynamic content loads
const observer = new MutationObserver(() => {
initCodeCopy();
});
observer.observe(document.body, { childList: true, subtree: true });
})();
</script>