MikeCoder /
MJsonViewer
| 1 | ////////////////////////////////////////////////////////////////////////////////////// |
||
| 2 | // Copyright © 2017 TangDongxin |
||
| 3 | // |
||
| 4 | // Permission is hereby granted, free of charge, to any person obtaining |
||
| 5 | // a copy of this software and associated documentation files (the "Software"), |
||
| 6 | // to deal in the Software without restriction, including without limitation |
||
| 7 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, |
||
| 8 | // and/or sell copies of the Software, and to permit persons to whom the |
||
| 9 | // Software is furnished to do so, subject to the following conditions: |
||
| 10 | // |
||
| 11 | // The above copyright notice and this permission notice shall be included |
||
| 12 | // in all copies or substantial portions of the Software. |
||
| 13 | // |
||
| 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
||
| 15 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES |
||
| 16 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
||
| 17 | // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, |
||
| 18 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, |
||
| 19 | // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE |
||
| 20 | // OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
||
| 21 | ////////////////////////////////////////////////////////////////////////////////////// |
||
| 22 | |||
| 23 | // =========================================== |
||
| 24 | // JSON PARSER |
||
| 25 | // =========================================== |
||
| 26 | |||
| 27 | var bgColor, intColor, strColor, keyColor, defaultColor; |
||
| 28 | var fontStyle; |
||
| 29 | var strictOnly, hideDetails; |
||
| 30 | |||
| 31 | function onError(error) { |
||
| 32 | console.log(error); |
||
| 33 | } |
||
| 34 | |||
| 35 | function onGot(result) { |
||
| 36 | if (result[0]) { |
||
| 37 | fontStyle = result[0].fontStyle || "Consolas"; |
||
| 38 | bgColor = result[0].bgColor || "#FDF6E3"; |
||
| 39 | intColor = result[0].intColor || "#657A81"; |
||
| 40 | strColor = result[0].strColor || "#2AA198"; |
||
| 41 | keyColor = result[0].keyColor || "#B58900"; |
||
| 42 | defaultColor = result[0].defaultColor || "#586E75"; |
||
| 43 | |||
| 44 | strictOnly = result[0].strictOnly || false; |
||
| 45 | hideDetails = result[0].hideDetails || false; |
||
| 46 | } else { |
||
| 47 | fontStyle = result.fontStyle || "Consolas"; |
||
| 48 | bgColor = result.bgColor || "#FDF6E3"; |
||
| 49 | intColor = result.intColor || "#657A81"; |
||
| 50 | strColor = result.strColor || "#2AA198"; |
||
| 51 | keyColor = result.keyColor || "#B58900"; |
||
| 52 | defaultColor = result.defaultColor || "#586E75"; |
||
| 53 | |||
| 54 | strictOnly = result.strictOnly || false; |
||
| 55 | hideDetails = result.hideDetails || false; |
||
| 56 | } |
||
| 57 | |||
| 58 | var str, jsonpMatch, hovered, tag, |
||
| 59 | chrome = this.chrome || this.browser, |
||
| 60 | jsonRe = /^\s*(?:\[\s*(?=-?\d|true|false|null|["[{])[^]*\]|\{\s*"[^]+\})\s*$/, |
||
| 61 | div = document.createElement("div"), |
||
| 62 | body = document.body, |
||
| 63 | first = body && body.firstChild, |
||
| 64 | mod = /Mac|iPod|iPhone|iPad|Pike/.test(navigator.platform) ? "metaKey" : "ctrlKey", |
||
| 65 | // rand = Math.random().toString(36).slice(2), |
||
| 66 | rand = 1; |
||
| 67 | HOV = "H" + rand, |
||
| 68 | DIV = "D" + rand, |
||
| 69 | KEY = "K" + rand, |
||
| 70 | STR = "S" + rand, |
||
| 71 | BOOL = "B" + rand, |
||
| 72 | ERR = "E" + rand, |
||
| 73 | COLL = "C" + rand; |
||
| 74 | |||
| 75 | function reconvert(str) { |
||
| 76 | str = str.replace(/(\\u)(\w{1,4})/gi, function($0) { |
||
| 77 | return (String.fromCharCode(parseInt((escape($0).replace(/(%5Cu)(\w{1,4})/g, "$2")), 16))); |
||
| 78 | }); |
||
| 79 | str = str.replace(/(&#x)(\w{1,4});/gi, function($0) { |
||
| 80 | return String.fromCharCode(parseInt(escape($0).replace(/(%26%23x)(\w{1,4})(%3B)/g, "$2"), 16)); |
||
| 81 | }); |
||
| 82 | str = str.replace(/(&#)(\d{1,6});/gi, function($0) { |
||
| 83 | return String.fromCharCode(parseInt(escape($0).replace(/(%26%23)(\d{1,6})(%3B)/g, "$2"))); |
||
| 84 | }); |
||
| 85 | |||
| 86 | return str; |
||
| 87 | } |
||
| 88 | |||
| 89 | function units(size) { |
||
| 90 | return size > 1048576 ? (0 | (size / 1048576)) + "MB" : |
||
| 91 | size > 1024 ? (0 | (size / 1024)) + "KB" : |
||
| 92 | size + "B"; |
||
| 93 | } |
||
| 94 | |||
| 95 | function fragment(a, b) { |
||
| 96 | var frag = document.createDocumentFragment(); |
||
| 97 | frag.appendChild(document.createTextNode(a)); |
||
| 98 | if (b) { |
||
| 99 | frag.appendChild(div.cloneNode()); |
||
| 100 | frag.appendChild(document.createTextNode(b)); |
||
| 101 | } else { |
||
| 102 | frag.appendChild(document.createElement("br")); |
||
| 103 | } |
||
| 104 | return frag; |
||
| 105 | } |
||
| 106 | |||
| 107 | function change(node, query, name, set) { |
||
| 108 | var list = node.querySelectorAll(query), |
||
| 109 | i = list.length; |
||
| 110 | for (; i--;) list[i].classList[set ? "add" : "remove"](name); |
||
| 111 | } |
||
| 112 | |||
| 113 | function changeSiblings(node, name, set) { |
||
| 114 | var tmp, i = 0, |
||
| 115 | query = []; |
||
| 116 | |||
| 117 | for (; node && node.tagName === "I";) { |
||
| 118 | tmp = node.previousElementSibling; |
||
| 119 | if (tmp && tmp.className == KEY) { |
||
| 120 | query.unshift(".D" + rand + ">i.I" + rand + "[data-key='" + node.dataset.key + "']"); |
||
| 121 | } else if (query[0]) { |
||
| 122 | query.unshift(".D" + rand + ">i.I" + rand); |
||
| 123 | } else { |
||
| 124 | for (; tmp; tmp = tmp.previousElementSibling) |
||
| 125 | if (tmp.tagName === "BR") i++; |
||
| 126 | query.unshift(".D" + rand + ">" + (i ? "br:nth-of-type(" + i + ")+i.I" + rand : "i.I" + rand + ":first-child")); |
||
| 127 | } |
||
| 128 | node = node.parentNode && node.parentNode.previousElementSibling; |
||
| 129 | } |
||
| 130 | if (!query[1]) return; |
||
| 131 | query[0] = ".R" + rand + ">i.I" + rand; |
||
| 132 | change(document, query.join("+"), name, set); |
||
| 133 | } |
||
| 134 | |||
| 135 | function keydown(e) { |
||
| 136 | if (hovered) { |
||
| 137 | e.preventDefault(); |
||
| 138 | if (e.altKey) { |
||
| 139 | changeSiblings(hovered, HOV, 1); |
||
| 140 | } else if (e[mod]) { |
||
| 141 | change(hovered.nextSibling, "i.I" + rand, HOV, 1); |
||
| 142 | } |
||
| 143 | } |
||
| 144 | } |
||
| 145 | |||
| 146 | function init() { |
||
| 147 | tag = document.createElement("style"); |
||
| 148 | tag.textContent = [ |
||
| 149 | '.R', ',.D', '{font:16px ' + fontStyle + '}' + |
||
| 150 | '.D', '{margin-left:6px; padding-left:1em; margin-top: 1px; border-left:1px dashed; border-color: #93A1A1;}' + |
||
| 151 | '.X', '{border:1px solid #ccc; padding:1em}' + |
||
| 152 | 'a.L', '{text-decoration:none}' + |
||
| 153 | 'a.L', ':hover,a.L', ':focus{text-decoration:underline}' + |
||
| 154 | 'i.I', '{cursor:pointer;color:#ccc}' + |
||
| 155 | 'i.H', ',i.I', ':hover{text-shadow: 1px 1px 3px #999; color:#333}' + |
||
| 156 | 'i.I', ':before{content:" ▼ "}' + |
||
| 157 | 'i.C', ':before{content:" ▶ "}' + |
||
| 158 | 'i.I', ':after{content:attr(data-content)}' + |
||
| 159 | 'i.C', '+.D', '{width:1px; height:1px; margin:0; padding:0; border:0; display:inline-block; overflow:hidden}' + |
||
| 160 | '.S', '{color:' + strColor + '}' + // string |
||
| 161 | '.K', '{color:' + keyColor + '}' + // key |
||
| 162 | '.E', '{color:#BCADAD}' + // error |
||
| 163 | '.B', '{color:' + intColor + '}' + // number and bool |
||
| 164 | '.E', ',.B', '{font-style: italic}' + // number bold |
||
| 165 | 'h3.E', '{margin:0 0 1em}' |
||
| 166 | ].join(rand); |
||
| 167 | |||
| 168 | tag.textContent = tag.textContent + 'body {background: ' + bgColor + '; color:' + defaultColor + ';}'; |
||
| 169 | |||
| 170 | div.classList.add(DIV); |
||
| 171 | document.head.appendChild(tag); |
||
| 172 | document.addEventListener("keydown", keydown); |
||
| 173 | document.addEventListener("keyup", function(e) { |
||
| 174 | if (hovered) change(document, "." + HOV, HOV); |
||
| 175 | }) |
||
| 176 | document.addEventListener("mouseover", function(e) { |
||
| 177 | if (e.target.tagName === "I") { |
||
| 178 | hovered = e.target; |
||
| 179 | keydown(e); |
||
| 180 | } |
||
| 181 | }) |
||
| 182 | document.addEventListener("mouseout", function(e) { |
||
| 183 | if (hovered) { |
||
| 184 | change(document, "." + HOV, HOV); |
||
| 185 | hovered = null; |
||
| 186 | } |
||
| 187 | }) |
||
| 188 | } |
||
| 189 | |||
| 190 | function draw(str, to, first, box) { |
||
| 191 | tag || init(); |
||
| 192 | |||
| 193 | var re = /("(?:((?:https?|file):\/\/(?:\\?\S)+?)|(?:\\?.)*?)")\s*(:?)|-?\d+\.?\d*(?:e[+-]?\d+)?|true|false|null|[[\]{},]|(\S[^-[\]{},"\d]*)/gi, |
||
| 194 | node = div.cloneNode(), |
||
| 195 | link = document.createElement("a"), |
||
| 196 | span = document.createElement("span"), |
||
| 197 | info = document.createElement("i"), |
||
| 198 | colon = document.createTextNode(": "), |
||
| 199 | comma = fragment(","), |
||
| 200 | path = [], |
||
| 201 | cache = { |
||
| 202 | "{": fragment("{", "}"), |
||
| 203 | "[": fragment("[", "]") |
||
| 204 | }; |
||
| 205 | |||
| 206 | node.className = "R" + rand + (box ? " " + box : ""); |
||
| 207 | |||
| 208 | link.classList.add("L" + rand); |
||
| 209 | info.classList.add("I" + rand); |
||
| 210 | |||
| 211 | to.addEventListener("click", function(e) { |
||
| 212 | var target = e.target, |
||
| 213 | open = target.classList.contains(COLL); |
||
| 214 | if (target.tagName == "I") { |
||
| 215 | if (e.altKey) { |
||
| 216 | changeSiblings(target, COLL, !open); |
||
| 217 | } else if (e[mod]) { |
||
| 218 | open = target.nextSibling.querySelector("i"); |
||
| 219 | if (open) change(target.nextSibling, "i", COLL, !open.classList.contains(COLL)); |
||
| 220 | } else { |
||
| 221 | target.classList[open ? "remove" : "add"](COLL); |
||
| 222 | } |
||
| 223 | } |
||
| 224 | }, true); |
||
| 225 | |||
| 226 | to.replaceChild(box = node, first); |
||
| 227 | loop(str, re); |
||
| 228 | |||
| 229 | function loop(str, re) { |
||
| 230 | str = reconvert(str); |
||
| 231 | var match, val, tmp, i = 0, |
||
| 232 | len = str.length; |
||
| 233 | try { |
||
| 234 | for (; match = re.exec(str);) { |
||
| 235 | val = match[0]; |
||
| 236 | if (val == "{" || val == "[") { |
||
| 237 | path.push(node); |
||
| 238 | node.appendChild(cache[val].cloneNode(true)); |
||
| 239 | node = node.lastChild.previousSibling; |
||
| 240 | node.len = 1; |
||
| 241 | node.start = re.lastIndex; |
||
| 242 | } else if ((val == "}" || val == "]") && node.len) { |
||
| 243 | if (node.childNodes.length) { |
||
| 244 | tmp = info.cloneNode(); |
||
| 245 | if (!hideDetails) { |
||
| 246 | tmp.dataset.content = node.len + ( |
||
| 247 | node.len == 1 ? |
||
| 248 | (val == "]" ? " item, " : " property, ") : |
||
| 249 | (val == "]" ? " items, " : " properties, ") |
||
| 250 | ) + units(re.lastIndex - node.start + 1); |
||
| 251 | } |
||
| 252 | |||
| 253 | if ((val = node.previousElementSibling) && val.className == KEY) { |
||
| 254 | tmp.dataset.key = reconvert(val.textContent.slice(1, -1).replace(/'/, "\\'")); |
||
| 255 | } |
||
| 256 | node.parentNode.insertBefore(tmp, node); |
||
| 257 | } else { |
||
| 258 | node.parentNode.removeChild(node); |
||
| 259 | } |
||
| 260 | node = path.pop(); |
||
| 261 | } else if (val == ",") { |
||
| 262 | node.len += 1; |
||
| 263 | node.appendChild(comma.cloneNode(true)); |
||
| 264 | } else { |
||
| 265 | if (match[2]) { |
||
| 266 | tmp = link.cloneNode(); |
||
| 267 | tmp.href = match[2].replace(/\\"/g, '"'); |
||
| 268 | } else { |
||
| 269 | tmp = span.cloneNode(); |
||
| 270 | } |
||
| 271 | tmp.textContent = match[1] || val; |
||
| 272 | tmp.classList.add(match[3] ? KEY : match[1] ? STR : match[4] ? ERR : BOOL); |
||
| 273 | node.appendChild(tmp); |
||
| 274 | if (match[3]) { |
||
| 275 | node.appendChild(colon.cloneNode()); |
||
| 276 | } |
||
| 277 | } |
||
| 278 | if (++i > 1000) { |
||
| 279 | document.title = (0 | (100 * re.lastIndex / len)) + "% of " + units(len); |
||
| 280 | return setTimeout(function() { |
||
| 281 | loop(str, re) |
||
| 282 | }); |
||
| 283 | } |
||
| 284 | } |
||
| 285 | document.title = "" |
||
| 286 | JSON.parse(str) |
||
| 287 | } catch (e) { |
||
| 288 | tmp = document.createElement("h3"); |
||
| 289 | tmp.className = ERR; |
||
| 290 | tmp.textContent = e; |
||
| 291 | box.insertBefore(tmp, box.firstChild); |
||
| 292 | } |
||
| 293 | } |
||
| 294 | } |
||
| 295 | |||
| 296 | if (strictOnly) { |
||
| 297 | // only render when the contentType is json |
||
| 298 | if (/[+\/]json$/i.test(document.contentType)) { |
||
| 299 | draw(str, body, first) |
||
| 300 | } |
||
| 301 | } else { |
||
| 302 | // check whether the content is json or like json |
||
| 303 | if (first && |
||
| 304 | (first.tagName == "PRE" && |
||
| 305 | first == body.lastElementChild || |
||
| 306 | first == body.lastChild && |
||
| 307 | first.nodeType == 3) && |
||
| 308 | (str = first.textContent) && |
||
| 309 | (/[+\/]json$/i.test(document.contentType) || |
||
| 310 | (jsonpMatch = /^\s*((?:\/\*\*\/\s*)?([$a-z_][$\w]*)\s*(?:&&\s*\2\s*)?\()([^]+)(\)[\s;]*)$/i.exec(str)) && |
||
| 311 | jsonRe.test(jsonpMatch[3]) || jsonRe.test(str))) { |
||
| 312 | if (jsonpMatch) { |
||
| 313 | str = jsonpMatch[3] |
||
| 314 | body.replaceChild(fragment(jsonpMatch[1], jsonpMatch[4]), first) |
||
| 315 | first = body.lastChild.previousSibling |
||
| 316 | } |
||
| 317 | draw(str, body, first) |
||
| 318 | } |
||
| 319 | } |
||
| 320 | |||
| 321 | chrome.runtime.onMessage.addListener(function(req, sender, sendResponse) { |
||
| 322 | var node, |
||
| 323 | sel = window.getSelection(), |
||
| 324 | range = sel.rangeCount && sel.getRangeAt(0), |
||
| 325 | str = range && range.toString() |
||
| 326 | |||
| 327 | if (!str) return |
||
| 328 | |||
| 329 | if (req.op === "formatSelection") { |
||
| 330 | node = document.createElement("div") |
||
| 331 | range.deleteContents() |
||
| 332 | range.insertNode(node) |
||
| 333 | sel.removeAllRanges() |
||
| 334 | draw(str, node.parentNode, node, "X" + rand) |
||
| 335 | } |
||
| 336 | }) |
||
| 337 | } |
||
| 338 | |||
| 339 | function formatJson(json, options) { |
||
| 340 | var reg = null, |
||
| 341 | formatted = '', |
||
| 342 | pad = 0, |
||
| 343 | PADDING = ' '; |
||
| 344 | options = options || {}; |
||
| 345 | options.newlineAfterColonIfBeforeBraceOrBracket = (options.newlineAfterColonIfBeforeBraceOrBracket === true) ? true : false; |
||
| 346 | options.spaceAfterColon = (options.spaceAfterColon === false) ? false : true; |
||
| 347 | if (typeof json !== 'string') { |
||
| 348 | json = JSON.stringify(json); |
||
| 349 | } else { |
||
| 350 | json = JSON.parse(json); |
||
| 351 | json = JSON.stringify(json); |
||
| 352 | } |
||
| 353 | reg = /([\{\}])/g; |
||
| 354 | json = json.replace(reg, '\r\n$1\r\n'); |
||
| 355 | reg = /([\[\]])/g; |
||
| 356 | json = json.replace(reg, '\r\n$1\r\n'); |
||
| 357 | reg = /(\,)/g; |
||
| 358 | json = json.replace(reg, '$1\r\n'); |
||
| 359 | reg = /(\r\n\r\n)/g; |
||
| 360 | json = json.replace(reg, '\r\n'); |
||
| 361 | reg = /\r\n\,/g; |
||
| 362 | json = json.replace(reg, ','); |
||
| 363 | if (!options.newlineAfterColonIfBeforeBraceOrBracket) { |
||
| 364 | reg = /\:\r\n\{/g; |
||
| 365 | json = json.replace(reg, ':{'); |
||
| 366 | reg = /\:\r\n\[/g; |
||
| 367 | json = json.replace(reg, ':['); |
||
| 368 | } |
||
| 369 | if (options.spaceAfterColon) { |
||
| 370 | reg = /\:/g; |
||
| 371 | json = json.replace(reg, ':'); |
||
| 372 | }(json.split('\r\n')).forEach(function (node, index) { |
||
| 373 | var i = 0, |
||
| 374 | indent = 0, |
||
| 375 | padding = ''; |
||
| 376 | if (node.match(/\{$/) || node.match(/\[$/)) { |
||
| 377 | indent = 1; |
||
| 378 | } else if (node.match(/\}/) || node.match(/\]/)) { |
||
| 379 | if (pad !== 0) { |
||
| 380 | pad -= 1; |
||
| 381 | } |
||
| 382 | } else { |
||
| 383 | indent = 0; |
||
| 384 | } |
||
| 385 | for (i = 0; i < pad; i++) { |
||
| 386 | padding += PADDING; |
||
| 387 | } |
||
| 388 | formatted += padding + node + '\r\n'; |
||
| 389 | pad += indent; |
||
| 390 | } |
||
| 391 | ); |
||
| 392 | return formatted; |
||
| 393 | }; |
||
| 394 | |||
| 395 | function isJSON(str) { |
||
| 396 | if (typeof str == 'string') { |
||
| 397 | try { |
||
| 398 | var obj = JSON.parse(str); |
||
| 399 | if (str.indexOf('{') > - 1) { |
||
| 400 | return true; |
||
| 401 | } else { |
||
| 402 | return false; |
||
| 403 | } |
||
| 404 | } catch (e) { |
||
| 405 | return false; |
||
| 406 | } |
||
| 407 | } |
||
| 408 | return false; |
||
| 409 | } |
||
| 410 | |||
| 411 | function onParse() { |
||
| 412 | var items = document.getElementsByClassName('S1'); |
||
| 413 | for (var i = 0; i < items.length; i++) { |
||
| 414 | try { |
||
| 415 | var json = (eval(items[i].innerHTML)); |
||
| 416 | if (isJSON(json)) { |
||
| 417 | var formated = formatJson(json); |
||
| 418 | console.log(formated); |
||
|
0 ignored issues
–
show
Debugging Code
introduced
by
Loading history...
|
|||
| 419 | items[i].onclick = function() { |
||
| 420 | alert(formated); |
||
| 421 | } |
||
| 422 | } |
||
| 423 | } catch (e) {} |
||
| 424 | } |
||
| 425 | } |
||
| 426 | |||
| 427 | var getting = browser.storage.local.get(); |
||
| 428 | getting.then(onGot, onError).then(onParse, onError); |
||
| 429 |