Dev: Log abstract

This commit is contained in:
surunzi
2016-10-11 14:00:50 +08:00
parent 4e056dd7a3
commit b9ff203840
5 changed files with 305 additions and 32 deletions

View File

@@ -1,5 +1,6 @@
import util from '../lib/util'
import stringify from '../lib/stringify.es6'
import origGetAbstract from '../lib/getAbstract.es6'
import highlight from '../lib/highlight.es6'
import beautify from 'js-beautify'
import JsonViewer from '../lib/JsonViewer.es6'
@@ -175,6 +176,14 @@ Log.showGetterVal = false;
Log.showUnenumerable = true;
Log.showSrcInSources = false;
var getAbstract = util.wrap(origGetAbstract, function (fn, obj)
{
return fn(obj, {
getterVal: Log.showGetterVal,
unenumerable: false
});
});
function stringifyWrapper(obj, options = {})
{
util.defaults(options, {
@@ -319,7 +328,7 @@ function substituteStr(args)
case 'O':
if (util.isObj(arg))
{
newStr += stringifyWrapper(arg);
newStr += getAbstract(arg);
}
break;
case 'o':
@@ -328,7 +337,7 @@ function substituteStr(args)
newStr += formatEl(arg);
} else if (util.isObj(arg))
{
newStr += stringifyWrapper(arg);
newStr += getAbstract(arg);
}
break;
case 'c':
@@ -355,7 +364,7 @@ function substituteStr(args)
function formatObj(val)
{
return `${getObjType(val)} ${stringifyWrapper(val)}`;
return `${getObjType(val)} ${getAbstract(val)}`;
}
function formatFn(val)

View File

@@ -56,19 +56,12 @@ function jsonToHtml(data, firstLevel)
function createEl(key, val, firstLevel)
{
var type = 'object',
open = '{',
close = '}';
var type = 'object';
if (key === 'erudaProto') key = '__proto__';
if (key === 'erudaId') return `<li id="${val}" class="eruda-hidden"></li>`;
if (util.isArr(val))
{
type = 'array';
open = '[';
close = ']';
}
if (util.isArr(val)) type = 'array';
function wrapKey(key)
{
@@ -89,13 +82,16 @@ function createEl(key, val, firstLevel)
}
if (util.isObj(val))
{
var objAbstract = val['erudaObjAbstract'] || util.upperFirst(type);
var obj = `<li>
<span class="eruda-expanded ${firstLevel ? '' : 'eruda-collapsed'}"></span>
${wrapKey(key)}
<span class="eruda-open">${open} ${(val['erudaObjAbstract'] || '')}</span>
<span class="eruda-open">${objAbstract}</span>
<ul class="eruda-${type}" ${firstLevel ? '' : 'style="display:none"'}>`;
obj += jsonToHtml(val);
return obj + `</ul><span class="eruda-close">${close}</span></li>`;
return obj + `</ul><span class="eruda-close"></span></li>`;
}
if (util.isNum(val) || util.isBool(val))
{

249
src/lib/getAbstract.es6 Normal file
View File

@@ -0,0 +1,249 @@
// Simple version for stringify, used for displaying object abstract.
import util from './util'
// Modified from: https://jsconsole.com/
export default function getAbstract(obj, {
visited = [],
topObj,
level = 0,
getterVal = false,
unenumerable = true
} = {})
{
let json = '',
type = '',
keyNum = 5,
parts = [],
names = [],
objEllipsis = '',
circular = false,
i, len;
topObj = topObj || obj;
let passOpts = {
visited, getterVal,
unenumerable,
level: level + 1
};
let doStringify = level === 0;
let keyWrapper = '<span style="color: #a71d5d;">',
fnWrapper = '<span style="color: #a71d5d;">',
numWrapper = '<span style="color: #0086b3;">',
nullWrapper = '<span style="color: #0086b3;">',
strWrapper = '<span style="color: #183691;">',
boolWrapper = '<span style="color: #0086b3;">',
specialWrapper = '<span style="color: #707d8b;">',
strEscape = str => util.escape(str),
wrapperEnd = '</span>';
let wrapKey = key => keyWrapper + strEscape(key) + wrapperEnd,
wrapNum = num => numWrapper + num + wrapperEnd,
wrapBool = bool => boolWrapper + bool + wrapperEnd,
wrapNull = str => nullWrapper + str + wrapperEnd;
function wrapStr(str)
{
str = util.toStr(str);
str = str.replace(/\\/g, '');
if (util.startWith(str, 'function'))
{
return fnWrapper + 'function' + wrapperEnd + ' ( )';
}
if (util.contain(SPECIAL_VAL, str) || util.startWith(str, 'Array['))
{
return specialWrapper + strEscape(str) + wrapperEnd;
}
if (util.startWith(str, '[circular]'))
{
return specialWrapper + '[circular]' + wrapperEnd;
}
if (util.startWith(str, '[object '))
{
return specialWrapper + strEscape(str.replace(/(\[object )|]/g, '')) + wrapperEnd;
}
return strWrapper + strEscape(`"${str}"`) + wrapperEnd;
}
try {
type = ({}).toString.call(obj);
} catch (e)
{
type = '[object Object]';
}
var isFn = (type == '[object Function]'),
isStr = (type == '[object String]'),
isArr = (type == '[object Array]'),
isObj = (type == '[object Object]'),
isNum = (type == '[object Number]'),
isSymbol = (type == '[object Symbol]'),
isBool = (type == '[object Boolean]');
for (i = 0, len = visited.length; i < len; i++)
{
if (obj === visited[i])
{
circular = true;
break;
}
}
if (circular)
{
json = wrapStr('[circular]');
} else if (isStr)
{
json = wrapStr(escapeJsonStr(obj));
} else if (isArr)
{
visited.push(obj);
if (doStringify)
{
json = '[';
util.each(obj, val => parts.push(`${getAbstract(val, passOpts)}`));
json += parts.join(', ') + ']';
} else
{
json = wrapStr(`Array[${obj.length}]`);
}
} else if (isObj)
{
visited.push(obj);
if (canBeProto(obj))
{
obj = Object.getPrototypeOf(obj);
}
names = unenumerable ? Object.getOwnPropertyNames(obj) : Object.keys(obj);
if (doStringify)
{
i = 1;
json = '{ ';
util.each(names, name =>
{
if (i > keyNum)
{
objEllipsis = '...';
return;
}
let key = wrapKey(escapeJsonStr(name));
if (!getterVal)
{
let descriptor = Object.getOwnPropertyDescriptor(obj, name);
if (descriptor.get)
{
parts.push(`${key}: ${wrapStr('(...)')}`);
i++;
return;
}
}
if (typeof topObj[name] === 'function') return;
parts.push(`${key}: ${getAbstract(topObj[name], passOpts)}`);
i++;
});
json += parts.join(', ') + objEllipsis + ' }';
} else
{
json = wrapStr('Object');
}
} else if (isNum)
{
json = obj + '';
if (util.endWith(json, 'Infinity') || json === 'NaN')
{
json = `"${json}"`;
} else
{
json = wrapNum(json);
}
} else if (isBool)
{
json = wrapBool(obj ? 'true' : 'false');
} else if (obj === null)
{
json = wrapNull('null');
} else if (isSymbol)
{
json = wrapStr('Symbol');
} else if (obj === undefined)
{
json = wrapStr('undefined');
} else if (type === '[object HTMLAllCollection]')
{
// https://docs.webplatform.org/wiki/dom/HTMLAllCollection
// Might cause a performance issue when stringify a dom element.
json = wrapStr('[object HTMLAllCollection]');
} else if (type === '[object HTMLDocument]' && level > 1)
{
// Same as reason above.
json = wrapStr('[object HTMLDocument]');
} else {
try
{
visited.push(obj);
if (canBeProto(obj))
{
obj = Object.getPrototypeOf(obj);
}
if (doStringify)
{
i = 1;
json = '{ ';
names = unenumerable ? Object.getOwnPropertyNames(obj) : Object.keys(obj);
util.each(names, name =>
{
if (i > keyNum)
{
objEllipsis = '...';
return;
}
let key = wrapKey(escapeJsonStr(name));
if (!getterVal)
{
let descriptor = Object.getOwnPropertyDescriptor(obj, name);
if (descriptor.get)
{
parts.push(`${key}: ${wrapStr('(...)')}`);
i++;
return;
}
}
if (typeof topObj[name] === 'function') return;
parts.push(`${key}: ${getAbstract(topObj[name], passOpts)}`);
i++;
});
json += parts.join(', ') + objEllipsis + ' }';
} else
{
json = wrapStr(obj);
}
} catch (e)
{
json = wrapStr(obj);
}
}
return json;
}
const SPECIAL_VAL = ['(...)', 'undefined', 'Symbol', 'Object'];
var escapeJsonStr = str => str.replace(/\\/g, '\\\\')
.replace(/"/g, '\\"')
.replace(/\f|\n|\r|\t/g, '');
function canBeProto(obj)
{
let emptyObj = util.isEmpty(Object.getOwnPropertyNames(obj)),
proto = Object.getPrototypeOf(obj);
return emptyObj && proto && proto !== Object.prototype;
}

View File

@@ -65,7 +65,6 @@
top: 3px;
}
li .collapsed ~ .close:before {
content: "... ";
color: #999;
}
.hidden ~ ul {

View File

@@ -1759,13 +1759,13 @@ module.exports = (function ()
* var Student = People.extend({
* initialize: function (name, age, school)
* {
* this.callSuper('initialize', name, age);
* this.callSuper(People, 'initialize', arguments);
*
* this.school = school.
* },
* introduce: function ()
* {
* return this.callSuper('introduce') + '\n I study at ' + this.school + '.'.
* return this.callSuper(People, 'introduce') + '\n I study at ' + this.school + '.'.
* }
* }, {
* is: function (obj)
@@ -1795,22 +1795,13 @@ module.exports = (function ()
{
var args = toArr(arguments);
if (has(ctor.prototype, 'initialize') &&
!regCallSuper.test(this.initialize.toString()) &&
this.callSuper)
{
args.unshift('initialize');
this.callSuper.apply(this, args);
args.shift();
}
return this.initialize
? this.initialize.apply(this, args) || this
: this;
};
inherits(ctor, parent);
ctor.superclass = ctor.prototype.superclass = parent;
ctor.prototype.superclass = parent;
ctor.extend = function (methods, statics)
{
@@ -1838,13 +1829,13 @@ module.exports = (function ()
var Base = exports.Base = makeClass(Object, {
className: 'Base',
callSuper: function (name)
callSuper: function (parent, name, args)
{
var superMethod = this.superclass.prototype[name];
var superMethod = parent.prototype[name];
if (!superMethod) return;
return superMethod.apply(this, toArr(arguments).slice(1));
return superMethod.apply(this, args);
},
toString: function ()
{
@@ -2588,7 +2579,7 @@ module.exports = (function ()
/* bind events to certain dom elements. TODO
*
* ```javascript
* event.on('#test', 'click', function ()
* $event.on('#test', 'click', function ()
* {
* // ...
* });
@@ -3420,7 +3411,7 @@ module.exports = (function ()
* |return|string|Globally-unique id|
*
* ```javascript
* uniqueId('eusita_'); // -> 'eustia_xxx'
* uniqId('eusita_'); // -> 'eustia_xxx'
* ```
*/
@@ -3504,5 +3495,34 @@ module.exports = (function ()
return exports;
})();
/* ------------------------------ wrap ------------------------------ */
var wrap = _.wrap = (function ()
{
/* Wrap the function inside a wrapper function, passing it as the first argument.
*
* |Name |Type |Desc |
* |-------|--------|----------------|
* |fn |* |Function to wrap|
* |wrapper|function|Wrapper function|
* |return |function|New function |
*
* ```javascript
* var p = wrap(escape, function(fn, text)
* {
* return '<p>' + fn(text) + '</p>';
* });
* p('You & Me'); // -> '<p>You &amp; Me</p>'
* ```
*/
function exports(fn, wrapper)
{
return partial(wrapper, fn);
}
return exports;
})();
return _;
})();