UNPKG

5.89 kBJavaScriptView Raw
1'use strict';
2
3// ### Module dependencies
4require('colors');
5var Utils = require('./utils');
6
7exports.version = require('../package.json').version;
8
9// ### Render function
10// *Parameters:*
11//
12// * **`data`**: Data to render
13// * **`options`**: Hash with different options to configure the parser
14// * **`indentation`**: Base indentation of the parsed output
15//
16// *Example of options hash:*
17//
18// {
19// emptyArrayMsg: '(empty)', // Rendered message on empty strings
20// keysColor: 'blue', // Color for keys in hashes
21// dashColor: 'red', // Color for the dashes in arrays
22// stringColor: 'grey', // Color for strings
23// defaultIndentation: 2 // Indentation on nested objects
24// }
25exports.render = function render(data, options, indentation) {
26
27 // Default values
28 indentation = indentation || 0;
29 options = options || {};
30 options.emptyArrayMsg = options.emptyArrayMsg || '(empty array)';
31 options.keysColor = options.keysColor || 'green';
32 options.dashColor = options.dashColor || 'green';
33 options.numberColor = options.numberColor || 'blue';
34 options.defaultIndentation = options.defaultIndentation || 2;
35
36 options.stringColor = options.stringColor || null;
37
38 var output = [];
39
40 // Helper function to detect if an object can be directly serializable
41 var isSerializable = function(input) {
42 if (typeof input === 'string' || typeof input === 'boolean' ||
43 typeof input === 'number' || input === null) {
44 return true;
45 }
46 return false;
47 };
48
49 var addColorToData = function(input) {
50 if (typeof input === 'string') {
51 // Print strings in regular terminal color
52 return options.stringColor ? input[options.stringColor] : input;
53 }
54
55 if (input === true) {
56 return (input+'').green;
57 }
58 if (input === false) {
59 return (input+'').red;
60 }
61 if (input === null) {
62 return (input+'').grey;
63 }
64 if (typeof input === 'number') {
65 return (input+'')[options.numberColor];
66 }
67 return (input+'');
68 };
69
70 // Render a string exactly equal
71 if (isSerializable(data)) {
72 output.push(Utils.indent(indentation) + addColorToData(data));
73 }
74 else if (Array.isArray(data)) {
75 // If the array is empty, render the `emptyArrayMsg`
76 if (data.length === 0) {
77 output.push(Utils.indent(indentation) + options.emptyArrayMsg);
78 } else {
79 data.forEach(function(element) {
80 // Prepend the dash at the begining of each array's element line
81 var line = Utils.indent(indentation) + ('- ')[options.dashColor];
82
83 // If the element of the array is a string, bool, number, or null
84 // render it in the same line
85 if (isSerializable(element)) {
86 line += exports.render(element, options);
87 output.push(line);
88
89 // If the element is an array or object, render it in next line
90 } else {
91 output.push(line);
92 output.push(exports.render(
93 element, options, indentation + options.defaultIndentation
94 ));
95 }
96 });
97 }
98 }
99 else if (typeof data === 'object') {
100 // Get the size of the longest index to align all the values
101 var maxIndexLength = Utils.getMaxIndexLength(data);
102 var key;
103 var isError = data instanceof Error;
104
105 Object.getOwnPropertyNames(data).forEach(function(i) {
106 // Prepend the index at the beginning of the line
107 key = Utils.indent(indentation) + (i + ': ')[options.keysColor];
108
109 // Skip `undefined`, it's not a valid JSON value.
110 if (data[i] === undefined) {
111 return;
112 }
113
114 // If the value is serializable, render it in the same line
115 if (isSerializable(data[i]) && (!isError || i !== 'stack')) {
116 key += exports.render(data[i], options, maxIndexLength - i.length);
117 output.push(key);
118
119 // If the index is an array or object, render it in next line
120 } else {
121 output.push(key);
122 output.push(
123 exports.render(
124 isError && i === 'stack' ? data[i].split('\n') : data[i],
125 options,
126 indentation + options.defaultIndentation
127 )
128 );
129 }
130 });
131 }
132 // Return all the lines as a string
133 return output.join('\n');
134};
135
136// ### Render from string function
137// *Parameters:*
138//
139// * **`data`**: Data to render as a string
140// * **`options`**: Hash with different options to configure the parser
141// * **`indentation`**: Base indentation of the parsed output
142//
143// *Example of options hash:*
144//
145// {
146// emptyArrayMsg: '(empty)', // Rendered message on empty strings
147// keysColor: 'blue', // Color for keys in hashes
148// dashColor: 'red', // Color for the dashes in arrays
149// defaultIndentation: 2 // Indentation on nested objects
150// }
151exports.renderString = function renderString(data, options, indentation) {
152
153 var output = '';
154 var parsedData;
155 // If the input is not a string or if it's empty, just return an empty string
156 if (typeof data !== 'string' || data === '') {
157 return '';
158 }
159
160 // Remove non-JSON characters from the beginning string
161 if (data[0] !== '{' && data[0] !== '[') {
162 var beginingOfJson;
163 if (data.indexOf('{') === -1) {
164 beginingOfJson = data.indexOf('[');
165 } else if (data.indexOf('[') === -1) {
166 beginingOfJson = data.indexOf('{');
167 } else if (data.indexOf('{') < data.indexOf('[')) {
168 beginingOfJson = data.indexOf('{');
169 } else {
170 beginingOfJson = data.indexOf('[');
171 }
172 output += data.substr(0, beginingOfJson) + '\n';
173 data = data.substr(beginingOfJson);
174 }
175
176 try {
177 parsedData = JSON.parse(data);
178 } catch (e) {
179 // Return an error in case of an invalid JSON
180 return 'Error:'.red + ' Not valid JSON!';
181 }
182
183 // Call the real render() method
184 output += exports.render(parsedData, options, indentation);
185 return output;
186};