Select a JSON string and display it in a formatted way.
// ==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, '&').replace(/</g, '<').replace(/>/g, '>');
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;
});
})();