123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229 |
- 'use strict';
- // ### Module dependencies
- require('colors');
- var Utils = require('./utils');
- exports.version = require('../package.json').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) {
- // Default values
- indentation = indentation || 0;
- options = options || {};
- options.emptyArrayMsg = options.emptyArrayMsg || '(empty array)';
- options.keysColor = options.keysColor || 'green';
- options.dashColor = options.dashColor || 'green';
- options.numberColor = options.numberColor || 'blue';
- options.defaultIndentation = options.defaultIndentation || 2;
- options.noColor = !!options.noColor;
- options.stringColor = options.stringColor || null;
- var output = [];
- // Helper function to detect if an object can be directly serializable
- var isSerializable = function(input, onlyPrimitives) {
- if (typeof input === 'boolean' ||
- typeof input === 'number' || input === null ||
- input instanceof Date) {
- return true;
- }
- if (typeof input === 'string' && input.indexOf('\n') === -1) {
- return true;
- }
- if (options.inlineArrays && !onlyPrimitives) {
- if (Array.isArray(input) && isSerializable(input[0], true)) {
- return true;
- }
- }
- return false;
- };
- var indentLines = function(string, spaces){
- var lines = string.split('\n');
- lines = lines.map(function(line){
- return Utils.indent(spaces) + line;
- });
- return lines.join('\n');
- };
- var addColorToData = function(input) {
- if (options.noColor) {
- return input;
- }
- if (typeof input === 'string') {
- // Print strings in regular terminal color
- return options.stringColor ? input[options.stringColor] : input;
- }
- var sInput = input + '';
- if (input === true) {
- return sInput.green;
- }
- if (input === false) {
- return sInput.red;
- }
- if (input === null) {
- return sInput.grey;
- }
- if (typeof input === 'number') {
- return sInput[options.numberColor];
- }
- if (Array.isArray(input)) {
- return input.join(', ');
- }
- return sInput;
- };
- // Render a string exactly equal
- if (isSerializable(data)) {
- output.push(Utils.indent(indentation) + addColorToData(data));
- }
- else if (typeof data === 'string') {
- //unserializable string means it's multiline
- output.push(Utils.indent(indentation) + '"""');
- output.push(indentLines(data, indentation + options.defaultIndentation));
- output.push(Utils.indent(indentation) + '"""');
- }
- 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 = ('- ');
- if (!options.noColor) {
- line = line[options.dashColor];
- }
- line = Utils.indent(indentation) + line;
- // If the element of the array is a string, bool, number, or null
- // render it in the same line
- if (isSerializable(element)) {
- line += exports.render(element, options);
- output.push(line);
- // If the element 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 align all the values
- var maxIndexLength = Utils.getMaxIndexLength(data);
- var key;
- var isError = data instanceof Error;
- Object.getOwnPropertyNames(data).forEach(function(i) {
- // Prepend the index at the beginning of the line
- key = (i + ': ');
- if (!options.noColor) {
- key = key[options.keysColor];
- }
- key = Utils.indent(indentation) + key;
- // Skip `undefined`, it's not a valid JSON value.
- if (data[i] === undefined) {
- return;
- }
- // If the value is serializable, render it in the same line
- if (isSerializable(data[i]) && (!isError || i !== 'stack')) {
- 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(
- isError && i === 'stack' ? data[i].split('\n') : 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) {
- 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 if (data.indexOf('{') < data.indexOf('[')) {
- beginingOfJson = data.indexOf('{');
- } else {
- beginingOfJson = 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, indentation);
- return output;
- };
|