diff --git a/doc/UTIL_API.md b/doc/UTIL_API.md index 5d324bf..63a710a 100644 --- a/doc/UTIL_API.md +++ b/doc/UTIL_API.md @@ -506,6 +506,52 @@ $test.find('.test').each(function (idx, element) { }); ``` +## Stack + +Stack data structure. + +### clear + +Clear the stack. + +### push + +Add an item to the stack. + +|Name |Type |Desc | +|------|------|------------| +|item |* |Item to add | +|return|number|Current size| + +### pop + +Get the last item of the stack. + +### peek + +Get the last item without removing it. + +### forEach + +Iterate over the stack. + +|Name |Type |Desc | +|--------|--------|--------------------------| +|iterator|function|Function invoked iteration| +|[ctx] |* |Function context | + +### toArr + +Convert the stack to a JavaScript array. + +```javascript +const stack = new Stack(); + +stack.push(2); // -> 1 +stack.push(3); // -> 2 +stack.pop(); // -> 3 +``` + ## Store Memory storage. @@ -1317,8 +1363,8 @@ comment, string, number, keyword, operator ```javascript highlight('const a = 5;', 'js', { - number: 'color:#0086b3;' -}); // -> 'const a = 5;' + keyword: 'color:#569cd6;' +}); // -> 'const a = 5;' ``` ## identity @@ -1650,6 +1696,21 @@ isObj({}); // -> true isObj([]); // -> true ``` +## isPrimitive + +Check if value is string, number, boolean or null. + +|Name |Type |Desc | +|------|-------|----------------------------| +|val |* |Value to check | +|return|boolean|True if value is a primitive| + +```javascript +isPrimitive(5); // -> true +isPrimitive('abc'); // -> true +isPrimitive(false); // -> true +``` + ## isPromise Check if value looks like a promise. diff --git a/src/Console/Log.js b/src/Console/Log.js index 972b89f..93e16a6 100644 --- a/src/Console/Log.js +++ b/src/Console/Log.js @@ -6,6 +6,7 @@ import { isObj, isStr, isErr, + isPrimitive, wrap, defaults, dateFormat, @@ -28,7 +29,8 @@ import { highlight, each, trim, - lowerCase + lowerCase, + keys } from '../lib/util' export default class Log { @@ -323,6 +325,8 @@ const getAbstract = wrap(origGetAbstract, function(fn, obj) { }) }) +const Value = '__ErudaValue' + function formatTable(args) { const table = args[0] let ret = '' @@ -332,33 +336,39 @@ function formatTable(args) { if (isStr(filter)) filter = toArr(filter) if (!isArr(filter)) filter = null - if (!isArr(table)) return formatMsg(args) + if (!isObj(table)) return formatMsg(args) - table.forEach(val => { - if (!isObj(val)) return - columns = columns.concat(Object.getOwnPropertyNames(val)) + each(table, val => { + if (isPrimitive(val)) { + columns.push(Value) + } else if (isObj(val)) { + columns = columns.concat(keys(val)) + } }) columns = unique(columns) columns.sort() if (filter) columns = columns.filter(val => contain(filter, val)) + if (columns.length > 20) columns = columns.slice(0, 20) if (isEmpty(columns)) return formatMsg(args) ret += '' - columns.forEach(val => (ret += ``)) + columns.forEach( + val => (ret += ``) + ) ret += '' - table.forEach((obj, idx) => { - if (!isObj(obj)) return + each(table, (obj, idx) => { ret += `` columns.forEach(column => { - let val = obj[column] - if (isUndef(val)) { - val = '' - } else if (isObj(val)) { - val = getObjType(val) + if (isObj(obj)) { + ret += + column === Value + ? '' + : `` + } else if (isPrimitive(obj)) { + ret += + column === Value ? `` : '' } - - ret += `` }) ret += '' }) @@ -369,6 +379,13 @@ function formatTable(args) { return ret } +function formatTableVal(val) { + if (isObj(val)) return (val = '{…}') + if (isPrimitive(val)) return getAbstract(val) + + return toStr(val) +} + const regJsUrl = /https?:\/\/([0-9.\-A-Za-z]+)(?::(\d+))?\/[A-Z.a-z0-9/]*\.js/g const regErudaJs = /eruda(\.min)?\.js/ diff --git a/src/lib/util.js b/src/lib/util.js index 6f010b6..fdca8f1 100644 --- a/src/lib/util.js +++ b/src/lib/util.js @@ -2596,6 +2596,34 @@ export var isNull = _.isNull = (function (exports) { return exports; })({}); +/* ------------------------------ isPrimitive ------------------------------ */ + +export var isPrimitive = _.isPrimitive = (function (exports) { + /* Check if value is string, number, boolean or null. + * + * |Name |Type |Desc | + * |------|-------|----------------------------| + * |val |* |Value to check | + * |return|boolean|True if value is a primitive| + */ + + /* example + * isPrimitive(5); // -> true + * isPrimitive('abc'); // -> true + * isPrimitive(false); // -> true + */ + + /* typescript + * export declare function isPrimitive(val: any): boolean; + */ + exports = function(val) { + var type = typeof val; + return val == null || (type !== 'function' && type !== 'object'); + }; + + return exports; +})({}); + /* ------------------------------ isPromise ------------------------------ */ export var isPromise = _.isPromise = (function (exports) { diff --git a/test/util.js b/test/util.js index f66777f..14fe619 100644 --- a/test/util.js +++ b/test/util.js @@ -16,6 +16,50 @@ if (typeof window === 'object' && window.util) _ = window.util; + /* ------------------------------ inherits ------------------------------ */ + + var inherits = _.inherits = (function (exports) { + /* Inherit the prototype methods from one constructor into another. + * + * |Name |Type |Desc | + * |----------|--------|-----------| + * |Class |function|Child Class| + * |SuperClass|function|Super Class| + */ + + /* example + * function People(name) { + * this._name = name; + * } + * People.prototype = { + * getName: function () { + * return this._name; + * } + * }; + * function Student(name) { + * this._name = name; + * } + * inherits(Student, People); + * const s = new Student('RedHood'); + * s.getName(); // -> 'RedHood' + */ + + /* typescript + * export declare function inherits(Class: Function, SuperClass: Function): void; + */ + exports = function(Class, SuperClass) { + if (objCreate) return (Class.prototype = objCreate(SuperClass.prototype)); + noop.prototype = SuperClass.prototype; + Class.prototype = new noop(); + }; + + var objCreate = Object.create; + + function noop() {} + + return exports; + })({}); + /* ------------------------------ noop ------------------------------ */ var noop = _.noop = (function (exports) { @@ -63,6 +107,61 @@ return exports; })({}); + /* ------------------------------ has ------------------------------ */ + + var has = _.has = (function (exports) { + /* Checks if key is a direct property. + * + * |Name |Type |Desc | + * |------|-------|--------------------------------| + * |obj |object |Object to query | + * |key |string |Path to check | + * |return|boolean|True if key is a direct property| + */ + + /* example + * has({one: 1}, 'one'); // -> true + */ + + /* typescript + * export declare function has(obj: {}, key: string): boolean; + */ + var hasOwnProp = Object.prototype.hasOwnProperty; + + exports = function(obj, key) { + return hasOwnProp.call(obj, key); + }; + + return exports; + })({}); + + /* ------------------------------ idxOf ------------------------------ */ + + var idxOf = _.idxOf = (function (exports) { + /* Get the index at which the first occurrence of value. + * + * |Name |Type |Desc | + * |---------|------|--------------------| + * |arr |array |Array to search | + * |val |* |Value to search for | + * |fromIdx=0|number|Index to search from| + * |return |number|Value index | + */ + + /* example + * idxOf([1, 2, 1, 2], 2, 2); // -> 3 + */ + + /* typescript + * export declare function idxOf(arr: any[], val: any, fromIdx?: number): number; + */ + exports = function(arr, val, fromIdx) { + return Array.prototype.indexOf.call(arr, val, fromIdx); + }; + + return exports; + })({}); + /* ------------------------------ isUndef ------------------------------ */ var isUndef = _.isUndef = (function (exports) { @@ -354,6 +453,62 @@ return exports; })({}); + /* ------------------------------ restArgs ------------------------------ */ + + var restArgs = _.restArgs = (function (exports) { + /* This accumulates the arguments passed into an array, after a given index. + * + * |Name |Type |Desc | + * |------------|--------|---------------------------------------| + * |function |function|Function that needs rest parameters | + * |[startIndex]|number |The start index to accumulates | + * |return |function|Generated function with rest parameters| + */ + + /* example + * const paramArr = restArgs(function (rest) { return rest }); + * paramArr(1, 2, 3, 4); // -> [1, 2, 3, 4] + */ + + /* typescript + * export declare function restArgs(fn: Function, startIndex?: number): Function; + */ + exports = function(fn, startIdx) { + startIdx = startIdx == null ? fn.length - 1 : +startIdx; + return function() { + var len = Math.max(arguments.length - startIdx, 0); + var rest = new Array(len); + var i; + + for (i = 0; i < len; i++) { + rest[i] = arguments[i + startIdx]; + } // Call runs faster than apply. + + switch (startIdx) { + case 0: + return fn.call(this, rest); + + case 1: + return fn.call(this, arguments[0], rest); + + case 2: + return fn.call(this, arguments[0], arguments[1], rest); + } + + var args = new Array(startIdx + 1); + + for (i = 0; i < startIdx; i++) { + args[i] = arguments[i]; + } + + args[startIdx] = rest; + return fn.apply(this, args); + }; + }; + + return exports; + })({}); + /* ------------------------------ optimizeCb ------------------------------ */ var optimizeCb = _.optimizeCb = (function (exports) { @@ -432,6 +587,33 @@ return exports; })({}); + /* ------------------------------ endWith ------------------------------ */ + + var endWith = _.endWith = (function (exports) { + /* Check if string ends with the given target string. + * + * |Name |Type |Desc | + * |------|-------|-------------------------------| + * |str |string |The string to search | + * |suffix|string |String suffix | + * |return|boolean|True if string ends with target| + */ + + /* example + * endWith('ab', 'b'); // -> true + */ + + /* typescript + * export declare function endWith(str: string, suffix: string): boolean; + */ + exports = function(str, suffix) { + var idx = str.length - suffix.length; + return idx >= 0 && str.indexOf(suffix, idx) === idx; + }; + + return exports; + })({}); + /* ------------------------------ toStr ------------------------------ */ var toStr = _.toStr = (function (exports) { @@ -460,31 +642,58 @@ return exports; })({}); - /* ------------------------------ has ------------------------------ */ + /* ------------------------------ escapeJsStr ------------------------------ */ - var has = _.has = (function (exports) { - /* Checks if key is a direct property. + var escapeJsStr = _.escapeJsStr = (function (exports) { + /* Escape string to be a valid JavaScript string literal between quotes. * - * |Name |Type |Desc | - * |------|-------|--------------------------------| - * |obj |object |Object to query | - * |key |string |Path to check | - * |return|boolean|True if key is a direct property| + * http://www.ecma-international.org/ecma-262/5.1/#sec-7.8.4 + * + * |Name |Type |Desc | + * |------|------|----------------| + * |str |string|String to escape| + * |return|string|Escaped string | */ /* example - * has({one: 1}, 'one'); // -> true + * escapeJsStr('\"\n'); // -> '\\"\\\\n' */ /* typescript - * export declare function has(obj: {}, key: string): boolean; + * export declare function escapeJsStr(str: string): string; */ - var hasOwnProp = Object.prototype.hasOwnProperty; - exports = function(obj, key) { - return hasOwnProp.call(obj, key); + /* dependencies + * toStr + */ + + exports = function(str) { + return toStr(str).replace(regEscapeChars, function(char) { + switch (char) { + case '"': + case "'": + case '\\': + return '\\' + char; + + case '\n': + return '\\n'; + + case '\r': + return '\\r'; + // Line separator + + case '\u2028': + return '\\u2028'; + // Paragraph separator + + case '\u2029': + return '\\u2029'; + } + }); }; + var regEscapeChars = /["'\\\n\r\u2028\u2029]/g; + return exports; })({}); @@ -572,6 +781,169 @@ return exports; })({}); + /* ------------------------------ isArr ------------------------------ */ + + var isArr = _.isArr = (function (exports) { + /* Check if value is an `Array` object. + * + * |Name |Type |Desc | + * |------|-------|----------------------------------| + * |val |* |Value to check | + * |return|boolean|True if value is an `Array` object| + */ + + /* example + * isArr([]); // -> true + * isArr({}); // -> false + */ + + /* typescript + * export declare function isArr(val: any): boolean; + */ + + /* dependencies + * objToStr + */ + + exports = + Array.isArray || + function(val) { + return objToStr(val) === '[object Array]'; + }; + + return exports; + })({}); + + /* ------------------------------ castPath ------------------------------ */ + + var castPath = _.castPath = (function (exports) { + /* Cast value into a property path array. + * + * |Name |Type |Desc | + * |------|------------|-------------------| + * |path |string array|Value to inspect | + * |[obj] |object |Object to query | + * |return|array |Property path array| + */ + + /* example + * castPath('a.b.c'); // -> ['a', 'b', 'c'] + * castPath(['a']); // -> ['a'] + * castPath('a[0].b'); // -> ['a', '0', 'b'] + * castPath('a.b.c', {'a.b.c': true}); // -> ['a.b.c'] + */ + + /* typescript + * export declare function castPath(path: string | string[], obj?: any): string[]; + */ + + /* dependencies + * has isArr + */ + + exports = function(str, obj) { + if (isArr(str)) return str; + if (obj && has(obj, str)) return [str]; + var ret = []; + str.replace(regPropName, function(match, number, quote, str) { + ret.push(quote ? str.replace(regEscapeChar, '$1') : number || match); + }); + return ret; + }; // Lodash _stringToPath + + var regPropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g; + var regEscapeChar = /\\(\\)?/g; + + return exports; + })({}); + + /* ------------------------------ safeGet ------------------------------ */ + + var safeGet = _.safeGet = (function (exports) { + /* Get object property, don't throw undefined error. + * + * |Name |Type |Desc | + * |------|------------|-------------------------| + * |obj |object |Object to query | + * |path |array string|Path of property to get | + * |return|* |Target value or undefined| + */ + + /* example + * const obj = {a: {aa: {aaa: 1}}}; + * safeGet(obj, 'a.aa.aaa'); // -> 1 + * safeGet(obj, ['a', 'aa']); // -> {aaa: 1} + * safeGet(obj, 'a.b'); // -> undefined + */ + + /* typescript + * export declare function safeGet(obj: any, path: string | string[]): any; + */ + + /* dependencies + * isUndef castPath + */ + + exports = function(obj, path) { + path = castPath(path, obj); + var prop; + prop = path.shift(); + + while (!isUndef(prop)) { + obj = obj[prop]; + if (obj == null) return; + prop = path.shift(); + } + + return obj; + }; + + return exports; + })({}); + + /* ------------------------------ flatten ------------------------------ */ + + var flatten = _.flatten = (function (exports) { + /* Recursively flatten an array. + * + * |Name |Type |Desc | + * |------|-----|-------------------| + * |arr |array|Array to flatten | + * |return|array|New flattened array| + */ + + /* example + * flatten(['a', ['b', ['c']], 'd', ['e']]); // -> ['a', 'b', 'c', 'd', 'e'] + */ + + /* typescript + * export declare function flatten(arr: any[]): any[]; + */ + + /* dependencies + * isArr + */ + + exports = function(arr) { + return flat(arr, []); + }; + + function flat(arr, res) { + var len = arr.length, + i = -1, + cur; + + while (len--) { + cur = arr[++i]; + isArr(cur) ? flat(cur, res) : res.push(cur); + } + + return res; + } + + return exports; + })({}); + /* ------------------------------ isFn ------------------------------ */ var isFn = _.isFn = (function (exports) { @@ -651,6 +1023,30 @@ return exports; })({}); + /* ------------------------------ isMiniProgram ------------------------------ */ + + var isMiniProgram = _.isMiniProgram = (function (exports) { + /* Check if running in wechat mini program. + */ + + /* example + * console.log(isMiniProgram); // -> true if running in mini program. + */ + + /* typescript + * export declare const isMiniProgram: boolean; + */ + + /* dependencies + * isFn + */ + /* eslint-disable no-undef */ + + exports = typeof wx !== 'undefined' && isFn(wx.openLocation); + + return exports; + })({}); + /* ------------------------------ isNum ------------------------------ */ var isNum = _.isNum = (function (exports) { @@ -721,35 +1117,32 @@ return exports; })({}); - /* ------------------------------ isArr ------------------------------ */ + /* ------------------------------ isStr ------------------------------ */ - var isArr = _.isArr = (function (exports) { - /* Check if value is an `Array` object. + var isStr = _.isStr = (function (exports) { + /* Check if value is a string primitive. * - * |Name |Type |Desc | - * |------|-------|----------------------------------| - * |val |* |Value to check | - * |return|boolean|True if value is an `Array` object| + * |Name |Type |Desc | + * |------|-------|-----------------------------------| + * |val |* |Value to check | + * |return|boolean|True if value is a string primitive| */ /* example - * isArr([]); // -> true - * isArr({}); // -> false + * isStr('licia'); // -> true */ /* typescript - * export declare function isArr(val: any): boolean; + * export declare function isStr(val: any): boolean; */ /* dependencies * objToStr */ - exports = - Array.isArray || - function(val) { - return objToStr(val) === '[object Array]'; - }; + exports = function(val) { + return objToStr(val) === '[object String]'; + }; return exports; })({}); @@ -958,6 +1351,78 @@ return exports; })({}); + /* ------------------------------ values ------------------------------ */ + + var values = _.values = (function (exports) { + /* Create an array of the own enumerable property values of object. + * + * |Name |Type |Desc | + * |------|------|------------------------| + * |obj |object|Object to query | + * |return|array |Array of property values| + */ + + /* example + * values({one: 1, two: 2}); // -> [1, 2] + */ + + /* typescript + * export declare function values(obj: any): any[]; + */ + + /* dependencies + * each + */ + + exports = function(obj) { + var ret = []; + each(obj, function(val) { + ret.push(val); + }); + return ret; + }; + + return exports; + })({}); + + /* ------------------------------ contain ------------------------------ */ + + var contain = _.contain = (function (exports) { + /* Check if the value is present in the list. + * + * |Name |Type |Desc | + * |------|-------------------|------------------------------------| + * |target|array object string|Target object | + * |value |* |Value to check | + * |return|boolean |True if value is present in the list| + */ + + /* example + * contain([1, 2, 3], 1); // -> true + * contain({a: 1, b: 2}, 1); // -> true + * contain('abc', 'a'); // -> true + */ + + /* typescript + * export declare function contain( + * arr: any[] | {} | string, + * val: any + * ): boolean; + */ + + /* dependencies + * idxOf isStr isArrLike values + */ + + exports = function(arr, val) { + if (isStr(arr)) return arr.indexOf(val) > -1; + if (!isArrLike(arr)) arr = values(arr); + return idxOf(arr, val) >= 0; + }; + + return exports; + })({}); + /* ------------------------------ extendOwn ------------------------------ */ var extendOwn = _.extendOwn = (function (exports) { @@ -987,36 +1452,6 @@ return exports; })({}); - /* ------------------------------ isStr ------------------------------ */ - - var isStr = _.isStr = (function (exports) { - /* Check if value is a string primitive. - * - * |Name |Type |Desc | - * |------|-------|-----------------------------------| - * |val |* |Value to check | - * |return|boolean|True if value is a string primitive| - */ - - /* example - * isStr('licia'); // -> true - */ - - /* typescript - * export declare function isStr(val: any): boolean; - */ - - /* dependencies - * objToStr - */ - - exports = function(val) { - return objToStr(val) === '[object String]'; - }; - - return exports; - })({}); - /* ------------------------------ isEmpty ------------------------------ */ var isEmpty = _.isEmpty = (function (exports) { @@ -1097,6 +1532,100 @@ return exports; })({}); + /* ------------------------------ isNaN ------------------------------ */ + + var isNaN = _.isNaN = (function (exports) { + /* Check if value is an NaN. + * + * |Name |Type |Desc | + * |------|-------|-----------------------| + * |val |* |Value to check | + * |return|boolean|True if value is an NaN| + * + * Undefined is not an NaN, different from global isNaN function. + */ + + /* example + * isNaN(0); // -> false + * isNaN(NaN); // -> true + */ + + /* typescript + * export declare function isNaN(val: any): boolean; + */ + + /* dependencies + * isNum + */ + + exports = function(val) { + return isNum(val) && val !== +val; + }; + + return exports; + })({}); + + /* ------------------------------ isNil ------------------------------ */ + + var isNil = _.isNil = (function (exports) { + /* Check if value is null or undefined, the same as value == null. + * + * |Name |Type |Desc | + * |------|-------|----------------------------------| + * |val |* |Value to check | + * |return|boolean|True if value is null or undefined| + */ + + /* example + * isNil(null); // -> true + * isNil(void 0); // -> true + * isNil(undefined); // -> true + * isNil(false); // -> false + * isNil(0); // -> false + * isNil([]); // -> false + */ + + /* typescript + * export declare function isNil(val: any): boolean; + */ + exports = function(val) { + return val == null; + }; + + return exports; + })({}); + + /* ------------------------------ isPromise ------------------------------ */ + + var isPromise = _.isPromise = (function (exports) { + /* Check if value looks like a promise. + * + * |Name |Type |Desc | + * |------|-------|----------------------------------| + * |val |* |Value to check | + * |return|boolean|True if value looks like a promise| + */ + + /* example + * isPromise(new Promise(function () {})); // -> true + * isPromise({}); // -> false + */ + + /* typescript + * export declare function isPromise(val: any): boolean; + */ + + /* dependencies + * isObj isFn + */ + + exports = function(val) { + return isObj(val) && isFn(val.then); + }; + + return exports; + })({}); + /* ------------------------------ ltrim ------------------------------ */ var ltrim = _.ltrim = (function (exports) { @@ -1266,6 +1795,40 @@ return exports; })({}); + /* ------------------------------ difference ------------------------------ */ + + var difference = _.difference = (function (exports) { + /* Create an array of unique array values not included in the other given array. + * + * |Name |Type |Desc | + * |---------|-----|----------------------------| + * |arr |array|Array to inspect | + * |[...rest]|array|Values to exclude | + * |return |array|New array of filtered values| + */ + + /* example + * difference([3, 2, 1], [4, 2]); // -> [3, 1] + */ + + /* typescript + * export declare function difference(arr: any[], ...rest: any[]): any[]; + */ + + /* dependencies + * restArgs flatten filter contain + */ + + exports = restArgs(function(arr, rest) { + rest = flatten(rest); + return filter(arr, function(val) { + return !contain(rest, val); + }); + }); + + return exports; + })({}); + /* ------------------------------ evalCss ------------------------------ */ _.evalCss = (function (exports) { /* Eval css. @@ -1496,6 +2059,35 @@ return exports; })({}); + /* ------------------------------ extend ------------------------------ */ + + var extend = _.extend = (function (exports) { + /* Copy all of the properties in the source objects over to the destination object. + * + * |Name |Type |Desc | + * |-----------|------|------------------| + * |destination|object|Destination object| + * |...sources |object|Sources objects | + * |return |object|Destination object| + */ + + /* example + * extend({name: 'RedHood'}, {age: 24}); // -> {name: 'RedHood', age: 24} + */ + + /* typescript + * export declare function extend(destination: any, ...sources: any[]): any; + */ + + /* dependencies + * createAssigner allKeys + */ + + exports = createAssigner(allKeys); + + return exports; + })({}); + /* ------------------------------ map ------------------------------ */ var map = _.map = (function (exports) { @@ -1736,6 +2328,198 @@ return exports; })({}); + /* ------------------------------ toArr ------------------------------ */ + + var toArr = _.toArr = (function (exports) { + /* Convert value to an array. + * + * |Name |Type |Desc | + * |------|-----|----------------| + * |val |* |Value to convert| + * |return|array|Converted array | + */ + + /* example + * toArr({a: 1, b: 2}); // -> [{a: 1, b: 2}] + * toArr('abc'); // -> ['abc'] + * toArr(1); // -> [1] + * toArr(null); // -> [] + */ + + /* typescript + * export declare function toArr(val: any): any[]; + */ + + /* dependencies + * isArrLike map isArr isStr + */ + + exports = function(val) { + if (!val) return []; + if (isArr(val)) return val; + if (isArrLike(val) && !isStr(val)) return map(val); + return [val]; + }; + + return exports; + })({}); + + /* ------------------------------ Class ------------------------------ */ + + var Class = _.Class = (function (exports) { + /* Create JavaScript class. + * + * |Name |Type |Desc | + * |---------|--------|---------------------------------| + * |methods |object |Public methods | + * |[statics]|object |Static methods | + * |return |function|Function used to create instances| + */ + + /* example + * const People = Class({ + * initialize: function People(name, age) { + * this.name = name; + * this.age = age; + * }, + * introduce: function () { + * return 'I am ' + this.name + ', ' + this.age + ' years old.'; + * } + * }); + * + * const Student = People.extend({ + * initialize: function Student(name, age, school) { + * this.callSuper(People, 'initialize', arguments); + * + * this.school = school; + * }, + * introduce: function () { + * return this.callSuper(People, 'introduce') + '\n I study at ' + this.school + '.'; + * } + * }, { + * is: function (obj) { + * return obj instanceof Student; + * } + * }); + * + * const a = new Student('allen', 17, 'Hogwarts'); + * a.introduce(); // -> 'I am allen, 17 years old. \n I study at Hogwarts.' + * Student.is(a); // -> true + */ + + /* typescript + * export declare namespace Class { + * class Base { + * toString(): string; + * } + * class IConstructor extends Base { + * constructor(...args: any[]); + * static extend(methods: any, statics: any): IConstructor; + * static inherits(Class: Function): void; + * static methods(methods: any): IConstructor; + * static statics(statics: any): IConstructor; + * [method: string]: any; + * } + * } + * export declare function Class(methods: any, statics?: any): Class.IConstructor; + */ + + /* dependencies + * extend toArr inherits safeGet isMiniProgram + */ + + exports = function(methods, statics) { + return Base.extend(methods, statics); + }; + + function makeClass(parent, methods, statics) { + statics = statics || {}; + var className = + methods.className || safeGet(methods, 'initialize.name') || ''; + delete methods.className; + var ctor; + + if (isMiniProgram) { + ctor = function() { + var args = toArr(arguments); + return this.initialize + ? this.initialize.apply(this, args) || this + : this; + }; + } else { + ctor = new Function( + 'toArr', + 'return function ' + + className + + '()' + + '{' + + 'var args = toArr(arguments);' + + 'return this.initialize ? this.initialize.apply(this, args) || this : this;' + + '};' + )(toArr); + } + + inherits(ctor, parent); + ctor.prototype.constructor = ctor; + + ctor.extend = function(methods, statics) { + return makeClass(ctor, methods, statics); + }; + + ctor.inherits = function(Class) { + inherits(ctor, Class); + }; + + ctor.methods = function(methods) { + extend(ctor.prototype, methods); + return ctor; + }; + + ctor.statics = function(statics) { + extend(ctor, statics); + return ctor; + }; + + ctor.methods(methods).statics(statics); + return ctor; + } + + var Base = (exports.Base = makeClass(Object, { + className: 'Base', + callSuper: function(parent, name, args) { + var superMethod = parent.prototype[name]; + return superMethod.apply(this, args); + }, + toString: function() { + return this.constructor.name; + } + })); + + return exports; + })({}); + + /* ------------------------------ now ------------------------------ */ + + var now = _.now = (function (exports) { + /* Gets the number of milliseconds that have elapsed since the Unix epoch. + */ + + /* example + * now(); // -> 1468826678701 + */ + + /* typescript + * export declare function now(): number; + */ + exports = + Date.now || + function() { + return new Date().getTime(); + }; + + return exports; + })({}); + /* ------------------------------ rtrim ------------------------------ */ var rtrim = _.rtrim = (function (exports) { @@ -2088,5 +2872,406 @@ return exports; })({}); + /* ------------------------------ type ------------------------------ */ + + var type = _.type = (function (exports) { + /* Determine the internal JavaScript [[Class]] of an object. + * + * |Name |Type |Desc | + * |--------------|-------|-----------------| + * |val |* |Value to get type| + * |lowerCase=true|boolean|LowerCase result | + * |return |string |Type of object | + */ + + /* example + * type(5); // -> 'number' + * type({}); // -> 'object' + * type(function () {}); // -> 'function' + * type([]); // -> 'array' + * type([], false); // -> 'Array' + * type(async function () {}, false); // -> 'AsyncFunction' + */ + + /* typescript + * export declare function type(val: any, lowerCase?: boolean): string; + */ + + /* dependencies + * objToStr isNaN + */ + + exports = function(val) { + var lowerCase = + arguments.length > 1 && arguments[1] !== undefined + ? arguments[1] + : true; + if (val === null) return lowerCase ? 'null' : 'Null'; + if (val === undefined) return lowerCase ? 'undefined' : 'Undefined'; + if (isNaN(val)) return lowerCase ? 'nan' : 'NaN'; + var ret = objToStr(val).match(regObj); + if (!ret) return ''; + return lowerCase ? ret[1].toLowerCase() : ret[1]; + }; + + var regObj = /^\[object\s+(.*?)]$/; + + return exports; + })({}); + + /* ------------------------------ toSrc ------------------------------ */ + + var toSrc = _.toSrc = (function (exports) { + /* Convert function to its source code. + * + * |Name |Type |Desc | + * |------|--------|-------------------| + * |fn |function|Function to convert| + * |return|string |Source code | + */ + + /* example + * toSrc(Math.min); // -> 'function min() { [native code] }' + * toSrc(function () {}) // -> 'function () { }' + */ + + /* typescript + * export declare function toSrc(fn: Function): string; + */ + + /* dependencies + * isNil + */ + + exports = function(fn) { + if (isNil(fn)) return ''; + + try { + return fnToStr.call(fn); + /* eslint-disable no-empty */ + } catch (e) {} + + try { + return fn + ''; + /* eslint-disable no-empty */ + } catch (e) {} + + return ''; + }; + + var fnToStr = Function.prototype.toString; + + return exports; + })({}); + + /* ------------------------------ stringifyAll ------------------------------ */ + _.stringifyAll = (function (exports) { + /* Stringify object into json with types. + * + * |Name |Type |Desc | + * |---------|------|-------------------| + * |obj |* |Object to stringify| + * |[options]|object|Stringify options | + * |return |string|Stringified object | + * + * Available options: + * + * |Name |Type |Desc | + * |------------------|-------|-------------------------| + * |unenumerable=false|boolean|Include unenumerable keys| + * |symbol=false |boolean|Include symbol keys | + * |accessGetter=false|boolean|Access getter value | + * |timeout=0 |number |Timeout of stringify | + * |depth=0 |number |Max depth of recursion | + * |[ignore] |array |Values to ignore | + * + * When time is out, all remaining values will all be "Timeout". + */ + + /* example + * stringifyAll(function test() {}); // -> '{"value":"function test() {}","type":"Function",...}' + */ + + /* typescript + * export declare namespace stringifyAll { + * interface IOptions { + * unenumerable?: boolean; + * symbol?: boolean; + * accessGetter?: boolean; + * timeout?: number; + * depth?: number; + * ignore?: any[]; + * } + * } + * export declare function stringifyAll( + * obj: any, + * options?: stringifyAll.IOptions + * ): string; + */ + + /* dependencies + * escapeJsStr type toStr endWith toSrc keys each Class getProto difference extend isPromise filter now allKeys contain + */ + + exports = function(obj) { + var _ref = + arguments.length > 1 && arguments[1] !== undefined + ? arguments[1] + : {}, + self = _ref.self, + _ref$startTime = _ref.startTime, + startTime = _ref$startTime === void 0 ? now() : _ref$startTime, + _ref$timeout = _ref.timeout, + timeout = _ref$timeout === void 0 ? 0 : _ref$timeout, + _ref$depth = _ref.depth, + depth = _ref$depth === void 0 ? 0 : _ref$depth, + _ref$curDepth = _ref.curDepth, + curDepth = _ref$curDepth === void 0 ? 1 : _ref$curDepth, + _ref$visitor = _ref.visitor, + visitor = _ref$visitor === void 0 ? new Visitor() : _ref$visitor, + _ref$unenumerable = _ref.unenumerable, + unenumerable = _ref$unenumerable === void 0 ? false : _ref$unenumerable, + _ref$symbol = _ref.symbol, + symbol = _ref$symbol === void 0 ? false : _ref$symbol, + _ref$accessGetter = _ref.accessGetter, + accessGetter = _ref$accessGetter === void 0 ? false : _ref$accessGetter, + _ref$ignore = _ref.ignore, + ignore = _ref$ignore === void 0 ? [] : _ref$ignore; + + var json = ''; + var options = { + visitor: visitor, + unenumerable: unenumerable, + symbol: symbol, + accessGetter: accessGetter, + depth: depth, + curDepth: curDepth + 1, + timeout: timeout, + startTime: startTime, + ignore: ignore + }; + var t = type(obj, false); + + if (t === 'String') { + json = wrapStr(obj); + } else if (t === 'Number') { + json = toStr(obj); + + if (endWith(json, 'Infinity')) { + json = '{"value":"'.concat(json, '","type":"Number"}'); + } + } else if (t === 'NaN') { + json = '{"value":"NaN","type":"Number"}'; + } else if (t === 'Boolean') { + json = obj ? 'true' : 'false'; + } else if (t === 'Null') { + json = 'null'; + } else if (t === 'Undefined') { + json = '{"type":"Undefined"}'; + } else if (t === 'Symbol') { + var val = 'Symbol'; + + try { + val = toStr(obj); + /* eslint-disable no-empty */ + } catch (e) {} + + json = '{"value":'.concat(wrapStr(val), ',"type":"Symbol"}'); + } else { + if (timeout && now() - startTime > timeout) { + return wrapStr('Timeout'); + } + + if (depth && curDepth > depth) { + return wrapStr('{...}'); + } + + json = '{'; + var parts = []; + var visitedObj = visitor.get(obj); + var id; + + if (visitedObj) { + id = visitedObj.id; + parts.push('"reference":'.concat(id)); + } else { + id = visitor.set(obj); + parts.push('"id":'.concat(id)); + } + + parts.push('"type":"'.concat(t, '"')); + + if (endWith(t, 'Function')) { + parts.push('"value":'.concat(wrapStr(toSrc(obj)))); + } else if (t === 'RegExp') { + parts.push('"value":'.concat(wrapStr(obj))); + } + + if (!visitedObj) { + var enumerableKeys = keys(obj); + + if (enumerableKeys.length) { + parts.push( + iterateObj( + 'enumerable', + enumerableKeys, + self || obj, + options + ) + ); + } + + if (unenumerable) { + var unenumerableKeys = difference( + allKeys(obj, { + prototype: false, + unenumerable: true + }), + enumerableKeys + ); + + if (unenumerableKeys.length) { + parts.push( + iterateObj( + 'unenumerable', + unenumerableKeys, + self || obj, + options + ) + ); + } + } + + if (symbol) { + var symbolKeys = filter( + allKeys(obj, { + prototype: false, + symbol: true + }), + function(key) { + return typeof key === 'symbol'; + } + ); + + if (symbolKeys.length) { + parts.push( + iterateObj('symbol', symbolKeys, self || obj, options) + ); + } + } + + var prototype = getProto(obj); + + if (prototype && !contain(ignore, prototype)) { + var proto = '"proto":'.concat( + exports( + prototype, + extend(options, { + self: self || obj + }) + ) + ); + parts.push(proto); + } + } + + json += parts.join(',') + '}'; + } + + return json; + }; + + function iterateObj(name, keys, obj, options) { + var parts = []; + each(keys, function(key) { + var val; + var descriptor = Object.getOwnPropertyDescriptor(obj, key); + var hasGetter = descriptor && descriptor.get; + var hasSetter = descriptor && descriptor.set; + + if (!options.accessGetter && hasGetter) { + val = '(...)'; + } else { + try { + val = obj[key]; + + if (contain(options.ignore, val)) { + return; + } + + if (isPromise(val)) { + val.catch(function() {}); + } + } catch (e) { + val = e.message; + } + } + + parts.push(''.concat(wrapKey(key), ':').concat(exports(val, options))); + + if (hasGetter) { + parts.push( + '' + .concat(wrapKey('get ' + toStr(key)), ':') + .concat(exports(descriptor.get, options)) + ); + } + + if (hasSetter) { + parts.push( + '' + .concat(wrapKey('set ' + toStr(key)), ':') + .concat(exports(descriptor.set, options)) + ); + } + }); + return '"'.concat(name, '":{') + parts.join(',') + '}'; + } + + function wrapKey(key) { + return '"'.concat(escapeJsonStr(key), '"'); + } + + function wrapStr(str) { + return '"'.concat(escapeJsonStr(toStr(str)), '"'); + } + + function escapeJsonStr(str) { + return escapeJsStr(str) + .replace(/\\'/g, "'") + .replace(/\t/g, '\\t'); + } + + var Visitor = Class({ + initialize: function() { + this.id = 0; + this.visited = []; + }, + set: function(val) { + var visited = this.visited, + id = this.id; + var obj = { + id: id, + val: val + }; + visited.push(obj); + this.id++; + return id; + }, + get: function(val) { + var visited = this.visited; + + for (var i = 0, len = visited.length; i < len; i++) { + var obj = visited[i]; + if (val === obj.val) return obj; + } + + return false; + } + }); + + return exports; + })({}); + return _; })); \ No newline at end of file
(index)${val}${val === Value ? 'Value' : toStr(val)}
${idx}${formatTableVal(obj[column])}${formatTableVal(obj)}${val}