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