contentscript-jsonformat.js 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. /**
  2. * content_scripts中如果被检测到当前页面内容为json数据,则自动进行JSON格式化
  3. */
  4. baidu.csJsonFormat = (function () {
  5. "use strict";
  6. var _htmlFragment = [
  7. '<div class="mod-json mod-contentscript"><div class="rst-item">',
  8. '<div id="formatTips">本页JSON数据由FeHelper进行自动格式化,若有任何问题,点击这里提交 ',
  9. '<a href="http://www.baidufe.com/fehelper/feedback.html" target="_blank">意见反馈</a>',
  10. '</div>',
  11. '<div id="formattingMsg">',
  12. '<svg id="spinner" width="16" height="16" viewBox="0 0 300 300" xmlns="http://www.w3.org/2000/svg" version="1.1">',
  13. '<path d="M 150,0 a 150,150 0 0,1 106.066,256.066 l -35.355,-35.355 a -100,-100 0 0,0 -70.711,-170.711 z" fill="#3d7fe6"></path>',
  14. '</svg>加载中...',
  15. '</div>',
  16. '<div id="jfCallbackName_start" class="callback-name"></div>',
  17. '<div id="jfContent"></div>',
  18. '<pre id="jfContent_pre"></pre>',
  19. '<div id="jfCallbackName_end" class="callback-name"></div>',
  20. '</div></div>'
  21. ].join('');
  22. var _loadCss = function () {
  23. var fcpCss = chrome.extension.getURL('static/css/fe-jsonformat-content.css');
  24. jQuery('<link id="_fehelper_fcp_css_" href="' + fcpCss + '" rel="stylesheet" type="text/css" />').appendTo('head');
  25. };
  26. /**
  27. * 从页面提取JSON文本
  28. * @return {*}
  29. * @private
  30. */
  31. var _getJsonText = function () {
  32. var pre = $('body>pre:eq(0)')[0] || {textContent: ""};
  33. var source = $.trim(pre.textContent);
  34. if (!source) {
  35. source = $.trim(document.body.textContent || '')
  36. }
  37. if (!source) {
  38. return false;
  39. }
  40. // 如果body的内容还包含HTML标签,肯定不是合法的json了
  41. // 如果是合法的json,也只可能有一个text节点
  42. var nodes = document.body.childNodes;
  43. var newSource = '';
  44. for (var i = 0, len = nodes.length; i < len; i++) {
  45. if (nodes[i].nodeType == Node.TEXT_NODE) {
  46. newSource += nodes[i].textContent;
  47. } else if (nodes[i].nodeType == Node.ELEMENT_NODE) {
  48. var tagName = nodes[i].tagName.toLowerCase();
  49. var html = $.trim(nodes[i].textContent);
  50. // 如果是pre标签,则看内容是不是和source一样,一样则continue
  51. if (tagName === 'pre' && html === source) {
  52. continue;
  53. } else if (tagName === 'embed' && nodes[i].offsetWidth === 0) {
  54. // 如果用户安装迅雷或者其他的插件,也回破坏页面结构,需要兼容一下
  55. continue;
  56. } else {
  57. return false;
  58. }
  59. } else {
  60. return false;
  61. }
  62. }
  63. return newSource || source;
  64. };
  65. /**
  66. * 此方法用于将Unicode码解码为正常字符串
  67. * @param {Object} text
  68. */
  69. var _uniDecode = function (text) {
  70. text = text.replace(/\\/g, "%").replace('%U','%u').replace('%u0025', '%25');
  71. text = unescape(text.toString().replace(/%2B/g, "+"));
  72. var matches = text.match(/(%u00([0-9A-F]{2}))/gi);
  73. if (matches) {
  74. for (var matchid = 0; matchid < matches.length; matchid++) {
  75. var code = matches[matchid].substring(1, 3);
  76. var x = Number("0x" + code);
  77. if (x >= 128) {
  78. text = text.replace(matches[matchid], code);
  79. }
  80. }
  81. }
  82. text = unescape(text.toString().replace(/%2B/g, "+"));
  83. return text;
  84. };
  85. /**
  86. * 执行format操作
  87. * @private
  88. */
  89. var _format = function () {
  90. var source = _getJsonText();
  91. if (!source) {
  92. return;
  93. }
  94. // JSONP形式下的callback name
  95. var funcName = null;
  96. // json对象
  97. var jsonObj = null;
  98. var newSource = '';
  99. // 下面校验给定字符串是否为一个合法的json
  100. try {
  101. // 再看看是不是jsonp的格式
  102. var reg = /^([\w\.]+)\(\s*([\s\S]*)\s*\)$/igm;
  103. var matches = reg.exec(source);
  104. if (matches != null) {
  105. funcName = matches[1];
  106. newSource = matches[2];
  107. jsonObj = new Function("return " + newSource)();
  108. }
  109. } catch (ex) {
  110. return;
  111. }
  112. try {
  113. if (jsonObj == null || typeof jsonObj != 'object') {
  114. jsonObj = new Function("return " + source)();
  115. // 还要防止下面这种情况: "{\"ret\":\"0\", \"msg\":\"ok\"}"
  116. if (typeof jsonObj == "string") {
  117. // 再来一次
  118. jsonObj = new Function("return " + jsonObj)();
  119. }
  120. }
  121. } catch (e) {
  122. return;
  123. }
  124. // 是json格式,可以进行JSON自动格式化
  125. if (jsonObj != null && typeof jsonObj == "object") {
  126. try {
  127. // 要尽量保证格式化的东西一定是一个json,所以需要把内容进行JSON.stringify处理
  128. newSource = JSON.stringify(jsonObj);
  129. // 如果newSource的长度比原source长度短很多的话,猜测应该是格式化错了,需要撤销操作
  130. // 这里一定要unicode decode一下,要不然会出现误判
  131. if(newSource.length * 2 < (_uniDecode(source)).length) {
  132. return ;
  133. }
  134. } catch (ex) {
  135. // 通过JSON反解不出来的,一定有问题
  136. return;
  137. }
  138. $('body').html(_htmlFragment);
  139. _loadCss();
  140. // 点击区块高亮
  141. $('#jfContent').delegate('.kvov', 'click', function (e) {
  142. $('#jfContent .kvov').removeClass('x-outline');
  143. $(this).removeClass('x-hover').addClass('x-outline');
  144. if (!$(e.target).is('.kvov .e')) {
  145. e.stopPropagation();
  146. } else {
  147. $(e.target).parent().trigger('click');
  148. }
  149. }).delegate('.kvov', 'mouseover', function (e) {
  150. $(this).addClass('x-hover');
  151. return false;
  152. }).delegate('.kvov', 'mouseout', function (e) {
  153. $(this).removeClass('x-hover');
  154. });
  155. JsonFormatEntrance.clear();
  156. JsonFormatEntrance.format(newSource);
  157. // 如果是JSONP格式的,需要把方法名也显示出来
  158. if (funcName != null) {
  159. $('#jfCallbackName_start').html(funcName + '(');
  160. $('#jfCallbackName_end').html(')');
  161. }
  162. }
  163. };
  164. var _init = function () {
  165. $(function () {
  166. if (!/^filesystem\:/.test(location.href)) {
  167. _format();
  168. }
  169. });
  170. };
  171. return {
  172. init: _init
  173. };
  174. })();
  175. baidu.csJsonFormat.init();