123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331 |
- /**
- * content_scripts中如果被检测到当前页面内容为json数据,则自动进行JSON格式化
- */
- baidu.csJsonFormat = (function () {
- "use strict";
- var _htmlFragment = [
- '<div class="mod-json mod-contentscript"><div class="rst-item">',
- '<div id="formattingMsg">',
- '<svg id="spinner" width="16" height="16" viewBox="0 0 300 300" xmlns="http://www.w3.org/2000/svg" version="1.1">',
- '<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>',
- '</svg>加载中...',
- '</div>',
- '<div id="jfCallbackName_start" class="callback-name"></div>',
- '<div id="jfContent"></div>',
- '<pre id="jfContent_pre"></pre>',
- '<div id="jfCallbackName_end" class="callback-name"></div>',
- '</div></div>'
- ].join('');
- var _loadCss = function () {
- var fcpCss = chrome.extension.getURL('static/css/fe-jsonformat-content.css');
- jQuery('<link id="_fehelper_fcp_css_" href="' + fcpCss + '" rel="stylesheet" type="text/css" />').appendTo('head');
- };
- /**
- * 从页面提取JSON文本
- * @returns {string}
- * @private
- */
- var _getJsonText = function () {
- var pre = $('body>pre:eq(0)')[0] || {textContent: ""};
- var source = $.trim(pre.textContent);
- if (!source) {
- source = $.trim(document.body.textContent || '')
- }
- if (!source) {
- return false;
- }
- // 如果body的内容还包含HTML标签,肯定不是合法的json了
- // 如果是合法的json,也只可能有一个text节点
- var nodes = document.body.childNodes;
- var newSource = '';
- for (var i = 0, len = nodes.length; i < len; i++) {
- if (nodes[i].nodeType == Node.TEXT_NODE) {
- newSource += nodes[i].textContent;
- } else if (nodes[i].nodeType == Node.ELEMENT_NODE) {
- var tagName = nodes[i].tagName.toLowerCase();
- var html = $.trim(nodes[i].textContent);
- // 如果是pre标签,则看内容是不是和source一样,一样则continue
- if (tagName === 'pre' && html === source) {
- continue;
- } else if ((nodes[i].offsetWidth === 0 || nodes[i].offsetHeight === 0 || !html) && ['script', 'link'].indexOf(tagName) == -1) {
- // 如果用户安装迅雷或者其他的插件,也回破坏页面结构,需要兼容一下
- continue;
- } else {
- return false;
- }
- } else {
- return false;
- }
- }
- return $.trim(newSource || '') || source;
- };
- /**
- * 此方法用于将Unicode码解码为正常字符串
- * @param {Object} text
- */
- var _uniDecode = function (text) {
- text = text.replace(/\\/g, "%").replace('%U', '%u').replace('%u0025', '%25');
- text = unescape(text.toString().replace(/%2B/g, "+"));
- var matches = text.match(/(%u00([0-9A-F]{2}))/gi);
- if (matches) {
- for (var matchid = 0; matchid < matches.length; matchid++) {
- var code = matches[matchid].substring(1, 3);
- var x = Number("0x" + code);
- if (x >= 128) {
- text = text.replace(matches[matchid], code);
- }
- }
- }
- text = unescape(text.toString().replace(/%2B/g, "+"));
- return text;
- };
- /**
- * chrome 下复制到剪贴板
- * @param text
- */
- var _copyToClipboard = function (text) {
- var input = document.createElement('textarea');
- input.style.position = 'fixed';
- input.style.opacity = 0;
- input.value = text;
- document.body.appendChild(input);
- input.select();
- document.execCommand('Copy');
- document.body.removeChild(input);
- alert('Json片段复制成功,随处粘贴可用!')
- };
- /**
- * 给某个节点增加操作项
- * @param el
- * @private
- */
- var _addOptForItem = function (el) {
- // 下载json片段
- var fnDownload = function (ec) {
- var txt = el.text().replace(/":\s/gm, '":').replace(/,$/, '').trim();
- if (!(/^{/.test(txt) && /\}$/.test(txt)) && !(/^\[/.test(txt) && /\]$/.test(txt))) {
- txt = '{' + txt + '}';
- }
- try {
- txt = JSON.stringify(JSON.parse(txt), null, 4);
- } catch (err) {
- }
- // 下载片段
- var dt = (new Date()).format('yyyyMMddHHmmss');
- var blob = new Blob([txt], {type: 'application/octet-stream'});
- $(this).attr('download', 'FeHelper-' + dt + '.json').attr('href', URL.createObjectURL(blob));
- };
- // 复制json片段
- var fnCopy = function (ec) {
- var txt = el.text().replace(/":\s/gm, '":').replace(/,$/, '').trim();
- if (!(/^{/.test(txt) && /\}$/.test(txt)) && !(/^\[/.test(txt) && /\]$/.test(txt))) {
- txt = '{' + txt + '}';
- }
- try {
- txt = JSON.stringify(JSON.parse(txt), null, 4);
- } catch (err) {
- }
- _copyToClipboard(txt);
- };
- // 删除json片段
- var fnDel = function (ed) {
- if (el.parent().is('#formattedJson')) {
- alert('如果连最外层的Json也删掉的话,就没啥意义了哦!');
- return false;
- }
- alert('节点已删除成功!');
- el.remove();
- boxOpt.css('top', -1000).hide();
- };
- var boxOpt = $('#boxOpt');
- if (!boxOpt.length) {
- boxOpt = $('<div id="boxOpt"><a class="opt-download" target="_blank">下载</a>|<a class="opt-copy">复制</a>|<a class="opt-del">删除</a></div>').appendTo('body');
- }
- boxOpt.find('a.opt-download').unbind('click').bind('click', fnDownload);
- boxOpt.find('a.opt-copy').unbind('click').bind('click', fnCopy);
- boxOpt.find('a.opt-del').unbind('click').bind('click', fnDel);
- boxOpt.css({
- left: el.offset().left + el.width() - 90,
- top: el.offset().top
- }).show();
- };
- /**
- * 事件绑定
- * @private
- */
- var _bindEvent = function () {
- // 点击区块高亮
- $('#jfContent').delegate('.kvov', 'click', function (e) {
- if($(this).hasClass('x-outline')) {
- $('#boxOpt').remove();
- $(this).removeClass('x-outline');
- return false;
- }
- $('#jfContent .kvov').removeClass('x-outline');
- var el = $(this).removeClass('x-hover').addClass('x-outline');
- // 增加复制、删除功能
- _addOptForItem(el);
- if (!$(e.target).is('.kvov .e')) {
- e.stopPropagation();
- } else {
- $(e.target).parent().trigger('click');
- }
- }).delegate('.kvov', 'mouseover', function (e) {
- $(this).addClass('x-hover');
- return false;
- }).delegate('.kvov', 'mouseout', function (e) {
- $(this).removeClass('x-hover');
- });
- };
- /**
- * 执行format操作
- * @private
- */
- var _format = function () {
- var source = _getJsonText();
- if (!source) {
- return;
- }
- // JSONP形式下的callback name
- var funcName = null;
- // json对象
- var jsonObj = null;
- var newSource = source;
- var fnTry = null;
- var fnCatch = null;
- // 下面校验给定字符串是否为一个合法的json
- try {
- // 再看看是不是jsonp的格式
- var reg = /^([\w\.]+)\(\s*([\s\S]*)\s*\)$/gm;
- var reTry = /^(try\s*\{\s*)?/g;
- var reCatch = /(\}\s*catch\s*\(\s*\S+\s*\)\s*\{([\s\S])*\})?$/g;
- // 检测是否有try-catch包裹
- var sourceReplaced = source.replace(reTry, function () {
- fnTry = fnTry ? fnTry : arguments[1];
- return '';
- }).replace(reCatch, function () {
- fnCatch = fnCatch ? fnCatch : arguments[1];
- return '';
- }).trim();
- var matches = reg.exec(sourceReplaced);
- if (matches != null && (fnTry && fnCatch || !fnTry && !fnCatch)) {
- funcName = matches[1];
- newSource = matches[2];
- jsonObj = new Function("return " + newSource)();
- } else {
- reg = /^([\{\[])/;
- if (!reg.test(source)) {
- return;
- }
- }
- // 强化验证
- if (jsonObj == null || typeof jsonObj != 'object') {
- jsonObj = new Function("return " + source)();
- // 还要防止下面这种情况: "{\"ret\":\"0\", \"msg\":\"ok\"}"
- if (typeof jsonObj == "string") {
- // 再来一次
- jsonObj = new Function("return " + jsonObj)();
- }
- }
- } catch (ex) {
- return;
- }
- // 是json格式,可以进行JSON自动格式化
- if (jsonObj != null && typeof jsonObj == "object") {
- try {
- // 要尽量保证格式化的东西一定是一个json,所以需要把内容进行JSON.stringify处理
- var jsonStr = JSON.stringify(jsonObj);
- // 如果newSource的长度比原source长度短很多的话,猜测应该是格式化错了,需要撤销操作
- // 这里一定要unicode decode一下,要不然会出现误判
- var len1 = jsonStr.replace(/'|"|\s/g, '').length;
- var len2 = (_uniDecode(newSource)).replace(/'|"|\s/g, '').length;
- // 误差不允许超过20%
- if (Math.abs(len1 - len2) / ((len1 + len2) / 2) > 0.2) {
- return;
- }
- newSource = jsonStr;
- } catch (ex) {
- // 通过JSON反解不出来的,一定有问题
- return;
- }
- $('body').html(_htmlFragment);
- _loadCss();
- _bindEvent();
- JsonFormatEntrance.clear();
- JsonFormatEntrance.format(newSource);
- // 如果是JSONP格式的,需要把方法名也显示出来
- if (funcName != null) {
- if (fnTry && fnCatch) {
- $('#jfCallbackName_start').html('<pre style="padding:0">' + fnTry + '</pre>' + funcName + '(');
- $('#jfCallbackName_end').html(')<br><pre style="padding:0">' + fnCatch + '</pre>');
- } else {
- $('#jfCallbackName_start').html(funcName + '(');
- $('#jfCallbackName_end').html(')');
- }
- }
- }
- };
- var _init = function () {
- $(function () {
- if (baidu.feOption.pageJsonMustFormat) {
- _format();
- } else {
- chrome.extension.sendMessage({
- type: MSG_TYPE.GET_OPTIONS,
- items: ['JSON_PAGE_FORMAT']
- }, function (opts) {
- if (!opts || opts.JSON_PAGE_FORMAT != 'false') {
- _format();
- }
- });
- }
- });
- };
- return {
- init: _init
- };
- })();
- baidu.csJsonFormat.init();
|