Last active
November 15, 2022 12:01
-
-
Save ramazansancar/633312aec1a1674eadc391efd381f78a to your computer and use it in GitHub Desktop.
JSON Viewer Extension
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var port = chrome.runtime.connect(), | |
collapsers, | |
options, | |
jsonObject, | |
rawData, | |
errorLocs = []; | |
function displayError(error, loc, offset) { | |
var locKey = loc.first_column + ';' + | |
loc.first_line + ';' + | |
loc.last_column + ';' + | |
loc.last_line; | |
if (errorLocs.indexOf(locKey) == -1) { | |
errorLocs.push(locKey); | |
var link = document.createElement('link'), | |
pre = document.body.firstChild.firstChild, | |
text = pre.textContent.substring(offset), | |
range = document.createRange(), | |
imgError = document.createElement('img'), | |
content = document.createElement('div'), | |
errorPosition = document.createElement('span'), | |
container = document.createElement('div'), | |
closeButton = document.createElement('div'), | |
start = 0, | |
ranges = [], | |
idx = 0, | |
end; | |
link.rel = 'stylesheet'; | |
link.type = 'text/css'; | |
link.href = chrome.runtime.getURL('assets/css/content_error.css'); | |
document.head.appendChild(link); | |
while (idx != -1) { | |
idx = text.indexOf('\n', start); | |
ranges.push(start); | |
start = idx + 1; | |
} | |
start = ranges[loc.first_line - 1] + loc.first_column + offset; | |
end = ranges[loc.last_line - 1] + loc.last_column + offset; | |
range.setStart(pre, start); | |
if (start == end - 1) { | |
range.setEnd(pre, start); | |
} else { | |
range.setEnd(pre, end); | |
} | |
errorPosition.className = 'error-position'; | |
errorPosition.id = 'error-position'; | |
range.surroundContents(errorPosition); | |
imgError.src = chrome.runtime.getURL('assets/images/error.gif'); | |
errorPosition.appendChild(imgError); | |
closeButton.className = 'close-error'; | |
closeButton.onclick = function () { | |
content.parentElement.removeChild(content); | |
}; | |
content.className = 'content'; | |
content.textContent = error; | |
content.appendChild(closeButton); | |
container.className = 'container'; | |
container.appendChild(content); | |
errorPosition.parentNode.insertBefore(container, errorPosition.nextSibling); | |
location.hash = 'error-position'; | |
history.replaceState({}, '', '#'); | |
} | |
} | |
function displayUI(theme, html) { | |
var statusElement, | |
toolboxElement, | |
expandElement, | |
reduceElement, | |
viewSourceElement, | |
optionsElement, | |
content = "", | |
copyPathElement; | |
content += '<link rel="stylesheet" type="text/css" href="' + chrome.runtime.getURL('assets/css/jsonview-core.css') + '">'; | |
content += '<style>' + theme + '</style>'; | |
content += html; | |
document.body.innerHTML = content; | |
collapsers = document.querySelectorAll('#json .collapsible .collapsible'); | |
copyPathElement = document.createElement('div'); | |
copyPathElement.className = 'copy-path'; | |
statusElement = document.createElement('div'); | |
statusElement.className = 'status'; | |
statusElement.appendChild(copyPathElement); | |
document.body.appendChild(statusElement); | |
toolboxElement = document.createElement('div'); | |
toolboxElement.className = 'toolbox'; | |
expandElement = document.createElement('button'); | |
expandElement.id = 'expand_all'; | |
expandElement.innerText = "+"; | |
reduceElement = document.createElement('button'); | |
reduceElement.id = 'reduce_all'; | |
reduceElement.innerText = "-"; | |
viewSourceElement = document.createElement('button'); | |
viewSourceElement.id = 'view_source'; | |
viewSourceElement.innerText = "View source"; | |
// viewSourceElement.target = "_blank"; | |
// viewSourceElement.href = "view-source:" + location.href; | |
optionsElement = document.createElement('img'); | |
optionsElement.title = 'options'; | |
optionsElement.src = chrome.runtime.getURL('assets/images/options.png'); | |
toolboxElement.appendChild(expandElement); | |
toolboxElement.appendChild(reduceElement); | |
toolboxElement.appendChild(viewSourceElement); | |
toolboxElement.appendChild(optionsElement); | |
document.body.appendChild(toolboxElement); | |
document.body.addEventListener('click', onToggle, false); | |
document.body.addEventListener('mouseover', onMouseMove, false); | |
document.body.addEventListener('click', onMouseClick, false); | |
document.body.addEventListener('contextmenu', onContextMenu, false); | |
expandElement.addEventListener('click', onExpand, false); | |
reduceElement.addEventListener('click', onReduce, false); | |
viewSourceElement.addEventListener('click', onViewSource, false); | |
optionsElement.addEventListener('click', onOptions, false); | |
copyPathElement.addEventListener( | |
'click', | |
function () { | |
port.postMessage({ | |
copyPropertyPath: true, | |
path: statusElement.innerText | |
}); | |
}, | |
false | |
); | |
} | |
function onToggle(event) { | |
var collapsed, ellipsis, target = event.target; | |
if (event.target.className == 'collapser') { | |
ellipsis = target.parentNode.getElementsByClassName('ellipsis')[0]; | |
collapsed = target.parentNode.getElementsByClassName('collapsible')[0]; | |
if (collapsed.parentNode.classList.contains('collapsed')) { | |
collapsed.parentNode.classList.remove('collapsed'); | |
} else { | |
collapsed.parentNode.classList.add('collapsed'); | |
ellipsis.setAttribute('data-value', collapsed.childElementCount.toString()); | |
} | |
} | |
} | |
function onExpand() { | |
Array.prototype.forEach.call(collapsers, function (collapsed) { | |
if (collapsed.parentNode.classList.contains('collapsed')) { | |
collapsed.parentNode.classList.remove('collapsed'); | |
} | |
}); | |
} | |
function onReduce() { | |
Array.prototype.forEach.call(collapsers, function (collapsed) { | |
if (!collapsed.parentNode.classList.contains('collapsed')) { | |
var ellipsis = collapsed.parentNode.getElementsByClassName('ellipsis')[0]; | |
if (ellipsis) { | |
ellipsis.setAttribute('data-value', collapsed.childElementCount.toString()); | |
} | |
collapsed.parentNode.classList.add('collapsed'); | |
} | |
}); | |
} | |
function onViewSource() { | |
openNewContent('assets/source.html'); | |
} | |
function onOptions() { | |
openNewContent('assets/options.html'); | |
} | |
function openNewContent(contentPath) { | |
return window.open(chrome.runtime.getURL(contentPath), '_blank').focus(); | |
} | |
function getParentLI(element) { | |
if (element.tagName != 'LI') | |
while (element && element.tagName != 'LI') | |
element = element.parentNode; | |
if (element && element.tagName == 'LI') | |
return element; | |
} | |
var onMouseMove = (function () { | |
var hoveredLI; | |
function onMouseOut() { | |
var statusElement = document.querySelector('.status'); | |
if (hoveredLI) { | |
hoveredLI.firstChild.classList.remove('hovered'); | |
hoveredLI = null; | |
statusElement.innerText = ''; | |
} | |
} | |
return function (event) { | |
var str = "", statusElement = document.querySelector('.status'); | |
var element = getParentLI(event.target); | |
if (element) { | |
if (hoveredLI) | |
hoveredLI.firstChild.classList.remove('hovered'); | |
hoveredLI = element; | |
element.firstChild.classList.add('hovered'); | |
do { | |
if (element.parentNode.classList.contains('array')) { | |
var index = [].indexOf.call(element.parentNode.children, element); | |
str = '[' + index + ']' + str; | |
} | |
if (element.parentNode.classList.contains('obj')) { | |
str = "." + element.firstChild.firstChild.innerText + str; | |
} | |
element = element.parentNode.parentNode.parentNode; | |
} while (element.tagName == 'LI'); | |
if (str.charAt(0) == '.') | |
str = str.substring(1); | |
statusElement.innerText = str; | |
return; | |
} | |
onMouseOut(); | |
}; | |
})(); | |
var selectedLI; | |
function onMouseClick() { | |
if (selectedLI) | |
selectedLI.firstChild.classList.remove('selected'); | |
selectedLI = getParentLI(event.target); | |
if (selectedLI) { | |
selectedLI.firstChild.classList.add('selected'); | |
} | |
} | |
function onContextMenu() { | |
var currentLI, | |
statusElement, | |
selection = "", | |
value; | |
currentLI = getParentLI(event.target); | |
statusElement = document.querySelector('.status'); | |
if (currentLI) { | |
if (Array.isArray(jsonObject)) | |
value = eval('(jsonObject' + statusElement.innerText + ')'); | |
else | |
value = eval('(jsonObject.' + statusElement.innerText + ')'); | |
port.postMessage({ | |
copyPropertyPath: true, | |
path: statusElement.innerText, | |
value: typeof value == 'object' ? JSON.stringify(value) : value | |
}); | |
} | |
} | |
function extractData(rawText) { | |
var tokens, text = rawText.trim(); | |
function test(text) { | |
return ((text.charAt(0) == '[' && text.charAt(text.length - 1) == ']') || | |
(text.charAt(0) == '{' && text.charAt(text.length - 1) == '}')); | |
} | |
if (test(text)) { | |
return { | |
text: rawText, | |
offset: 0 | |
}; | |
} | |
tokens = text.match(/^([^\s\(]*)\s*\(([\s\S]*)\)\s*;?$/); | |
if (tokens && tokens[1] && tokens[2]) { | |
if (test(tokens[2].trim())) { | |
return { | |
fnName: tokens[1], | |
text: tokens[2], | |
offset: rawText.indexOf(tokens[2]) | |
}; | |
} | |
} | |
} | |
function processData(data) { | |
var xhr, jsonText; | |
function formatToHTML(fnName, offset) { | |
if (!jsonText) return; | |
port.postMessage({ | |
jsonToHTML: true, | |
json: jsonText, | |
fnName: fnName, | |
offset: offset | |
}); | |
try { | |
jsonObject = JSON.parse(jsonText); | |
} catch (e) { | |
} | |
} | |
if (window == top || options.injectInFrame) { | |
if (options.safeMethod) { | |
xhr = new XMLHttpRequest(); | |
xhr.onreadystatechange = function () { | |
if (this.readyState == 4) { | |
data = extractData(this.responseText); | |
if (data) { | |
jsonText = data.text; | |
formatToHTML(data.fnName, data.offset); | |
} | |
} | |
}; | |
xhr.open('GET', document.location.href, true); | |
xhr.send(null); | |
} else if (data) { | |
jsonText = data.text; | |
formatToHTML(data.fnName, data.offset); | |
} | |
} | |
} | |
function init(data) { | |
port.onMessage.addListener(function (msg) { | |
if (msg.onInit) { | |
options = msg.options; | |
processData(data); | |
} | |
if (msg.onJsonToHTML) { | |
if (msg.html) { | |
displayUI(msg.theme, msg.html); | |
} else if (msg.json) { | |
port.postMessage({ | |
getError: true, | |
json: json, | |
fnName: fnName | |
}); | |
} | |
} | |
if (msg.onGetError) { | |
displayError(msg.error, msg.loc, msg.offset); | |
} | |
}); | |
port.postMessage({ | |
init: true, | |
rawData: rawData.innerHTML | |
}); | |
} | |
function stripJsonPrefix(text) { | |
// Some implementations return a JSON_PREFIX to help avoid | |
// allowing your JSON replies to be turned into JSONP replies. | |
var JSON_PREFIXES = [")]}', ", ")]}',\n"]; | |
JSON_PREFIXES.forEach(function (prefix) { | |
if (text.substr(0, prefix.length) == prefix) { | |
text = text.substr(prefix.length); | |
} | |
}); | |
return text; | |
} | |
function load() { | |
if (document.body && | |
( | |
document.body.childNodes[0] && | |
document.body.childNodes[0].tagName == 'PRE' || | |
document.body.children.length == 0 | |
) | |
) { | |
var data; | |
rawData = document.body.children.length ? document.body.childNodes[0] : document.body; | |
data = extractData(stripJsonPrefix(rawData.innerText)); | |
if (data) { | |
init(data); | |
} | |
} | |
} | |
document.addEventListener('DOMContentLoaded', load, false); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
body { | |
margin-bottom: 23px; | |
white-space: normal !important; | |
} | |
ul { | |
list-style-type: none; | |
padding: 0px; | |
margin: 0px 0px 0px 26px; | |
} | |
li { | |
position: relative; | |
} | |
.hoverable { | |
transition: background-color .2s ease-out 0s; | |
-webkit-transition: background-color .2s ease-out 0s; | |
display: inline-block; | |
} | |
.hovered { | |
transition-delay: .2s; | |
-webkit-transition-delay: .2s; | |
} | |
.selected { | |
outline: dotted 1px; | |
} | |
.collapsed > .collapsible { | |
display: none; | |
} | |
.ellipsis { | |
display: none; | |
} | |
.collapsed > .ellipsis { | |
display: inherit; | |
} | |
.collapser { | |
position: absolute; | |
top: 1px; | |
left: -1.5em; | |
cursor: default; | |
user-select: none; | |
-webkit-user-select: none; | |
} | |
.status { | |
position: fixed; | |
left: 0px; | |
bottom: 0px; | |
min-width: 628px; | |
border: 1px solid #c2c2c2; | |
border-bottom-width: 0px; | |
border-left-width: 0px; | |
border-top-right-radius: 4px; | |
height: 16px; | |
padding: 2px 7px 2px 4px; | |
font-family: sans-serif; | |
font-size: 12px; | |
opacity: 0; | |
background-color: #d2d2f6; | |
color: #696969; | |
transition: opacity .2s ease-out; | |
-webkit-transition: opacity .2s ease-out; | |
user-select: none; | |
-webkit-user-select: none; | |
} | |
.status:not(:empty ) { | |
opacity: 1; | |
} | |
.toolbox { | |
font-family: sans-serif; | |
font-size: 13px; | |
opacity: .25; | |
background-color: #d2d2f6; | |
position: fixed; | |
right: 0px; | |
top: 0px; | |
border: 0px solid #c2c2c2; | |
border-bottom-width: 1px; | |
border-left-width: 1px; | |
border-bottom-left-radius: 4px; | |
padding-bottom: 3px; | |
transition: opacity .2s ease-out; | |
-webkit-transition: opacity .2s ease-out; | |
cursor: default; | |
user-select: none; | |
-webkit-user-select: none; | |
padding-left: 2px; | |
} | |
.toolbox:hover { | |
opacity: 1; | |
} | |
.toolbox > * { | |
padding-left: 3px; | |
padding-right: 3px; | |
} | |
.toolbox > a { | |
padding-left: 5px; | |
} | |
.toolbox > img { | |
height: 20px; | |
vertical-align: middle; | |
cursor: pointer; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment