forked from yeoman/stringify-object
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
125 lines (99 loc) · 3.12 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
'use strict';
const isRegexp = require('is-regexp');
const isObj = require('is-obj');
const getOwnEnumPropSymbols = require('get-own-enumerable-property-symbols');
module.exports = (val, opts, pad) => {
const seen = [];
return (function stringify(val, opts, pad) {
opts = opts || {};
opts.indent = opts.indent || '\t';
pad = pad || '';
let tokens;
if (opts.inlineCharacterLimit === undefined) {
tokens = {
newLine: '\n',
newLineOrSpace: '\n',
pad,
indent: pad + opts.indent
};
} else {
tokens = {
newLine: '@@__STRINGIFY_OBJECT_NEW_LINE__@@',
newLineOrSpace: '@@__STRINGIFY_OBJECT_NEW_LINE_OR_SPACE__@@',
pad: '@@__STRINGIFY_OBJECT_PAD__@@',
indent: '@@__STRINGIFY_OBJECT_INDENT__@@'
};
}
const expandWhiteSpace = string => {
if (opts.inlineCharacterLimit === undefined) {
return string;
}
const oneLined = string
.replace(new RegExp(tokens.newLine, 'g'), '')
.replace(new RegExp(tokens.newLineOrSpace, 'g'), ' ')
.replace(new RegExp(tokens.pad + '|' + tokens.indent, 'g'), '');
if (oneLined.length <= opts.inlineCharacterLimit) {
return oneLined;
}
return string
.replace(new RegExp(tokens.newLine + '|' + tokens.newLineOrSpace, 'g'), '\n')
.replace(new RegExp(tokens.pad, 'g'), pad)
.replace(new RegExp(tokens.indent, 'g'), pad + opts.indent);
};
if (seen.indexOf(val) !== -1) {
return '"[Circular]"';
}
if (val === null ||
val === undefined ||
typeof val === 'number' ||
typeof val === 'boolean' ||
typeof val === 'function' ||
typeof val === 'symbol' ||
isRegexp(val)) {
return String(val);
}
if (val instanceof Date) {
return `new Date('${val.toISOString()}')`;
}
if (Array.isArray(val)) {
if (val.length === 0) {
return '[]';
}
seen.push(val);
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;
}).join('') + tokens.pad + ']';
seen.pop(val);
return expandWhiteSpace(ret);
}
if (isObj(val)) {
const objKeys = Object.keys(val).concat(getOwnEnumPropSymbols(val));
if (objKeys.length === 0) {
return '{}';
}
seen.push(val);
const ret = '{' + tokens.newLine + objKeys.map((el, i) => {
if (opts.filter && !opts.filter(val, el)) {
return '';
}
const eol = objKeys.length - 1 === i ? tokens.newLine : ',' + tokens.newLineOrSpace;
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;
}).join('') + tokens.pad + '}';
seen.pop(val);
return expandWhiteSpace(ret);
}
if (opts.joinLines !== false) {
val = String(val).replace(/[\r\n]/g, x => x === '\n' ? '\\n' : '\\r');
}
if (opts.singleQuotes === false) {
val = val.replace(/"/g, '\\"');
return `"${val}"`;
}
val = val.replace(/'/g, '\\\'');
return `'${val}'`;
})(val, opts, pad);
};