Skip to content

Commit 574a4d8

Browse files
committed
feat: 為教學內容的程式碼區塊添加複製功能
- 每個程式碼區塊右上角添加複製按鈕 - 滑鼠懸停時顯示按鈕,平時隱藏 - 點擊後顯示「✓ 已複製」確認訊息 - 支援現代 Clipboard API 和降級方案 - 2秒後自動恢復按鈕狀態
1 parent d652346 commit 574a4d8

1 file changed

Lines changed: 96 additions & 0 deletions

File tree

index.html

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,11 +283,41 @@
283283
padding: 15px;
284284
overflow-x: auto;
285285
margin: 15px 0;
286+
position: relative;
286287
}
287288

288289
.markdown-content pre code {
289290
background: none;
290291
padding: 0;
292+
display: block;
293+
padding-right: 50px;
294+
}
295+
296+
.copy-button {
297+
position: absolute;
298+
top: 5px;
299+
right: 5px;
300+
padding: 5px 10px;
301+
background: #667eea;
302+
color: white;
303+
border: none;
304+
border-radius: 4px;
305+
font-size: 12px;
306+
cursor: pointer;
307+
opacity: 0;
308+
transition: opacity 0.3s;
309+
}
310+
311+
.markdown-content pre:hover .copy-button {
312+
opacity: 1;
313+
}
314+
315+
.copy-button:hover {
316+
background: #5a67d8;
317+
}
318+
319+
.copy-button.copied {
320+
background: #48bb78;
291321
}
292322

293323
.markdown-content blockquote {
@@ -512,6 +542,9 @@ <h2>📚 8 個學習場景</h2>
512542
// 顯示內容
513543
body.innerHTML = html;
514544

545+
// 為所有程式碼區塊添加複製按鈕
546+
addCopyButtons();
547+
515548
// 滾動到頂部
516549
body.parentElement.scrollTop = 0;
517550

@@ -545,6 +578,69 @@ <h2>❌ 載入失敗</h2>
545578
closeMarkdown();
546579
}
547580
});
581+
582+
// 添加複製按鈕到程式碼區塊
583+
function addCopyButtons() {
584+
const codeBlocks = document.querySelectorAll('.markdown-content pre');
585+
586+
codeBlocks.forEach((block, index) => {
587+
// 創建複製按鈕
588+
const button = document.createElement('button');
589+
button.className = 'copy-button';
590+
button.textContent = '複製';
591+
button.setAttribute('data-code-index', index);
592+
593+
// 複製功能
594+
button.addEventListener('click', async function() {
595+
const code = block.querySelector('code');
596+
const textToCopy = code.textContent || code.innerText;
597+
598+
try {
599+
await navigator.clipboard.writeText(textToCopy);
600+
601+
// 顯示複製成功
602+
button.textContent = '✓ 已複製';
603+
button.classList.add('copied');
604+
605+
// 2秒後恢復
606+
setTimeout(() => {
607+
button.textContent = '複製';
608+
button.classList.remove('copied');
609+
}, 2000);
610+
611+
} catch (err) {
612+
// 降級方案:使用傳統方法
613+
const textArea = document.createElement('textarea');
614+
textArea.value = textToCopy;
615+
textArea.style.position = 'fixed';
616+
textArea.style.left = '-999999px';
617+
document.body.appendChild(textArea);
618+
textArea.select();
619+
620+
try {
621+
document.execCommand('copy');
622+
button.textContent = '✓ 已複製';
623+
button.classList.add('copied');
624+
625+
setTimeout(() => {
626+
button.textContent = '複製';
627+
button.classList.remove('copied');
628+
}, 2000);
629+
} catch (err) {
630+
button.textContent = '複製失敗';
631+
setTimeout(() => {
632+
button.textContent = '複製';
633+
}, 2000);
634+
}
635+
636+
document.body.removeChild(textArea);
637+
}
638+
});
639+
640+
// 添加按鈕到程式碼區塊
641+
block.appendChild(button);
642+
});
643+
}
548644
</script>
549645
</body>
550646
</html>

0 commit comments

Comments
 (0)