ID | Title | Duration (ms) |
---|---|---|
1 | Purdy should display an error | 9 |
2 | Purdy should display an error with detail | 4 |
3 | Purdy should indent array correctly | 6 |
4 | Purdy allows for removal of array index | 1 |
5 | Purdy honors indent level | 1 |
6 | Purdy prints arguments function | 0 |
7 | Purdy should print plain | 1 |
8 | Purdy should handle circular references | 1 |
9 | Purdy should print a function | 0 |
10 | Purdy should print an anonymous function | 1 |
11 | Purdy should print a string | 0 |
12 | Purdy should print a date | 2 |
13 | Purdy should print a number | 1 |
14 | Purdy should print null | 0 |
15 | Purdy should print undefined | 1 |
16 | Purdy should print a regular expression | 1 |
17 | Purdy should print a false boolean | 0 |
18 | Purdy should print a true boolean | 1 |
19 | Purdy should print an empty array without extra indentation | 1 |
20 | Purdy should print an empty object without extra indentation | 0 |
21 | Purdy should print a more complex object | 4 |
22 | Purdy should not print circular after second use | 1 |
23 | Purdy shows circular reference with path | 2 |
24 | Purdy will keep a path for an object in Hoek format | 5 |
25 | Purdy indents object the way it should | 1 |
26 | Purdy aligns object the way it should | 2 |
27 | Purdy prints directly to console | 4 |
28 | Purdy prints symbols | 1 |
29 | Purdy prints only symbols | 0 |
Line | Hits | Source |
---|---|---|
1 | // Load modules | |
2 | ||
3 | 1 | var Chalk = require('chalk'); |
4 | 1 | var Hoek = require('hoek'); |
5 | ||
6 | ||
7 | // declare internals | |
8 | ||
9 | 1 | var internals = { |
10 | indentLevel: 0, | |
11 | colors: { | |
12 | BoolFalse: 'red.bold', | |
13 | BoolTrue: 'green.bold', | |
14 | Circular: 'grey.bold', | |
15 | Date: 'green', | |
16 | error: 'red', | |
17 | Function: 'cyan', | |
18 | Key: 'white.bold', | |
19 | Null: 'red.bold', | |
20 | Number: 'blue.bold', | |
21 | RegExp: 'magenta', | |
22 | String: 'yellow', | |
23 | Undefined: 'red.inverse', | |
24 | path: 'blue' | |
25 | }, | |
26 | defaults: { | |
27 | plain: false, | |
28 | path: false, | |
29 | indent: 4, | |
30 | align: 'left', | |
31 | arrayIndex: true, | |
32 | pathPrefix: '// ' | |
33 | } | |
34 | }; | |
35 | ||
36 | ||
37 | 1 | internals.purdy = function (object, options) { |
38 | ||
39 | 1 | return console.log(internals.stringify(object, options)); |
40 | }; | |
41 | ||
42 | ||
43 | 1 | internals.stringify = function (object, options) { |
44 | ||
45 | 32 | internals.seen = []; |
46 | 32 | internals.path = []; |
47 | 32 | internals.settings = Hoek.applyToDefaults(internals.defaults, options || {}); |
48 | 32 | return internals.travel(object, ''); |
49 | }; | |
50 | ||
51 | ||
52 | 1 | internals.purdy.stringify = internals.stringify; |
53 | ||
54 | ||
55 | 1 | module.exports = internals.purdy; |
56 | ||
57 | ||
58 | 1 | internals.travel = function (object, path) { |
59 | ||
60 | 106 | var type = global.toString.call(object).split(' ')[1].slice(0, -1); |
61 | 106 | var format = ''; |
62 | ||
63 | 106 | if (internals[type]) { |
64 | 58 | format = internals[type](object, path); |
65 | } | |
66 | else { | |
67 | 48 | format = String(object); |
68 | } | |
69 | ||
70 | 106 | return internals.colorize(format, type); |
71 | }; | |
72 | ||
73 | ||
74 | 1 | internals.colorize = function (string, type) { |
75 | ||
76 | 177 | if (internals.settings.plain) { |
77 | 85 | return string; |
78 | } | |
79 | ||
80 | 92 | var colors = internals.colors[type]; |
81 | 92 | if (!colors) { |
82 | 23 | return string; |
83 | } | |
84 | ||
85 | 69 | var colorArr = colors.split('.'); |
86 | ||
87 | 69 | for (var i = 0, il = colorArr.length; i < il; ++i) { |
88 | 118 | var color = colorArr[i]; |
89 | 118 | string = Chalk[color](string); |
90 | } | |
91 | ||
92 | 69 | return string; |
93 | }; | |
94 | ||
95 | ||
96 | 1 | internals.lengthCompare = function (a, b) { |
97 | ||
98 | 57 | return a.length - b.length; |
99 | }; | |
100 | ||
101 | ||
102 | 1 | internals.tidyPath = function (path) { |
103 | ||
104 | 4 | return internals.colorize(path.slice(1, path.size), 'path'); |
105 | }; | |
106 | ||
107 | 1 | internals.Object = function (object, path) { |
108 | ||
109 | 24 | var keys = Object.keys(object); |
110 | ||
111 | if ( Object.getOwnPropertySymbols ) { |
|
112 | 24 | keys = keys.concat(Object.getOwnPropertySymbols(object)); |
113 | } | |
114 | ||
115 | 24 | if (keys.length === 0) { |
116 | 1 | return '{}'; |
117 | } | |
118 | ||
119 | 23 | var index = internals.seen.indexOf(object); |
120 | 23 | if (index !== -1) { |
121 | 3 | return internals.showCircular(index); |
122 | } | |
123 | 20 | internals.seen.push(object); |
124 | 20 | internals.path.push(path); |
125 | ||
126 | 20 | var keyLengths = Hoek.clone(keys); |
127 | 20 | internals.indentLevel = internals.indentLevel + 1; |
128 | 20 | var out = '{\n'; |
129 | ||
130 | 20 | for (var i = 0, il = keys.length; i < il; ++i) { |
131 | 32 | var key = keys[i]; |
132 | 32 | var item = object[key]; |
133 | 32 | if (internals.settings.path && path.length > 0) { |
134 | 3 | keyLengths.push(internals.settings.pathPrefix); |
135 | 3 | out = out + internals.indent() + |
136 | internals.colorize(internals.settings.pathPrefix, 'path') + | |
137 | internals.tidyPath(path + '.' + key) + '\n'; | |
138 | } | |
139 | 32 | var longest = keyLengths.sort(internals.lengthCompare)[keyLengths.length - 1]; |
140 | 32 | var keyStr = key.toString(); |
141 | 32 | out = out + internals.indent() + '' + (internals.printMember(keyStr, longest) + ':') + ' ' + internals.travel(item, path + '.' + keyStr); |
142 | 32 | if (i !== il - 1) { |
143 | 12 | out = out + ','; |
144 | } | |
145 | 32 | out = out + '\n'; |
146 | } | |
147 | 20 | internals.indentLevel = internals.indentLevel - 1; |
148 | 20 | out = out + internals.indent() + '}'; |
149 | 20 | return out; |
150 | }; | |
151 | ||
152 | ||
153 | 1 | internals.showCircular = function (index) { |
154 | ||
155 | 5 | var showPath = internals.path[index]; |
156 | 5 | showPath = showPath === '' ? '' : ' ' + showPath.slice(1, showPath.length); |
157 | 5 | return internals.colorize('[Circular~' + showPath + ']', 'Circular'); |
158 | }; | |
159 | ||
160 | ||
161 | 1 | internals.Array = function (array, path) { |
162 | ||
163 | 17 | if (array.length === 0) { |
164 | 1 | return '[]'; |
165 | } | |
166 | ||
167 | 16 | var index = internals.seen.indexOf(array); |
168 | 16 | if (index !== -1) { |
169 | 2 | return internals.showCircular(index); |
170 | } | |
171 | 14 | internals.seen.push(array); |
172 | 14 | internals.path.push(path); |
173 | ||
174 | 14 | var out = '[\n'; |
175 | 14 | internals.indentLevel = internals.indentLevel + 1; |
176 | ||
177 | 14 | for (var i = 0, il = array.length; i < il; ++i) { |
178 | 42 | var item = array[i]; |
179 | 42 | if (internals.settings.path && path.length > 0) { |
180 | 1 | out = out + internals.indent() + |
181 | internals.colorize(internals.settings.pathPrefix, 'path') + | |
182 | internals.tidyPath(path + '.' + i) + '\n'; | |
183 | } | |
184 | 42 | var indexStr = internals.settings.arrayIndex ? '[' + internals.printMember(i, il) + '] ' : ''; |
185 | 42 | out = out + internals.indent() + '' + indexStr + internals.travel(item, path + '.' + i); |
186 | 42 | if (i !== il - 1) { |
187 | 28 | out = out + ','; |
188 | } | |
189 | 42 | out = out + '\n'; |
190 | } | |
191 | 14 | internals.indentLevel = internals.indentLevel - 1; |
192 | 14 | out = out + internals.indent() + ']'; |
193 | 14 | return out; |
194 | }; | |
195 | ||
196 | ||
197 | 1 | internals.Error = function (err) { |
198 | ||
199 | 2 | if (Object.keys(err).length === 0) { |
200 | 1 | return internals.colorize('[' + err + ']', 'error'); |
201 | } | |
202 | 1 | var obj = internals.Object(err); |
203 | 1 | return obj.replace(/^{/, '{ ' + internals.colorize('[Error: ' + err.message + ']', 'error') ); |
204 | }; | |
205 | ||
206 | ||
207 | 1 | internals.String = function (str) { |
208 | ||
209 | 12 | return '\'' + str + '\''; |
210 | }; | |
211 | ||
212 | 1 | internals.Arguments = function (obj) { |
213 | ||
214 | 1 | var arr = Array.prototype.slice.call(obj); |
215 | 1 | return internals.Array(arr); |
216 | }; | |
217 | ||
218 | ||
219 | 1 | internals.Boolean = function (bool) { |
220 | ||
221 | 2 | if (bool === true) { |
222 | 1 | return internals.colorize(bool + '', 'BoolTrue'); |
223 | } | |
224 | 1 | return internals.colorize(bool + '', 'BoolFalse'); |
225 | }; | |
226 | ||
227 | ||
228 | 1 | internals.Function = function (func) { |
229 | ||
230 | 2 | if (func.name) { |
231 | 1 | return internals.colorize('[Function: ' + func.name + ']', 'Function'); |
232 | } | |
233 | 1 | return internals.colorize('[Function: ?]', 'Function'); |
234 | }; | |
235 | ||
236 | ||
237 | 1 | internals.indent = function () { |
238 | ||
239 | 112 | return internals.spaces(internals.indentLevel * internals.settings.indent); |
240 | }; | |
241 | ||
242 | ||
243 | 1 | internals.spaces = function (count) { |
244 | ||
245 | 164 | var out = ''; |
246 | 164 | for (var i = 0; i < count; i++) { |
247 | 596 | out = out + ' '; |
248 | } | |
249 | ||
250 | 164 | return out; |
251 | }; | |
252 | ||
253 | ||
254 | 1 | internals.printMember = function (member, max) { |
255 | ||
256 | 52 | if (internals.settings.align === 'left') { |
257 | 24 | max = 0; |
258 | } | |
259 | 52 | var memberLength = member.length; |
260 | 52 | var maxLength = max.length; |
261 | 52 | var toShift = maxLength - memberLength; |
262 | 52 | return internals.colorize(internals.spaces(toShift) + member, 'Key'); |
263 | }; | |
264 |