jetsung zrewidował ten Gist 5 months ago. Przejdź do rewizji
1 file changed, 2 insertions, 2 deletions
juejin.user.js
| @@ -1,8 +1,8 @@ | |||
| 1 | 1 | // ==UserScript== | |
| 2 | 2 | // @name 掘金复制代码段 | |
| 3 | 3 | // @namespace https://docs.scriptcat.org/ | |
| 4 | - | // @version 0.0.1 | |
| 5 | - | // @description 清空掘金代码块头部右侧原有按钮,仅保留一个自定义“复制代码段”按钮,点击后复制纯净代码文本(无行号、无HTML样式) | |
| 4 | + | // @version 0.1.0 | |
| 5 | + | // @description 免登录复制掘金代码片段 | |
| 6 | 6 | // @author You | |
| 7 | 7 | // @match https://juejin.cn/post/* | |
| 8 | 8 | // @icon https://www.google.com/s2/favicons?sz=64&domain=juejin.cn | |
jetsung zrewidował ten Gist 5 months ago. Przejdź do rewizji
1 file changed, 104 insertions
juejin.user.js(stworzono plik)
| @@ -0,0 +1,104 @@ | |||
| 1 | + | // ==UserScript== | |
| 2 | + | // @name 掘金复制代码段 | |
| 3 | + | // @namespace https://docs.scriptcat.org/ | |
| 4 | + | // @version 0.0.1 | |
| 5 | + | // @description 清空掘金代码块头部右侧原有按钮,仅保留一个自定义“复制代码段”按钮,点击后复制纯净代码文本(无行号、无HTML样式) | |
| 6 | + | // @author You | |
| 7 | + | // @match https://juejin.cn/post/* | |
| 8 | + | // @icon https://www.google.com/s2/favicons?sz=64&domain=juejin.cn | |
| 9 | + | // @downloadURL https://gist.asfd.cn/jetsung/juejin/raw/HEAD/juejin.user.js | |
| 10 | + | // @updateURL https://gist.asfd.cn/jetsung/juejin/raw/HEAD/juejin.user.js | |
| 11 | + | // @grant none | |
| 12 | + | // ==/UserScript== | |
| 13 | + | ||
| 14 | + | (function() { | |
| 15 | + | 'use strict'; | |
| 16 | + | ||
| 17 | + | // 自定义按钮样式 | |
| 18 | + | const customBtnStyle = { | |
| 19 | + | display: 'inline-block', | |
| 20 | + | padding: '2px 10px', | |
| 21 | + | marginLeft: '8px', | |
| 22 | + | fontSize: '13px', | |
| 23 | + | color: '#fff', | |
| 24 | + | backgroundColor: '#007fff', | |
| 25 | + | borderRadius: '6px', | |
| 26 | + | cursor: 'pointer', | |
| 27 | + | userSelect: 'none', | |
| 28 | + | transition: 'all 0.3s', | |
| 29 | + | boxShadow: '0 2px 4px rgba(0,0,0,0.1)' | |
| 30 | + | }; | |
| 31 | + | ||
| 32 | + | function addCustomCopyButton() { | |
| 33 | + | document.querySelectorAll('.code-block-extension-header').forEach(header => { | |
| 34 | + | const headerRight = header.querySelector('.code-block-extension-headerRight'); | |
| 35 | + | if (!headerRight || headerRight.querySelector('.juejin-custom-copy-btn')) return; | |
| 36 | + | ||
| 37 | + | // 清空右侧所有原有按钮 | |
| 38 | + | headerRight.innerHTML = ''; | |
| 39 | + | ||
| 40 | + | // 创建自定义按钮 | |
| 41 | + | const copyBtn = document.createElement('div'); | |
| 42 | + | copyBtn.className = 'juejin-custom-copy-btn'; | |
| 43 | + | copyBtn.textContent = '复制代码段'; | |
| 44 | + | Object.assign(copyBtn.style, customBtnStyle); | |
| 45 | + | ||
| 46 | + | // 悬停与成功效果 | |
| 47 | + | copyBtn.addEventListener('mouseenter', () => copyBtn.style.backgroundColor = '#0066cc'); | |
| 48 | + | copyBtn.addEventListener('mouseleave', () => { | |
| 49 | + | if (copyBtn.textContent !== '复制成功') copyBtn.style.backgroundColor = '#007fff'; | |
| 50 | + | }); | |
| 51 | + | ||
| 52 | + | headerRight.appendChild(copyBtn); | |
| 53 | + | ||
| 54 | + | // 复制逻辑(更稳健的纯文本提取) | |
| 55 | + | copyBtn.addEventListener('click', async () => { | |
| 56 | + | const codeContainer = header.parentElement.querySelector('pre code') || | |
| 57 | + | header.nextElementSibling?.querySelector('code') || | |
| 58 | + | header.parentElement.querySelector('code.hljs'); | |
| 59 | + | ||
| 60 | + | if (!codeContainer) { | |
| 61 | + | copyBtn.textContent = '无代码'; | |
| 62 | + | setTimeout(() => copyBtn.textContent = '复制代码段', 2000); | |
| 63 | + | return; | |
| 64 | + | } | |
| 65 | + | ||
| 66 | + | let pureCode = ''; | |
| 67 | + | ||
| 68 | + | // 优先尝试直接取 code 的纯文本(最干净) | |
| 69 | + | if (codeContainer.textContent) { | |
| 70 | + | pureCode = codeContainer.textContent.trim(); | |
| 71 | + | } else { | |
| 72 | + | // 备选:逐行提取 | |
| 73 | + | const lines = Array.from(codeContainer.querySelectorAll('div, span, .code-block-extension-codeLine')) | |
| 74 | + | .map(el => el.textContent || ''); | |
| 75 | + | pureCode = lines.join('\n').trim(); | |
| 76 | + | } | |
| 77 | + | ||
| 78 | + | // 去除可能的行号前缀(如果还有残留) | |
| 79 | + | pureCode = pureCode.replace(/^\s*\d+\s*/gm, '').trim(); | |
| 80 | + | ||
| 81 | + | try { | |
| 82 | + | await navigator.clipboard.writeText(pureCode); | |
| 83 | + | copyBtn.textContent = '复制成功 ✓'; | |
| 84 | + | copyBtn.style.backgroundColor = '#52c41a'; | |
| 85 | + | setTimeout(() => { | |
| 86 | + | copyBtn.textContent = '复制代码段'; | |
| 87 | + | copyBtn.style.backgroundColor = '#007fff'; | |
| 88 | + | }, 2000); | |
| 89 | + | } catch (err) { | |
| 90 | + | console.error('复制失败', err); | |
| 91 | + | copyBtn.textContent = '复制失败'; | |
| 92 | + | setTimeout(() => copyBtn.textContent = '复制代码段', 2000); | |
| 93 | + | } | |
| 94 | + | }); | |
| 95 | + | }); | |
| 96 | + | } | |
| 97 | + | ||
| 98 | + | // 页面初次加载 | |
| 99 | + | window.addEventListener('load', addCustomCopyButton); | |
| 100 | + | ||
| 101 | + | // 动态监听(掘金是 SPA,内容会异步加载) | |
| 102 | + | const observer = new MutationObserver(addCustomCopyButton); | |
| 103 | + | observer.observe(document.body, { childList: true, subtree: true }); | |
| 104 | + | })(); | |