diff --git a/src/Console/Log.es6 b/src/Console/Log.es6
index 7665514..5c53c81 100644
--- a/src/Console/Log.es6
+++ b/src/Console/Log.es6
@@ -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)
diff --git a/src/lib/JsonViewer.es6 b/src/lib/JsonViewer.es6
index 17663c9..9e26faf 100644
--- a/src/lib/JsonViewer.es6
+++ b/src/lib/JsonViewer.es6
@@ -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 `
`;
- 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 = `
${wrapKey(key)}
- ${open} ${(val['erudaObjAbstract'] || '')}
+ ${objAbstract}
`;
obj += jsonToHtml(val);
- return obj + `
${close}`;
+
+ return obj + ``;
}
if (util.isNum(val) || util.isBool(val))
{
diff --git a/src/lib/getAbstract.es6 b/src/lib/getAbstract.es6
new file mode 100644
index 0000000..d74bcde
--- /dev/null
+++ b/src/lib/getAbstract.es6
@@ -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 = '',
+ fnWrapper = '',
+ numWrapper = '',
+ nullWrapper = '',
+ strWrapper = '',
+ boolWrapper = '',
+ specialWrapper = '',
+ strEscape = str => util.escape(str),
+ wrapperEnd = '';
+
+ 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;
+}
diff --git a/src/lib/json.scss b/src/lib/json.scss
index 042dbd6..9e18e9b 100644
--- a/src/lib/json.scss
+++ b/src/lib/json.scss
@@ -65,7 +65,6 @@
top: 3px;
}
li .collapsed ~ .close:before {
- content: "... ";
color: #999;
}
.hidden ~ ul {
diff --git a/src/lib/util.js b/src/lib/util.js
index 1061108..28dc450 100644
--- a/src/lib/util.js
+++ b/src/lib/util.js
@@ -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 '' + fn(text) + '
';
+ * });
+ * p('You & Me'); // -> 'You & Me
'
+ * ```
+ */
+
+ function exports(fn, wrapper)
+ {
+ return partial(wrapper, fn);
+ }
+
+ return exports;
+ })();
+
return _;
})();
\ No newline at end of file