From a4948ada05f3a1fbb2b736e78e30013145fc0721 Mon Sep 17 00:00:00 2001 From: Justin Searls Date: Wed, 15 Mar 2017 06:33:01 +0100 Subject: [PATCH] Add a transform option (#45) --- index.js | 12 ++++++++++-- readme.md | 35 +++++++++++++++++++++++++++++++++++ test.js | 25 +++++++++++++++++++++++++ 3 files changed, 70 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index 04a90bc..4a55bd9 100644 --- a/index.js +++ b/index.js @@ -76,7 +76,11 @@ module.exports = (val, opts, pad) => { const ret = '[' + tokens.newLine + val.map((el, i) => { const eol = val.length - 1 === i ? tokens.newLine : ',' + tokens.newLineOrSpace; - return tokens.indent + stringify(el, opts, pad + opts.indent) + eol; + let value = stringify(el, opts, pad + opts.indent); + if (opts.transform) { + value = opts.transform(val, i, value); + } + return tokens.indent + value + eol; }).join('') + tokens.pad + ']'; seen.pop(val); @@ -102,7 +106,11 @@ module.exports = (val, opts, pad) => { const isSymbol = typeof el === 'symbol'; const isClassic = !isSymbol && /^[a-z$_][a-z$_0-9]*$/i.test(el); const key = isSymbol || isClassic ? el : stringify(el, opts); - return tokens.indent + String(key) + ': ' + stringify(val[el], opts, pad + opts.indent) + eol; + let value = stringify(val[el], opts, pad + opts.indent); + if (opts.transform) { + value = opts.transform(val, el, value); + } + return tokens.indent + String(key) + ': ' + value + eol; }).join('') + tokens.pad + '}'; seen.pop(val); diff --git a/readme.md b/readme.md index 9cf345c..177f054 100644 --- a/readme.md +++ b/readme.md @@ -79,6 +79,41 @@ Type: `Function` Expected to return a `boolean` of whether to include the property `prop` of the object `obj` in the output. +##### transform(obj, prop, originalResult) + +Type: `Function`
+Default: `undefined` + +Expected to return a `string` that transforms the string that resulted from stringifying `obj[prop]`. This can be used to detect special types of objects that need to be stringified in a particular way. The `transform` function might return an alternate string in this case, otherwise returning the `originalResult`. + +Here's an example that uses the `transform` option to mask fields named "password": + +```js +const obj = { + user: 'becky', + password: 'secret' +} + +const pretty = stringifyObject(obj, { + transform: (obj, prop, originalResult) => { + if (prop === 'password') { + return originalResult.replace(/\w/g, '*'); + } else { + return originalResult; + } + } +}); + +console.log(pretty); +/* +{ + user: 'becky', + password: '******' +} +*/ +``` + + ##### inlineCharacterLimit Type: `number` diff --git a/test.js b/test.js index 804ed97..c56b804 100644 --- a/test.js +++ b/test.js @@ -72,6 +72,31 @@ it('considering filter option to stringify an object', () => { assert.equal(actual, '{\n\tbar: {\n\t\tval: 10\n\t}\n}'); }); +it('allows an object to be transformed', () => { + const obj = { + foo: { + val: 10 + }, + bar: 9, + baz: [8] + }; + + const actual = stringifyObject(obj, { + transform: (obj, prop, result) => { + if (prop === 'val') { + return String(obj[prop] + 1); + } else if (prop === 'bar') { + return '\'' + result + 'L\''; + } else if (obj[prop] === 8) { + return 'LOL'; + } + return result; + } + }); + + assert.equal(actual, '{\n\tfoo: {\n\t\tval: 11\n\t},\n\tbar: \'9L\',\n\tbaz: [\n\t\tLOL\n\t]\n}'); +}); + it('should not crash with circular references in arrays', () => { const array = []; array.push(array);