1 | | <span class="c">// Package for formatting JSON data in a coloured </span> |
2 | | <span class="c">// YAML-style, perfect for CLI output</span> |
3 | | |
4 | | <span class="c">// ### Export package</span> |
5 | 1 | module<span class="k">.</span>exports <span class="k">=</span> exports<span class="k">;</span> |
6 | | |
7 | | |
8 | | <span class="c">// ### Module dependencies</span> |
9 | 1 | <span class="k">var</span> colors <span class="k">=</span> require<span class="k">(</span><span class="s">'colors'</span><span class="k">);</span> |
10 | 1 | <span class="k">var</span> Utils <span class="k">=</span> require<span class="k">(</span><span class="s">'./utils'</span><span class="k">);</span> |
11 | 1 | <span class="k">var</span> fs <span class="k">=</span> require<span class="k">(</span><span class="s">'fs'</span><span class="k">);</span> |
12 | | |
13 | | <span class="c">// ### Package version</span> |
14 | 1 | exports<span class="k">.</span>version <span class="k">=</span> JSON<span class="k">.</span>parse<span class="k">(</span>fs<span class="k">.</span>readFileSync<span class="k">(</span>__dirname <span class="k">+</span> <span class="s">'/../package.json'</span><span class="k">,</span> <span class="s">'utf8'</span><span class="k">)).</span>version<span class="k">;</span> |
15 | | |
16 | | <span class="c">// ### Render function</span> |
17 | | <span class="c">// *Parameters:*</span> |
18 | | <span class="c">//</span> |
19 | | <span class="c">// * **`data`**: Data to render</span> |
20 | | <span class="c">// * **`options`**: Hash with different options to configure the parser</span> |
21 | | <span class="c">// * **`indentation`**: Base indentation of the parsed output</span> |
22 | | <span class="c">//</span> |
23 | | <span class="c">// *Example of options hash:*</span> |
24 | | <span class="c">// </span> |
25 | | <span class="c">// {</span> |
26 | | <span class="c">// emptyArrayMsg: '(empty)', // Rendered message on empty strings</span> |
27 | | <span class="c">// keysColor: 'blue', // Color for keys in hashes</span> |
28 | | <span class="c">// dashColor: 'red', // Color for the dashes in arrays</span> |
29 | | <span class="c">// defaultIndentation: 2 // Indentation on nested objects</span> |
30 | | <span class="c">// }</span> |
31 | 1 | exports<span class="k">.</span>render <span class="k">=</span> <span class="k">function</span> render<span class="k">(</span>data<span class="k">,</span> options<span class="k">,</span> indentation<span class="k">)</span> <span class="k">{</span> |
32 | 51 | <span class="s">"use strict"</span><span class="k">;</span> |
33 | | |
34 | | <span class="c">// Default value for the indentation param</span> |
35 | 51 | indentation <span class="k">=</span> indentation <span class="k">||</span> <span class="s">0</span><span class="k">;</span> |
36 | | |
37 | | <span class="c">// Default values for the options</span> |
38 | 51 | options <span class="k">=</span> options <span class="k">||</span> <span class="k">{}</span><span class="k">;</span> |
39 | 51 | options<span class="k">.</span>emptyArrayMsg <span class="k">=</span> options<span class="k">.</span>emptyArrayMsg <span class="k">||</span> <span class="s">'(empty array)'</span><span class="k">;</span> |
40 | 51 | options<span class="k">.</span>keysColor <span class="k">=</span> options<span class="k">.</span>keysColor <span class="k">||</span> <span class="s">"green"</span><span class="k">;</span> |
41 | 51 | options<span class="k">.</span>dashColor <span class="k">=</span> options<span class="k">.</span>dashColor <span class="k">||</span> <span class="s">"green"</span><span class="k">;</span> |
42 | 51 | options<span class="k">.</span>defaultIndentation <span class="k">=</span> options<span class="k">.</span>defaultIndentation <span class="k">||</span> <span class="s">2</span><span class="k">;</span> |
43 | | |
44 | | <span class="c">// Initialize the output (it's an array of lines)</span> |
45 | 51 | <span class="k">var</span> output <span class="k">=</span> <span class="k">[];</span> |
46 | | |
47 | | <span class="c">// Helper function to detect if an object can be serializable directly</span> |
48 | 51 | <span class="k">var</span> isSerializable <span class="k">=</span> <span class="k">function</span><span class="k">(</span>input<span class="k">)</span> <span class="k">{</span> |
49 | 73 | <span class="k">if</span> <span class="k">(</span><span class="k">typeof</span> input <span class="k">===</span> <span class="s">'string'</span> <span class="k">||</span> <span class="k">typeof</span> input <span class="k">===</span> <span class="s">'boolean'</span> <span class="k">||</span> |
50 | | <span class="k">typeof</span> input <span class="k">===</span> <span class="s">'number'</span> <span class="k">||</span> input <span class="k">===</span> <span class="k">null</span><span class="k">)</span> <span class="k">{</span> |
51 | 49 | <span class="k">return</span> <span class="k">true</span><span class="k">;</span> |
52 | | <span class="k">}</span> |
53 | 24 | <span class="k">return</span> <span class="k">false</span><span class="k">;</span> |
54 | | <span class="k">}</span><span class="k">;</span> |
55 | | |
56 | 51 | <span class="k">var</span> addColorToData <span class="k">=</span> <span class="k">function</span><span class="k">(</span>input<span class="k">)</span> <span class="k">{</span> |
57 | 33 | <span class="k">if</span> <span class="k">(</span><span class="k">typeof</span> input <span class="k">===</span> <span class="s">'string'</span><span class="k">)</span> <span class="k">{</span> |
58 | | <span class="c">// Print strings in regular terminal color</span> |
59 | 29 | <span class="k">return</span> input<span class="k">;</span> |
60 | | <span class="k">}</span> |
61 | | |
62 | 4 | <span class="k">if</span> <span class="k">(</span>input <span class="k">===</span> <span class="k">true</span><span class="k">)</span> <span class="k">{</span> |
63 | 1 | <span class="k">return</span> <span class="k">(</span>input<span class="k">+</span><span class="s">''</span><span class="k">).</span>green<span class="k">;</span> |
64 | | <span class="k">}</span> |
65 | 3 | <span class="k">if</span> <span class="k">(</span>input <span class="k">===</span> <span class="k">false</span><span class="k">)</span> <span class="k">{</span> |
66 | 1 | <span class="k">return</span> <span class="k">(</span>input<span class="k">+</span><span class="s">''</span><span class="k">).</span>red<span class="k">;</span> |
67 | | <span class="k">}</span> |
68 | 2 | <span class="k">if</span> <span class="k">(</span>input <span class="k">===</span> <span class="k">null</span><span class="k">)</span> <span class="k">{</span> |
69 | 1 | <span class="k">return</span> <span class="k">(</span>input<span class="k">+</span><span class="s">''</span><span class="k">).</span>grey<span class="k">;</span> |
70 | | <span class="k">}</span> |
71 | 1 | <span class="k">if</span> <span class="k">(</span><span class="k">typeof</span> input <span class="k">===</span> <span class="s">'number'</span><span class="k">)</span> <span class="k">{</span> |
72 | 1 | <span class="k">return</span> <span class="k">(</span>input<span class="k">+</span><span class="s">''</span><span class="k">).</span>blue<span class="k">;</span> |
73 | | <span class="k">}</span> |
74 | 0 | <span class="k">return</span> <span class="k">(</span>input<span class="k">+</span><span class="s">''</span><span class="k">);</span> |
75 | | <span class="k">}</span><span class="k">;</span> |
76 | | |
77 | | <span class="c">// Render a string exactly equal</span> |
78 | 51 | <span class="k">if</span> <span class="k">(</span>isSerializable<span class="k">(</span>data<span class="k">))</span> <span class="k">{</span> |
79 | 33 | output<span class="k">.</span>push<span class="k">(</span>Utils<span class="k">.</span>indent<span class="k">(</span>indentation<span class="k">)</span> <span class="k">+</span> addColorToData<span class="k">(</span>data<span class="k">));</span> |
80 | | <span class="k">}</span> |
81 | 18 | <span class="k">else</span> <span class="k">if</span> <span class="k">(</span>Array<span class="k">.</span>isArray<span class="k">(</span>data<span class="k">))</span> <span class="k">{</span> |
82 | | <span class="c">// If the array is empty, render the `emptyArrayMsg`</span> |
83 | 8 | <span class="k">if</span> <span class="k">(</span>data<span class="k">.</span>length <span class="k">===</span> <span class="s">0</span><span class="k">)</span> <span class="k">{</span> |
84 | 2 | output<span class="k">.</span>push<span class="k">(</span>Utils<span class="k">.</span>indent<span class="k">(</span>indentation<span class="k">)</span> <span class="k">+</span> options<span class="k">.</span>emptyArrayMsg<span class="k">);</span> |
85 | | <span class="k">}</span> <span class="k">else</span> <span class="k">{</span> |
86 | 6 | data<span class="k">.</span>forEach<span class="k">(</span><span class="k">function</span><span class="k">(</span>element<span class="k">)</span> <span class="k">{</span> |
87 | | <span class="c">// Prepend the dash at the begining of each array's element line</span> |
88 | 13 | <span class="k">var</span> line <span class="k">=</span> Utils<span class="k">.</span>indent<span class="k">(</span>indentation<span class="k">)</span> <span class="k">+</span> <span class="k">(</span><span class="s">'- '</span><span class="k">)[</span>options<span class="k">.</span>dashColor<span class="k">];</span> |
89 | | |
90 | | <span class="c">// If the element of the array is a string, render it in the same line</span> |
91 | 13 | <span class="k">if</span> <span class="k">(</span><span class="k">typeof</span> element <span class="k">===</span> <span class="s">'string'</span><span class="k">)</span> <span class="k">{</span> |
92 | 11 | line <span class="k">+=</span> exports<span class="k">.</span>render<span class="k">(</span>element<span class="k">,</span> options<span class="k">);</span> |
93 | 11 | output<span class="k">.</span>push<span class="k">(</span>line<span class="k">);</span> |
94 | | |
95 | | <span class="c">// If the element of the array is an array or object, render it in next line</span> |
96 | | <span class="k">}</span> <span class="k">else</span> <span class="k">{</span> |
97 | 2 | output<span class="k">.</span>push<span class="k">(</span>line<span class="k">);</span> |
98 | 2 | output<span class="k">.</span>push<span class="k">(</span> |
99 | | exports<span class="k">.</span>render<span class="k">(</span>element<span class="k">,</span> options<span class="k">,</span> indentation <span class="k">+</span> options<span class="k">.</span>defaultIndentation<span class="k">)</span> |
100 | | <span class="k">);</span> |
101 | | <span class="k">}</span> |
102 | | <span class="k">}</span><span class="k">);</span> |
103 | | <span class="k">}</span> |
104 | | <span class="k">}</span> |
105 | 10 | <span class="k">else</span> <span class="k">if</span> <span class="k">(</span><span class="k">typeof</span> data <span class="k">===</span> <span class="s">'object'</span><span class="k">)</span> <span class="k">{</span> |
106 | | <span class="c">// Get the size of the longest index to render all the values on the same column</span> |
107 | 10 | <span class="k">var</span> maxIndexLength <span class="k">=</span> Utils<span class="k">.</span>getMaxIndexLength<span class="k">(</span>data<span class="k">);</span> |
108 | 10 | <span class="k">var</span> key<span class="k">;</span> |
109 | | |
110 | 10 | <span class="k">for</span><span class="k">(</span><span class="k">var</span> i <span class="k">in</span> data<span class="k">)</span> <span class="k">{</span> |
111 | | <span class="c">// Prepend the index at the beginning of the line</span> |
112 | 22 | key <span class="k">=</span> Utils<span class="k">.</span>indent<span class="k">(</span>indentation<span class="k">)</span> <span class="k">+</span> <span class="k">(</span>i <span class="k">+</span> <span class="s">': '</span><span class="k">)[</span>options<span class="k">.</span>keysColor<span class="k">];</span> |
113 | | |
114 | | <span class="c">// If the value is serializable, render it in the same line</span> |
115 | 22 | <span class="k">if</span> <span class="k">(</span>isSerializable<span class="k">(</span>data<span class="k">[</span>i<span class="k">]))</span> <span class="k">{</span> |
116 | 16 | key <span class="k">+=</span> exports<span class="k">.</span>render<span class="k">(</span>data<span class="k">[</span>i<span class="k">],</span> options<span class="k">,</span> maxIndexLength <span class="k">-</span> i<span class="k">.</span>length<span class="k">);</span> |
117 | 16 | output<span class="k">.</span>push<span class="k">(</span>key<span class="k">);</span> |
118 | | |
119 | | <span class="c">// If the index is an array or object, render it in next line</span> |
120 | | <span class="k">}</span> <span class="k">else</span> <span class="k">{</span> |
121 | 6 | output<span class="k">.</span>push<span class="k">(</span>key<span class="k">);</span> |
122 | 6 | output<span class="k">.</span>push<span class="k">(</span> |
123 | | exports<span class="k">.</span>render<span class="k">(</span>data<span class="k">[</span>i<span class="k">],</span> options<span class="k">,</span> indentation <span class="k">+</span> options<span class="k">.</span>defaultIndentation<span class="k">)</span> |
124 | | <span class="k">);</span> |
125 | | <span class="k">}</span> |
126 | | <span class="k">}</span> |
127 | | <span class="k">}</span> |
128 | | <span class="c">// Return all the lines as a string</span> |
129 | 51 | <span class="k">return</span> output<span class="k">.</span>join<span class="k">(</span><span class="s">'</span><span class="t">\n</span><span class="s">'</span><span class="k">);</span> |
130 | | <span class="k">}</span><span class="k">;</span> |