Pretty-prints a Javascript value for viewing. - Node.js Object

Node.js examples for Object:Object Operation

Description

Pretty-prints a Javascript value for viewing.

Demo Code

/**/*  ww  w. ja v a 2 s.c  o  m*/
 * Pretty-prints a Javascript value for viewing.
 * Identifies circular references
 **/
var utils = {
  pretty_print: function(value, depth) {
    if (typeof depth === "undefined") {
      depth = 5;
    }

    var seen = [];

    return (function(value, depth) {
      if (!depth) { return "\u2026"; /* Ellipsis */}
      if (value === null) return "null";
      
      //return typeof value;

      switch (typeof value) {
      case "undefined": return "undefined";
      case "string": return utils.string_format(value);
      case "number":
      case "boolean": return value.toString();
      case "function":

        if (value.name && value.name !== "anonymous") {
          return "(function) "+value.name;
        }

        if (Object.prototype.toString.call(value) === "[object RegExp]")
          return RegExp.prototype.toString.call(value);

        // Collapse whitespace
        var str;
        str = Function.prototype.toString.call(value).replace(/\s+/g, " ");
        
        // Truncate just enough so you can identify the function
        if (str.length > 48) {
          return str.substr(0, 46)+"\u2026}";
        } else {
          return str;
        }
      case "object":
      
        // Only way to get internal [[Class]] property
        var type = Object.prototype.toString.call(value);
        type = type.slice(8, -1);
        switch (type) {
          case "Date":
            return "(object) " +
              Date.prototype.toString.call(value);
          case "Boolean":
            return "(object) " +
              Boolean.prototype.toString.call(value);
          case "Number":
            return "(object) " +
              Number.prototype.toString.call(value);
          case "RegExp": // Sometimes a RegExp is not a function
            return RegExp.prototype.toString.call(value);
          case "String":
            return "(object) " +
              utils.string_format(
                String.prototype.toString.call(value));
        }
          
        try {

          if (~seen.indexOf(value)) return "(Circular)";
          seen.push(value);
        
          var array = [], braces, props, prepend_key;

          if (Array.isArray(value)) {
            braces = "[]";
            props = [];
            prepend_key = false;
            for( var i = 0, len = value.length; i < len; i++ ) {
              props.push(i);
            }
          } else {
            braces = "{}";
            props = Object.getOwnPropertyNames(value).sort();
            prepend_key = true;
          }
        
          for( var i = 0, len = props.length; i < len; i++ ) {
            var desc = Object.getOwnPropertyDescriptor(value, props[i]);
            var string;
            if (typeof desc === "undefined" || desc.hasOwnProperty("value")) {
              string = (prepend_key ? props[i]+": " : "") +
                arguments.callee(value[props[i]], depth-1);
            } else {
              var getset = [];
              if (typeof desc.get !== "undefined") getset.push("Getter");
              if (typeof desc.set !== "undefined") getset.push("Setter");
              string = (prepend_key ? props[i]+": " : "") +
                "("+getset.join("/")+")";
            }
            array.push(string);
          }

          return braces[0]+array.join(", ")+braces[1];
        } catch (e) {
          return "(Semanticless: "+e.message+")";
        } finally {
          seen.pop();
        }
      case "xml":
        // Weird syntax!! D:
        return eval("XML.prettyPrinting = false; XML.prototype.function::toXMLString.call(value)");
      }
      return "(unknown)";
    })(value, depth);
  },
  /**
   * Format string value so it is readable. This replaces control
   * characters with their hex equivalent in Javascript notation.
   * Quotes are not escaped for readability. Only double quotes are placed
   * around it, so it's easy to see that it is a string.
   **/
  string_format: function(value) {
    return "'"+value.replace(/[\u0000-\u001f\u007f-\u009f\ufffe-\uffff]/g,
      function(v) {
      var escaped, code = v.charCodeAt(0);
      switch (code) {
      case 0: escaped = "\\0"; break;
      case 7: escaped = "\\a"; break;
      case 8: escaped = "\\b"; break;
      case 9: escaped = "\\t"; break;
      case 10: escaped = "\\n"; break;
      case 11: escaped = "\\v"; break;
      case 12: escaped = "\\f"; break;
      case 13: escaped = "\\r"; break;
      case 27: escaped = "\\e"; break;
      default:
        escaped = "\\" + (code>=256?"u":"x") + (code<=16?"0":"") +
          code.toString(16).toUpperCase();
        break;
      }
      return escaped;
    })+"'";
  },
  type_is_obvious: function(value) {
    switch (typeof value) {
      case "function":
        var type = Object.prototype.toString.call(value);
        type = type.slice(8, -1);
        if (type === "RegExp") {
          return false;
        }
      case "undefined": return true;
      case "number":
      case "boolean":
      case "string": return false;
      case "object":
        var type = Object.prototype.toString.call(value);
        type = type.slice(8, -1);
        switch (type) {
        case "Date":
        case "Number":
        case "Boolean":
        case "String": return true;
        }
    }
    return false;
  },
  generate: function(result, error, sandbox) {
    return JSON.stringify({
      data: {
        type: typeof result,
        console: consoledata,
        obvioustype: this.type_is_obvious(result)
      },
      error: error ? error.name+": "+error.message : null,
      result: this.pretty_print(result)
    });
  }
};

/**
 * The main run function.
 * Accepts a function that executes the code and returns a value,
 * with the specified argument used as a global object
 * Returns a string of json
 **/

exports.run = function(execute) {
  var result, error;
  try {
    result = execute(global);
  } catch(e) {
    if (typeof e.name !== "undefined" &&
      typeof e.message !== "undefined") {
      error = e;
      error.name = e.name; // Weird bug
    } else {
      error = {name: "Uncaught value", message: utils.pretty_print(e)};
    }
  }
  return utils.generate(result, error, global);
};
exports.pretty_print = utils.pretty_print;
exports.string_format = utils.string_format;

Related Tutorials