// ==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);
})();