// ==UserScript== // @name JavaGuide Copy Cleaner // @namespace https://tampermonkey.net/ // @version 1.0 // @description 删除JavaGuide复制追加的版权尾巴节点,并移除复制HTML中的链接(保留内容与结构) // @match *://javaguide.cn/* // @match *://www.javaguide.cn/* // @run-at document-start // @grant none // ==/UserScript== (function () { 'use strict'; // 识别“尾巴”的关键词:命中任意一个就认为是尾巴容器 const TAIL_KEYWORDS = [ '著作权归JavaGuide', '基于MIT协议', '原文链接' ]; function looksLikeTail(text) { if (!text) return false; const t = String(text).replace(/\s+/g, ''); return TAIL_KEYWORDS.some(k => t.includes(k.replace(/\s+/g, ''))); } // 把 去掉但保留它里面的节点(文本/代码/加粗等) function unwrapAllAnchors(root) { root.querySelectorAll('a').forEach(a => { const frag = document.createDocumentFragment(); while (a.firstChild) frag.appendChild(a.firstChild); a.replaceWith(frag); }); } // 删除“尾巴节点”:删除任何 textContent 命中关键词的元素(优先删块级容器) function removeTailNodes(root) { // 从深到浅遍历,避免先删父导致漏判 const all = Array.from(root.querySelectorAll('*')).reverse(); for (const el of all) { const txt = (el.textContent || '').trim(); if (!txt) continue; if (looksLikeTail(txt)) { el.remove(); } } } function cleanHtml(html) { if (!html || typeof html !== 'string') return html; const box = document.createElement('div'); box.innerHTML = html; removeTailNodes(box); unwrapAllAnchors(box); return box.innerHTML.trim(); } function cleanPlain(text) { if (!text) return text; // 从出现“著作权归JavaGuide”那行开始删到结尾(兼容多行) return String(text) .replace(/\n*\s*著作权归\s*JavaGuide[\s\S]*$/i, '') .trim(); } // 核心:拦截 setData —— 网站往剪贴板塞 HTML/文本时都会走这里(很常见) const origSetData = DataTransfer.prototype.setData; DataTransfer.prototype.setData = function (type, data) { try { if (typeof data === 'string') { if (type === 'text/html') data = cleanHtml(data); if (type === 'text/plain') data = cleanPlain(data); } } catch (_) {} return origSetData.call(this, type, data); }; // 兜底:有些站会用 copy 事件自己 setData,这里保证我们最后写回一次 document.addEventListener('copy', (e) => { try { if (!e.clipboardData) return; const html = e.clipboardData.getData('text/html'); const text = e.clipboardData.getData('text/plain'); // 如果这次复制根本没有HTML数据,就不动(避免破坏普通复制) if (html) { e.preventDefault(); e.stopImmediatePropagation(); e.clipboardData.setData('text/html', cleanHtml(html)); e.clipboardData.setData('text/plain', cleanPlain(text || '')); } } catch (_) {} }, true); })();