Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c7c5e04b8b | ||
|
|
a2efc328d4 | ||
|
|
97b8591fec | ||
|
|
4750728630 | ||
|
|
2ee0cec69a | ||
|
|
7a84c5e024 | ||
|
|
6365ca2155 | ||
|
|
e68e16744f | ||
|
|
39f58d6888 | ||
|
|
edbc96dba4 | ||
|
|
d5c5f6bb29 | ||
|
|
cbfc92cdd5 | ||
|
|
66d62175ce | ||
|
|
19ee292719 |
@@ -1 +1,2 @@
|
||||
src/lib/util.js
|
||||
src/lib/util.js
|
||||
src/lib/stringifyUtil.js
|
||||
@@ -2,7 +2,8 @@
|
||||
"env": {
|
||||
"browser": true,
|
||||
"commonjs": true,
|
||||
"es6": true
|
||||
"es6": true,
|
||||
"worker": true
|
||||
},
|
||||
"extends": "eslint:recommended",
|
||||
"parserOptions": {
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -7,6 +7,9 @@ eruda.js
|
||||
!/test/eruda.js
|
||||
eruda.min.js
|
||||
eruda.js.map
|
||||
stringifyWorker.js
|
||||
!/src/lib/stringifyWorker.js
|
||||
stringifyWorker.js.map
|
||||
/script/icomoon/
|
||||
/src/**/*.js.map
|
||||
npm-debug.log
|
||||
|
||||
@@ -14,3 +14,5 @@
|
||||
karma.conf.js
|
||||
karma.sauce.js
|
||||
npm-debug.log
|
||||
stringifyWorker.js
|
||||
stringifyWorker.js.map
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- "8"
|
||||
sudo: required
|
||||
addons:
|
||||
chrome: stable
|
||||
sauce_connect: true
|
||||
|
||||
@@ -111,6 +111,7 @@ It is possible to enhance Eruda with more features by writing plugins. Check sou
|
||||
* [eruda-features](https://github.com/liriliri/eruda-features): Browser feature detections.
|
||||
* [eruda-timing](https://github.com/liriliri/eruda-timing): Show performance and resource timing.
|
||||
* [eruda-memory](https://github.com/liriliri/eruda-memory): Display page memory info.
|
||||
* [eruda-code](https://github.com/liriliri/eruda-code): Run JavaScript code.
|
||||
|
||||
When writing plugins, you can use utilities exposed by Eruda, see [docs](doc/UTIL_API.md) here.
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ Eruda 是一个专为手机网页前端设计的调试面板,类似 DevTools
|
||||
通过CDN使用:
|
||||
|
||||
```html
|
||||
<script src="//cdn.bootcss.com/eruda/1.3.2/eruda.min.js"></script>
|
||||
<script src="//cdn.bootcss.com/eruda/1.4.0/eruda.min.js"></script>
|
||||
<script>eruda.init();</script>
|
||||
```
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ Display console logs. Implementation detail follows the [console api spec](https
|
||||
|displayGetterVal |boolean|Access getter value |
|
||||
|viewLogInSources |boolean|View log in sources panel |
|
||||
|displayIfErr |boolean|Auto display if error occurs |
|
||||
|useWorker |boolean|Use web worker |
|
||||
|maxLogNum |string |Max log number |
|
||||
|
||||
```javascript
|
||||
@@ -189,12 +190,21 @@ Remove specified snippet.
|
||||
|----|------|-----------------|
|
||||
|name|string|Snippet to remove|
|
||||
|
||||
### run
|
||||
|
||||
Run specified snippet.
|
||||
|
||||
|Name|Type |Desc |
|
||||
|----|------|--------------|
|
||||
|name|string|Snippet to run|
|
||||
|
||||
```javascript
|
||||
snippets.add('hello', function ()
|
||||
{
|
||||
console.log('Hello World!');
|
||||
}, 'Display hello on console');
|
||||
|
||||
snippets.run('hello');
|
||||
snippets.remove('hello');
|
||||
```
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* ```
|
||||
*/
|
||||
|
||||
_('meta clamp trim each map');
|
||||
_('meta clamp trim each map isNaN');
|
||||
|
||||
function exports()
|
||||
{
|
||||
@@ -31,5 +31,10 @@ function exports()
|
||||
if (key === 'minimum-scale') minScale = +val;
|
||||
});
|
||||
|
||||
return clamp(initialScale, minScale, maxScale);
|
||||
let ret = clamp(initialScale, minScale, maxScale);
|
||||
|
||||
// Some will use ';' to be the separator, need to avoid the wrong result.
|
||||
if (isNaN(ret)) return 1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
11
package.json
11
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "eruda",
|
||||
"version": "1.4.0",
|
||||
"version": "1.4.1",
|
||||
"description": "Console for Mobile Browsers",
|
||||
"main": "eruda.js",
|
||||
"scripts": {
|
||||
@@ -19,12 +19,18 @@
|
||||
"eustia": {
|
||||
"eruda": {
|
||||
"files": "src/**/*.js",
|
||||
"ignore": "src/**/stringify.js",
|
||||
"output": "src/lib/util.js",
|
||||
"exclude": [
|
||||
"createCfg"
|
||||
],
|
||||
"format": "es"
|
||||
},
|
||||
"stringify": {
|
||||
"files": "src/lib/stringify.js",
|
||||
"output": "src/lib/stringifyUtil.js",
|
||||
"format": "es"
|
||||
},
|
||||
"test": {
|
||||
"files": [
|
||||
"test/*.js",
|
||||
@@ -86,6 +92,7 @@
|
||||
"remap-istanbul": "^0.9.5",
|
||||
"sass-loader": "^6.0.6",
|
||||
"webpack": "^3.10.0",
|
||||
"webpack-dev-server": "^2.9.7"
|
||||
"webpack-dev-server": "^2.9.7",
|
||||
"worker-loader": "^1.1.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,17 @@ module.exports = {
|
||||
},
|
||||
module: {
|
||||
loaders: [
|
||||
{
|
||||
test: /Worker\.js$/,
|
||||
use: {
|
||||
loader: 'worker-loader',
|
||||
options: {
|
||||
inline: true,
|
||||
fallback: true,
|
||||
name: '[name].js'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
test: /\.js$/,
|
||||
exclude: /node_modules/,
|
||||
|
||||
@@ -3,6 +3,7 @@ import Tool from '../DevTools/Tool';
|
||||
import {noop, evalCss, $} from '../lib/util';
|
||||
import emitter from '../lib/emitter';
|
||||
import Settings from '../Settings/Settings';
|
||||
import stringify from './stringify';
|
||||
|
||||
export default class Console extends Tool
|
||||
{
|
||||
@@ -219,14 +220,18 @@ export default class Console extends Tool
|
||||
displayGetterVal: false,
|
||||
viewLogInSources: false,
|
||||
displayIfErr: false,
|
||||
useWorker: true,
|
||||
maxLogNum: 'infinite'
|
||||
});
|
||||
|
||||
let isWorkerSupported = !!window.Worker;
|
||||
|
||||
let maxLogNum = cfg.get('maxLogNum');
|
||||
maxLogNum = maxLogNum === 'infinite' ? maxLogNum : +maxLogNum;
|
||||
|
||||
if (cfg.get('catchGlobalErr')) this.catchGlobalErr();
|
||||
if (cfg.get('overrideConsole')) this.overrideConsole();
|
||||
if (cfg.get('useWorker') && isWorkerSupported) stringify.useWorker = true;
|
||||
logger.displayHeader(cfg.get('displayExtraInfo'));
|
||||
logger.displayUnenumerable(cfg.get('displayUnenumerable'));
|
||||
logger.displayGetterVal(cfg.get('displayGetterVal'));
|
||||
@@ -244,6 +249,7 @@ export default class Console extends Tool
|
||||
case 'displayUnenumerable': return logger.displayUnenumerable(val);
|
||||
case 'displayGetterVal': return logger.displayGetterVal(val);
|
||||
case 'viewLogInSources': return logger.viewLogInSources(val);
|
||||
case 'useWorker': stringify.useWorker = val; return;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -257,6 +263,7 @@ export default class Console extends Tool
|
||||
.switch(cfg, 'displayUnenumerable', 'Display Unenumerable Properties')
|
||||
.switch(cfg, 'displayGetterVal', 'Access Getter Value');
|
||||
|
||||
if (isWorkerSupported) settings.switch(cfg, 'useWorker', 'Use Web Worker');
|
||||
if (sources) settings.switch(cfg, 'viewLogInSources', 'View Log In Sources Panel');
|
||||
|
||||
settings.select(cfg, 'maxLogNum', 'Max Log Number', ['infinite', '250', '125', '100', '50', '10'])
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import stringify from '../lib/stringify';
|
||||
import stringify from './stringify';
|
||||
import origGetAbstract from '../lib/getAbstract';
|
||||
import highlight from '../lib/highlight';
|
||||
import beautify from 'js-beautify';
|
||||
@@ -94,12 +94,13 @@ export default class Log
|
||||
|
||||
if (this._needSrc())
|
||||
{
|
||||
let setSrc = result => this.src = result;
|
||||
if (type === 'table')
|
||||
{
|
||||
this.src = extractObj(args[0]);
|
||||
extractObj(args[0], {}, setSrc);
|
||||
} else
|
||||
{
|
||||
this.src = extractObj(args.length === 1 && isObj(args[0]) ? args[0] : args);
|
||||
extractObj(args.length === 1 && isObj(args[0]) ? args[0] : args, {}, setSrc);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -383,7 +384,10 @@ function substituteStr(args)
|
||||
|
||||
function formatObj(val)
|
||||
{
|
||||
return `${getObjType(val)} ${getAbstract(val)}`;
|
||||
let type = getObjType(val);
|
||||
if (type === 'Array' && val.length > 1) type = `(${val.length})`;
|
||||
|
||||
return `${type} ${getAbstract(val)}`;
|
||||
}
|
||||
|
||||
function formatFn(val)
|
||||
@@ -424,12 +428,12 @@ let getCurTime = () => dateFormat('HH:MM:ss');
|
||||
let tpl = require('./Log.hbs');
|
||||
let render = data => tpl(data);
|
||||
|
||||
function extractObj(obj, options = {})
|
||||
function extractObj(obj, options = {}, cb)
|
||||
{
|
||||
defaults(options, {
|
||||
getterVal: Log.showGetterVal,
|
||||
unenumerable: Log.showUnenumerable
|
||||
});
|
||||
|
||||
return JSON.parse(stringify(obj, options));
|
||||
stringify(obj, options, result => cb(JSON.parse(result)));
|
||||
}
|
||||
|
||||
@@ -361,9 +361,11 @@ let evalJs = jsInput =>
|
||||
{
|
||||
let ret;
|
||||
|
||||
try {
|
||||
try
|
||||
{
|
||||
ret = eval.call(window, `(${jsInput})`);
|
||||
} catch (e) {
|
||||
} catch (e)
|
||||
{
|
||||
ret = eval.call(window, jsInput);
|
||||
}
|
||||
|
||||
|
||||
49
src/Console/stringify.js
Normal file
49
src/Console/stringify.js
Normal file
@@ -0,0 +1,49 @@
|
||||
import stringify from '../lib/stringify';
|
||||
import StringifyWorker from '../lib/stringifyWorker';
|
||||
import {nextTick, uniqId} from '../lib/util';
|
||||
|
||||
let isWorkerSupported = !!window.Worker;
|
||||
|
||||
let callbacks = {},
|
||||
worker;
|
||||
|
||||
if (isWorkerSupported)
|
||||
{
|
||||
worker = new StringifyWorker();
|
||||
worker.onmessage = function (e)
|
||||
{
|
||||
let [id, result] = e.data;
|
||||
if (callbacks[id])
|
||||
{
|
||||
callbacks[id](result);
|
||||
delete callbacks[id];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function exports(obj, options, cb)
|
||||
{
|
||||
let useWorker = exports.useWorker && isWorkerSupported;
|
||||
|
||||
if (useWorker)
|
||||
{
|
||||
let id = uniqId('stringifyWorker');
|
||||
callbacks[id] = cb;
|
||||
// Some native object can't be cloned, such as window.location.
|
||||
try
|
||||
{
|
||||
worker.postMessage([id, obj, options]);
|
||||
return;
|
||||
} catch (e)
|
||||
{
|
||||
delete callbacks[id];
|
||||
}
|
||||
}
|
||||
|
||||
let result = stringify(obj, options);
|
||||
nextTick(() => cb(result));
|
||||
}
|
||||
|
||||
exports.useWorker = false;
|
||||
|
||||
export default exports;
|
||||
@@ -21,7 +21,6 @@ export default class DevTools extends Emitter
|
||||
{
|
||||
super();
|
||||
|
||||
if (!isMobile()) evalCss(require('../style/scrollbar.css'));
|
||||
this._style = evalCss(require('./DevTools.scss'));
|
||||
|
||||
this.$container = $container;
|
||||
@@ -76,7 +75,7 @@ export default class DevTools extends Emitter
|
||||
if (this._tools[name]) return logger.warn(`Tool ${name} already exists`);
|
||||
|
||||
this._$tools.prepend(`<div class="eruda-${name} eruda-tool"></div>`);
|
||||
tool.init(this._$tools.find(`.eruda-${name}`), this);
|
||||
tool.init(this._$tools.find(`.eruda-${name}.eruda-tool`), this);
|
||||
tool.active = false;
|
||||
this._tools[name] = tool;
|
||||
|
||||
|
||||
@@ -49,6 +49,15 @@ export default class Snippets extends Tool
|
||||
|
||||
return this;
|
||||
}
|
||||
run(name)
|
||||
{
|
||||
let snippets = this._snippets;
|
||||
|
||||
for (let i = 0, len = snippets.length; i < len; i++)
|
||||
{
|
||||
if (snippets[i].name === name) this._run(i);
|
||||
}
|
||||
}
|
||||
clear()
|
||||
{
|
||||
this._snippets = [];
|
||||
|
||||
@@ -96,6 +96,14 @@ export default [
|
||||
},
|
||||
desc: 'Display memory'
|
||||
},
|
||||
{
|
||||
name: 'Load Code Plugin',
|
||||
fn()
|
||||
{
|
||||
loadPlugin('code');
|
||||
},
|
||||
desc: 'Edit and Run JavaScript'
|
||||
},
|
||||
{
|
||||
name: 'Restore Settings',
|
||||
fn()
|
||||
@@ -192,6 +200,7 @@ function loadPlugin(name)
|
||||
let pluginVersion = {
|
||||
fps: '1.0.2',
|
||||
features: '1.0.2',
|
||||
timing: '1.0.1',
|
||||
memory: '1.0.1'
|
||||
timing: '1.1.1',
|
||||
memory: '1.0.1',
|
||||
code: '1.0.0'
|
||||
};
|
||||
|
||||
@@ -10,9 +10,14 @@ import {
|
||||
uniqId,
|
||||
upperFirst,
|
||||
isNum,
|
||||
toNum,
|
||||
isBool,
|
||||
escape,
|
||||
toStr
|
||||
toStr,
|
||||
chunk,
|
||||
each,
|
||||
map,
|
||||
isNaN
|
||||
} from './util';
|
||||
|
||||
export default class JsonViewer
|
||||
@@ -22,20 +27,122 @@ export default class JsonViewer
|
||||
evalCss(require('./json.scss'));
|
||||
|
||||
this._data = [data];
|
||||
this._data.erudaId = uniqId('erudaJson');
|
||||
this._$el = $el;
|
||||
this._map = {};
|
||||
createMap(this._map, this._data);
|
||||
|
||||
this._appendTpl();
|
||||
this._bindEvent();
|
||||
}
|
||||
jsonToHtml(data, firstLevel)
|
||||
{
|
||||
let ret = '';
|
||||
|
||||
for (let key in data)
|
||||
{
|
||||
let val = data[key];
|
||||
|
||||
if (key === 'erudaObjAbstract' ||
|
||||
key === 'erudaCircular' ||
|
||||
key === 'erudaId' ||
|
||||
key === 'erudaSplitArr' ||
|
||||
(isStr(val) && startWith(val, 'erudaJson'))) continue;
|
||||
|
||||
if (Object.hasOwnProperty.call(data, key)) ret += this.createEl(key, val, firstLevel);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
createEl(key, val, firstLevel = false)
|
||||
{
|
||||
let type = 'object',
|
||||
isUnenumerable = false,
|
||||
id;
|
||||
|
||||
if (key === 'erudaProto') key = '__proto__';
|
||||
if (startWith(key, 'erudaUnenumerable'))
|
||||
{
|
||||
key = trim(key.replace('erudaUnenumerable', ''));
|
||||
isUnenumerable = true;
|
||||
}
|
||||
|
||||
if (isArr(val)) type = 'array';
|
||||
|
||||
function wrapKey(key)
|
||||
{
|
||||
if (firstLevel) return '';
|
||||
if (isObj(val) && val.erudaSplitArr) return '';
|
||||
|
||||
let keyClass = 'eruda-key';
|
||||
if (isUnenumerable || contain(LIGHTER_KEY, key)) keyClass = 'eruda-key-lighter';
|
||||
|
||||
return `<span class="${keyClass}">${encode(key)}</span>: `;
|
||||
}
|
||||
|
||||
if (val === null)
|
||||
{
|
||||
return `<li>
|
||||
${wrapKey(key)}
|
||||
<span class="eruda-null">null</span>
|
||||
</li>`;
|
||||
}
|
||||
|
||||
if (isObj(val))
|
||||
{
|
||||
id = val.erudaId;
|
||||
let circularId = val.erudaCircular;
|
||||
let objAbstract = val['erudaObjAbstract'] || upperFirst(type);
|
||||
|
||||
let obj = `<li ${firstLevel ? 'data-first-level="true"' : ''} ${'data-object-id="' + (circularId ? circularId : id) + '"'}>
|
||||
<span class="${firstLevel ? '' : 'eruda-expanded eruda-collapsed'}"></span>
|
||||
${wrapKey(key)}
|
||||
<span class="eruda-open">${firstLevel ? '' : objAbstract}</span>
|
||||
<ul class="eruda-${type}" ${firstLevel ? '' : 'style="display:none"'}>`;
|
||||
|
||||
if (firstLevel) obj += this.jsonToHtml(this._map[id]);
|
||||
|
||||
return obj + '</ul><span class="eruda-close"></span></li>';
|
||||
}
|
||||
if (isNum(val) || isBool(val))
|
||||
{
|
||||
return `<li>
|
||||
${wrapKey(key)}
|
||||
<span class="eruda-${typeof val}">${encode(val)}</span>
|
||||
</li>`;
|
||||
}
|
||||
if (isStr(val) && startWith(val, 'function'))
|
||||
{
|
||||
return `<li>
|
||||
${wrapKey(key)}
|
||||
<span class="eruda-function">${encode(val).replace('function', '')}</span>
|
||||
</li>`;
|
||||
}
|
||||
if (val === 'undefined' || val === 'Symbol' || val === '(...)')
|
||||
{
|
||||
return `<li>
|
||||
${wrapKey(key)}
|
||||
<span class="eruda-special">${val}</span>
|
||||
</li>`;
|
||||
}
|
||||
|
||||
return `<li>
|
||||
${wrapKey(key)}
|
||||
<span class="eruda-${typeof val}">"${encode(val)}"</span>
|
||||
</li>`;
|
||||
}
|
||||
_appendTpl()
|
||||
{
|
||||
this._$el.html(jsonToHtml(this._data, this._map, true));
|
||||
let data = this._map[this._data.erudaId];
|
||||
|
||||
this._$el.html(this.jsonToHtml(data, true));
|
||||
}
|
||||
_bindEvent()
|
||||
{
|
||||
let map = this._map;
|
||||
|
||||
let self = this;
|
||||
|
||||
this._$el.on('click', 'li', function (e)
|
||||
{
|
||||
let $this = $(this),
|
||||
@@ -45,7 +152,7 @@ export default class JsonViewer
|
||||
if ($this.data('first-level')) return;
|
||||
if (circularId)
|
||||
{
|
||||
$this.find('ul').html(jsonToHtml(map[circularId], map, false));
|
||||
$this.find('ul').html(self.jsonToHtml(map[circularId], false));
|
||||
$this.rmAttr('data-object-id');
|
||||
}
|
||||
|
||||
@@ -67,108 +174,86 @@ export default class JsonViewer
|
||||
}
|
||||
}
|
||||
|
||||
function jsonToHtml(data, map, firstLevel)
|
||||
function createMap(map, data)
|
||||
{
|
||||
let ret = '';
|
||||
let id;
|
||||
|
||||
for (let key in data)
|
||||
if (data.erudaId)
|
||||
{
|
||||
id = data.erudaId;
|
||||
} else
|
||||
{
|
||||
id = uniqId('erudaJson');
|
||||
data.erudaId = id;
|
||||
}
|
||||
|
||||
if (id)
|
||||
{
|
||||
let objAbstract = data.erudaObjAbstract;
|
||||
|
||||
let isArr = objAbstract && startWith(objAbstract, 'Array');
|
||||
if (isArr)
|
||||
{
|
||||
let arr = objToArr(data);
|
||||
if (arr.length > 100) data = splitBigArr(objToArr(data), id);
|
||||
}
|
||||
map[id] = data;
|
||||
}
|
||||
|
||||
for (let key in data)
|
||||
{
|
||||
let val = data[key];
|
||||
|
||||
if (key === 'erudaObjAbstract' ||
|
||||
key === 'erudaCircular' ||
|
||||
key === 'erudaId' ||
|
||||
(isStr(val) && startWith(val, 'erudaJson'))) continue;
|
||||
|
||||
if (Object.hasOwnProperty.call(data, key)) ret += createEl(key, val, map, firstLevel);
|
||||
if (isObj(val)) createMap(map, val);
|
||||
}
|
||||
}
|
||||
|
||||
function splitBigArr(val, id)
|
||||
{
|
||||
let ret = chunk(val, 100);
|
||||
let idx = 0;
|
||||
ret = map(ret, val =>
|
||||
{
|
||||
let obj = {};
|
||||
let startIdx = idx;
|
||||
obj.erudaObjAbstract = '[' + startIdx;
|
||||
each(val, val =>
|
||||
{
|
||||
obj[idx] = val;
|
||||
idx += 1;
|
||||
});
|
||||
let endIdx = idx - 1;
|
||||
obj.erudaObjAbstract += ((endIdx - startIdx) > 0 ? (' … ' + endIdx) : '') + ']';
|
||||
obj.erudaId = uniqId('erudaJson');
|
||||
obj.erudaSplitArr = true;
|
||||
return obj;
|
||||
});
|
||||
each(val.erudaStrKeys, (val, key) => ret[key] = val);
|
||||
ret.erudaId = id;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
function createEl(key, val, map, firstLevel = false)
|
||||
function objToArr(val)
|
||||
{
|
||||
let type = 'object',
|
||||
isUnenumerable = false,
|
||||
id;
|
||||
let ret = [];
|
||||
|
||||
if (key === 'erudaProto') key = '__proto__';
|
||||
if (startWith(key, 'erudaUnenumerable'))
|
||||
let strKeys = {};
|
||||
|
||||
each(val, (val, key) =>
|
||||
{
|
||||
key = trim(key.replace('erudaUnenumerable', ''));
|
||||
isUnenumerable = true;
|
||||
}
|
||||
|
||||
if (isArr(val)) type = 'array';
|
||||
|
||||
function wrapKey(key)
|
||||
{
|
||||
if (firstLevel) return '';
|
||||
|
||||
let keyClass = 'eruda-key';
|
||||
if (isUnenumerable || contain(LIGHTER_KEY, key)) keyClass = 'eruda-key-lighter';
|
||||
|
||||
return `<span class="${keyClass}">${encode(key)}</span>: `;
|
||||
}
|
||||
|
||||
if (val === null)
|
||||
{
|
||||
return `<li>
|
||||
${wrapKey(key)}
|
||||
<span class="eruda-null">null</span>
|
||||
</li>`;
|
||||
}
|
||||
if (isObj(val))
|
||||
{
|
||||
if (val.erudaId)
|
||||
let idx = toNum(key);
|
||||
if (!isNaN(idx))
|
||||
{
|
||||
id = val.erudaId;
|
||||
} else
|
||||
ret[idx] = val;
|
||||
} else
|
||||
{
|
||||
id = uniqId('erudaJson');
|
||||
val.erudaId = id;
|
||||
strKeys[key] = val;
|
||||
}
|
||||
let circularId = val.erudaCircular;
|
||||
if (id) map[id] = val;
|
||||
let objAbstract = val['erudaObjAbstract'] || upperFirst(type);
|
||||
});
|
||||
|
||||
let obj = `<li ${firstLevel ? 'data-first-level="true"' : ''} ${'data-object-id="' + (circularId ? circularId : id) + '"'}>
|
||||
<span class="${firstLevel ? '' : 'eruda-expanded eruda-collapsed'}"></span>
|
||||
${wrapKey(key)}
|
||||
<span class="eruda-open">${firstLevel ? '' : objAbstract}</span>
|
||||
<ul class="eruda-${type}" ${firstLevel ? '' : 'style="display:none"'}>`;
|
||||
ret['erudaStrKeys'] = strKeys;
|
||||
|
||||
let jsonHtml = jsonToHtml(val, map);
|
||||
if (firstLevel) obj += jsonHtml;
|
||||
|
||||
return obj + '</ul><span class="eruda-close"></span></li>';
|
||||
}
|
||||
if (isNum(val) || isBool(val))
|
||||
{
|
||||
return `<li>
|
||||
${wrapKey(key)}
|
||||
<span class="eruda-${typeof val}">${encode(val)}</span>
|
||||
</li>`;
|
||||
}
|
||||
if (isStr(val) && startWith(val, 'function'))
|
||||
{
|
||||
return `<li>
|
||||
${wrapKey(key)}
|
||||
<span class="eruda-function">${encode(val).replace('function', '')}</span>
|
||||
</li>`;
|
||||
}
|
||||
if (val === 'undefined' || val === 'Symbol' || val === '(...)')
|
||||
{
|
||||
return `<li>
|
||||
${wrapKey(key)}
|
||||
<span class="eruda-special">${val}</span>
|
||||
</li>`;
|
||||
}
|
||||
|
||||
return `<li>
|
||||
${wrapKey(key)}
|
||||
<span class="eruda-${typeof val}">"${encode(val)}"</span>
|
||||
</li>`;
|
||||
return ret;
|
||||
}
|
||||
|
||||
const LIGHTER_KEY = ['__proto__'];
|
||||
|
||||
@@ -66,7 +66,7 @@ export default function getAbstract(obj, {
|
||||
{
|
||||
if (i > keyNum)
|
||||
{
|
||||
objEllipsis = '...';
|
||||
objEllipsis = ', …';
|
||||
return;
|
||||
}
|
||||
let key = wrapKey(escapeJsonStr(name));
|
||||
@@ -118,11 +118,22 @@ export default function getAbstract(obj, {
|
||||
if (doStringify)
|
||||
{
|
||||
json = '[';
|
||||
each(obj, val => parts.push(`${getAbstract(val, passOpts)}`));
|
||||
json += parts.join(', ') + ']';
|
||||
let len = obj.length,
|
||||
arrEllipsis = '';
|
||||
|
||||
if (len > 100)
|
||||
{
|
||||
len = 100;
|
||||
arrEllipsis = ', …';
|
||||
}
|
||||
for (let i = 0; i < len; i++)
|
||||
{
|
||||
parts.push(`${getAbstract(obj[i], passOpts)}`);
|
||||
}
|
||||
json += parts.join(', ') + arrEllipsis + ']';
|
||||
} else
|
||||
{
|
||||
json = wrapStr(`Array[${obj.length}]`);
|
||||
json = wrapStr(`Array(${obj.length})`);
|
||||
}
|
||||
} else if (isObj)
|
||||
{
|
||||
@@ -137,10 +148,11 @@ export default function getAbstract(obj, {
|
||||
i = 1;
|
||||
json = '{ ';
|
||||
each(names, objIteratee);
|
||||
json += moveFnToTail(parts).join(', ') + objEllipsis + ' }';
|
||||
json += parts.join(', ') + objEllipsis + ' }';
|
||||
} else
|
||||
{
|
||||
json = getObjType(obj);
|
||||
if (json === 'Object') json = '{…}';
|
||||
}
|
||||
} else if (isNum)
|
||||
{
|
||||
@@ -178,10 +190,11 @@ export default function getAbstract(obj, {
|
||||
json = '{ ';
|
||||
names = unenumerable ? Object.getOwnPropertyNames(obj) : Object.keys(obj);
|
||||
each(names, objIteratee);
|
||||
json += moveFnToTail(parts).join(', ') + objEllipsis + ' }';
|
||||
json += parts.join(', ') + objEllipsis + ' }';
|
||||
} else
|
||||
{
|
||||
json = getObjType(obj);
|
||||
if (json === 'Object') json = '{…}';
|
||||
}
|
||||
} catch (e)
|
||||
{
|
||||
@@ -201,16 +214,3 @@ function canBeProto(obj)
|
||||
|
||||
return emptyObj && proto && proto !== Object.prototype;
|
||||
}
|
||||
|
||||
function moveFnToTail(parts)
|
||||
{
|
||||
let front = [],
|
||||
tail = [];
|
||||
|
||||
each(parts, val =>
|
||||
{
|
||||
val.indexOf('function') > -1 ? tail.push(val) : front.push(val);
|
||||
});
|
||||
|
||||
return front.concat(tail);
|
||||
}
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
li {
|
||||
position: relative;
|
||||
white-space: nowrap;
|
||||
line-height: 16px;
|
||||
min-height: 16px;
|
||||
}
|
||||
& > li > .key {
|
||||
display: none;
|
||||
@@ -59,14 +61,14 @@
|
||||
position: absolute;
|
||||
border-top-color: $gray;
|
||||
left: -12px;
|
||||
top: 5px;
|
||||
top: 6px;
|
||||
}
|
||||
.collapsed:before {
|
||||
content: "";
|
||||
border-left-color: $gray;
|
||||
border-top-color: transparent;
|
||||
left: -10px;
|
||||
top: 3px;
|
||||
top: 4px;
|
||||
}
|
||||
li .collapsed ~ .close:before {
|
||||
color: #999;
|
||||
|
||||
@@ -12,7 +12,7 @@ import {
|
||||
uniqId,
|
||||
last,
|
||||
extend
|
||||
} from './util';
|
||||
} from './stringifyUtil';
|
||||
|
||||
// Modified from: https://jsconsole.com/
|
||||
export default function stringify(obj, {
|
||||
@@ -281,7 +281,7 @@ function canBeProto(obj)
|
||||
|
||||
function getObjAbstract(obj)
|
||||
{
|
||||
if (isArr(obj)) return `Array[${obj.length}]`;
|
||||
if (isArr(obj)) return `Array(${obj.length})`;
|
||||
if (isFn(obj)) return getFnAbstract(obj);
|
||||
if (isRegExp(obj)) return obj.toString();
|
||||
|
||||
@@ -313,7 +313,10 @@ class Visitor
|
||||
}
|
||||
visit(val)
|
||||
{
|
||||
let id = uniqId('erudaJson');
|
||||
/* Add 0 to distinguish stringify generated id from JsonViewer id.
|
||||
* When used in web worker, they are not calling the same uniqId method, thus result may be repeated.
|
||||
*/
|
||||
let id = uniqId('erudaJson0');
|
||||
|
||||
this._visited.push({id, val, abstract: {}});
|
||||
this._map[id] = last(this._visited);
|
||||
|
||||
1152
src/lib/stringifyUtil.js
Normal file
1152
src/lib/stringifyUtil.js
Normal file
File diff suppressed because it is too large
Load Diff
8
src/lib/stringifyWorker.js
Normal file
8
src/lib/stringifyWorker.js
Normal file
@@ -0,0 +1,8 @@
|
||||
import stringify from './stringify';
|
||||
|
||||
onmessage = function (e)
|
||||
{
|
||||
let [id, obj, options] = e.data;
|
||||
let result = stringify(obj, options);
|
||||
postMessage([id, result]);
|
||||
};
|
||||
@@ -620,6 +620,49 @@ export var kebabCase = _.kebabCase = (function ()
|
||||
return exports;
|
||||
})();
|
||||
|
||||
/* ------------------------------ chunk ------------------------------ */
|
||||
|
||||
export var chunk = _.chunk = (function ()
|
||||
{
|
||||
/* Split array into groups the length of given size.
|
||||
*
|
||||
* |Name |Type |Desc |
|
||||
* |--------|------|--------------------|
|
||||
* |arr |array |Array to process |
|
||||
* |[size=1]|number|Length of each chunk|
|
||||
*
|
||||
* ```javascript
|
||||
* chunk([1, 2, 3, 4], 2); // -> [[1, 2], [3, 4]]
|
||||
* chunk([1, 2, 3, 4], 3); // -> [[1, 2, 3], [4]]
|
||||
* chunk([1, 2, 3, 4]); // -> [[1], [2], [3], [4]]
|
||||
* ```
|
||||
*/
|
||||
|
||||
/* module
|
||||
* env: all
|
||||
* test: all
|
||||
*/
|
||||
|
||||
function exports(arr, size)
|
||||
{
|
||||
var ret = [];
|
||||
|
||||
size = size || 1;
|
||||
|
||||
for (var i = 0, len = Math.ceil(arr.length / size); i < len; i++)
|
||||
{
|
||||
var start = i * size,
|
||||
end = start + size;
|
||||
|
||||
ret.push(arr.slice(start, end));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
return exports;
|
||||
})();
|
||||
|
||||
/* ------------------------------ clamp ------------------------------ */
|
||||
|
||||
export var clamp = _.clamp = (function ()
|
||||
@@ -6786,7 +6829,7 @@ export var viewportScale = _.viewportScale = (function ()
|
||||
*/
|
||||
|
||||
/* dependencies
|
||||
* meta clamp trim each map
|
||||
* meta clamp trim each map isNaN
|
||||
*/
|
||||
|
||||
function exports()
|
||||
@@ -6813,7 +6856,12 @@ export var viewportScale = _.viewportScale = (function ()
|
||||
if (key === 'minimum-scale') minScale = +val;
|
||||
});
|
||||
|
||||
return clamp(initialScale, minScale, maxScale);
|
||||
let ret = clamp(initialScale, minScale, maxScale);
|
||||
|
||||
// Some will use ';' to be the separator, need to avoid the wrong result.
|
||||
if (isNaN(ret)) return 1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
return exports;
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
::-webkit-scrollbar {
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
}
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
::-webkit-scrollbar-track {
|
||||
background: transparent;
|
||||
border: 0px none #ffffff;
|
||||
border-radius: 0px;
|
||||
}
|
||||
::-webkit-scrollbar-corner {
|
||||
background: transparent;
|
||||
}
|
||||
@@ -31,6 +31,9 @@
|
||||
<li>
|
||||
<a href="#" id="trigger-error">Trigger Error</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#" id="big-array">Big Array</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
<script>
|
||||
@@ -99,6 +102,14 @@
|
||||
{
|
||||
triggerError();
|
||||
});
|
||||
addClickEvent('big-array', function ()
|
||||
{
|
||||
var arr = [];
|
||||
for (var i = 0; i < 10000; i++) {
|
||||
arr.push(i);
|
||||
}
|
||||
console.log(arr);
|
||||
});
|
||||
</script>
|
||||
<script>boot();</script>
|
||||
</body>
|
||||
|
||||
Reference in New Issue
Block a user