// ==UserScript== // @name 掘金复制代码段 // @namespace https://docs.scriptcat.org/ // @version 0.1.0 // @description 免登录复制掘金代码片段 // @author You // @match https://juejin.cn/post/* // @icon https://www.google.com/s2/favicons?sz=64&domain=juejin.cn // @grant none // ==/UserScript== (function() { 'use strict'; // 自定义按钮样式 const customBtnStyle = { display: 'inline-block', padding: '2px 10px', marginLeft: '8px', fontSize: '13px', color: '#fff', backgroundColor: '#007fff', borderRadius: '6px', cursor: 'pointer', userSelect: 'none', transition: 'all 0.3s', boxShadow: '0 2px 4px rgba(0,0,0,0.1)' }; function addCustomCopyButton() { document.querySelectorAll('.code-block-extension-header').forEach(header => { const headerRight = header.querySelector('.code-block-extension-headerRight'); if (!headerRight || headerRight.querySelector('.juejin-custom-copy-btn')) return; // 清空右侧所有原有按钮 headerRight.innerHTML = ''; // 创建自定义按钮 const copyBtn = document.createElement('div'); copyBtn.className = 'juejin-custom-copy-btn'; copyBtn.textContent = '复制代码段'; Object.assign(copyBtn.style, customBtnStyle); // 悬停与成功效果 copyBtn.addEventListener('mouseenter', () => copyBtn.style.backgroundColor = '#0066cc'); copyBtn.addEventListener('mouseleave', () => { if (copyBtn.textContent !== '复制成功') copyBtn.style.backgroundColor = '#007fff'; }); headerRight.appendChild(copyBtn); // 复制逻辑(更稳健的纯文本提取) copyBtn.addEventListener('click', async () => { const codeContainer = header.parentElement.querySelector('pre code') || header.nextElementSibling?.querySelector('code') || header.parentElement.querySelector('code.hljs'); if (!codeContainer) { copyBtn.textContent = '无代码'; setTimeout(() => copyBtn.textContent = '复制代码段', 2000); return; } let pureCode = ''; // 优先尝试直接取 code 的纯文本(最干净) if (codeContainer.textContent) { pureCode = codeContainer.textContent.trim(); } else { // 备选:逐行提取 const lines = Array.from(codeContainer.querySelectorAll('div, span, .code-block-extension-codeLine')) .map(el => el.textContent || ''); pureCode = lines.join('\n').trim(); } // 去除可能的行号前缀(如果还有残留) pureCode = pureCode.replace(/^\s*\d+\s*/gm, '').trim(); try { await navigator.clipboard.writeText(pureCode); copyBtn.textContent = '复制成功 ✓'; copyBtn.style.backgroundColor = '#52c41a'; setTimeout(() => { copyBtn.textContent = '复制代码段'; copyBtn.style.backgroundColor = '#007fff'; }, 2000); } catch (err) { console.error('复制失败', err); copyBtn.textContent = '复制失败'; setTimeout(() => copyBtn.textContent = '复制代码段', 2000); } }); }); } // 页面初次加载 window.addEventListener('load', addCustomCopyButton); // 动态监听(掘金是 SPA,内容会异步加载) const observer = new MutationObserver(addCustomCopyButton); observer.observe(document.body, { childList: true, subtree: true }); })();