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 | var bgColor, intColor, strColor, keyColor, defaultColor; |
||
| 24 | |||
| 25 | function onError(error) { |
||
| 26 | console.log(`Error: ${error}`); |
||
| 27 | } |
||
| 28 | |||
| 29 | function onGot(result) { |
||
| 30 | console.log((result[0])); |
||
|
0 ignored issues
–
show
Debugging Code
introduced
by
Loading history...
|
|||
| 31 | bgColor = result[0].bgColor || "#FDF6E3"; |
||
| 32 | intColor = result[0].intColor || "#657A81"; |
||
| 33 | strColor = result[0].strColor || "#2AA198"; |
||
| 34 | keyColor = result[0].keyColor || "#B58900"; |
||
| 35 | defaultColor = result[0].defaultColor || "#586E75"; |
||
| 36 | |||
| 37 | var str, jsonpMatch, hovered, tag, |
||
| 38 | chrome = this.chrome || this.browser, |
||
| 39 | jsonRe = /^\s*(?:\[\s*(?=-?\d|true|false|null|["[{])[^]*\]|\{\s*"[^]+\})\s*$/, |
||
| 40 | div = document.createElement("div"), |
||
| 41 | body = document.body, |
||
| 42 | first = body && body.firstChild, |
||
| 43 | mod = /Mac|iPod|iPhone|iPad|Pike/.test(navigator.platform) ? "metaKey" : "ctrlKey", |
||
| 44 | rand = Math.random().toString(36).slice(2), |
||
| 45 | HOV = "H" + rand, |
||
| 46 | DIV = "D" + rand, |
||
| 47 | KEY = "K" + rand, |
||
| 48 | STR = "S" + rand, |
||
| 49 | BOOL = "B" + rand, |
||
| 50 | ERR = "E" + rand, |
||
| 51 | COLL = "C" + rand; |
||
| 52 | |||
| 53 | function reconvert(str){ |
||
| 54 | str = str.replace(/(\\u)(\w{1,4})/gi, function($0) { |
||
| 55 | return (String.fromCharCode(parseInt((escape($0).replace(/(%5Cu)(\w{1,4})/g, "$2")), 16))); |
||
| 56 | }); |
||
| 57 | str = str.replace(/(&#x)(\w{1,4});/gi, function($0) { |
||
| 58 | return String.fromCharCode(parseInt(escape($0).replace(/(%26%23x)(\w{1,4})(%3B)/g, "$2"),16)); |
||
| 59 | }); |
||
| 60 | str = str.replace(/(&#)(\d{1,6});/gi, function($0) { |
||
| 61 | return String.fromCharCode(parseInt(escape($0).replace(/(%26%23)(\d{1,6})(%3B)/g, "$2"))); |
||
| 62 | }); |
||
| 63 | |||
| 64 | return str; |
||
| 65 | } |
||
| 66 | |||
| 67 | function units(size) { |
||
| 68 | return size > 1048576 ? (0|(size / 1048576)) + "MB" : |
||
| 69 | size > 1024 ? (0|(size / 1024)) + "KB" : |
||
| 70 | size + "B"; |
||
| 71 | } |
||
| 72 | |||
| 73 | function fragment(a, b) { |
||
| 74 | var frag = document.createDocumentFragment(); |
||
| 75 | frag.appendChild(document.createTextNode(a)); |
||
| 76 | if (b) { |
||
| 77 | frag.appendChild(div.cloneNode()); |
||
| 78 | frag.appendChild(document.createTextNode(b)); |
||
| 79 | } else { |
||
| 80 | frag.appendChild(document.createElement("br")); |
||
| 81 | } |
||
| 82 | return frag; |
||
| 83 | } |
||
| 84 | |||
| 85 | function change(node, query, name, set) { |
||
| 86 | var list = node.querySelectorAll(query), i = list.length; |
||
| 87 | for (; i--; ) list[i].classList[set ? "add" : "remove"](name); |
||
| 88 | } |
||
| 89 | |||
| 90 | function changeSiblings(node, name, set) { |
||
| 91 | var tmp, i = 0, query = []; |
||
| 92 | |||
| 93 | for (; node && node.tagName === "I"; ) { |
||
| 94 | tmp = node.previousElementSibling; |
||
| 95 | if (tmp && tmp.className == KEY) { |
||
| 96 | query.unshift(".D" + rand + ">i.I" + rand + "[data-key='" + node.dataset.key + "']"); |
||
| 97 | } else if (query[0]) { |
||
| 98 | query.unshift(".D" + rand + ">i.I" + rand); |
||
| 99 | } else { |
||
| 100 | for (; tmp; tmp = tmp.previousElementSibling) if (tmp.tagName === "BR") i++; |
||
| 101 | query.unshift(".D" + rand + ">" + (i ? "br:nth-of-type(" + i + ")+i.I" + rand : "i.I" + rand + ":first-child")); |
||
| 102 | } |
||
| 103 | node = node.parentNode && node.parentNode.previousElementSibling; |
||
| 104 | } |
||
| 105 | if (!query[1]) return; |
||
| 106 | query[0] = ".R" + rand + ">i.I" + rand; |
||
| 107 | change(document, query.join("+"), name, set); |
||
| 108 | } |
||
| 109 | |||
| 110 | function keydown(e) { |
||
| 111 | if (hovered) { |
||
| 112 | e.preventDefault(); |
||
| 113 | if (e.altKey) { |
||
| 114 | changeSiblings(hovered, HOV, 1); |
||
| 115 | } else if (e[mod]) { |
||
| 116 | change(hovered.nextSibling, "i.I" + rand, HOV, 1); |
||
| 117 | } |
||
| 118 | } |
||
| 119 | } |
||
| 120 | |||
| 121 | function init() { |
||
| 122 | tag = document.createElement("style"); |
||
| 123 | tag.textContent = [ |
||
| 124 | '.R', ',.D', '{font:16px consolas, Menlo, monospace}' + |
||
| 125 | '.D', '{margin-left:6px; padding-left:1em; margin-top: 1px; border-left:1px dashed; border-color: #93A1A1;}' + |
||
| 126 | '.X', '{border:1px solid #ccc; padding:1em}' + |
||
| 127 | 'a.L', '{text-decoration:none}' + |
||
| 128 | 'a.L', ':hover,a.L', ':focus{text-decoration:underline}' + |
||
| 129 | 'i.I', '{cursor:pointer;color:#ccc}' + |
||
| 130 | 'i.H', ',i.I', ':hover{text-shadow: 1px 1px 3px #999; color:#333}'+ |
||
| 131 | 'i.I', ':before{content:" ▼ "}' + |
||
| 132 | 'i.C', ':before{content:" ▶ "}' + |
||
| 133 | 'i.I', ':after{content:attr(data-content)}' + |
||
| 134 | 'i.C', '+.D', '{width:1px; height:1px; margin:0; padding:0; border:0; display:inline-block; overflow:hidden}' + |
||
| 135 | '.S', '{color:' + strColor + '}' + // string |
||
| 136 | '.K', '{color:' + keyColor + '}' + // key |
||
| 137 | '.E', '{color:#BCADAD}' + // error |
||
| 138 | '.B', '{color:' + intColor + '}' + // number and bool |
||
| 139 | '.E', ',.B', '{font-style: italic}' + // number bold |
||
| 140 | 'h3.E', '{margin:0 0 1em}' |
||
| 141 | ].join(rand); |
||
| 142 | |||
| 143 | tag.textContent = tag.textContent + 'body {background: ' + bgColor + '; color:' + defaultColor + ';}'; |
||
| 144 | |||
| 145 | div.classList.add(DIV); |
||
| 146 | document.head.appendChild(tag); |
||
| 147 | document.addEventListener("keydown", keydown); |
||
| 148 | document.addEventListener("keyup", function(e) { |
||
| 149 | if (hovered) change(document, "." + HOV, HOV); |
||
| 150 | }) |
||
| 151 | document.addEventListener("mouseover", function(e) { |
||
| 152 | if (e.target.tagName === "I") { |
||
| 153 | hovered = e.target; |
||
| 154 | keydown(e); |
||
| 155 | } |
||
| 156 | }) |
||
| 157 | document.addEventListener("mouseout", function(e) { |
||
| 158 | if (hovered) { |
||
| 159 | change(document, "." + HOV, HOV); |
||
| 160 | hovered = null; |
||
| 161 | } |
||
| 162 | }) |
||
| 163 | } |
||
| 164 | |||
| 165 | function draw(str, to, first, box) { |
||
| 166 | tag || init(); |
||
| 167 | |||
| 168 | var re = /("(?:((?:https?|file):\/\/(?:\\?\S)+?)|(?:\\?.)*?)")\s*(:?)|-?\d+\.?\d*(?:e[+-]?\d+)?|true|false|null|[[\]{},]|(\S[^-[\]{},"\d]*)/gi |
||
| 169 | , node = div.cloneNode() |
||
| 170 | , link = document.createElement("a") |
||
| 171 | , span = document.createElement("span") |
||
| 172 | , info = document.createElement("i") |
||
| 173 | , colon = document.createTextNode(": ") |
||
| 174 | , comma = fragment(",") |
||
| 175 | , path = [] |
||
| 176 | , cache = { |
||
| 177 | "{": fragment("{", "}"), |
||
| 178 | "[": fragment("[", "]") |
||
| 179 | }; |
||
| 180 | |||
| 181 | node.className = "R" + rand + (box ? " " + box : ""); |
||
| 182 | |||
| 183 | link.classList.add("L" + rand); |
||
| 184 | info.classList.add("I" + rand); |
||
| 185 | |||
| 186 | to.addEventListener("click", function(e) { |
||
| 187 | var target = e.target, open = target.classList.contains(COLL); |
||
| 188 | if (target.tagName == "I") { |
||
| 189 | if (e.altKey) { |
||
| 190 | changeSiblings(target, COLL, !open); |
||
| 191 | } else if (e[mod]) { |
||
| 192 | open = target.nextSibling.querySelector("i"); |
||
| 193 | if (open) change(target.nextSibling, "i", COLL, !open.classList.contains(COLL)); |
||
| 194 | } else { |
||
| 195 | target.classList[open ? "remove" : "add"](COLL); |
||
| 196 | } |
||
| 197 | } |
||
| 198 | }, true); |
||
| 199 | |||
| 200 | to.replaceChild(box = node, first); |
||
| 201 | loop(str, re); |
||
| 202 | |||
| 203 | function loop(str, re) { |
||
| 204 | str = reconvert(str); |
||
| 205 | var match, val, tmp, i = 0, len = str.length; |
||
| 206 | try { |
||
| 207 | for (; match = re.exec(str); ) { |
||
| 208 | val = match[0]; |
||
| 209 | if (val == "{" || val == "[") { |
||
| 210 | path.push(node); |
||
| 211 | node.appendChild(cache[val].cloneNode(true)); |
||
| 212 | node = node.lastChild.previousSibling; |
||
| 213 | node.len = 1; |
||
| 214 | node.start = re.lastIndex; |
||
| 215 | } else if ((val == "}" || val == "]") && node.len) { |
||
| 216 | if (node.childNodes.length) { |
||
| 217 | tmp = info.cloneNode(); |
||
| 218 | tmp.dataset.content = node.len + ( |
||
| 219 | node.len == 1 ? |
||
| 220 | (val == "]" ? " item, " : " property, ") : |
||
| 221 | (val == "]" ? " items, " : " properties, ") |
||
| 222 | ) + units(re.lastIndex - node.start + 1); |
||
| 223 | |||
| 224 | if ((val = node.previousElementSibling) && val.className == KEY) { |
||
| 225 | tmp.dataset.key = reconvert(val.textContent.slice(1, -1).replace(/'/, "\\'")); |
||
| 226 | } |
||
| 227 | node.parentNode.insertBefore(tmp, node); |
||
| 228 | } else { |
||
| 229 | node.parentNode.removeChild(node); |
||
| 230 | } |
||
| 231 | node = path.pop(); |
||
| 232 | } else if (val == ",") { |
||
| 233 | node.len += 1; |
||
| 234 | node.appendChild(comma.cloneNode(true)); |
||
| 235 | } else { |
||
| 236 | if (match[2]) { |
||
| 237 | tmp = link.cloneNode(); |
||
| 238 | tmp.href = match[2].replace(/\\"/g, '"'); |
||
| 239 | } else { |
||
| 240 | tmp = span.cloneNode(); |
||
| 241 | } |
||
| 242 | tmp.textContent = match[1] || val; |
||
| 243 | tmp.classList.add(match[3] ? KEY : match[1] ? STR : match[4] ? ERR : BOOL); |
||
| 244 | node.appendChild(tmp); |
||
| 245 | if (match[3]) { |
||
| 246 | node.appendChild(colon.cloneNode()); |
||
| 247 | } |
||
| 248 | } |
||
| 249 | if (++i > 1000) { |
||
| 250 | document.title = (0|(100*re.lastIndex/len)) + "% of " + units(len); |
||
| 251 | return setTimeout(function() { loop(str, re) }); |
||
| 252 | } |
||
| 253 | } |
||
| 254 | document.title = "" |
||
| 255 | JSON.parse(str) |
||
| 256 | } catch(e) { |
||
| 257 | tmp = document.createElement("h3"); |
||
| 258 | tmp.className = ERR; |
||
| 259 | tmp.textContent = e; |
||
| 260 | box.insertBefore(tmp, box.firstChild); |
||
| 261 | } |
||
| 262 | } |
||
| 263 | } |
||
| 264 | |||
| 265 | // check whether the content is json or like json |
||
| 266 | if (first |
||
| 267 | && (first.tagName == "PRE" |
||
| 268 | && first == body.lastElementChild |
||
| 269 | || first == body.lastChild |
||
| 270 | && first.nodeType == 3) |
||
| 271 | && (str = first.textContent) |
||
| 272 | && (/[+\/]json$/i.test(document.contentType) |
||
| 273 | || (jsonpMatch = /^\s*((?:\/\*\*\/\s*)?([$a-z_][$\w]*)\s*(?:&&\s*\2\s*)?\()([^]+)(\)[\s;]*)$/i.exec(str)) |
||
| 274 | && jsonRe.test(jsonpMatch[3]) || jsonRe.test(str))) |
||
| 275 | { |
||
| 276 | if (jsonpMatch) { |
||
| 277 | str = jsonpMatch[3] |
||
| 278 | body.replaceChild(fragment(jsonpMatch[1], jsonpMatch[4]), first) |
||
| 279 | first = body.lastChild.previousSibling |
||
| 280 | } |
||
| 281 | draw(str, body, first) |
||
| 282 | } |
||
| 283 | |||
| 284 | chrome.runtime.onMessage.addListener(function(req, sender, sendResponse) { |
||
| 285 | var node, |
||
| 286 | sel = window.getSelection(), |
||
| 287 | range = sel.rangeCount && sel.getRangeAt(0), |
||
| 288 | str = range && range.toString() |
||
| 289 | |||
| 290 | if (!str) return |
||
| 291 | |||
| 292 | if (req.op === "formatSelection") { |
||
| 293 | node = document.createElement("div") |
||
| 294 | range.deleteContents() |
||
| 295 | range.insertNode(node) |
||
| 296 | sel.removeAllRanges() |
||
| 297 | draw(str, node.parentNode, node, "X" + rand) |
||
| 298 | } |
||
| 299 | }) |
||
| 300 | } |
||
| 301 | |||
| 302 | var getting = browser.storage.local.get(); |
||
| 303 | getting.then(onGot, onError); |
||
| 304 | |||
| 305 |