// ==UserScript== // @name NodeSeek一键复制代码块 // @namespace https://www.nodeseek.com/space/3444 // @version 2025-04-19 // @description 用于在 NodeSeek 论坛一键复制代码块 // @license MIT // @author Anya // @match https://www.nodeseek.com/* // @icon https://www.nodeseek.com/static/image/favicon/android-chrome-192x192.png // @grant none // @downloadURL https://update.greasyfork.icu/scripts/533312/NodeSeek%E4%B8%80%E9%94%AE%E5%A4%8D%E5%88%B6%E4%BB%A3%E7%A0%81%E5%9D%97.user.js // @updateURL https://update.greasyfork.icu/scripts/533312/NodeSeek%E4%B8%80%E9%94%AE%E5%A4%8D%E5%88%B6%E4%BB%A3%E7%A0%81%E5%9D%97.meta.js // ==/UserScript== (function() { 'use strict'; // 样式注入:为复制按钮设置位置和外观 const style = document.createElement('style'); style.textContent = ` .tm-copy-btn { position: absolute; top: 8px; right: 8px; padding: 2px 8px; font-size: 12px; background: #4CAF50; color: white; border: none; border-radius: 3px; cursor: pointer; z-index: 1000; opacity: 0.8; transition: opacity 0.2s; } .tm-copy-btn:hover { opacity: 1; } pre.tm-copy-wrapper { position: relative !important; } `; document.head.appendChild(style); // 给单个
 添加复制按钮
    function addCopyBtn(pre) {
        if (pre.classList.contains('tm-copy-wrapper')) return; // 已处理过
        const code = pre.querySelector('code');
        if (!code) return;

        pre.classList.add('tm-copy-wrapper');
        const btn = document.createElement('button');
        btn.className = 'tm-copy-btn';
        btn.textContent = '复制';
        btn.addEventListener('click', () => {
            // 复制 code 内的纯文本
            const text = code.innerText;
            navigator.clipboard.writeText(text).then(() => {
                btn.textContent = '已复制';
                setTimeout(() => { btn.textContent = '复制'; }, 2000);
            }).catch(err => {
                console.error('复制失败:', err);
                btn.textContent = '失败';
                setTimeout(() => { btn.textContent = '复制'; }, 2000);
            });
        });
        pre.appendChild(btn);
    }

    // 扫描页面中所有符合条件的 pre
    function scanAndAttach() {
        document.querySelectorAll('pre').forEach(addCopyBtn);
    }

    // 页面初次加载时运行一次
    scanAndAttach();

    // 针对动态添加的 
,使用 MutationObserver
    const observer = new MutationObserver(mutations => {
        for (const m of mutations) {
            for (const node of m.addedNodes) {
                if (!(node instanceof HTMLElement)) continue;
                // 如果直接是 
,或包含若干 
                if (node.matches('pre')) {
                    addCopyBtn(node);
                } else {
                    node.querySelectorAll?.('pre').forEach(addCopyBtn);
                }
            }
        }
    });
    observer.observe(document.body, { childList: true, subtree: true });
})();