1 | 'use strict';
|
2 |
|
3 | const indent = require('./indent');
|
4 |
|
5 | const getMaxIndexLength = (input) => {
|
6 | let maxWidth = 0;
|
7 |
|
8 | Object.keys(input).forEach((key) => {
|
9 |
|
10 | if (input[key] === undefined)
|
11 | return;
|
12 | maxWidth = Math.max(maxWidth, key.length);
|
13 | });
|
14 |
|
15 | return maxWidth;
|
16 | };
|
17 |
|
18 |
|
19 | const isSerializable = (input, onlyPrimitives, options) => {
|
20 | if (
|
21 | typeof input === 'boolean'
|
22 | || typeof input === 'number'
|
23 | || typeof input === 'function'
|
24 | || input === null
|
25 | || input instanceof Date
|
26 | )
|
27 | return true;
|
28 |
|
29 | if (typeof input === 'string' && input.indexOf('\n') === -1)
|
30 | return true;
|
31 |
|
32 |
|
33 | if (options.inlineArrays && !onlyPrimitives)
|
34 | if (Array.isArray(input) && isSerializable(input[0], true, options)) {
|
35 | return true;
|
36 | }
|
37 |
|
38 |
|
39 | return false;
|
40 | };
|
41 |
|
42 | const addColorToData = (input, {
|
43 | colors, stringColor, numberColor,
|
44 | }) => {
|
45 | if (typeof input === 'string')
|
46 |
|
47 | return stringColor ? colors[stringColor](input) : input;
|
48 |
|
49 |
|
50 | const sInput = `${input}`;
|
51 |
|
52 | if (input === true)
|
53 | return colors.green(sInput);
|
54 |
|
55 | if (input === false)
|
56 | return colors.red(sInput);
|
57 |
|
58 | if (input === null)
|
59 | return colors.grey(sInput);
|
60 |
|
61 | if (typeof input === 'number')
|
62 | return colors[numberColor](sInput);
|
63 |
|
64 | if (typeof input === 'function')
|
65 | return 'function() {}';
|
66 |
|
67 |
|
68 | if (Array.isArray(input))
|
69 | return input.join(', ');
|
70 |
|
71 |
|
72 | return sInput;
|
73 | };
|
74 |
|
75 | const indentLines = (string, spaces) => {
|
76 | let lines = string.split('\n');
|
77 | lines = lines.map(line => indent(spaces) + line);
|
78 | return lines.join('\n');
|
79 | };
|
80 |
|
81 | const renderToArray = (data, options, indentation) => {
|
82 | if (isSerializable(data, false, options))
|
83 | return [indent(indentation) + addColorToData(data, options)];
|
84 |
|
85 |
|
86 |
|
87 | if (typeof data === 'string')
|
88 | return [
|
89 | `${indent(indentation)}"""`,
|
90 | indentLines(data, indentation + options.defaultIndentation),
|
91 | `${indent(indentation)}"""`,
|
92 | ];
|
93 |
|
94 |
|
95 | if (Array.isArray(data)) {
|
96 |
|
97 | if (data.length === 0)
|
98 | return [indent(indentation) + options.emptyArrayMsg];
|
99 |
|
100 |
|
101 | const outputArray = [];
|
102 |
|
103 | data.forEach((element) => {
|
104 |
|
105 | let line = '- ';
|
106 | line = options.colors[options.dashColor](line);
|
107 |
|
108 | line = indent(indentation) + line;
|
109 |
|
110 |
|
111 |
|
112 | if (isSerializable(element, false, options)) {
|
113 | line += renderToArray(element, options, 0)[0];
|
114 | outputArray.push(line);
|
115 |
|
116 |
|
117 | } else {
|
118 | outputArray.push(line);
|
119 | outputArray.push(...renderToArray(element, options, indentation + options.defaultIndentation));
|
120 | }
|
121 | });
|
122 |
|
123 | return outputArray;
|
124 | }
|
125 |
|
126 | if (data instanceof Error)
|
127 | return renderToArray(
|
128 | {
|
129 | message: data.message,
|
130 | stack: data.stack.split('\n'),
|
131 | },
|
132 | options,
|
133 | indentation,
|
134 | );
|
135 |
|
136 |
|
137 |
|
138 |
|
139 | const maxIndexLength = options.noAlign ? 0 : getMaxIndexLength(data);
|
140 | let key;
|
141 | const output = [];
|
142 |
|
143 | Object.keys(data).forEach((i) => {
|
144 |
|
145 | key = (`${i}: `);
|
146 | key = options.colors[options.keysColor](key);
|
147 |
|
148 | key = indent(indentation, key);
|
149 |
|
150 |
|
151 | if (data[i] === undefined)
|
152 | return;
|
153 |
|
154 |
|
155 |
|
156 | if (isSerializable(data[i], false, options)) {
|
157 | const nextIndentation = options.noAlign ? 0 : maxIndexLength - i.length;
|
158 | key += renderToArray(data[i], options, nextIndentation)[0];
|
159 | output.push(key);
|
160 |
|
161 |
|
162 | } else {
|
163 | output.push(key);
|
164 | output.push(...renderToArray(
|
165 | data[i],
|
166 | options,
|
167 | indentation + options.defaultIndentation,
|
168 | ));
|
169 | }
|
170 | });
|
171 | return output;
|
172 | };
|
173 |
|
174 |
|
175 |
|
176 |
|
177 |
|
178 |
|
179 |
|
180 |
|
181 |
|
182 |
|
183 |
|
184 |
|
185 |
|
186 |
|
187 |
|
188 |
|
189 |
|
190 | const render = function render(data, indentation, {
|
191 | emptyArrayMsg = '(empty array)',
|
192 | keysColor = 'green',
|
193 | dashColor = 'green',
|
194 | numberColor = 'blue',
|
195 | defaultIndentation = 2,
|
196 | noAlign = false,
|
197 | stringColor = null,
|
198 | colors,
|
199 | }) {
|
200 | if (!colors)
|
201 | throw new Error('Colors library required');
|
202 |
|
203 |
|
204 | indentation = indentation || 0;
|
205 |
|
206 | return renderToArray(data, {
|
207 | emptyArrayMsg,
|
208 | keysColor,
|
209 | dashColor,
|
210 | numberColor,
|
211 | defaultIndentation,
|
212 | noAlign,
|
213 | stringColor,
|
214 | colors,
|
215 | }, indentation).join('\n');
|
216 | };
|
217 |
|
218 |
|
219 |
|
220 |
|
221 |
|
222 |
|
223 |
|
224 |
|
225 |
|
226 |
|
227 |
|
228 |
|
229 |
|
230 |
|
231 |
|
232 |
|
233 | const renderString = function renderString(data, options, indentation) {
|
234 | let output = '';
|
235 | let parsedData;
|
236 |
|
237 | if (typeof data !== 'string' || data === '')
|
238 | return '';
|
239 |
|
240 |
|
241 |
|
242 | if (data[0] !== '{' && data[0] !== '[') {
|
243 | let beginningOfJson;
|
244 | if (data.indexOf('{') === -1)
|
245 | beginningOfJson = data.indexOf('[');
|
246 | else if (data.indexOf('[') === -1)
|
247 | beginningOfJson = data.indexOf('{');
|
248 | else if (data.indexOf('{') < data.indexOf('['))
|
249 | beginningOfJson = data.indexOf('{');
|
250 | else
|
251 | beginningOfJson = data.indexOf('[');
|
252 |
|
253 | output += `${data.substr(0, beginningOfJson)}\n`;
|
254 | data = data.substr(beginningOfJson);
|
255 | }
|
256 |
|
257 | try {
|
258 | parsedData = JSON.parse(data);
|
259 | } catch (e) {
|
260 |
|
261 | return `${options.colors.red('Error:')} Not valid JSON!`;
|
262 | }
|
263 |
|
264 |
|
265 | output += exports.render(parsedData, options, indentation);
|
266 | return output;
|
267 | };
|
268 |
|
269 | module.exports = {
|
270 | render,
|
271 | renderString,
|
272 | };
|