// ==UserScript== // @name Bilibili Copy Cleaner 专栏复制免后缀 // @namespace https://space.bilibili.com/13723713 // @version 1.0.1 // @description 移除 Bilibili 专栏复制时自动添加的多余信息,如作者、链接和出处。 // @author 朝潮 // @match *://www.bilibili.com/read/* // @grant none // @run-at document-end // @license MIT // @downloadURL none // ==/UserScript== (function() { 'use strict'; console.log('Bilibili Copy Cleaner 脚本已启动'); /** * 向页面注入一个脚本,以便在页面上下文中监听并处理 copy 事件。 */ function injectScript() { const script = document.createElement('script'); script.textContent = ` (function() { 'use strict'; console.log('Injected Copy Cleaner 脚本已启动'); /** * 处理 copy 事件,移除选中文本中的多余后缀信息。 * @param {ClipboardEvent} e - 复制事件对象 */ function handleCopyEvent(e) { console.log('捕获到 copy 事件(注入脚本)'); // 获取当前选中的文本 let selectedText = window.getSelection().toString(); console.log('原始选中的文本:', selectedText); // 定义用于移除后缀的正则表达式 const suffixPattern = /作者:[\s\S]*?出处:bilibili\s*$/; // 使用正则表达式移除后缀 const cleanedText = selectedText.replace(suffixPattern, ''); console.log('清理后的文本:', cleanedText); // 阻止默认的复制行为和事件传播 e.preventDefault(); e.stopImmediatePropagation(); // 将清理后的文本设置到剪贴板 if (e.clipboardData) { e.clipboardData.setData('text/plain', cleanedText); console.log('通过 e.clipboardData 更新剪贴板'); } else if (window.clipboardData) { // 兼容旧版 IE window.clipboardData.setData('Text', cleanedText); console.log('通过 window.clipboardData 更新剪贴板'); } else { console.warn('无法访问剪贴板数据'); } } // 添加 copy 事件监听器,使用捕获阶段优先处理 document.addEventListener('copy', handleCopyEvent, true); /** * 使用 MutationObserver 监控页面内容的变化,移除动态添加的 copy 事件监听器或属性。 */ const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { mutation.addedNodes.forEach((node) => { if (node.nodeType === Node.ELEMENT_NODE) { // 选择可能包含 copy 限制的元素 node.querySelectorAll('.article-holder, .content-container, .qmd-editor, .ql-editor').forEach(element => { if (element.oncopy) { element.oncopy = null; console.log('移除动态添加元素的 oncopy 属性:', element); } // 移除可能存在的 copy 事件监听器 element.removeEventListener('copy', null); }); } }); }); }); // 开始观察整个文档的子节点和子树变化 observer.observe(document.body, { childList: true, subtree: true }); /** * 初始移除页面加载时可能存在的复制限制。 */ document.querySelectorAll('.article-holder, .content-container, .qmd-editor, .ql-editor').forEach(element => { // 解除用户选择限制,确保文本可被选中和复制 element.style.userSelect = 'text'; element.style.webkitUserSelect = 'text'; element.style.msUserSelect = 'text'; element.style.mozUserSelect = 'text'; if (element.oncopy) { element.oncopy = null; console.log('移除初始元素的 oncopy 属性:', element); } // 移除可能存在的 copy 事件监听器 element.removeEventListener('copy', null); }); })(); `; document.body.appendChild(script); } // 注入脚本到页面 injectScript(); })();