Completed
Push — master ( a00cdd...6ad87d )
by Dongxin
01:02
created

mjsonviewer.js (17 issues)

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}`);
0 ignored issues
show
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
27
}
28
29
function onGot(result) {
30
    console.log((result[0]));
0 ignored issues
show
console.log looks like debug code. Are you sure you do not want to remove it?
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",
0 ignored issues
show
The variable navigator seems to be never declared. If this is a global, consider adding a /** global: navigator */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
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);
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
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++;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
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;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
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) {
0 ignored issues
show
The parameter e is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
149
            if (hovered) change(document, "." + HOV, HOV);
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
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) {
0 ignored issues
show
The parameter e is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
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));
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
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);
0 ignored issues
show
The variable node is changed as part of the for loop for example by node.lastChild.previousSibling on line 212. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
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)
0 ignored issues
show
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
256
            } catch(e) {
257
                tmp = document.createElement("h3");
258
                tmp.className = ERR;
259
                tmp.textContent = e;
260
                box.insertBefore(tmp, box.firstChild);
0 ignored issues
show
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
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) {
0 ignored issues
show
The parameter sendResponse is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
The parameter sender is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
285
        var node,
286
            sel   = window.getSelection(),
287
            range = sel.rangeCount && sel.getRangeAt(0),
288
            str   = range && range.toString()
289
290
        if (!str) return
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
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();
0 ignored issues
show
The variable browser seems to be never declared. If this is a global, consider adding a /** global: browser */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
303
getting.then(onGot, onError);
304
305