UNPKG

2.91 kBPlain TextView Raw
1/* toSource by Marcello Bastea-Forte - zlib license */
2export default function toSource(
3 object: unknown,
4 replacer?: (a: any) => any,
5 indent: false | string = ' ',
6 startingIndent: string = '',
7): string {
8 const seen: any[] = [];
9 return walk(
10 object,
11 replacer,
12 indent === false ? '' : indent,
13 startingIndent,
14 seen,
15 );
16
17 function walk(
18 object: any,
19 replacer: ((a: any) => any) | undefined,
20 indent: string,
21 currentIndent: string,
22 seen: any[],
23 ): string {
24 const nextIndent = currentIndent + indent;
25 object = replacer ? replacer(object) : object;
26
27 switch (typeof object) {
28 case 'string':
29 return JSON.stringify(object);
30 case 'number':
31 if (Object.is(object, -0)) {
32 return '-0';
33 }
34 return String(object);
35 case 'boolean':
36 case 'undefined':
37 return String(object);
38 case 'function':
39 return object.toString();
40 }
41
42 if (object === null) {
43 return 'null';
44 }
45 if (object instanceof RegExp) {
46 return object.toString();
47 }
48 if (object instanceof Date) {
49 return `new Date(${object.getTime()})`;
50 }
51 if (object instanceof Set) {
52 return `new Set(${walk(
53 Array.from(object.values()),
54 replacer,
55 indent,
56 nextIndent,
57 seen,
58 )})`;
59 }
60 if (object instanceof Map) {
61 return `new Map(${walk(
62 Array.from(object.entries()),
63 replacer,
64 indent,
65 nextIndent,
66 seen,
67 )})`;
68 }
69
70 if (seen.indexOf(object) >= 0) {
71 return '{$circularReference:1}';
72 }
73 seen.push(object);
74
75 function join(elements: any[]) {
76 return (
77 indent.slice(1) +
78 elements.join(',' + (indent && '\n') + nextIndent) +
79 (indent ? ' ' : '')
80 );
81 }
82
83 if (Array.isArray(object)) {
84 return `[${join(
85 object.map((element) =>
86 walk(element, replacer, indent, nextIndent, seen.slice()),
87 ),
88 )}]`;
89 }
90 const keys = Object.keys(object);
91 if (keys.length) {
92 return `{${join(
93 keys.map(
94 (key) =>
95 (legalKey(key) ? key : JSON.stringify(key)) +
96 ':' +
97 walk(object[key], replacer, indent, nextIndent, seen.slice()),
98 ),
99 )}}`;
100 }
101 return '{}';
102 }
103}
104
105const KEYWORD_REGEXP =
106 /^(abstract|boolean|break|byte|case|catch|char|class|const|continue|debugger|default|delete|do|double|else|enum|export|extends|false|final|finally|float|for|function|goto|if|implements|import|in|instanceof|int|interface|long|native|new|null|package|private|protected|public|return|short|static|super|switch|synchronized|this|throw|throws|transient|true|try|typeof|undefined|var|void|volatile|while|with)$/;
107
108function legalKey(key: string) {
109 return (
110 /^([a-z_$][0-9a-z_$]*|[0-9]+)$/gi.test(key) && !KEYWORD_REGEXP.test(key)
111 );
112}