JSON formatter

Format JSON data in a beautiful way.

当前为 2015-07-01 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name JSON formatter
  3. // @namespace http://gerald.top
  4. // @description Format JSON data in a beautiful way.
  5. // @description:zh-CN 更加漂亮地显示JSON数据。
  6. // @version 1.0
  7. // @match *://*/*
  8. // @grant GM_addStyle
  9. // @grant GM_registerMenuCommand
  10. // ==/UserScript==
  11.  
  12. function safeHTML(html) {
  13. return html.replace(/[<&]/g, function (key) {
  14. return {
  15. '<': '&lt;',
  16. '&': '&amp;',
  17. }[key];
  18. });
  19. }
  20.  
  21. function join(list) {
  22. var html = [];
  23. var open = false;
  24. var last = null;
  25. var close = function () {
  26. html.push('</li>');
  27. open = false;
  28. last = null;
  29. };
  30. list.forEach(function (item) {
  31. if (open && !item.backwards)
  32. close();
  33. if (!open) {
  34. html.push('<li>');
  35. open = true;
  36. }
  37. if (item.backwards && last && last.forwards)
  38. html.push(last.separator);
  39. html.push(item.data);
  40. if (!item.forwards)
  41. close();
  42. else
  43. last = item;
  44. });
  45. if (open) html.push('</li>');
  46. return html.join('');
  47. }
  48.  
  49. function getHtml(data, cls) {
  50. return '<span class="' + (cls || typeof data) + '">' + data + '</span>';
  51. }
  52.  
  53. function render(data) {
  54. if (Array.isArray(data)) {
  55. var arr = [];
  56. var ret = {
  57. backwards: true,
  58. forwards: true,
  59. separator: getHtml(',', 'separator'),
  60. };
  61. arr.push(getHtml('[', 'operator'));
  62. if (data.length) {
  63. arr.push('<ul>');
  64. arr.push(join(data.map(render)));
  65. arr.push('</ul>');
  66. } else {
  67. arr.push(getHtml('', 'separator'));
  68. ret.backwards = ret.forwards = false;
  69. }
  70. arr.push(getHtml(']', 'operator'));
  71. ret.data = arr.join('');
  72. return ret;
  73. } else if (data === null)
  74. return {data: getHtml('null', 'null'), backwards: true};
  75. else if (typeof data == 'object') {
  76. var arr = [];
  77. var ret = {
  78. backwards: true,
  79. forwards: true,
  80. separator: getHtml(',', 'separator'),
  81. };
  82. arr.push(getHtml('{', 'operator'));
  83. var objdata = [];
  84. for (var key in data) {
  85. objdata.push({
  86. data: getHtml(key, 'key'),
  87. forwards: true,
  88. separator: getHtml(':', 'separator'),
  89. });
  90. objdata.push(render(data[key]));
  91. }
  92. if (objdata.length) {
  93. arr.push('<ul>');
  94. arr.push(join(objdata));
  95. arr.push('</ul>');
  96. } else {
  97. arr.push(getHtml('', 'separator'));
  98. ret.backwards = ret.forwards = false;
  99. }
  100. arr.push(getHtml('}', 'operator'));
  101. ret.data = arr.join('');
  102. return ret;
  103. } else
  104. return {
  105. backwards: true,
  106. data: getHtml(data),
  107. };
  108. }
  109.  
  110. function formatJSON() {
  111. if (config.formatted) {
  112. document.body.innerHTML = config.raw;
  113. config.formatted = false;
  114. } else {
  115. if (!('raw' in config)) {
  116. config.raw = document.body.innerHTML;
  117. config.data = JSON.parse(document.body.innerText);
  118. config.style = GM_addStyle(
  119. 'ul.root{padding-left:0;}' +
  120. 'li{list-style:none;}' +
  121. '.separator{margin-right:.5em;}' +
  122. '.number{color:darkorange;}' +
  123. '.key{color:brown;}' +
  124. '.string{color:green;}' +
  125. '.operator{color:blue;}'
  126. );
  127. }
  128. var ret = render(config.data);
  129. document.body.innerHTML = '<ul class="root"><li>' + ret.data + '</li></ul>';
  130. config.formatted = true;
  131. }
  132. }
  133.  
  134. var config = {};
  135. if (/\/json$/.test(document.contentType))
  136. formatJSON();
  137. GM_registerMenuCommand('Toggle JSON format', formatJSON);