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