Greasy Fork

Greasy Fork is available in English.

NodeSeek一键复制代码块

用于在 NodeSeek 论坛一键复制代码块

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

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

    // 给单个 <pre><code> 添加复制按钮
    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();

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