contentscript-jsonformat.js 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  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/item/889639af23968ee688b9.html#comment" target="_blank">意见反馈</a>',
  10. '&nbsp;&nbsp;或者&nbsp;&nbsp;<a href="#" id="makeAutoJsonFormatOff">禁用此功能</a>',
  11. '</div>',
  12. '<div id="formattingMsg">',
  13. '<svg id="spinner" width="16" height="16" viewBox="0 0 300 300" xmlns="http://www.w3.org/2000/svg" version="1.1">',
  14. '<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>',
  15. '</svg>加载中...',
  16. '</div>',
  17. '<div id="jfCallbackName_start" class="callback-name"></div>',
  18. '<div id="jfContent"></div>',
  19. '<pre id="jfContent_pre"></pre>',
  20. '<div id="jfCallbackName_end" class="callback-name"></div>',
  21. '</div></div>'
  22. ].join('');
  23. var _loadCss = function () {
  24. var fcpCss = chrome.extension.getURL('static/css/fe-jsonformat.css');
  25. jQuery('<link id="_fehelper_fcp_css_" href="' + fcpCss + '" rel="stylesheet" type="text/css" />').appendTo('head');
  26. };
  27. /**
  28. * 将escape过的HTML再反解回来
  29. * @param txt
  30. * @return {String|XML}
  31. * @private
  32. */
  33. var _unEscapeHTML = function(txt) {
  34. return txt.replace(/&amp;/g,'&').replace(/&gt;/g,'>')
  35. .replace(/&lt;/g,'<').replace(/&quot;/g,'"')
  36. .replace(/&#39;/g,"'");
  37. };
  38. /**
  39. * 从页面提取JSON文本
  40. * @return {*}
  41. * @private
  42. */
  43. var _getJsonText = function(){
  44. var source = $.trim($('body>pre:eq(0)').html());
  45. if (!source) {
  46. source = $.trim($('body').html())
  47. }
  48. if (!source) {
  49. return;
  50. }
  51. // jQuery的html方法是把内容编码后输出的,所以需要反解回去
  52. source = _unEscapeHTML(source);
  53. // 如果body的内容还包含HTML标签,肯定不是合法的json了
  54. // 如果是合法的json,也只可能有一个text节点
  55. var nodes = document.body.childNodes;
  56. var json_text_detected = false;
  57. for (var i = 0, len = nodes.length; i < len; i++) {
  58. if (nodes[i].nodeType == Node.TEXT_NODE) {
  59. if (!json_text_detected) {
  60. source = nodes[i].textContent;
  61. json_text_detected = true;
  62. } else {
  63. return;
  64. }
  65. } else if (nodes[i].nodeType == Node.ELEMENT_NODE) {
  66. var tagName = nodes[i].tagName.toLowerCase();
  67. var html = $.trim(_unEscapeHTML($(nodes[i]).html()));
  68. // 如果是pre标签,则看内容是不是和source一样,一样则continue
  69. if(tagName === 'pre' && html === source) {
  70. continue;
  71. }
  72. // 如果用户安装迅雷或者其他的插件,也回破坏页面结构,需要兼容一下
  73. else if (tagName === 'embed' && nodes[i].offsetWidth === 0) {
  74. continue;
  75. } else {
  76. return;
  77. }
  78. } else {
  79. return;
  80. }
  81. }
  82. return source;
  83. };
  84. /**
  85. * 执行format操作
  86. * @private
  87. */
  88. var _format = function () {
  89. var source = _getJsonText();
  90. if(!source) {
  91. return;
  92. }
  93. // JSONP形式下的callback name
  94. var funcName = null;
  95. // json对象
  96. var jsonObj = null;
  97. // 下面校验给定字符串是否为一个合法的json
  98. try {
  99. jsonObj = new Function("return " + source)();
  100. // 还要防止下面这种情况: "{\"ret\":\"0\", \"msg\":\"ok\"}"
  101. if (typeof jsonObj == "string") {
  102. // 再来一次
  103. jsonObj = new Function("return " + jsonObj)();
  104. }
  105. } catch (ex) {
  106. // 再看看是不是jsonp的格式
  107. var reg = /^([\w\.]+)\(\s*([\s\S]*)\s*\)$/igm;
  108. var matches = reg.exec(source);
  109. if (matches == null) {
  110. return;
  111. }
  112. funcName = matches[1];
  113. source = matches[2];
  114. try {
  115. jsonObj = new Function("return " + source)();
  116. } catch (e) {
  117. return;
  118. }
  119. }
  120. // 是json格式,可以进行JSON自动格式化
  121. if (typeof jsonObj == "object") {
  122. try {
  123. // 要尽量保证格式化的东西一定是一个json,所以需要把内容进行JSON.stringify处理
  124. source = JSON.stringify(jsonObj);
  125. } catch (ex) {
  126. // 通过JSON反解不出来的,一定有问题
  127. return;
  128. }
  129. $('body').html(_htmlFragment);
  130. _loadCss();
  131. JsonFormatEntrance.clear();
  132. JsonFormatEntrance.format(source);
  133. // 如果是JSONP格式的,需要把方法名也显示出来
  134. if (funcName != null) {
  135. $('#jfCallbackName_start').html(funcName + '(');
  136. $('#jfCallbackName_end').html(')');
  137. }
  138. // 允许禁用
  139. $('#makeAutoJsonFormatOff').click(function (e) {
  140. baidu.feOption.setOptions({
  141. "opt_item_autojson":'false'
  142. });
  143. alert("以后可以从FeHelper的选项页面中重新开启");
  144. window.location.reload(true);
  145. });
  146. }
  147. };
  148. var _init = function () {
  149. $(function () {
  150. baidu.feOption.getOptions(["opt_item_autojson"], function (opts) {
  151. if (opts["opt_item_autojson"] != 'false') {
  152. _format();
  153. }
  154. });
  155. });
  156. };
  157. return {
  158. init:_init
  159. };
  160. })();
  161. baidu.csJsonFormat.init();