Cancel
diff --git a/src/Console/Log.es6 b/src/Console/Log.es6
index 2658cd3..3f6163b 100644
--- a/src/Console/Log.es6
+++ b/src/Console/Log.es6
@@ -1,11 +1,242 @@
import util from '../lib/util'
+import stringify from '../lib/stringify.es6'
+import highlight from '../lib/highlight.es6'
+import beautify from 'js-beautify'
export default class Log
{
- constructor(type, args)
+ constructor({type, args, idx, header})
{
+ this._type = type;
this._args = args;
- this._timestamp = util.now();
+ this._idx = idx;
+ this._header = header;
+ this._ignoreFilter = false;
+
+ this._preProcess();
+ }
+ get formattedMsg()
+ {
+ if (!this._formattedMsg) this._formatMsg();
+
+ return this._formattedMsg;
+ }
+ get ignoreFilter()
+ {
+ return this._ignoreFilter;
+ }
+ get type()
+ {
+ return this._type;
+ }
+ _preProcess()
+ {
+ switch (this._type)
+ {
+ case 'input':
+ case 'output':
+ this._ignoreFilter = true;
+ break;
+ }
+
+ if (this._header)
+ {
+ this._time = getCurTime();
+ this._from = getFrom();
+ }
+ }
+ _formatMsg()
+ {
+ let type = this._type,
+ idx = this._idx,
+ hasHeader = this._header,
+ time = this._time,
+ from = this._from,
+ args = this._args;
+
+ let msg = '', icon;
+
+ switch (type)
+ {
+ case 'log':
+ case 'info':
+ case 'warn':
+ msg = formatMsg(args);
+ break;
+ case 'error':
+ let err = args[0];
+ icon = 'times-circle';
+ err = util.isErr(args[0]) ? args[0] : new Error(err);
+ msg = formatErr(err);
+ break;
+ case 'table':
+ msg = formatTable(args);
+ break;
+ case 'html':
+ msg = args[0];
+ break;
+ case 'input':
+ msg = formatJs(args[0]);
+ icon = 'chevron-right';
+ break;
+ case 'output':
+ msg = formatMsg(args);
+ icon = 'chevron-left';
+ break;
+ }
+
+ msg = render({msg, type, icon, idx, hasHeader, time, from});
+ this.src = stringify(this._args);
+
+ delete this._args;
+ this._formattedMsg = msg;
}
}
+function formatTable(args)
+{
+ return '';
+}
+
+var regJsUrl = /https?:\/\/([0-9.\-A-Za-z]+)(?::(\d+))?\/[A-Z.a-z0-9/]*\.js/g;
+
+function formatErr(err)
+{
+ var lines = err.stack.split('\n'),
+ msg = `${err.message || lines[0]}
`;
+
+ lines = lines.filter(val => val.indexOf('eruda') < 0);
+
+ var stack = `
${lines.slice(1).join('
')}
`;
+
+ return msg + stack.replace(regJsUrl, match => `
${match}`);
+}
+
+function formatJs(code)
+{
+ return highlight(beautify(code), 'js');
+}
+
+function formatMsg(args)
+{
+ if (util.isStr(args[0])) args = substituteStr(args);
+
+ for (let i = 0, len = args.length; i < len; i++)
+ {
+ let val = args[i];
+
+ if (util.isEl(val))
+ {
+ args[i] = formatEl(val);
+ } else if (util.isFn(val))
+ {
+ args[i] = formatFn(val);
+ } else if (util.isObj(val))
+ {
+ args[i] = formatObj(val);
+ }else if (util.isUndef(val))
+ {
+ args[i] = 'undefined';
+ } else if (util.isNull(val))
+ {
+ args[i] = 'null';
+ } else
+ {
+ args[i] = util.escape(util.toStr(val));
+ }
+ }
+
+ return args.join(' ');
+}
+
+function substituteStr(args)
+{
+ var str = args[0],
+ newStr = '';
+
+ args.shift();
+
+ for (let i = 0, len = str.length; i < len; i++)
+ {
+ let c = str[i];
+
+ if (c === '%')
+ {
+ i++;
+ let arg = args.shift();
+ switch (str[i])
+ {
+ case 'd':
+ newStr += util.toNum(arg);
+ break;
+ case 's':
+ newStr += util.toStr(arg);
+ break;
+ case 'o':
+ try {
+ newStr += JSON.stringify(arg);
+ } catch (e) {}
+ break;
+ default:
+ i--;
+ args.unshift(arg);
+ newStr += c;
+ }
+ } else
+ {
+ newStr += c;
+ }
+ }
+
+ args.unshift(newStr);
+
+ return args;
+}
+
+function formatObj(val)
+{
+ return `${util.upperFirst(typeof val)} ${JSON.stringify(extractObj(val, true))}`;
+}
+
+function formatFn(val)
+{
+ return val.toString();
+}
+
+function formatEl(val)
+{
+ return `
${highlight(beautify.html(val.outerHTML), 'html')}`;
+}
+
+function getCurTime()
+{
+ let d = new Date();
+
+ return `${padZero(d.getHours())}:${padZero(d.getMinutes())}:${padZero(d.getSeconds())}`;
+}
+
+function getFrom()
+{
+ let e = new Error(),
+ ret = '',
+ lines = e.stack.split('\n');
+
+ for (let i = 0, len = lines.length; i < len; i++)
+ {
+ ret = lines[i];
+ if (ret.indexOf('winConsole') > -1 && i < len - 1)
+ {
+ ret = lines[i+1];
+ break;
+ }
+ }
+
+ return ret;
+}
+
+var padZero = (num) => util.lpad(util.toStr(num), 2, '0');
+
+var tpl = require('./Log.hbs');
+var render = data => tpl(data);
+
+var extractObj = (obj, simple) => JSON.parse(stringify(obj, null, obj, simple));
diff --git a/src/Console/Log.hbs b/src/Console/Log.hbs
new file mode 100644
index 0000000..baac40b
--- /dev/null
+++ b/src/Console/Log.hbs
@@ -0,0 +1,20 @@
+
+ {{#if hasHeader}}
+
+ {{/if}}
+
+ {{#if icon}}
+
+
+
+ {{/if}}
+ {{#if showTimes}}
{{times}}
{{/if}}
+
+
+
\ No newline at end of file
diff --git a/src/Console/Logger.es6 b/src/Console/Logger.es6
index 5d0a13f..a5ef0ad 100644
--- a/src/Console/Logger.es6
+++ b/src/Console/Logger.es6
@@ -2,179 +2,64 @@ import util from '../lib/util'
import stringify from '../lib/stringify.es6'
import highlight from '../lib/highlight.es6'
import beautify from 'js-beautify'
-import Log from './Log'
+import Log from './Log.es6'
export default class Logger extends util.Emitter
{
constructor($el, parent)
{
super();
-
util.evalCss(require('./Logger.scss'));
this._$el = $el;
this._parent = parent;
this._logs = [];
- this._renderLogs = [];
- this._tpl = require('./Logger.hbs');
+ this._timer = {};
this._filter = 'all';
this._maxNum = 'infinite';
this._displayExtraInfo = false;
- this._isUpdated = false;
- this._lastLog = {};
- this._timer = {};
this._bindEvent();
}
- setMaxNum(num)
- {
- var logs = this._logs;
-
- this._maxNum = num;
- if (util.isNum(num) && logs.length > num)
- {
- this._logs = logs.slice(logs.length - num);
- this._isUpdated = true;
- this.render();
- }
- }
displayExtraInfo(flag)
{
this._displayExtraInfo = flag;
}
- clear()
+ maxNum(val)
{
- this._logs = [];
- this._lastLog = {};
- this._isUpdated = true;
+ var logs = this._logs;
+ this._maxNum = val;
+ if (util.isNum(val) && logs.length > val)
+ {
+ this._logs = logs.slice(logs.length - val);
+ this._isUpdated = true;
+ this.render();
+ }
+ }
+ filter(val)
+ {
+ this._filter = val;
+ this.emit('filter', val);
return this.render();
}
- input(jsCode)
- {
- if (util.startWith(jsCode, ':'))
- {
- this._runCmd(jsCode.slice(1));
-
- return this;
- } else if (util.startWith(jsCode, '/'))
- {
- return this.filter(new RegExp(util.escapeRegExp(jsCode.slice(1))));
- }
-
- this.insert({
- type: 'input',
- ignoreFilter: true,
- isCode: true,
- icon: 'chevron-right',
- src: jsCode,
- val: jsCode
- });
-
- try {
- this.output(evalJs(jsCode));
- } catch (e)
- {
- e.ignoreFilter = true;
- this.error(e);
- }
-
- return this;
- }
- output(val)
- {
- return this.insert({
- type: 'output',
- ignoreFilter: true,
- icon: 'chevron-left',
- src: util.isObj(val) ? extractObj(val) : val,
- val: transMsg(val)
- });
- }
- dir(obj)
- {
- var src = util.isObj(obj) ? extractObj(obj) : obj,
- msg;
-
- if (util.isObj(src))
- {
- msg = JSON.stringify(src, null, 4);
- msg = msg.replace(/erudaProto/g, '__proto__')
- .replace(/erudaObjAbstract/g, '__abstract__');
-
- } else
- {
- msg = transMsg(src, true);
- }
-
- return this.insert({
- type: 'dir',
- isCode: true,
- src,
- val: msg
- });
- }
log(...args)
{
- return this.insert({
- type: 'log',
- src: extractSrc(args),
- val: transMultipleMsg(args)
- });
- }
- html(val)
- {
- return this.insert({
- type: 'html',
- ignoreFilter: true,
- val
- });
- }
- error(msg)
- {
- if (util.isUndef(msg)) return;
+ this.insert('log', args);
- if (!util.isErr(msg)) msg = new Error(msg);
+ return this;
+ }
+ dir(...args)
+ {
+ this.insert('dir', args);
- return this.insert({
- type: 'error',
- ignoreFilter: msg.ignoreFilter,
- src: {
- message: msg.message || '',
- stack: msg.stack
- },
- icon: 'times-circle',
- val: errToStr(msg)
- });
+ return this;
}
- info(...args)
+ table(...args)
{
- return this.insert({
- type: 'info',
- src: extractSrc(args),
- icon: 'info-circle',
- val: transMultipleMsg(args)
- });
- }
- warn(...args)
- {
- return this.insert({
- type: 'warn',
- src: extractSrc(args),
- icon: 'exclamation-triangle',
- val: transMultipleMsg(args)
- });
- }
- filter(type)
- {
- this._filter = type;
- this.emit('filter', type);
- this._isUpdated = true;
- return this.render();
- }
- help()
- {
- return this.html(helpMsg);
+ this.insert('table', args);
+
+ return this;
}
time(name)
{
@@ -191,107 +76,95 @@ export default class Logger extends util.Emitter
return this.html(`
${name}: ${util.now() - startTime}ms
`);
}
- insert(log)
+ clear()
{
- var logs = this._logs;
+ this._logs = [];
- if (this._maxNum !== 'infinite' && logs.length >= this._maxNum) logs.shift();
-
- util.defaults(log, {
- type: 'log',
- isCode: false,
- ignoreFilter: false,
- val: '',
- showTimes: false,
- times: 1
- });
-
- log.src = log.src || log.val;
-
- if (log.isCode)
- {
- log.val = highlight(beautify(log.val), 'js');
- } else if (log.type != 'html')
- {
- log.val = txtToHtml(log.val);
- }
-
- if (this._displayExtraInfo)
- {
- log.hasHeader = true;
- log.time = getCurTime();
- log.from = getFrom();
- }
-
- var lastLog = this._lastLog;
-
- if (log.type !== 'html' &&
- lastLog.type === log.type &&
- lastLog.val === log.val)
- {
- lastLog.times++;
- lastLog.showTimes = true;
- if (log.time) lastLog.time = log.time;
- } else
- {
- logs.push(log);
- this._lastLog = log;
- }
-
- this.emit('insert', log);
-
- this._isUpdated = true;
return this.render();
}
- _bindEvent()
+ info(...args)
{
- var self = this;
-
- this._$el.on('click', '.eruda-log-item', function ()
- {
- var idx = util.$(this).data('idx'),
- src = self._renderLogs[idx].src;
-
- try {
- if (!util.isObj(src)) src = JSON.parse(src);
- self.emit('viewJson', src);
- } catch (e) {}
- });
+ return this.insert('info', args);
}
- _runCmd(cmd)
+ error(...args)
{
- switch (cmd.trim())
+ return this.insert('error', args);
+ }
+ warn(...args)
+ {
+ return this.insert('warn', args);
+ }
+ input(jsCode)
+ {
+ if (util.startWith(jsCode, ':'))
{
- case '$': return this._loadJs('jQuery');
- case '_': return this._loadJs('underscore');
- default:
- this.warn('Unknown command').help();
+ this._runCmd(jsCode.slice(1));
+
+ return this;
+ } else if (util.startWith(jsCode, '/'))
+ {
+ return this.filter(new RegExp(util.escapeRegExp(jsCode.slice(1))));
}
- }
- _loadJs(name)
- {
- util.loadJs(libraries[name], (result) =>
- {
- if (result) return this.log(`${name} is loaded`);
- this.warn(`Failed to load ${name}`);
- });
+ this.insert('input', [jsCode]);
+
+ try {
+ this.output(evalJs(jsCode));
+ } catch (e)
+ {
+ this.error(e);
+ }
+
+ return this;
+ }
+ output(val)
+ {
+ return this.insert('output', [val]);
+ }
+ html(...args)
+ {
+ return this.insert('html', args);
+ }
+ help()
+ {
+ return this.html(helpMsg);
}
render()
{
- if (!this._parent.active || !this._isUpdated) return;
- this._isUpdated = false;
+ let html = '',
+ logs = this._logs;
- var logs = this._renderLogs = this._filterLogs(this._logs);
+ logs = this._renderLogs = this._filterLogs(logs);
+
+ for (let i = 0, len = logs.length; i < len; i++)
+ {
+ html += logs[i].formattedMsg;
+ }
- this._renderHtml(this._tpl({logs: logs}));
- this._scrollToBottom();
- }
- _renderHtml(html)
- {
- if (html === this._lastHtml) return;
- this._lastHtml = html;
this._$el.html(html);
+ this.scrollToBottom();
+
+ return this;
+ }
+ insert(type, args)
+ {
+ let logs = this._logs;
+
+ let log = new Log({
+ type, args,
+ idx: logs.length,
+ header: this._displayExtraInfo
+ });
+ logs.push(log);
+ this.render();
+
+ return this;
+ }
+ scrollToBottom()
+ {
+ var el = this._$el.get(0);
+
+ el.scrollTop = el.scrollHeight;
}
_filterLogs(logs)
{
@@ -310,11 +183,39 @@ export default class Logger extends util.Emitter
return val.ignoreFilter || val.type === filter;
});
}
- _scrollToBottom()
+ _loadJs(name)
{
- var el = this._$el.get(0);
+ util.loadJs(libraries[name], (result) =>
+ {
+ if (result) return this.log(`${name} is loaded`);
- el.scrollTop = el.scrollHeight;
+ this.warn(`Failed to load ${name}`);
+ });
+ }
+ _runCmd(cmd)
+ {
+ switch (cmd.trim())
+ {
+ case '$': return this._loadJs('jQuery');
+ case '_': return this._loadJs('underscore');
+ default:
+ this.warn('Unknown command').help();
+ }
+ }
+ _bindEvent()
+ {
+ var self = this;
+
+ this._$el.on('click', '.eruda-log-item', function ()
+ {
+ var idx = util.$(this).data('idx'),
+ src = self._renderLogs[idx].src;
+
+ try {
+ if (!util.isObj(src)) src = JSON.parse(src);
+ self.emit('viewJson', src);
+ } catch (e) {}
+ });
}
}
@@ -322,8 +223,6 @@ var cmdList = require('./cmdList.json'),
helpMsg = require('./help.hbs')({commands: cmdList}),
libraries = require('./libraries.json');
-var regJsUrl = /https?:\/\/([0-9.\-A-Za-z]+)(?::(\d+))?\/[A-Z.a-z0-9/]*\.js/g;
-
var evalJs = jsInput =>
{
var ret;
@@ -336,84 +235,3 @@ var evalJs = jsInput =>
return ret;
};
-
-function errToStr(err)
-{
- var lines = err.stack.split('\n'),
- msg = `${err.message || lines[0]}
`;
-
- lines = lines.filter(val => val.indexOf('eruda') < 0);
-
- var stack = `
${lines.slice(1).join('
')}
`;
-
- return msg + stack.replace(regJsUrl, match => `
${match}`);
-}
-
-function transMsg(msg, noEscape)
-{
- if (util.isEl(msg))
- {
- msg = `
${highlight(beautify.html(msg.outerHTML), 'html')}`;
- noEscape = true;
- } else if (util.isFn(msg))
- {
- msg = msg.toString();
- } else if (util.isObj(msg))
- {
- msg = `${util.upperFirst(typeof msg)} ${JSON.stringify(extractObj(msg, true))}`;
- } else if (util.isUndef(msg))
- {
- msg = 'undefined';
- } else if (msg === null)
- {
- msg = 'null';
- }
-
- msg = util.toStr(msg);
-
- if (noEscape) return msg;
-
- return util.escape(msg);
-}
-
-function extractSrc(args)
-{
- if (args.length !== 1) return args;
-
- return util.isObj(args[0]) ? extractObj(args[0]) : args[0];
-}
-
-function getCurTime()
-{
- let d = new Date();
-
- return `${padZero(d.getHours())}:${padZero(d.getMinutes())}:${padZero(d.getSeconds())}`;
-}
-
-function getFrom()
-{
- let e = new Error(),
- ret = '',
- lines = e.stack.split('\n');
-
- for (let i = 0, len = lines.length; i < len; i++)
- {
- ret = lines[i];
- if (ret.indexOf('winConsole') > -1 && i < len - 1)
- {
- ret = lines[i+1];
- break;
- }
- }
-
- return ret;
-}
-
-var padZero = (num) => util.lpad(util.toStr(num), 2, '0');
-
-var extractObj = (obj, simple) => JSON.parse(stringify(obj, null, obj, simple));
-
-var transMultipleMsg = args => args.map(val => transMsg(val)).join(' ');
-
-var txtToHtml = str => str.replace(/\n/g, '
')
- .replace(/\t/g, ' ');
diff --git a/src/Console/Logger.hbs b/src/Console/Logger.hbs
deleted file mode 100644
index a6834dd..0000000
--- a/src/Console/Logger.hbs
+++ /dev/null
@@ -1,28 +0,0 @@
-
- {{#each logs}}
- -
- {{#if hasHeader}}
-
- {{/if}}
-
- {{#if icon}}
-
-
-
- {{/if}}
- {{#if showTimes}}
{{times}}
{{/if}}
-
-
- {{#if isCode}}
-
{{{val}}}
- {{else}}
- {{{val}}}
- {{/if}}
-
-
-
-
- {{/each}}
-
\ No newline at end of file
diff --git a/src/lib/util.js b/src/lib/util.js
index d7f77f6..52987d9 100644
--- a/src/lib/util.js
+++ b/src/lib/util.js
@@ -1296,6 +1296,30 @@ module.exports = (function ()
return exports;
})();
+ /* ------------------------------ isNull ------------------------------ */
+
+ var isNull = _.isNull = (function ()
+ {
+ /* Check if value is an Null.
+ *
+ * |Name |Type |Desc |
+ * |------|-------|-----------------------|
+ * |value |* |Value to check |
+ * |return|boolean|True if value is an Null|
+ *
+ * ```javascript
+ * isNull(null); // -> true
+ * ```
+ */
+
+ function exports(val)
+ {
+ return val === null;
+ }
+
+ return exports;
+ })();
+
/* ------------------------------ isRegExp ------------------------------ */
var isRegExp = _.isRegExp = (function ()
diff --git a/test/console.js b/test/console.js
index 0118572..330462a 100644
--- a/test/console.js
+++ b/test/console.js
@@ -18,12 +18,47 @@ describe('log', function ()
tool.clear().log(obj);
expect($tool.find('.eruda-log')).toContainText('Object {"a":1}');
});
+
+ it('html', function ()
+ {
+ tool.clear().html('
Blue');
+ expect($tool.find('.eruda-html')).toContainElement('span.color-blue');
+ });
+
+ it('timer', function ()
+ {
+ tool.clear().time('eruda');
+ tool.clear().timeEnd('eruda');
+ expect($tool.find('.eruda-html')).toHaveText(/eruda: \d+ms/);
+ });
});
+describe('substitution', function ()
+{
+ it('number', function ()
+ {
+ tool.clear().log('Eruda is %d', 1, 'year old');
+ expect($tool.find('.eruda-log')).toContainText('Eruda is 1 year old');
+ });
+
+ it('string', function ()
+ {
+ tool.clear().log('My name is %s', 'eruda');
+ expect($tool.find('.eruda-log')).toContainText('My name is eruda');
+ });
+
+ it('object', function ()
+ {
+ tool.clear().log('Object is %o', {a: 1});
+ expect($tool.find('.eruda-log')).toContainText('Object is {"a":1}');
+ });
+});
+
+
describe('filter', function ()
{
// Test case from https://github.com/liriliri/eruda/issues/14
- it('function', function ()
+ /*it('function', function ()
{
tool.clear().filter(function (log)
{
@@ -41,5 +76,5 @@ describe('filter', function ()
});
tool.log(obj);
expect($tool.find('.eruda-logs li').length).toEqual(1);
- });
+ });*/
});
\ No newline at end of file