UNPKG

util-ex

Version:

Browser-friendly enhanced util fully compatible with standard node.js

309 lines (297 loc) 10.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; exports.inspect = inspect; var _string = _interopRequireDefault(require("./is/type/string.js")); var _number = _interopRequireDefault(require("./is/type/number.js")); var _null = _interopRequireDefault(require("./is/type/null.js")); var _error = _interopRequireDefault(require("./is/type/error.js")); var _date = _interopRequireDefault(require("./is/type/date.js")); var _regexp = _interopRequireDefault(require("./is/type/regexp.js")); var _function = _interopRequireDefault(require("./is/type/function.js")); var _array = _interopRequireDefault(require("./is/type/array.js")); var _undefined = _interopRequireDefault(require("./is/type/undefined.js")); var _extend2 = _interopRequireDefault(require("./_extend.js")); var _boolean = _interopRequireDefault(require("./is/type/boolean.js")); var shims = _interopRequireWildcard(require("./_shims.js")); function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); } function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } const hasOwnProperty = Object.prototype.hasOwnProperty; /* legacy: obj, showHidden, depth, colors */ /** * Return a string representation of an object, including its properties and nested objects, with customizable options. * * Echos the value of a value. Try to print the value out * in the best way possible given the different types. * * @param {*} obj - The object to inspect. * @param {object|boolean=} opts - Customizable options to control the behavior of the inspection. If it's a boolean, it sets the "showHidden" option. * @param {boolean=false} opts.showHidden - Whether to show non-enumerable properties of objects. * @param {number=2} opts.depth - How many levels deep nested objects are inspected. * @param {boolean=false} opts.colors - Whether to color the output. * @param {boolean=true} opts.customInspect - Whether to inspect custom inspect functions on objects. * @returns {string} The formatted string representing the object. */ function inspect(obj, opts) { // default options const ctx = { seen: [], stylize: stylizeNoColor }; // legacy... if (arguments.length >= 3) ctx.depth = arguments[2]; if (arguments.length >= 4) ctx.colors = arguments[3]; if ((0, _boolean.default)(opts)) { // legacy... ctx.showHidden = opts; } else if (opts) { // got an "options" object (0, _extend2.default)(ctx, opts); } // set default options if ((0, _undefined.default)(ctx.showHidden)) ctx.showHidden = false; if ((0, _undefined.default)(ctx.depth)) ctx.depth = 2; if ((0, _undefined.default)(ctx.colors)) ctx.colors = false; if ((0, _undefined.default)(ctx.customInspect)) ctx.customInspect = true; if (ctx.colors) ctx.stylize = stylizeWithColor; return formatValue(ctx, obj, ctx.depth); } // http://en.wikipedia.org/wiki/ANSI_escape_code#graphics inspect.colors = { 'bold': [1, 22], 'italic': [3, 23], 'underline': [4, 24], 'inverse': [7, 27], 'white': [37, 39], 'grey': [90, 39], 'black': [30, 39], 'blue': [34, 39], 'cyan': [36, 39], 'green': [32, 39], 'magenta': [35, 39], 'red': [31, 39], 'yellow': [33, 39] }; // Don't use 'blue' not visible on cmd.exe inspect.styles = { 'special': 'cyan', 'number': 'yellow', 'boolean': 'yellow', 'undefined': 'grey', 'null': 'bold', 'string': 'green', 'date': 'magenta', // "name": intentionally not styling 'regexp': 'red' }; function stylizeWithColor(str, styleType) { const style = inspect.styles[styleType]; if (style) { return `\u001B[${inspect.colors[style][0]}m${str}\u001B[${inspect.colors[style][1]}m`; } else { return str; } } function stylizeNoColor(str, _styleType) { return str; } function arrayToHash(array) { const hash = {}; array.forEach(val => { hash[val] = true; }); return hash; } function formatValue(ctx, value, recurseTimes) { // Provide a hook for user-specified inspect functions. // Check that value is an object with an inspect function on it if (ctx.customInspect && value && (0, _function.default)(value.inspect) && // Filter out the util module, it's inspect function is special value.inspect !== exports.inspect && // Also filter out any prototype objects using the circular check. !(value.constructor && value.constructor.prototype === value)) { let ret = value.inspect(recurseTimes); if (!(0, _string.default)(ret)) { ret = formatValue(ctx, ret, recurseTimes); } return ret; } // Primitive types cannot have properties const primitive = formatPrimitive(ctx, value); if (primitive) { return primitive; } // Look up the keys of the object. let keys = shims.keys(value); const visibleKeys = arrayToHash(keys); if (ctx.showHidden) { keys = shims.getOwnPropertyNames(value); } // Some type of object without properties can be shortcutted. if (keys.length === 0) { if ((0, _function.default)(value)) { const name = value.name ? `: ${value.name}` : ''; return ctx.stylize(`[Function${name}]`, 'special'); } if ((0, _regexp.default)(value)) { return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); } if ((0, _date.default)(value)) { return ctx.stylize(Date.prototype.toString.call(value), 'date'); } if ((0, _error.default)(value)) { return formatError(value); } } let base = ''; let array = false; let braces = ['{', '}']; // Make Array say that they are Array if ((0, _array.default)(value)) { array = true; braces = ['[', ']']; } // Make functions say that they are functions if ((0, _function.default)(value)) { const n = value.name ? `: ${value.name}` : ''; base = ` [Function${n}]`; } // Make RegExps say that they are RegExps if ((0, _regexp.default)(value)) { base = ` ${RegExp.prototype.toString.call(value)}`; } // Make dates with properties first say the date if ((0, _date.default)(value)) { base = ` ${Date.prototype.toUTCString.call(value)}`; } // Make error with message first say the error if ((0, _error.default)(value)) { base = ` ${formatError(value)}`; } if (keys.length === 0 && (!array || value.length === 0)) { return braces[0] + base + braces[1]; } if (recurseTimes < 0) { if ((0, _regexp.default)(value)) { return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); } else { return ctx.stylize('[Object]', 'special'); } } ctx.seen.push(value); let output; if (array) { output = formatArray(ctx, value, recurseTimes, visibleKeys, keys); } else { output = keys.map(key => { return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array); }); } ctx.seen.pop(); return reduceToSingleString(output, base, braces); } function formatPrimitive(ctx, value) { if ((0, _undefined.default)(value)) return ctx.stylize('undefined', 'undefined'); if ((0, _string.default)(value)) { const simple = `'${JSON.stringify(value).replace(/^"|"$/g, '').replace(/'/g, "\\'").replace(/\\"/g, '"')}'`; return ctx.stylize(simple, 'string'); } if ((0, _number.default)(value)) return ctx.stylize(`${value}`, 'number'); if ((0, _boolean.default)(value)) return ctx.stylize(`${value}`, 'boolean'); // For some reason typeof null is "object", so special case here. if ((0, _null.default)(value)) return ctx.stylize('null', 'null'); } function formatError(value) { return `[${Error.prototype.toString.call(value)}]`; } function formatArray(ctx, value, recurseTimes, visibleKeys, keys) { const output = []; for (let i = 0, l = value.length; i < l; ++i) { if (hasOwnProperty.call(value, String(i))) { output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, String(i), true)); } else { output.push(''); } } keys.forEach(key => { if (!key.match(/^\d+$/)) { output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, key, true)); } }); return output; } function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) { let name, str; const desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] }; if (desc.get) { if (desc.set) { str = ctx.stylize('[Getter/Setter]', 'special'); } else { str = ctx.stylize('[Getter]', 'special'); } } else { if (desc.set) { str = ctx.stylize('[Setter]', 'special'); } } if (!hasOwnProperty.call(visibleKeys, key)) { name = `[${key}]`; } if (!str) { if (ctx.seen.indexOf(desc.value) === -1) { if ((0, _null.default)(recurseTimes)) { str = formatValue(ctx, desc.value, null); } else { str = formatValue(ctx, desc.value, recurseTimes - 1); } if (str.indexOf('\n') !== -1) { if (array) { str = str.split('\n').map(line => { return ` ${line}`; }).join('\n').substr(2); } else { str = `\n${str.split('\n').map(line => { return ` ${line}`; }).join('\n')}`; } } } else { str = ctx.stylize('[Circular]', 'special'); } } if ((0, _undefined.default)(name)) { if (array && key.match(/^\d+$/)) { return str; } name = JSON.stringify(`${key}`); if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { name = name.substr(1, name.length - 2); name = ctx.stylize(name, 'name'); } else { name = name.replace(/'/g, "\\'").replace(/\\"/g, '"').replace(/(^"|"$)/g, "'"); name = ctx.stylize(name, 'string'); } } return `${name}: ${str}`; } function reduceToSingleString(output, base, braces) { // eslint-disable-next-line unused-imports/no-unused-vars let numLinesEst = 0; const length = output.reduce((prev, cur) => { numLinesEst++; if (cur.indexOf('\n') !== -1) { numLinesEst++; } // eslint-disable-next-line no-control-regex return prev + cur.replace(/\u001B\[\d\d?m/g, '').length + 1; }, 0); if (length > 60) { return `${braces[0] + (base === '' ? '' : `${base}\n `)} ${output.join(',\n ')} ${braces[1]}`; } return `${braces[0] + base} ${output.join(', ')} ${braces[1]}`; } var _default = exports.default = inspect;