UNPKG

5.59 kBJavaScriptView Raw
1// Load modules
2
3var Chalk = require('chalk');
4var Hoek = require('hoek');
5
6
7// declare internals
8
9var internals = {
10 indentLevel: 0,
11 colors: {
12 BoolFalse: 'red.bold',
13 BoolTrue: 'green.bold',
14 Circular: 'grey.bold',
15 Date: 'green',
16 Function: 'cyan',
17 Key: 'white.bold',
18 Null: 'red.bold',
19 Number: 'blue.bold',
20 RegExp: 'magenta',
21 String: 'yellow',
22 Undefined: 'red.inverse',
23 path: 'blue'
24 },
25 defaults: {
26 plain: false,
27 path: false,
28 pathPrefix: '// '
29 }
30};
31
32
33internals.purdy = function (object, options) {
34
35 return console.log(internals.stringify(object, options));
36};
37
38
39internals.stringify = function (object, options) {
40
41 if (!process.stdout.isTTY) {
42 internals.defaults.plain = true;
43 }
44 internals.seen = [];
45 internals.path = [];
46 internals.settings = Hoek.applyToDefaults(internals.defaults, options || {});
47 return internals.travel(object, '');
48};
49
50
51internals.purdy.stringify = internals.stringify;
52
53
54module.exports = internals.purdy;
55
56
57internals.travel = function (object, path) {
58
59 var type = global.toString.call(object).split(' ')[1].slice(0, -1);
60 var format = '';
61
62 if (internals[type]) {
63 format = internals[type](object, path);
64 }
65 else {
66 format = object + '';
67 }
68
69 return internals.colorize(format, type);
70};
71
72
73internals.colorize = function (string, type) {
74
75 if (internals.settings.plain) {
76 return string;
77 }
78
79 var colors = internals.colors[type];
80 if (!colors) {
81 return string;
82 }
83
84 var colorArr = colors.split('.');
85
86 for (var i = 0, il = colorArr.length; i < il; ++i) {
87 var color = colorArr[i];
88 string = Chalk[color](string);
89 }
90
91 return string;
92};
93
94
95internals.lengthCompare = function (a, b) {
96 return a.length - b.length;
97};
98
99
100internals.tidyPath = function (path) {
101
102 return internals.colorize(path.slice(1, path.size), 'path');
103};
104
105internals.Object = function (object, path) {
106
107 if (Object.keys(object).length === 0) {
108 return '{}';
109 }
110
111 var index = internals.seen.indexOf(object);
112 if (index !== -1) {
113 return internals.showCircular(index);
114 }
115 internals.seen.push(object);
116 internals.path.push(path);
117
118 var keys = Object.keys(object);
119 var keyLengths = Hoek.clone(keys);
120 internals.indentLevel = internals.indentLevel + 1;
121 var out = '{\n';
122
123 keyLengths.push(internals.settings.pathPrefix);
124 var longest = keyLengths.sort(internals.lengthCompare)[keyLengths.length - 1];
125
126 for (var i = 0, il = keys.length; i < il; ++i) {
127 var key = keys[i];
128 var item = object[key];
129 if (internals.settings.path && path.length > 0) {
130 out = out + internals.indent() +
131 internals.colorize(internals.settings.pathPrefix, 'path') +
132 internals.tidyPath(path + '.' + key) + '\n';
133 }
134 out = out + internals.indent() + '' + (internals.printMember(key, longest) + ':') + ' ' + internals.travel(item, path + '.' + key);
135 if (i !== il - 1) {
136 out = out + ',';
137 }
138 out = out + '\n';
139 }
140 internals.indentLevel = internals.indentLevel - 1;
141 out = out + internals.indent() + '}';
142 return out;
143};
144
145
146internals.showCircular = function (index) {
147 var showPath = internals.path[index];
148 showPath = showPath === '' ? '' : ' ' + showPath.slice(1, showPath.length);
149 return internals.colorize('[Circular~' + showPath + ']', 'Circular');
150};
151
152
153internals.Array = function (array, path) {
154
155 if (array.length === 0) {
156 return '[]';
157 }
158
159 var index = internals.seen.indexOf(array);
160 if (index !== -1) {
161 return internals.showCircular(index);
162 }
163 internals.seen.push(array);
164 internals.path.push(path);
165
166 var out = '[\n';
167 internals.indentLevel = internals.indentLevel + 1;
168
169 for (var i = 0, il = array.length; i < il; ++i) {
170 var item = array[i];
171 if (internals.settings.path && path.length > 0) {
172 out = out + internals.indent() +
173 internals.colorize(internals.settings.pathPrefix, 'path') +
174 internals.tidyPath(path + '.' + i) + '\n';
175 }
176 out = out + internals.indent() + '' + ('[' + internals.printMember(i, il) + ']') + ' ' + internals.travel(item, path + '.' + i);
177 if (i !== il - 1) {
178 out = out + ',';
179 }
180 out = out + '\n';
181 }
182 internals.indentLevel = internals.indentLevel - 1;
183 out = out + internals.indent() + ']';
184 return out;
185};
186
187
188internals.String = function (str) {
189
190 return '\'' + str + '\'';
191};
192
193
194internals.Boolean = function (bool) {
195
196 if (bool === true) {
197 return internals.colorize(bool + '', 'BoolTrue');
198 }
199 return internals.colorize(bool + '', 'BoolFalse');
200};
201
202
203internals.Function = function (func) {
204 if (func.name) {
205 return internals.colorize('[Function: ' + func.name + ']', 'Function');
206 }
207 return internals.colorize('[Function: ?]', 'Function');
208};
209
210
211internals.indent = function () {
212
213 return internals.spaces(internals.indentLevel * 4);
214};
215
216
217internals.spaces = function (count) {
218
219 var out = '';
220 for (var i = 0; i < count; i++) {
221 out = out + ' ';
222 }
223
224 return out;
225};
226
227
228internals.printMember = function (member, max) {
229
230 var memberLength = (member + '').length;
231 var maxLength = (max + '').length;
232 var toShift = maxLength - memberLength;
233 return internals.colorize(internals.spaces(toShift) + member, 'Key');
234};