Stringify any JavaScript value.
npm install @permafrost-dev/pretty-format---
This package originally comes from the jest package _(27.0.0-next.3)_. It is located under packages/pretty-format.
The original package author was James Kyle
---
This package is largely unchanged from the original with the exception of removing several plugins, including support for React components.
---
Stringify any JavaScript value.
- Serialize built-in JavaScript types.
- Serialize application-specific data types with built-in or user-defined plugins.
``sh
$ npm install @permafrost-dev/pretty-format
or
$ yarn add @permafrost-dev/pretty-format
`
`js`
const {format: prettyFormat} = require('@permafrost-dev/pretty-format'); // CommonJS
`js`
import {format as prettyFormat} from '@permafrost-dev/pretty-format'; // ES2015 modules
`js
const val = {object: {}};
val.circularReference = val;
val[Symbol('foo')] = 'foo';
val.map = new Map([['prop', 'value']]);
val.array = [-0, Infinity, NaN];
console.log(prettyFormat(val));
/*
Object {
"array": Array [
-0,
Infinity,
NaN,
],
"circularReference": [Circular],
"map": Map {
"prop" => "value",
},
"object": Object {},
Symbol(foo): "foo",
}
*/
`
`js
function onClick() {}
console.log(prettyFormat(onClick));
/*
[Function onClick]
*/
const options = {
printFunctionName: false,
};
console.log(prettyFormat(onClick, options));
/*
[Function]
*/
`
| key | type | default | description |
| :------------------ | :-------- | :--------- | :------------------------------------------------------ |
| callToJSON | boolean | true | call toJSON method (if it exists) on objects |escapeRegex
| | boolean | false | escape special characters in regular expressions |escapeString
| | boolean | true | escape special characters in strings |highlight
| | boolean | false | highlight syntax with colors in terminal (some plugins) |indent
| | number | 2 | spaces in each level of indentation |maxDepth
| | number | Infinity | levels to print in arrays, objects, elements, and so on |min
| | boolean | false | minimize added space: no indentation nor line breaks |plugins
| | array | [] | plugins to serialize application-specific data types |printFunctionName
| | boolean | true | include or omit the name of a function |theme
| | object | | colors to highlight syntax in terminal |
Property values of theme are from ansi-styles colors
`js`
const DEFAULT_THEME = {
comment: 'gray',
content: 'reset',
prop: 'yellow',
tag: 'cyan',
value: 'green',
};Usage in Jest
For snapshot tests, Jest uses pretty-format with options that include some of its built-in plugins. For this purpose, plugins are also known as snapshot serializers.
To serialize application-specific data types, you can add modules to devDependencies of a project, and then:
In an individual test file, you can add a module as follows. It precedes any modules from Jest configuration.
`js
import serializer from 'my-serializer-module';
expect.addSnapshotSerializer(serializer);
// tests which have expect(value).toMatchSnapshot() assertions`
For all test files, you can specify modules in Jest configuration. They precede built-in plugins for HTML data types. For example, in a package.json file:
`json`
{
"jest": {
"snapshotSerializers": ["my-serializer-module"]
}
}
A plugin is a JavaScript object.
If options has a plugins array: for the first plugin whose test(val) method returns a truthy value, then prettyFormat(val, options) returns the result from either:
- serialize(val, …) method of the improved interface (available in version 21 or later)print(val, …)
- method of the original interface (if plugin does not have serialize method)
Write test so it can receive val argument of any type. To serialize objects which have certain properties, then a guarded expression like val != null && … or more concise val && … prevents the following errors:
- TypeError: Cannot read property 'whatever' of nullTypeError: Cannot read property 'whatever' of undefined
-
Pay attention to efficiency in test because pretty-format calls it often.
The improved interface is available in version 21 or later.
Write serialize to return a string, given the arguments:
- val which “passed the test”config
- unchanging object: derived from optionsindentation
- current string: concatenate to indent from configdepth
- current number: compare to maxDepth from configrefs
- current array: find circular references in objectsprinter
- callback function: serialize children
| key | type | description |
| :------------------ | :-------- | :------------------------------------------------------ |
| callToJSON | boolean | call toJSON method (if it exists) on objects |colors
| | Object | escape codes for colors to highlight syntax |escapeRegex
| | boolean | escape special characters in regular expressions |escapeString
| | boolean | escape special characters in strings |indent
| | string | spaces in each level of indentation |maxDepth
| | number | levels to print in arrays, objects, elements, and so on |min
| | boolean | minimize added space: no indentation nor line breaks |plugins
| | array | plugins to serialize application-specific data types |printFunctionName
| | boolean | include or omit the name of a function |spacingInner
| | strong | spacing to separate items in a list |spacingOuter
| | strong | spacing to enclose a list of items |
Each property of colors in config corresponds to a property of theme in options:
- the key is the same (for example, tag)colors
- the value in is a object with open and close properties whose values are escape codes from ansi-styles for the color value in theme (for example, 'cyan')
Some properties in config are derived from min in options:
- spacingInner and spacingOuter are newline if min is falsespacingInner
- is space and spacingOuter is empty string if min is true
This plugin is a pattern you can apply to serialize composite data types. Side note: pretty-format does not need a plugin to serialize arrays.
`js
// We reused more code when we factored out a function for child items
// that is independent of depth, name, and enclosing punctuation (see below).
const SEPARATOR = ',';
function serializeItems(items, config, indentation, depth, refs, printer) {
if (items.length === 0) {
return '';
}
const indentationItems = indentation + config.indent;
return (
config.spacingOuter +
items
.map(
item =>
indentationItems +
printer(item, config, indentationItems, depth, refs), // callback
)
.join(SEPARATOR + config.spacingInner) +
(config.min ? '' : SEPARATOR) + // following the last item
config.spacingOuter +
indentation
);
}
const plugin = {
test(val) {
return Array.isArray(val);
},
serialize(array, config, indentation, depth, refs, printer) {
const name = array.constructor.name;
return ++depth > config.maxDepth
? '[' + name + ']'
: (config.min ? '' : name + ' ') +
'[' +
serializeItems(array, config, indentation, depth, refs, printer) +
']';
},
};
`
`js`
const val = {
filter: 'completed',
items: [
{
text: 'Write test',
completed: true,
},
{
text: 'Write serialize',
completed: true,
},
],
};
`js`
console.log(
prettyFormat(val, {
plugins: [plugin],
}),
);
/*
Object {
"filter": "completed",
"items": Array [
Object {
"completed": true,
"text": "Write test",
},
Object {
"completed": true,
"text": "Write serialize",
},
],
}
*/
`js`
console.log(
prettyFormat(val, {
indent: 4,
plugins: [plugin],
}),
);
/*
Object {
"filter": "completed",
"items": Array [
Object {
"completed": true,
"text": "Write test",
},
Object {
"completed": true,
"text": "Write serialize",
},
],
}
*/
`js`
console.log(
prettyFormat(val, {
maxDepth: 1,
plugins: [plugin],
}),
);
/*
Object {
"filter": "completed",
"items": [Array],
}
*/
`js`
console.log(
prettyFormat(val, {
min: true,
plugins: [plugin],
}),
);
/*
{"filter": "completed", "items": [{"completed": true, "text": "Write test"}, {"completed": true, "text": "Write serialize"}]}
*/
The original interface is adequate for plugins:
- that do not depend on options other than highlight or mindepth
- that do not depend on or refs in recursive traversal, and
- if values either
- do not require indentation, or
- do not occur as children of JavaScript data structures (for example, array)
Write print to return a string, given the arguments:
- val which “passed the test”printer(valChild)
- current callback function: serialize childrenindenter(lines)
- current callback function: indent lines at the next levelconfig
- unchanging object: derived from optionscolors
- unchanging object: derived from options
The 3 properties of config are min in options and:
- spacing and edgeSpacing are newline if min is falsespacing
- is space and edgeSpacing is empty string if min is true
Each property of colors corresponds to a property of theme in options:
- the key is the same (for example, tag)colors
- the value in is a object with open and close properties whose values are escape codes from ansi-styles for the color value in theme (for example, 'cyan')
This plugin prints functions with the number of named arguments excluding rest argument.
`js[Function ${val.name || 'anonymous'} ${val.length}]
const plugin = {
print(val) {
return ;`
},
test(val) {
return typeof val === 'function';
},
};
`js
const val = {
onClick(event) {},
render() {},
};
prettyFormat(val, {
plugins: [plugin],
});
/*
Object {
"onClick": [Function onClick 1],
"render": [Function render 0],
}
*/
prettyFormat(val);
/*
Object {
"onClick": [Function onClick],
"render": [Function render],
}
*/
`
This plugin ignores the printFunctionName option. That limitation of the original print interface is a reason to use the improved serialize interface, described above.
`js
prettyFormat(val, {
plugins: [pluginOld],
printFunctionName: false,
});
/*
Object {
"onClick": [Function onClick 1],
"render": [Function render 0],
}
*/
prettyFormat(val, {
printFunctionName: false,
});
/*
Object {
"onClick": [Function],
"render": [Function],
}
*/
`
node-ray uses Jest for unit tests. To run the test suite:
npm run test`
---
Please see CHANGELOG for more information on what has changed recently.
Please review our security policy on how to report security vulnerabilities.
- James Kyle
- Patrick Organ
- All Contributors