initial commit. phase 1 complete

This commit is contained in:
2026-05-05 20:45:19 +02:00
parent d9c68313a0
commit 89e058ffac
20631 changed files with 3224610 additions and 43 deletions
+3
View File
@@ -0,0 +1,3 @@
__tests__
perf
.travis.yml
+15
View File
@@ -0,0 +1,15 @@
## ISC License
Copyright (c) 2016, James Kyle <me@thejameskyle.com>
Permission to use, copy, modify, and/or distribute this software for any purpose
with or without fee is hereby granted, provided that the above copyright notice
and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
THIS SOFTWARE.
+94
View File
@@ -0,0 +1,94 @@
# pretty-format [![Travis build status](http://img.shields.io/travis/thejameskyle/pretty-format.svg?style=flat)](https://travis-ci.org/thejameskyle/pretty-format)
> Stringify any JavaScript value.
- Supports [all built-in JavaScript types](#type-support)
- [Blazingly fast](https://gist.github.com/thejameskyle/2b04ffe4941aafa8f970de077843a8fd) (similar performance to v8's `JSON.stringify` and significantly faster than Node's `util.format`)
- Plugin system for extending with custom types (i.e. [`ReactTestComponent`](#reacttestcomponent-plugin))
## Installation
```sh
$ npm install pretty-format
```
## Usage
```js
var prettyFormat = require('pretty-format');
var obj = { property: {} };
obj.circularReference = obj;
obj[Symbol('foo')] = 'foo';
obj.map = new Map();
obj.map.set('prop', 'value');
obj.array = [1, NaN, Infinity];
console.log(prettyFormat(obj));
```
**Result:**
```js
Object {
"property": Object {},
"circularReference": [Circular],
"map": Map {
"prop" => "value"
},
"array": Array [
1,
NaN,
Infinity
],
Symbol(foo): "foo"
}
```
#### Type Support
`Object`, `Array`, `ArrayBuffer`, `DataView`, `Float32Array`, `Float64Array`, `Int8Array`, `Int16Array`, `Int32Array`, `Uint8Array`, `Uint8ClampedArray`, `Uint16Array`, `Uint32Array`, `arguments`, `Boolean`, `Date`, `Error`, `Function`, `Infinity`, `Map`, `NaN`, `null`, `Number`, `RegExp`, `Set`, `String`, `Symbol`, `undefined`, `WeakMap`, `WeakSet`
### Plugins
Pretty format also supports adding plugins:
```js
var fooPlugin = {
test: function(val) {
return val && val.hasOwnProperty('foo');
},
print: function(val, print, indent) {
return 'Foo: ' + print(val.foo);
}
};
var obj = { foo: { bar: {} } };
prettyFormat(obj, {
plugins: [fooPlugin]
});
// Foo: Object {
// "bar": Object {}
// }
```
#### `ReactTestComponent` plugin
```js
var prettyFormat = require('pretty-format');
var reactPlugin = require('pretty-format/plugins/ReactTestComponent');
var React = require('react');
var renderer = require('react/lib/ReactTestRenderer');
var jsx = React.createElement('h1', null, 'Hello World');
prettyFormat(renderer.create(jsx).toJSON(), {
plugins: [reactPlugin]
});
// <h1>
// Hello World
// </h1>
```
+343
View File
@@ -0,0 +1,343 @@
'use strict';
const printString = require('./printString');
const toString = Object.prototype.toString;
const toISOString = Date.prototype.toISOString;
const errorToString = Error.prototype.toString;
const regExpToString = RegExp.prototype.toString;
const symbolToString = Symbol.prototype.toString;
const SYMBOL_REGEXP = /^Symbol\((.*)\)(.*)$/;
const NEWLINE_REGEXP = /\n/ig;
const getSymbols = Object.getOwnPropertySymbols || (obj => []);
function isToStringedArrayType(toStringed) {
return (
toStringed === '[object Array]' ||
toStringed === '[object ArrayBuffer]' ||
toStringed === '[object DataView]' ||
toStringed === '[object Float32Array]' ||
toStringed === '[object Float64Array]' ||
toStringed === '[object Int8Array]' ||
toStringed === '[object Int16Array]' ||
toStringed === '[object Int32Array]' ||
toStringed === '[object Uint8Array]' ||
toStringed === '[object Uint8ClampedArray]' ||
toStringed === '[object Uint16Array]' ||
toStringed === '[object Uint32Array]'
);
}
function printNumber(val) {
if (val != +val) return 'NaN';
const isNegativeZero = val === 0 && (1 / val) < 0;
return isNegativeZero ? '-0' : '' + val;
}
function printFunction(val) {
if (val.name === '') {
return '[Function anonymous]'
} else {
return '[Function ' + val.name + ']';
}
}
function printSymbol(val) {
return symbolToString.call(val).replace(SYMBOL_REGEXP, 'Symbol($1)');
}
function printError(val) {
return '[' + errorToString.call(val) + ']';
}
function printBasicValue(val) {
if (val === true || val === false) return '' + val;
if (val === undefined) return 'undefined';
if (val === null) return 'null';
const typeOf = typeof val;
if (typeOf === 'number') return printNumber(val);
if (typeOf === 'string') return '"' + printString(val) + '"';
if (typeOf === 'function') return printFunction(val);
if (typeOf === 'symbol') return printSymbol(val);
const toStringed = toString.call(val);
if (toStringed === '[object WeakMap]') return 'WeakMap {}';
if (toStringed === '[object WeakSet]') return 'WeakSet {}';
if (toStringed === '[object Function]' || toStringed === '[object GeneratorFunction]') return printFunction(val, min);
if (toStringed === '[object Symbol]') return printSymbol(val);
if (toStringed === '[object Date]') return toISOString.call(val);
if (toStringed === '[object Error]') return printError(val);
if (toStringed === '[object RegExp]') return regExpToString.call(val);
if (toStringed === '[object Arguments]' && val.length === 0) return 'Arguments []';
if (isToStringedArrayType(toStringed) && val.length === 0) return val.constructor.name + ' []';
if (val instanceof Error) return printError(val);
return false;
}
function printList(list, indent, prevIndent, spacing, edgeSpacing, refs, maxDepth, currentDepth, plugins, min) {
let body = '';
if (list.length) {
body += edgeSpacing;
const innerIndent = prevIndent + indent;
for (let i = 0; i < list.length; i++) {
body += innerIndent + print(list[i], indent, innerIndent, spacing, edgeSpacing, refs, maxDepth, currentDepth, plugins, min);
if (i < list.length - 1) {
body += ',' + spacing;
}
}
body += edgeSpacing + prevIndent;
}
return '[' + body + ']';
}
function printArguments(val, indent, prevIndent, spacing, edgeSpacing, refs, maxDepth, currentDepth, plugins, min) {
return (min ? '' : 'Arguments ') + printList(val, indent, prevIndent, spacing, edgeSpacing, refs, maxDepth, currentDepth, plugins, min);
}
function printArray(val, indent, prevIndent, spacing, edgeSpacing, refs, maxDepth, currentDepth, plugins, min) {
return (min ? '' : val.constructor.name + ' ') + printList(val, indent, prevIndent, spacing, edgeSpacing, refs, maxDepth, currentDepth, plugins, min);
}
function printMap(val, indent, prevIndent, spacing, edgeSpacing, refs, maxDepth, currentDepth, plugins, min) {
let result = 'Map {';
const iterator = val.entries();
let current = iterator.next();
if (!current.done) {
result += edgeSpacing;
const innerIndent = prevIndent + indent;
while (!current.done) {
const key = print(current.value[0], indent, innerIndent, spacing, edgeSpacing, refs, maxDepth, currentDepth, plugins, min);
const value = print(current.value[1], indent, innerIndent, spacing, edgeSpacing, refs, maxDepth, currentDepth, plugins, min);
result += innerIndent + key + ' => ' + value;
current = iterator.next();
if (!current.done) {
result += ',' + spacing;
}
}
result += edgeSpacing + prevIndent;
}
return result + '}';
}
function printObject(val, indent, prevIndent, spacing, edgeSpacing, refs, maxDepth, currentDepth, plugins, min) {
const constructor = min ? '' : (val.constructor ? val.constructor.name + ' ' : 'Object ');
let result = constructor + '{';
let keys = Object.keys(val).sort();
const symbols = getSymbols(val);
if (symbols.length) {
keys = keys
.filter(key => !(typeof key === 'symbol' || toString.call(key) === '[object Symbol]'))
.concat(symbols);
}
if (keys.length) {
result += edgeSpacing;
const innerIndent = prevIndent + indent;
for (let i = 0; i < keys.length; i++) {
const key = keys[i];
const name = print(key, indent, innerIndent, spacing, edgeSpacing, refs, maxDepth, currentDepth, plugins, min);
const value = print(val[key], indent, innerIndent, spacing, edgeSpacing, refs, maxDepth, currentDepth, plugins, min);
result += innerIndent + name + ': ' + value;
if (i < keys.length - 1) {
result += ',' + spacing;
}
}
result += edgeSpacing + prevIndent;
}
return result + '}';
}
function printSet(val, indent, prevIndent, spacing, edgeSpacing, refs, maxDepth, currentDepth, plugins, min) {
let result = 'Set {';
const iterator = val.entries();
let current = iterator.next();
if (!current.done) {
result += edgeSpacing;
const innerIndent = prevIndent + indent;
while (!current.done) {
result += innerIndent + print(current.value[1], indent, innerIndent, spacing, edgeSpacing, refs, maxDepth, currentDepth, plugins, min);
current = iterator.next();
if (!current.done) {
result += ',' + spacing;
}
}
result += edgeSpacing + prevIndent;
}
return result + '}';
}
function printComplexValue(val, indent, prevIndent, spacing, edgeSpacing, refs, maxDepth, currentDepth, plugins, min) {
refs = refs.slice();
if (refs.indexOf(val) > -1) {
return '[Circular]';
} else {
refs.push(val);
}
currentDepth++;
const hitMaxDepth = currentDepth > maxDepth;
if (!hitMaxDepth && val.toJSON && typeof val.toJSON === 'function') {
return print(val.toJSON(), indent, prevIndent, spacing, edgeSpacing, refs, maxDepth, currentDepth, plugins, min);
}
const toStringed = toString.call(val);
if (toStringed === '[object Arguments]') {
return hitMaxDepth ? '[Arguments]' : printArguments(val, indent, prevIndent, spacing, edgeSpacing, refs, maxDepth, currentDepth, plugins, min);
} else if (isToStringedArrayType(toStringed)) {
return hitMaxDepth ? '[Array]' : printArray(val, indent, prevIndent, spacing, edgeSpacing, refs, maxDepth, currentDepth, plugins, min);
} else if (toStringed === '[object Map]') {
return hitMaxDepth ? '[Map]' : printMap(val, indent, prevIndent, spacing, edgeSpacing, refs, maxDepth, currentDepth, plugins, min);
} else if (toStringed === '[object Set]') {
return hitMaxDepth ? '[Set]' : printSet(val, indent, prevIndent, spacing, edgeSpacing, refs, maxDepth, currentDepth, plugins, min);
} else if (typeof val === 'object') {
return hitMaxDepth ? '[Object]' : printObject(val, indent, prevIndent, spacing, edgeSpacing, refs, maxDepth, currentDepth, plugins, min);
}
}
function printPlugin(val, indent, prevIndent, spacing, edgeSpacing, refs, maxDepth, currentDepth, plugins, min) {
let match = false;
let plugin;
for (let p = 0; p < plugins.length; p++) {
plugin = plugins[p];
if (plugin.test(val)) {
match = true;
break;
}
}
if (!match) {
return false;
}
function boundPrint(val) {
return print(val, indent, prevIndent, spacing, edgeSpacing, refs, maxDepth, currentDepth, plugins, min);
}
function boundIndent(str) {
const indentation = prevIndent + indent;
return indentation + str.replace(NEWLINE_REGEXP, '\n' + indentation);
}
return plugin.print(val, boundPrint, boundIndent, {
edgeSpacing: edgeSpacing,
spacing: spacing
});
}
function print(val, indent, prevIndent, spacing, edgeSpacing, refs, maxDepth, currentDepth, plugins, min) {
const basic = printBasicValue(val);
if (basic) return basic;
const plugin = printPlugin(val, indent, prevIndent, spacing, edgeSpacing, refs, maxDepth, currentDepth, plugins, min);
if (plugin) return plugin;
return printComplexValue(val, indent, prevIndent, spacing, edgeSpacing, refs, maxDepth, currentDepth, plugins, min);
}
const DEFAULTS = {
indent: 2,
min: false,
maxDepth: Infinity,
plugins: []
};
function validateOptions(opts) {
Object.keys(opts).forEach(key => {
if (!DEFAULTS.hasOwnProperty(key)) {
throw new Error('prettyFormat: Invalid option: ' + key);
}
});
if (opts.min && opts.indent !== undefined && opts.indent !== 0) {
throw new Error('prettyFormat: Cannot run with min option and indent');
}
}
function normalizeOptions(opts) {
const result = {};
Object.keys(DEFAULTS).forEach(key =>
result[key] = opts.hasOwnProperty(key) ? opts[key] : DEFAULTS[key]
);
if (result.min) {
result.indent = 0;
}
return result;
}
function createIndent(indent) {
return new Array(indent + 1).join(' ');
}
function prettyFormat(val, opts) {
if (!opts) {
opts = DEFAULTS;
} else {
validateOptions(opts)
opts = normalizeOptions(opts);
}
let indent;
let refs;
const prevIndent = '';
const currentDepth = 0;
const spacing = opts.min ? ' ' : '\n';
const edgeSpacing = opts.min ? '' : '\n';
if (opts && opts.plugins.length) {
indent = createIndent(opts.indent);
refs = [];
var pluginsResult = printPlugin(val, indent, prevIndent, spacing, edgeSpacing, refs, opts.maxDepth, currentDepth, opts.plugins, opts.min);
if (pluginsResult) return pluginsResult;
}
var basicResult = printBasicValue(val);
if (basicResult) return basicResult;
if (!indent) indent = createIndent(opts.indent);
if (!refs) refs = [];
return printComplexValue(val, indent, prevIndent, spacing, edgeSpacing, refs, opts.maxDepth, currentDepth, opts.plugins, opts.min);
}
module.exports = prettyFormat;
+26
View File
@@ -0,0 +1,26 @@
{
"name": "pretty-format",
"version": "3.8.0",
"description": "Stringify any JavaScript value.",
"license": "MIT",
"main": "index.js",
"author": "James Kyle <me@thejameskyle.com>",
"keywords": [],
"repository": "https://github.com/thejameskyle/pretty-format.git",
"bugs": "https://github.com/thejameskyle/pretty-format/issues",
"homepage": "https://github.com/thejameskle/pretty-format",
"scripts": {
"test": "jest",
"perf": "node perf/test.js"
},
"jest": {
"testEnvironment": "node",
"verbose": true
},
"devDependencies": {
"chalk": "^1.1.3",
"jest": "^15.1.1",
"left-pad": "^1.1.1",
"react": "15.3.0"
}
}
+74
View File
@@ -0,0 +1,74 @@
'use strict';
const printString = require('../printString');
const reactElement = Symbol.for('react.element');
function traverseChildren(opaqueChildren, cb) {
if (Array.isArray(opaqueChildren)) {
opaqueChildren.forEach(child => traverseChildren(child, cb));
} else if (opaqueChildren != null && opaqueChildren !== false) {
cb(opaqueChildren);
}
}
function printChildren(flatChildren, print, indent, opts) {
return flatChildren.map(node => {
if (typeof node === 'object') {
return printElement(node, print, indent, opts);
} else if (typeof node === 'string') {
return printString(node);
} else {
return print(node);
}
}).join(opts.edgeSpacing);
}
function printProps(props, print, indent, opts) {
return Object.keys(props).sort().map(name => {
if (name === 'children') {
return '';
}
const prop = props[name];
let printed = print(prop);
if (typeof prop !== 'string') {
if (printed.indexOf('\n') !== -1) {
printed = '{' + opts.edgeSpacing + indent(indent(printed) + opts.edgeSpacing + '}');
} else {
printed = '{' + printed + '}';
}
}
return opts.spacing + indent(name + '=') + printed;
}).join('');
}
function printElement(element, print, indent, opts) {
let result = '<' + element.type;
result += printProps(element.props, print, indent, opts);
const opaqueChildren = element.props.children;
if (opaqueChildren) {
let flatChildren = [];
traverseChildren(opaqueChildren, child => {
flatChildren.push(child);
});
const children = printChildren(flatChildren, print, indent, opts);
result += '>' + opts.edgeSpacing + indent(children) + opts.edgeSpacing + '</' + element.type + '>';
} else {
result += ' />';
}
return result;
}
module.exports = {
test(object) {
return object && object.$$typeof === reactElement;
},
print(val, print, indent, opts) {
return printElement(val, print, indent, opts);
}
};
+58
View File
@@ -0,0 +1,58 @@
'use strict';
const printString = require('../printString');
const reactTestInstance = Symbol.for('react.test.json');
function printChildren(children, print, indent, opts) {
return children.map(child => printInstance(child, print, indent, opts)).join(opts.edgeSpacing);
}
function printProps(props, print, indent, opts) {
return Object.keys(props).sort().map(name => {
const prop = props[name];
let printed = print(prop);
if (typeof prop !== 'string') {
if (printed.indexOf('\n') !== -1) {
printed = '{' + opts.edgeSpacing + indent(indent(printed) + opts.edgeSpacing + '}');
} else {
printed = '{' + printed + '}';
}
}
return opts.spacing + indent(name + '=') + printed;
}).join('');
}
function printInstance(instance, print, indent, opts) {
if (typeof instance == 'number') {
return print(instance);
} else if (typeof instance === 'string') {
return printString(instance);
}
let result = '<' + instance.type;
if (instance.props) {
result += printProps(instance.props, print, indent, opts);
}
if (instance.children) {
const children = printChildren(instance.children, print, indent, opts);
result += '>' + opts.edgeSpacing + indent(children) + opts.edgeSpacing + '</' + instance.type + '>';
} else {
result += ' />';
}
return result;
}
module.exports = {
test(object) {
return object && object.$$typeof === reactTestInstance;
},
print(val, print, indent, opts) {
return printInstance(val, print, indent, opts);
}
};
+7
View File
@@ -0,0 +1,7 @@
'use strict';
const ESCAPED_CHARACTERS = /(\\|\"|\')/g;
module.exports = function printString(val) {
return val.replace(ESCAPED_CHARACTERS, '\\$1');
}