prettyjson
Version:
Package for formatting JSON data in a coloured YAML-style, perfect for CLI output
187 lines (163 loc) • 5.93 kB
JavaScript
// Package for formatting JSON data in a coloured
// YAML-style, perfect for CLI output
// ### Export package
module.exports = exports;
// ### Module dependencies
var colors = require('colors');
var Utils = require('./utils');
var fs = require('fs');
// ### Package version
exports.version = JSON.parse(fs.readFileSync(__dirname + '/../package.json', 'utf8')).version;
// ### Render function
// *Parameters:*
//
// * **`data`**: Data to render
// * **`options`**: Hash with different options to configure the parser
// * **`indentation`**: Base indentation of the parsed output
//
// *Example of options hash:*
//
// {
// emptyArrayMsg: '(empty)', // Rendered message on empty strings
// keysColor: 'blue', // Color for keys in hashes
// dashColor: 'red', // Color for the dashes in arrays
// stringColor: 'grey', // Color for strings
// defaultIndentation: 2 // Indentation on nested objects
// }
exports.render = function render(data, options, indentation) {
"use strict";
// Default value for the indentation param
indentation = indentation || 0;
// Default values for the options
options = options || {};
options.emptyArrayMsg = options.emptyArrayMsg || '(empty array)';
options.keysColor = options.keysColor || "green";
options.dashColor = options.dashColor || "green";
options.defaultIndentation = options.defaultIndentation || 2;
options.stringColor = options.stringColor || null;
// Initialize the output (it's an array of lines)
var output = [];
// Helper function to detect if an object can be serializable directly
var isSerializable = function(input) {
if (typeof input === 'string' || typeof input === 'boolean' ||
typeof input === 'number' || input === null) {
return true;
}
return false;
};
var addColorToData = function(input) {
if (typeof input === 'string') {
// Print strings in regular terminal color
return options.stringColor ? input[options.stringColor] : input;
}
if (input === true) {
return (input+'').green;
}
if (input === false) {
return (input+'').red;
}
if (input === null) {
return (input+'').grey;
}
if (typeof input === 'number') {
return (input+'').blue;
}
return (input+'');
};
// Render a string exactly equal
if (isSerializable(data)) {
output.push(Utils.indent(indentation) + addColorToData(data));
}
else if (Array.isArray(data)) {
// If the array is empty, render the `emptyArrayMsg`
if (data.length === 0) {
output.push(Utils.indent(indentation) + options.emptyArrayMsg);
} else {
data.forEach(function(element) {
// Prepend the dash at the begining of each array's element line
var line = Utils.indent(indentation) + ('- ')[options.dashColor];
// If the element of the array is a string, render it in the same line
if (typeof element === 'string') {
line += exports.render(element, options);
output.push(line);
// If the element of the array is an array or object, render it in next line
} else {
output.push(line);
output.push(
exports.render(element, options, indentation + options.defaultIndentation)
);
}
});
}
}
else if (typeof data === 'object') {
// Get the size of the longest index to render all the values on the same column
var maxIndexLength = Utils.getMaxIndexLength(data);
var key;
for(var i in data) {
if (data.hasOwnProperty(i)) {
// Prepend the index at the beginning of the line
key = Utils.indent(indentation) + (i + ': ')[options.keysColor];
// If the value is serializable, render it in the same line
if (isSerializable(data[i])) {
key += exports.render(data[i], options, maxIndexLength - i.length);
output.push(key);
// If the index is an array or object, render it in next line
} else {
output.push(key);
output.push(
exports.render(data[i], options, indentation + options.defaultIndentation)
);
}
}
}
}
// Return all the lines as a string
return output.join('\n');
};
// ### Render from string function
// *Parameters:*
//
// * **`data`**: Data to render as a string
// * **`options`**: Hash with different options to configure the parser
// * **`indentation`**: Base indentation of the parsed output
//
// *Example of options hash:*
//
// {
// emptyArrayMsg: '(empty)', // Rendered message on empty strings
// keysColor: 'blue', // Color for keys in hashes
// dashColor: 'red', // Color for the dashes in arrays
// defaultIndentation: 2 // Indentation on nested objects
// }
exports.renderString = function renderString(data, options, indentation) {
"use strict";
var output = '';
var parsedData;
// If the input is not a string or if it's empty, just return an empty string
if (typeof data !== 'string' || data === '') {
return '';
}
// Remove non-JSON characters from the beginning string
if (data[0] !== '{' && data[0] !== '[') {
var beginingOfJson;
if (data.indexOf('{') === -1) {
beginingOfJson = data.indexOf('[');
} else if (data.indexOf('[') === -1) {
beginingOfJson = data.indexOf('{');
} else {
beginingOfJson = data.indexOf('{') < data.indexOf('[') ? data.indexOf('{') : data.indexOf('[');
}
output += data.substr(0, beginingOfJson) + "\n";
data = data.substr(beginingOfJson);
}
try {
parsedData = JSON.parse(data);
} catch (e) {
// Return an error in case of an invalid JSON
return 'Error:'.red + ' Not valid JSON!';
}
// Call the real render() method
output += exports.render(parsedData, options);
return output;
};