JSON Selector

Select a JSON string and display it in a formatted way.

Vous devrez installer une extension telle que Tampermonkey, Greasemonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Userscripts pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey pour installer ce script.

Vous devrez installer une extension de gestionnaire de script utilisateur pour installer ce script.

(J'ai déjà un gestionnaire de scripts utilisateur, laissez-moi l'installer !)

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

(J'ai déjà un gestionnaire de style utilisateur, laissez-moi l'installer!)

// ==UserScript==
// @name         JSON Selector
// @namespace    https://openuserjs.org/users/SkyedBlue
// @version      1.2
// @description  Select a JSON string and display it in a formatted way.
// @author       Skyed_blue
// @license      OSI-SPDX-Short-Identifier
// @match        http://*/*
// @match        https://*/*
// @grant        none
// @icon         http://t13.baidu.com/it/u=3464717519,1631837546&fm=224&app=112&f=JPEG?w=500&h=500
// ==/UserScript==


(function() {
    'use strict';

    const css = `
    #text-box-D {
        width: 64%; /* max-width: 64%; */
        word-wrap: break-word; /* 支持换行 */
        overflow: auto; /* 显示滚动条 */
        height: 90%; /* 固定高度 */
        z-index: 99999;
        display: none; /* 初始状态下隐藏文本展示框D */
        position: fixed; /* 设置文本展示框D的定位方式为绝对定位 */
        white-space: pre-wrap;  /* 支持换行 */
        left: 16%;
        top: 50px; /* 设置文本展示框D距离网站顶部50px的位置 */
        padding: 20px; /* 设置文本展示框D的边距 */
        border-radius: 10px; /* 设置文本展示框D的圆角 */
        box-shadow: 0 2px 2px rgba(0,0,0,0.1); /* 设置文本展示框D的阴影 */
        background-color: #fff; /* 设置文本展示框D的背景颜色 */
        font-size: 16px; /* 设置文本展示框D的字体大小 */
        line-height: 1.5; /* 设置文本展示框D的行高 */
        text-align: justify; /* 设置文本展示框D的文本对齐方式 */
    }

    /* Overlay style */
    #overlay {
            position: fixed;
            display: none;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background-color: rgba(0, 0, 0, 0.70);
            z-index: 99998;
        }

    .fade-in {
        animation: fade-in 0.15s ease-in-out;
    }

    .fade-out {
        animation: fade-out 0.15s ease-in-out;
    }

    @keyframes fade-in {
        from { opacity: 0; }
        to { opacity: 1; }
    }

    @keyframes fade-out {
        from { opacity: 1; }
        to { opacity: 0; }
    }

    .string { color: #3ab54a; font-weight: bold; }
    .number { color: #25aae2; font-weight: bold; }
    .boolean { color: #f1592a; font-weight: bold; }
    .null { color: #f1592a; font-weight: bold; }
    .key { color: #92278f; font-weight: bold; }
    `

    var node = document.createElement("style");
	node.type = "text/css";
	node.appendChild(document.createTextNode(css));

    var heads = document.getElementsByTagName("head");
	if (heads.length > 0) {
		heads[0].appendChild(node);
	} else {
		// no head yet, stick it whereever
		document.documentElement.appendChild(node);
	}

    var textBoxDDom = document.createElement('div');
    textBoxDDom.id = 'text-box-D';
    document.body.appendChild(textBoxDDom);

    var overlayDom = document.createElement('div');
    overlayDom.id = 'overlay';
    document.body.appendChild(overlayDom);




    function getJSON(str) {
        let stack = [];
        let res = [];
        for(let i = 0;i < str.length;i++)
        {
            if(str[i] === "{" || str[i] === "[") {
                stack.push(i);
            }
            if(str[i] === "}"|| str[i] === "]") {
                if (stack.length <= 0) {
                    continue;
                }
                let idx = stack.pop()
                if (stack.length <= 0) {
                    res.push(str.substring(idx, i+1));
                }
            }
        }
        return res
    }

    // num to str
    let numMp = new Map()

    function getNumMp(json) {
        let numbers = json.match(/\d+/g);
        numbers.forEach(num => {
        let key = parseInt(num);
        numMp.set(key, num);
        });
        return numMp;
    }

    function syntaxHighlight(json) {
    json = json.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
    return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function (match) {
        var cls = 'number';
        if (/^"/.test(match)) {
            if (/:$/.test(match)) {
                cls = 'key';
            } else {
                cls = 'string';
            }
        } else if (/true|false/.test(match)) {
            cls = 'boolean';
        } else if (/null/.test(match)) {
            cls = 'null';
        }
        if(cls == 'number') {
            match = numMp.get(parseInt(match))
        }
        return '<span class="' + cls + '">' + match + '</span>';
    });
}

    const textBoxD = document.getElementById("text-box-D");
    const overlay = document.getElementById("overlay");
    let flag = true;

    function showTextBox() {
        textBoxD.classList.add("fade-in");
        textBoxD.style.display = "block";
			document.getElementById("overlay").classList.add("fade-in");
			overlay.style.display = "block";
		}

    function hideTextBox() {
        textBoxD.classList.remove("fade-in");
        textBoxD.classList.add("fade-out");
        overlay.classList.remove("fade-in");
        overlay.classList.add("fade-out");
        setTimeout(function() {
            textBoxD.style.display = "none";
            textBoxD.classList.remove("fade-out");
            overlay.style.display = "none";
            overlay.classList.remove("fade-out");
        }, 150);
    }

    document.addEventListener("mouseup", function(e) { /* 在文字展示框B上监听鼠标抬起事件 */
        if (textBoxD.contains(e.target)) {
            return;
        }

        const selectedText = window.getSelection().toString(); /* 获取当前选择的文本 */

        if (!flag || selectedText.length <= 0) {
            flag = true;
            return;
        }

        let jsonList = getJSON(selectedText);
        if (jsonList.length <= 0) {
            return;
        }

        let hasJson = false;
        for(let i = jsonList.length-1;i >= 0;i--) {
            let jsonStr = jsonList[i]
            try {
                getNumMp(jsonStr);
                let jsonObj = JSON.parse(jsonStr);
                textBoxD.innerHTML = syntaxHighlight(JSON.stringify(jsonObj, null, 8));
                hasJson = true;
                break;
            } catch {
                continue;
            }
        }
        if(hasJson){
            document.addEventListener("mousedown", function(e) { /* 在文档中监听鼠标抬起事件 */
                if (textBoxD.style.display === "block" && !textBoxD.contains(e.target)) { /* 如果文本展示框D正在显示 */
                    hideTextBox();
                }
            });
            showTextBox();
        }

        flag = false;
    });
})();