您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Add copy button to code blocks on DeepWiki
// ==UserScript== // @name DeepWiki Code Copy // @namespace deepwiki_code_copy // @description Add copy button to code blocks on DeepWiki // @version 1.1.0 // @author roojay(https://github.com/roojay520) // @license http://opensource.org/licenses/MIT // @match https://deepwiki.com/* // @run-at document-end // @grant GM_addStyle // ==/UserScript== GM_addStyle(` .code-copy-button { position: absolute; top: 5px; right: 5px; padding: 4px 8px; background-color: rgba(0, 0, 0, 0.6); color: #fff; font-size: 12px; border-radius: 4px; cursor: pointer; opacity: 1; z-index: 100; border: none; outline: none; } .code-copy-button:hover { background-color: rgba(0, 0, 0, 0.8); } .code-copy-button.copied { background-color: #4caf50; } pre { position: relative; } `); (function() { /** Store processed code blocks to avoid duplicate processing */ const processedPre = new WeakSet(); /** Add copy buttons to code blocks */ function addCopyButtonsToCodeBlocks() { /** Get all top-level pre elements (not nested inside other pre elements) */ const preElements = Array.from(document.querySelectorAll('pre')).filter(pre => { // Check if this pre is nested inside another pre const parentPre = pre.closest('pre:not(:scope)'); return !parentPre; // If no parent pre, it's a top-level pre }); preElements.forEach(pre => { // Skip if already processed if (processedPre.has(pre)) { return; } // Mark as processed processedPre.add(pre); // Create copy button const copyButton = document.createElement('button'); copyButton.className = 'code-copy-button'; copyButton.textContent = 'Copy'; // Add copy functionality copyButton.addEventListener('click', function(e) { e.stopPropagation(); // Get clean code content by cloning the pre element, removing the button, and getting text const preClone = pre.cloneNode(true); const buttonInClone = preClone.querySelector('.code-copy-button'); if (buttonInClone) { buttonInClone.remove(); } const codeContent = preClone.textContent || ''; // Copy to clipboard navigator.clipboard.writeText(codeContent).then(() => { // Visual feedback on success copyButton.classList.add('copied'); copyButton.textContent = 'Copied!'; // Reset after 2 seconds setTimeout(() => { copyButton.classList.remove('copied'); copyButton.textContent = 'Copy'; }, 2000); }).catch(err => { console.error('Copy failed:', err); // Fallback copy method const textarea = document.createElement('textarea'); textarea.value = codeContent; textarea.style.position = 'fixed'; textarea.style.opacity = '0'; document.body.appendChild(textarea); textarea.select(); try { document.execCommand('copy'); copyButton.classList.add('copied'); copyButton.textContent = 'Copied!'; setTimeout(() => { copyButton.classList.remove('copied'); copyButton.textContent = 'Copy'; }, 2000); } catch (err) { console.error('Fallback copy failed:', err); copyButton.textContent = 'Copy failed'; } document.body.removeChild(textarea); }); }); // Add button to code block pre.appendChild(copyButton); }); } /** Initialize script */ function initScript() { // Process initially loaded code blocks addCopyButtonsToCodeBlocks(); // Watch for DOM changes to handle dynamically loaded code blocks const observer = new MutationObserver((mutations) => { let hasNewPre = false; mutations.forEach(mutation => { if (mutation.type === 'childList') { const addedNodes = Array.from(mutation.addedNodes); // Check for new pre elements or nodes that might contain pre elements const hasPreNodes = addedNodes.some(node => { if (node.nodeName === 'PRE') return true; if (node.nodeType === 1 && node.querySelector('pre')) return true; return false; }); if (hasPreNodes) { hasNewPre = true; } } }); if (hasNewPre) { addCopyButtonsToCodeBlocks(); } }); // Start observing document body observer.observe(document.body, { childList: true, subtree: true }); } // Start script when page is loaded if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initScript); } else { initScript(); } })();