JSON Copy Button

为类似demo.html结构的页面添加JSON复制按钮

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name         JSON Copy Button
// @namespace    http://tampermonkey.net/
// @version      0.4
// @description  为类似demo.html结构的页面添加JSON复制按钮
// @author       Trae AI
// @match        *://*/*
// @grant        GM_addStyle
// @grant        GM.addStyle
// @license MIT
// ==/UserScript==

(function() {
    'use strict';

    // 添加按钮样式
    GM_addStyle(`
        .json-copy-btn {
            position: absolute;
            top: 10px;
            left: 10px;
            padding: 4px 8px;
            background-color: #4CAF50;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            font-size: 12px;
            z-index: 10000;
        }
        .json-copy-btn:hover {
            background-color: #45a049;
        }
    `);

    // 检查页面是否包含类似结构
    function checkForJsonStructure() {
        const nodes = document.querySelectorAll('.vjs-tree:not([data-copy-button-added])') || [];
        console.log('检查页面JSON结构:', nodes.length > 0 ? '找到新的结构' : '未找到新的结构');
        return nodes;
    }

    // 创建复制按钮
    function createCopyButton(container) {
        console.log('创建复制按钮...');
        const button = document.createElement('button');
        button.className = 'json-copy-btn';
        button.textContent = '复制JSON';
        button.onclick = async () => {
            const jsonContent = extractJsonContent(container);
            try {
                await navigator.clipboard.writeText(jsonContent);
                console.log('JSON内容复制成功');
                button.textContent = '复制成功!';
                setTimeout(() => {
                    button.textContent = '复制JSON';
                }, 2000);
            } catch (err) {
                button.textContent = '复制失败';
                console.error('JSON内容复制失败:', err);
            }
        };
        container.style.position = 'relative';
        container.appendChild(button);
        container.setAttribute('data-copy-button-added', 'true');
    }

    // 提取JSON内容
    function extractJsonContent(container) {
        console.log('开始提取JSON内容...');
        const jsonObj = {};
        const nodes = container.querySelectorAll('.vjs-tree__node');
        
        nodes.forEach(node => {
            const key = node.querySelector('.vjs-key');
            const value = node.querySelector('.vjs-value');
            
            if (key && value) {
                const keyText = key.textContent.replace(':', '');
                let valueText = '';
                
                if (value.classList.contains('vjs-value__string')) {
                    valueText = value.textContent.replace(/^"(.*)"$/, '$1');
                } else if (value.classList.contains('vjs-value__number')) {
                    valueText = Number(value.textContent);
                } else if (value.textContent === '[') {
                    valueText = [];
                    // 处理数组内容
                    let nextNode = node.nextElementSibling;
                    while (nextNode && !nextNode.textContent.includes(']')) {
                        const arrayValue = nextNode.querySelector('.vjs-value');
                        if (arrayValue) {
                            valueText.push(arrayValue.textContent.replace(/^"(.*)"$/, '$1'));
                        }
                        nextNode = nextNode.nextElementSibling;
                    }
                }
                
                if (keyText && valueText !== '') {
                    jsonObj[keyText] = valueText;
                }
            }
        });
        
        const result = JSON.stringify(jsonObj, null, 2);
        console.log('JSON内容提取完成:', result);
        return result;
    }

    // 创建 MutationObserver 实例
    const observer = new MutationObserver((mutations) => {
        console.log('检测到 DOM 变化,正在检查 JSON 结构...');
        const newStructures = checkForJsonStructure();
        newStructures.forEach(structure => {
            console.log('发现新的 JSON 结构,添加复制按钮...');
            createCopyButton(structure);
        });
    });

    // 配置 observer
    const config = {
        childList: true,
        subtree: true
    };

    // 开始观察
    window.addEventListener('load', () => {
        console.log('页面加载完成,开始监听 DOM 变化...');
        observer.observe(document.body, config);
        
        // 初始检查
        const initialStructures = checkForJsonStructure();
        initialStructures.forEach(structure => {
            console.log('页面加载完成时发现 JSON 结构,添加复制按钮...');
            createCopyButton(structure);
        });
    });
})();