diff --git a/package-lock.json b/package-lock.json index 825c8b1..6179eee 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3724,6 +3724,11 @@ "is-property": "1.0.2" } }, + "get-own-enumerable-property-symbols": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-2.0.1.tgz", + "integrity": "sha512-TtY/sbOemiMKPRUDDanGCSgBYe7Mf0vbRsWnBZ+9yghpZ1MvcpSpuZFjHdEeY/LZjZy0vdLjS77L6HosisFiug==" + }, "get-pkg-repo": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/get-pkg-repo/-/get-pkg-repo-1.4.0.tgz", @@ -4480,8 +4485,7 @@ "is-obj": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", - "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", - "dev": true + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=" }, "is-observable": { "version": "0.2.0", @@ -4552,6 +4556,11 @@ "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=", "dev": true }, + "is-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", + "integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=" + }, "is-resolvable": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.0.0.tgz", @@ -8176,6 +8185,16 @@ "safe-buffer": "5.1.1" } }, + "stringify-object": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.2.1.tgz", + "integrity": "sha512-jPcQYw/52HUPP8uOE4kkjxl5bB9LfHkKCTptIk3qw7ozP5XMIMlHMLjt00GGSwW6DJAf/njY5EU6Vpwl4LlBKQ==", + "requires": { + "get-own-enumerable-property-symbols": "2.0.1", + "is-obj": "1.0.1", + "is-regexp": "1.0.0" + } + }, "stringstream": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", diff --git a/package.json b/package.json index 55e995f..8b3a1cb 100644 --- a/package.json +++ b/package.json @@ -79,5 +79,8 @@ "tslint": "^5.8.0", "tslint-config-unional": "^0.8.0", "typescript": "^2.6.1" + }, + "dependencies": { + "stringify-object": "^3.2.1" } } diff --git a/src/index.spec.ts b/src/formatFunction.spec.ts similarity index 99% rename from src/index.spec.ts rename to src/formatFunction.spec.ts index 4078c69..fc74256 100644 --- a/src/index.spec.ts +++ b/src/formatFunction.spec.ts @@ -1,5 +1,6 @@ import test from 'ava' -import { formatFunction } from './index'; + +import { formatFunction } from './index' test('anonymous function', t => { t.is(formatFunction(function () { }), 'function () {}') diff --git a/src/formatFunction.ts b/src/formatFunction.ts new file mode 100644 index 0000000..e20a4b4 --- /dev/null +++ b/src/formatFunction.ts @@ -0,0 +1,60 @@ +import os = require('os') + +export function formatFunction(fn: Function, option = { maxLength: 120 }) { + const str = fn.toString() + if (isArrow(str)) + return formatArrow(str, option.maxLength) + else + return formatFn(str, option.maxLength) +} + +function isArrow(str: string) { + const lines = str.split(os.EOL) + + // https://regex101.com/r/0HtLzb/1 + return /[\(]?.*[\)]? =>/.test(lines[0]) +} + +function formatArrow(str: string, maxLength) { + const lines = str.split(os.EOL) + const trimmedlines = lines.map(l => l.trim()) + let singleLine = trimmedlines.join(' '); + + // https://regex101.com/r/1Nv7hN/2 + const matchSingleExpression = /=> { return (.*); }/.exec(singleLine) + if (matchSingleExpression) { + const singleExpression = matchSingleExpression[1] + singleLine = lines[0].slice(0, lines[0].length - 1) + singleExpression + } + + if (singleLine.length > maxLength) { + singleLine = trimWithBracket(singleLine, maxLength) + } + if (singleLine.length > maxLength) { + // after trimming it is still too long + singleLine = singleLine.slice(0, maxLength - 3) + '...' + } + return singleLine +} + +function trimWithBracket(singleLine, maxLength) { + // https://regex101.com/r/HrkxfW/1 + const parts = /(.* { )(.*)( })/.exec(singleLine) + return parts ? parts[1] + parts[2].slice(0, maxLength - parts[1].length - parts[3].length - 3) + '...' + parts[3] : singleLine +} + +function formatFn(str: string, maxLength) { + const lines = str.split(os.EOL) + const trimmedlines = lines.map(l => l.trim()) + let singleLine = trimmedlines.join(' '); + + if (singleLine.length > maxLength) { + singleLine = trimWithBracket(singleLine, maxLength) + } + + if (singleLine.length > maxLength) { + // after trimming it is still too long + singleLine = singleLine.slice(0, maxLength - 3) + '...' + } + return singleLine +} diff --git a/src/formatObject.spec.ts b/src/formatObject.spec.ts new file mode 100644 index 0000000..00375af --- /dev/null +++ b/src/formatObject.spec.ts @@ -0,0 +1,42 @@ +import { test } from 'ava' + +import { formatObject } from './index' + +test('empty object', t => { + t.is(formatObject({}), '{}') +}) + +test('simple object', t => { + t.is(formatObject({ a: 1 }), '{ a: 1 }') +}) + +test('complex object', t => { + t.is(formatObject({ a: { b: 1, c: 'c' }, d: true }), `{ a: { b: 1, c: 'c' }, d: true }`) +}) + +test('object with function', t => { + t.is(formatObject({ a: () => { return true } }), `{ a: () => true }`) +}) + +test('long object', t => { + t.is(formatObject({ a: { b: 1, c: 'c' }, d: true }, { maxLength: 20 }), `{ a: { b: 1, c:... }`) +}) + +test('long object with function', t => { + t.is(formatObject({ a: () => false, c: { b: 1, c: 'c' }, d: true }, { maxLength: 20 }), `{ a: () => fals... }`) +}) + +test('object with long function', t => { + t.is(formatObject({ + a: function (x, y) { + console.log(1) + console.log(2) + console.log(3) + console.log(4) + console.log(5) + console.log(6) + x++ + return y + }, c: { b: 1, c: 'c' }, d: true + }, { maxLength: 100 }), `{ a: function (x, y) { console.log(1); console.log(2); console.log(3); console.log(4); console... }`) +}) diff --git a/src/formatObject.ts b/src/formatObject.ts new file mode 100644 index 0000000..cb0f866 --- /dev/null +++ b/src/formatObject.ts @@ -0,0 +1,20 @@ +import stringifyObject = require('stringify-object'); + +import { formatFunction } from './formatFunction' + +export function formatObject(obj, option = { maxLength: 120 }) { + let str: string = stringifyObject(obj, { + indent: ' ', + inlineCharacterLimit: Infinity, + transform: (obj, prop, originalResult) => { + if (typeof obj[prop] === 'function') + return formatFunction(obj[prop], { maxLength: Infinity }) + return originalResult + } + }) + str = str.replace(/\{/g, '{ ').replace(/\}/g, ' }').replace(/{\s{2}}/g, '{}') + if (str.length > option.maxLength) { + str = str.slice(0, option.maxLength - 5) + '...' + str.slice(-2) + } + return str +} diff --git a/src/index.ts b/src/index.ts index e20a4b4..fb82c0d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,60 +1,2 @@ -import os = require('os') - -export function formatFunction(fn: Function, option = { maxLength: 120 }) { - const str = fn.toString() - if (isArrow(str)) - return formatArrow(str, option.maxLength) - else - return formatFn(str, option.maxLength) -} - -function isArrow(str: string) { - const lines = str.split(os.EOL) - - // https://regex101.com/r/0HtLzb/1 - return /[\(]?.*[\)]? =>/.test(lines[0]) -} - -function formatArrow(str: string, maxLength) { - const lines = str.split(os.EOL) - const trimmedlines = lines.map(l => l.trim()) - let singleLine = trimmedlines.join(' '); - - // https://regex101.com/r/1Nv7hN/2 - const matchSingleExpression = /=> { return (.*); }/.exec(singleLine) - if (matchSingleExpression) { - const singleExpression = matchSingleExpression[1] - singleLine = lines[0].slice(0, lines[0].length - 1) + singleExpression - } - - if (singleLine.length > maxLength) { - singleLine = trimWithBracket(singleLine, maxLength) - } - if (singleLine.length > maxLength) { - // after trimming it is still too long - singleLine = singleLine.slice(0, maxLength - 3) + '...' - } - return singleLine -} - -function trimWithBracket(singleLine, maxLength) { - // https://regex101.com/r/HrkxfW/1 - const parts = /(.* { )(.*)( })/.exec(singleLine) - return parts ? parts[1] + parts[2].slice(0, maxLength - parts[1].length - parts[3].length - 3) + '...' + parts[3] : singleLine -} - -function formatFn(str: string, maxLength) { - const lines = str.split(os.EOL) - const trimmedlines = lines.map(l => l.trim()) - let singleLine = trimmedlines.join(' '); - - if (singleLine.length > maxLength) { - singleLine = trimWithBracket(singleLine, maxLength) - } - - if (singleLine.length > maxLength) { - // after trimming it is still too long - singleLine = singleLine.slice(0, maxLength - 3) + '...' - } - return singleLine -} +export * from './formatFunction' +export * from './formatObject'