index.js 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. var json = typeof JSON !== 'undefined' ? JSON : require('jsonify');
  2. module.exports = function (obj, opts) {
  3. if (!opts) opts = {};
  4. if (typeof opts === 'function') opts = { cmp: opts };
  5. var space = opts.space || '';
  6. if (typeof space === 'number') space = Array(space+1).join(' ');
  7. var cycles = (typeof opts.cycles === 'boolean') ? opts.cycles : false;
  8. var replacer = opts.replacer || function(key, value) { return value; };
  9. var cmp = opts.cmp && (function (f) {
  10. return function (node) {
  11. return function (a, b) {
  12. var aobj = { key: a, value: node[a] };
  13. var bobj = { key: b, value: node[b] };
  14. return f(aobj, bobj);
  15. };
  16. };
  17. })(opts.cmp);
  18. var seen = [];
  19. return (function stringify (parent, key, node, level) {
  20. var indent = space ? ('\n' + new Array(level + 1).join(space)) : '';
  21. var colonSeparator = space ? ': ' : ':';
  22. if (node && node.toJSON && typeof node.toJSON === 'function') {
  23. node = node.toJSON();
  24. }
  25. node = replacer.call(parent, key, node);
  26. if (node === undefined) {
  27. return;
  28. }
  29. if (typeof node !== 'object' || node === null) {
  30. return json.stringify(node);
  31. }
  32. if (isArray(node)) {
  33. var out = [];
  34. for (var i = 0; i < node.length; i++) {
  35. var item = stringify(node, i, node[i], level+1) || json.stringify(null);
  36. out.push(indent + space + item);
  37. }
  38. return '[' + out.join(',') + indent + ']';
  39. }
  40. else {
  41. if (seen.indexOf(node) !== -1) {
  42. if (cycles) return json.stringify('__cycle__');
  43. throw new TypeError('Converting circular structure to JSON');
  44. }
  45. else seen.push(node);
  46. var keys = objectKeys(node).sort(cmp && cmp(node));
  47. var out = [];
  48. for (var i = 0; i < keys.length; i++) {
  49. var key = keys[i];
  50. var value = stringify(node, key, node[key], level+1);
  51. if(!value) continue;
  52. var keyValue = json.stringify(key)
  53. + colonSeparator
  54. + value;
  55. ;
  56. out.push(indent + space + keyValue);
  57. }
  58. seen.splice(seen.indexOf(node), 1);
  59. return '{' + out.join(',') + indent + '}';
  60. }
  61. })({ '': obj }, '', obj, 0);
  62. };
  63. var isArray = Array.isArray || function (x) {
  64. return {}.toString.call(x) === '[object Array]';
  65. };
  66. var objectKeys = Object.keys || function (obj) {
  67. var has = Object.prototype.hasOwnProperty || function () { return true };
  68. var keys = [];
  69. for (var key in obj) {
  70. if (has.call(obj, key)) keys.push(key);
  71. }
  72. return keys;
  73. };