123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968 |
- /**
- * FeHelper Json Format Lib
- */
- let JsonFormatEntrance = (function () {
- "use strict";
- let jfContent,
- jfPre,
- jfStyleEl,
- jfOptEl,
- jfPathEl,
- formattingMsg;
- let lastKvovIdGiven = 0;
- let cachedJsonString = '';
- let _initElements = function () {
- jfContent = $('#jfContent');
- if (!jfContent[0]) {
- jfContent = $('<div id="jfContent" />').appendTo('body');
- }
- jfPre = $('#jfContent_pre');
- if (!jfPre[0]) {
- jfPre = $('<pre id="jfContent_pre" />').appendTo('body');
- }
- jfStyleEl = $('#jfStyleEl');
- if (!jfStyleEl[0]) {
- jfStyleEl = $('<style id="jfStyleEl" />').appendTo('head');
- }
- formattingMsg = $('#formattingMsg');
- if (!formattingMsg[0]) {
- formattingMsg = $('<div id="formattingMsg"><span class="x-loading"></span>格式化中...</div>').appendTo('body');
- }
- try {
- jfContent.html('').show();
- jfPre.html('').hide();
- jfPathEl && jfPathEl.hide();
- formattingMsg.hide();
- } catch (e) {
- }
- };
- // Add listener to receive response from BG when ready
- let postMessage = function (msg) {
- switch (msg[0]) {
- case 'NOT JSON' :
- jfPre.show();
- jfContent.html('<span class="x-json-tips">JSON不合法,请检查:</span>');
- break;
- case 'FORMATTING' :
- formattingMsg.show();
- break;
- case 'FORMATTED' :
- formattingMsg.hide();
- jfContent.html(msg[1]);
- _buildOptionBar();
- // 事件绑定
- _addEvents();
- // 支持文件下载
- _downloadSupport(cachedJsonString);
- break;
- default :
- throw new Error('Message not understood: ' + msg[0]);
- }
- };
- /**
- * HTML特殊字符格式化
- * @param str
- * @returns {*}
- */
- let htmlspecialchars = function (str) {
- str = str.replace(/&/g, '&');
- str = str.replace(/</g, '<');
- str = str.replace(/>/g, '>');
- str = str.replace(/"/g, '"');
- str = str.replace(/'/g, ''');
- return str;
- };
- /**
- * 执行代码格式化
- * @param {[type]} jsonStr [description]
- * @return {[type]}
- */
- let format = function (jsonStr) {
- cachedJsonString = JSON.stringify(JSON.parse(jsonStr), null, 4);
- _initElements();
- jfPre.html(htmlspecialchars(cachedJsonString));
- JsonFormatDealer.postMessage({
- type: "SENDING TEXT",
- text: jsonStr,
- length: jsonStr.length
- });
- };
- /**
- * 直接下载,能解决中文乱码
- * @param content
- * @private
- */
- let _downloadSupport = function (content) {
- // 下载链接
- let dt = (new Date()).format('yyyyMMddHHmmss');
- let blob = new Blob([content], {type: 'application/octet-stream'});
- let button = $('<button class="xjf-btn xjf-btn-right">下载JSON</button>').appendTo('#optionBar');
- if (typeof chrome === 'undefined' || !chrome.permissions) {
- button.click(function (e) {
- let aLink = $('#aLinkDownload');
- if (!aLink[0]) {
- aLink = $('<a id="aLinkDownload" target="_blank" title="保存到本地">下载JSON数据</a>').appendTo('body');
- aLink.attr('download', 'FeHelper-' + dt + '.json');
- aLink.attr('href', URL.createObjectURL(blob));
- }
- aLink[0].click();
- });
- } else {
- button.click(function (e) {
- // 请求权限
- chrome.permissions.request({
- permissions: ['downloads']
- }, (granted) => {
- if (granted) {
- chrome.downloads.download({
- url: URL.createObjectURL(blob),
- saveAs: true,
- conflictAction: 'overwrite',
- filename: 'FeHelper-' + dt + '.json'
- });
- } else {
- toast('必须接受授权,才能正常下载!');
- }
- });
- });
- }
- };
- /**
- * chrome 下复制到剪贴板
- * @param text
- */
- let _copyToClipboard = function (text) {
- let 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);
- toast('Json片段复制成功,随处粘贴可用!')
- };
- /**
- * 从el中获取json文本
- * @param el
- * @returns {string}
- */
- let getJsonText = function (el) {
- let 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) {
- }
- return txt;
- };
- /**
- * 给某个节点增加操作项
- * @param el
- * @private
- */
- let _addOptForItem = function (el) {
- // 下载json片段
- let fnDownload = function (ec) {
- let txt = getJsonText(el);
- // 下载片段
- let dt = (new Date()).format('yyyyMMddHHmmss');
- let blob = new Blob([txt], {type: 'application/octet-stream'});
- if (typeof chrome === 'undefined' || !chrome.permissions) {
- // 下载JSON的简单形式
- $(this).attr('download', 'FeHelper-' + dt + '.json').attr('href', URL.createObjectURL(blob));
- } else {
- // 请求权限
- chrome.permissions.request({
- permissions: ['downloads']
- }, (granted) => {
- if (granted) {
- chrome.downloads.download({
- url: URL.createObjectURL(blob),
- saveAs: true,
- conflictAction: 'overwrite',
- filename: 'FeHelper-' + dt + '.json'
- });
- } else {
- toast('必须接受授权,才能正常下载!');
- }
- });
- }
- };
- // 复制json片段
- let fnCopy = function (ec) {
- _copyToClipboard(getJsonText(el));
- };
- // 删除json片段
- let fnDel = function (ed) {
- if (el.parent().is('#formattedJson')) {
- toast('如果连最外层的Json也删掉的话,就没啥意义了哦!');
- return false;
- }
- toast('节点已删除成功!');
- el.remove();
- jfOptEl.css('top', -1000).hide();
- jfPathEl && jfPathEl.hide();
- };
- jfOptEl = $('#boxOpt');
- if (!jfOptEl.length) {
- jfOptEl = $('<div id="boxOpt"><a class="opt-download" target="_blank">下载</a>|<a class="opt-copy">复制</a>|<a class="opt-del">删除</a></div>').appendTo(jfContent);
- }
- jfOptEl.find('a.opt-download').unbind('click').bind('click', fnDownload);
- jfOptEl.find('a.opt-copy').unbind('click').bind('click', fnCopy);
- jfOptEl.find('a.opt-del').unbind('click').bind('click', fnDel);
- jfOptEl.css({
- left: el.offset().left + el.width() - 90,
- top: el.offset().top
- }).show();
- };
- /**
- * 折叠所有
- * @param elements
- */
- function collapse(elements) {
- let el;
- $.each(elements, function (i) {
- el = $(this);
- if (el.children('.blockInner').length) {
- el.addClass('collapsed');
- if (!el.attr('id')) {
- el.attr('id', 'kvov' + (++lastKvovIdGiven));
- let count = el.children('.blockInner').eq(0).children().length;
- // Generate comment text eg "4 items"
- let comment = count + (count === 1 ? ' item' : ' items');
- // Add CSS that targets it
- jfStyleEl[0].insertAdjacentHTML(
- 'beforeend',
- '\n#kvov' + lastKvovIdGiven + '.collapsed:after{color: #aaa; content:" // ' + comment + '"}'
- );
- }
- }
- });
- }
- /**
- * 创建几个全局操作的按钮,置于页面右上角即可
- * @private
- */
- let _buildOptionBar = function () {
- let optionBar = $('#optionBar');
- if (optionBar.length) {
- optionBar.html('');
- }else{
- optionBar = $('<span id="optionBar" />').appendTo(jfContent.parent());
- }
- $('<span class="x-split">|</span>').appendTo(optionBar);
- let buttonFormatted = $('<button class="xjf-btn xjf-btn-left">元数据</button>').appendTo(optionBar);
- let buttonCollapseAll = $('<button class="xjf-btn xjf-btn-mid">折叠所有</button>').appendTo(optionBar);
- let plainOn = false;
- buttonFormatted.bind('click', function (e) {
- if (plainOn) {
- plainOn = false;
- jfPre.hide();
- jfContent.show();
- buttonFormatted.text('元数据');
- } else {
- plainOn = true;
- jfPre.show();
- jfContent.hide();
- buttonFormatted.text('格式化');
- }
- jfOptEl && jfOptEl.hide();
- jfPathEl && jfPathEl.hide();
- });
- buttonCollapseAll.bind('click', function (e) {
- // 如果内容还没有格式化过,需要再格式化一下
- if (plainOn) {
- buttonFormatted.trigger('click');
- }
- if (buttonCollapseAll.text() === '折叠所有') {
- buttonCollapseAll.text('展开所有');
- collapse($('.objProp,.arrElem'));
- } else {
- buttonCollapseAll.text('折叠所有');
- $('.objProp,.arrElem').removeClass('collapsed');
- }
- jfOptEl && jfOptEl.hide();
- jfPathEl && jfPathEl.hide();
- });
- };
- // 显示当前节点的Key
- let _showJsonKey = function (curEl) {
- let keys = [];
- do {
- if (curEl.hasClass('arrElem')) {
- if (!curEl.hasClass('rootKvov')) {
- keys.unshift('[' + curEl.prevAll('.kvov').length + ']');
- }
- } else {
- keys.unshift(curEl.find('>.k').text());
- }
- if (curEl.parent().hasClass('rootKvov') || curEl.parent().parent().hasClass('rootKvov')) {
- break;
- }
- curEl = curEl.parent().parent();
- } while (curEl.length && !curEl.hasClass('rootKvov'));
- let path = keys.join('#@#').replace(/#@#\[/g, '[').replace(/#@#/g, '.');
- if (!jfPathEl) {
- jfPathEl = $('<div/>').css({
- position: 'fixed',
- bottom: 0,
- left: 0,
- background: 'rgb(0, 0, 0,0.6)',
- color: '#ff0',
- fontSize: '12px',
- fontWeight: 'bold',
- padding: '2px 10px 2px 2px',
- zIndex: 10
- }).appendTo('body');
- }
- jfPathEl.html('当前路径:' + path).show();
- };
- // 附加操作
- let _addEvents = function () {
- // 折叠、展开
- $('#jfContent span.e').bind('click', function (ev) {
- ev.preventDefault();
- let parentEl = $(this).parent();
- parentEl.toggleClass('collapsed');
- if (parentEl.hasClass('collapsed')) {
- collapse(parentEl);
- }
- });
- // 点击选中:高亮
- $('#jfContent .kvov').bind('click', function (e) {
- if ($(this).hasClass('x-outline')) {
- jfOptEl && jfOptEl.hide();
- jfPathEl && jfPathEl.hide();
- $(this).removeClass('x-outline');
- e.stopPropagation();
- return true;
- }
- $('.x-outline').removeClass('x-outline');
- let el = $(this).removeClass('x-hover').addClass('x-outline');
- // 增加复制、删除功能
- _addOptForItem(el);
- // 显示key
- _showJsonKey(el);
- if (!$(e.target).is('.kvov .e')) {
- e.stopPropagation();
- } else {
- $(e.target).parent().trigger('click');
- }
- // 触发钩子
- if (typeof window._OnJsonItemClickByFH === 'function') {
- window._OnJsonItemClickByFH(getJsonText(el));
- }
- }).bind('mouseover', function (e) {
- $(this).addClass('x-hover');
- return false;
- }).bind('mouseout', function (e) {
- $(this).removeClass('x-hover');
- });
- };
- return {
- format: format,
- postMessage: postMessage
- }
- })();
- let JsonFormatDealer = (function () {
- "use strict";
- // Constants
- let
- TYPE_STRING = 1,
- TYPE_NUMBER = 2,
- TYPE_OBJECT = 3,
- TYPE_ARRAY = 4,
- TYPE_BOOL = 5,
- TYPE_NULL = 6
- ;
- // Utility functions
- function removeComments(str) {
- str = ('__' + str + '__').split('');
- let mode = {
- singleQuote: false,
- doubleQuote: false,
- regex: false,
- blockComment: false,
- lineComment: false,
- condComp: false
- };
- for (let i = 0, l = str.length; i < l; i++) {
- if (mode.regex) {
- if (str[i] === '/' && str[i - 1] !== '\\') {
- mode.regex = false;
- }
- continue;
- }
- if (mode.singleQuote) {
- if (str[i] === "'" && str[i - 1] !== '\\') {
- mode.singleQuote = false;
- }
- continue;
- }
- if (mode.doubleQuote) {
- if (str[i] === '"' && str[i - 1] !== '\\') {
- mode.doubleQuote = false;
- }
- continue;
- }
- if (mode.blockComment) {
- if (str[i] === '*' && str[i + 1] === '/') {
- str[i + 1] = '';
- mode.blockComment = false;
- }
- str[i] = '';
- continue;
- }
- if (mode.lineComment) {
- if (str[i + 1] === '\n' || str[i + 1] === '\r') {
- mode.lineComment = false;
- }
- str[i] = '';
- continue;
- }
- if (mode.condComp) {
- if (str[i - 2] === '@' && str[i - 1] === '*' && str[i] === '/') {
- mode.condComp = false;
- }
- continue;
- }
- mode.doubleQuote = str[i] === '"';
- mode.singleQuote = str[i] === "'";
- if (str[i] === '/') {
- if (str[i + 1] === '*' && str[i + 2] === '@') {
- mode.condComp = true;
- continue;
- }
- if (str[i + 1] === '*') {
- str[i] = '';
- mode.blockComment = true;
- continue;
- }
- if (str[i + 1] === '/') {
- str[i] = '';
- mode.lineComment = true;
- continue;
- }
- mode.regex = true;
- }
- }
- return str.join('').slice(2, -2);
- }
- // Template elements
- let templates,
- baseDiv = document.createElement('div'),
- baseSpan = document.createElement('span');
- function getSpanBoth(innerText, className) {
- let span = baseSpan.cloneNode(false);
- span.className = className;
- span.innerText = innerText;
- return span;
- }
- function getSpanText(innerText) {
- let span = baseSpan.cloneNode(false);
- span.innerText = innerText;
- return span;
- }
- function getSpanClass(className) {
- let span = baseSpan.cloneNode(false);
- span.className = className;
- return span;
- }
- function getDivClass(className) {
- let span = baseDiv.cloneNode(false);
- span.className = className;
- return span;
- }
- // Create template nodes
- let templatesObj = {
- t_kvov: getDivClass('kvov'),
- t_key: getSpanClass('k'),
- t_string: getSpanClass('s'),
- t_number: getSpanClass('n'),
- t_exp: getSpanClass('e'),
- t_null: getSpanBoth('null', 'nl'),
- t_true: getSpanBoth('true', 'bl'),
- t_false: getSpanBoth('false', 'bl'),
- t_oBrace: getSpanBoth('{', 'b'),
- t_cBrace: getSpanBoth('}', 'b'),
- t_oBracket: getSpanBoth('[', 'b'),
- t_cBracket: getSpanBoth(']', 'b'),
- t_ellipsis: getSpanClass('ell'),
- t_blockInner: getSpanClass('blockInner'),
- t_colonAndSpace: document.createTextNode(':\u00A0'),
- t_commaText: document.createTextNode(','),
- t_dblqText: document.createTextNode('"')
- };
- // Core recursive DOM-building function
- function getKvovDOM(value, keyName) {
- let type,
- kvov,
- nonZeroSize,
- templates = templatesObj, // bring into scope for tiny speed boost
- objKey,
- keySpan,
- valueElement
- ;
- // Establish value type
- if (typeof value === 'string')
- type = TYPE_STRING;
- else if (typeof value === 'number')
- type = TYPE_NUMBER;
- else if (value === false || value === true)
- type = TYPE_BOOL;
- else if (value === null)
- type = TYPE_NULL;
- else if (value instanceof Array)
- type = TYPE_ARRAY;
- else
- type = TYPE_OBJECT;
- // Root node for this kvov
- kvov = templates.t_kvov.cloneNode(false);
- // Add an 'expander' first (if this is object/array with non-zero size)
- if (type === TYPE_OBJECT || type === TYPE_ARRAY) {
- if (typeof JSON.BigNumber === 'function' && value instanceof JSON.BigNumber) {
- value = JSON.stringify(value);
- type = TYPE_NUMBER;
- } else {
- nonZeroSize = false;
- for (objKey in value) {
- if (value.hasOwnProperty(objKey)) {
- nonZeroSize = true;
- break; // no need to keep counting; only need one
- }
- }
- if (nonZeroSize)
- kvov.appendChild(templates.t_exp.cloneNode(true));
- }
- }
- // If there's a key, add that before the value
- if (keyName !== false) { // NB: "" is a legal keyname in JSON
- // This kvov must be an object property
- kvov.classList.add('objProp');
- // Create a span for the key name
- keySpan = templates.t_key.cloneNode(false);
- keySpan.textContent = JSON.stringify(keyName).slice(1, -1); // remove quotes
- // Add it to kvov, with quote marks
- kvov.appendChild(templates.t_dblqText.cloneNode(false));
- kvov.appendChild(keySpan);
- kvov.appendChild(templates.t_dblqText.cloneNode(false));
- // Also add ": " (colon and non-breaking space)
- kvov.appendChild(templates.t_colonAndSpace.cloneNode(false));
- }
- else {
- // This is an array element instead
- kvov.classList.add('arrElem');
- }
- // Generate DOM for this value
- let blockInner, childKvov;
- switch (type) {
- case TYPE_STRING:
- // If string is a URL, get a link, otherwise get a span
- let innerStringEl = baseSpan.cloneNode(false),
- escapedString = JSON.stringify(value);
- escapedString = escapedString.substring(1, escapedString.length - 1); // remove quotes
- if (value[0] === 'h' && value.substring(0, 4) === 'http') { // crude but fast - some false positives, but rare, and UX doesn't suffer terribly from them.
- let innerStringA = document.createElement('A');
- innerStringA.href = value;
- innerStringA.innerText = escapedString;
- innerStringEl.appendChild(innerStringA);
- }
- else {
- innerStringEl.innerText = escapedString;
- }
- valueElement = templates.t_string.cloneNode(false);
- valueElement.appendChild(templates.t_dblqText.cloneNode(false));
- valueElement.appendChild(innerStringEl);
- valueElement.appendChild(templates.t_dblqText.cloneNode(false));
- kvov.appendChild(valueElement);
- break;
- case TYPE_NUMBER:
- // Simply add a number element (span.n)
- valueElement = templates.t_number.cloneNode(false);
- valueElement.innerText = value;
- kvov.appendChild(valueElement);
- break;
- case TYPE_OBJECT:
- // Add opening brace
- kvov.appendChild(templates.t_oBrace.cloneNode(true));
- // If any properties, add a blockInner containing k/v pair(s)
- if (nonZeroSize) {
- // Add ellipsis (empty, but will be made to do something when kvov is collapsed)
- kvov.appendChild(templates.t_ellipsis.cloneNode(false));
- // Create blockInner, which indents (don't attach yet)
- blockInner = templates.t_blockInner.cloneNode(false);
- // For each key/value pair, add as a kvov to blockInner
- let count = 0, k, comma;
- for (k in value) {
- if (value.hasOwnProperty(k)) {
- count++;
- childKvov = getKvovDOM(value[k], k);
- // Add comma
- comma = templates.t_commaText.cloneNode();
- childKvov.appendChild(comma);
- blockInner.appendChild(childKvov);
- }
- }
- // Now remove the last comma
- childKvov.removeChild(comma);
- // Add blockInner
- kvov.appendChild(blockInner);
- }
- // Add closing brace
- kvov.appendChild(templates.t_cBrace.cloneNode(true));
- break;
- case TYPE_ARRAY:
- // Add opening bracket
- kvov.appendChild(templates.t_oBracket.cloneNode(true));
- // If non-zero length array, add blockInner containing inner vals
- if (nonZeroSize) {
- // Add ellipsis
- kvov.appendChild(templates.t_ellipsis.cloneNode(false));
- // Create blockInner (which indents) (don't attach yet)
- blockInner = templates.t_blockInner.cloneNode(false);
- // For each key/value pair, add the markup
- for (let i = 0, length = value.length, lastIndex = length - 1; i < length; i++) {
- // Make a new kvov, with no key
- childKvov = getKvovDOM(value[i], false);
- // Add comma if not last one
- if (i < lastIndex)
- childKvov.appendChild(templates.t_commaText.cloneNode());
- // Append the child kvov
- blockInner.appendChild(childKvov);
- }
- // Add blockInner
- kvov.appendChild(blockInner);
- }
- // Add closing bracket
- kvov.appendChild(templates.t_cBracket.cloneNode(true));
- break;
- case TYPE_BOOL:
- if (value)
- kvov.appendChild(templates.t_true.cloneNode(true));
- else
- kvov.appendChild(templates.t_false.cloneNode(true));
- break;
- case TYPE_NULL:
- kvov.appendChild(templates.t_null.cloneNode(true));
- break;
- }
- return kvov;
- }
- // Function to convert object to an HTML string
- function jsonObjToHTML(obj, jsonpFunctionName) {
- // Format object (using recursive kvov builder)
- let rootKvov = getKvovDOM(obj, false);
- // The whole DOM is now built.
- // Set class on root node to identify it
- rootKvov.classList.add('rootKvov');
- // Make div#formattedJson and append the root kvov
- let divFormattedJson = document.createElement('DIV');
- divFormattedJson.id = 'formattedJson';
- divFormattedJson.appendChild(rootKvov);
- // Convert it to an HTML string (shame about this step, but necessary for passing it through to the content page)
- let returnHTML = divFormattedJson.outerHTML;
- // Top and tail with JSONP padding if necessary
- if (jsonpFunctionName !== null) {
- returnHTML =
- '<div id="jsonpOpener">' + jsonpFunctionName + ' ( </div>' +
- returnHTML +
- '<div id="jsonpCloser">)</div>';
- }
- // Return the HTML
- return returnHTML;
- }
- // Listen for requests from content pages wanting to set up a port
- let postMessage = function (msg) {
- let jsonpFunctionName = null;
- if (msg.type === 'SENDING TEXT') {
- // Try to parse as JSON
- let obj,
- text = msg.text;
- try {
- obj = JSON.parse(text);
- }
- catch (e) {
- // Not JSON; could be JSONP though.
- // Try stripping 'padding' (if any), and try parsing it again
- text = text.trim();
- // Find where the first paren is (and exit if none)
- let indexOfParen;
- if (!(indexOfParen = text.indexOf('('))) {
- JsonFormatEntrance.postMessage(['NOT JSON', 'no opening parenthesis']);
- return;
- }
- // Get the substring up to the first "(", with any comments/whitespace stripped out
- let firstBit = removeComments(text.substring(0, indexOfParen)).trim();
- if (!firstBit.match(/^[a-zA-Z_$][\.\[\]'"0-9a-zA-Z_$]*$/)) {
- // The 'firstBit' is NOT a valid function identifier.
- JsonFormatEntrance.postMessage(['NOT JSON', 'first bit not a valid function name']);
- return;
- }
- // Find last parenthesis (exit if none)
- let indexOfLastParen;
- if (!(indexOfLastParen = text.lastIndexOf(')'))) {
- JsonFormatEntrance.postMessage(['NOT JSON', 'no closing paren']);
- return;
- }
- // Check that what's after the last parenthesis is just whitespace, comments, and possibly a semicolon (exit if anything else)
- let lastBit = removeComments(text.substring(indexOfLastParen + 1)).trim();
- if (lastBit !== "" && lastBit !== ';') {
- JsonFormatEntrance.postMessage(['NOT JSON', 'last closing paren followed by invalid characters']);
- return;
- }
- // So, it looks like a valid JS function call, but we don't know whether it's JSON inside the parentheses...
- // Check if the 'argument' is actually JSON (and record the parsed result)
- text = text.substring(indexOfParen + 1, indexOfLastParen);
- try {
- obj = JSON.parse(text);
- }
- catch (e2) {
- // Just some other text that happens to be in a function call.
- // Respond as not JSON, and exit
- JsonFormatEntrance.postMessage(['NOT JSON', 'looks like a function call, but the parameter is not valid JSON']);
- return;
- }
- jsonpFunctionName = firstBit;
- }
- // If still running, we now have obj, which is valid JSON.
- // Ensure it's not a number or string (technically valid JSON, but no point prettifying it)
- if (typeof obj !== 'object' && typeof obj !== 'array') {
- JsonFormatEntrance.postMessage(['NOT JSON', 'technically JSON but not an object or array']);
- return;
- }
- JsonFormatEntrance.postMessage(['FORMATTING']);
- try {
- // 有的页面设置了 安全策略,连localStorage都不能用,setTimeout开启多线程就更别说了
- localStorage.getItem('just test : Blocked script execution in xxx?');
- // 在非UI线程中操作:异步。。。
- setTimeout(function () {
- // Do formatting
- let html = jsonObjToHTML(obj, jsonpFunctionName);
- // Post the HTML string to the content script
- JsonFormatEntrance.postMessage(['FORMATTED', html]);
- }, 0);
- } catch (ex) {
- // 错误信息类似:Failed to read the 'localStorage' property from 'Window': The document is sandboxed and lacks the 'allow-same-origin' flag.
- let html = jsonObjToHTML(obj, jsonpFunctionName);
- JsonFormatEntrance.postMessage(['FORMATTED', html]);
- }
- }
- };
- return {
- postMessage: postMessage
- };
- })();
- window.Formatter = {
- format: JsonFormatEntrance.format
- };
- /**
- * 日期格式化
- * @param {Object} pattern
- */
- Date.prototype.format = function (pattern) {
- let pad = function (source, length) {
- let pre = "",
- negative = (source < 0),
- string = String(Math.abs(source));
- if (string.length < length) {
- pre = (new Array(length - string.length + 1)).join('0');
- }
- return (negative ? "-" : "") + pre + string;
- };
- if ('string' !== typeof pattern) {
- return this.toString();
- }
- let replacer = function (patternPart, result) {
- pattern = pattern.replace(patternPart, result);
- };
- let year = this.getFullYear(),
- month = this.getMonth() + 1,
- date2 = this.getDate(),
- hours = this.getHours(),
- minutes = this.getMinutes(),
- seconds = this.getSeconds(),
- milliSec = this.getMilliseconds();
- replacer(/yyyy/g, pad(year, 4));
- replacer(/yy/g, pad(parseInt(year.toString().slice(2), 10), 2));
- replacer(/MM/g, pad(month, 2));
- replacer(/M/g, month);
- replacer(/dd/g, pad(date2, 2));
- replacer(/d/g, date2);
- replacer(/HH/g, pad(hours, 2));
- replacer(/H/g, hours);
- replacer(/hh/g, pad(hours % 12, 2));
- replacer(/h/g, hours % 12);
- replacer(/mm/g, pad(minutes, 2));
- replacer(/m/g, minutes);
- replacer(/ss/g, pad(seconds, 2));
- replacer(/s/g, seconds);
- replacer(/SSS/g, pad(milliSec, 3));
- replacer(/S/g, milliSec);
- return pattern;
- };
- /**
- * 自动消失的Alert弹窗
- * @param content
- */
- window.toast = function (content) {
- window.clearTimeout(window.feHelperAlertMsgTid);
- let elAlertMsg = document.querySelector("#fehelper_alertmsg");
- if (!elAlertMsg) {
- let elWrapper = document.createElement('div');
- elWrapper.innerHTML = '<div id="fehelper_alertmsg" style="position:fixed;top:5px;right:5px;z-index:1000000">' +
- '<p style="background:#000;display:inline-block;color:#fff;text-align:center;' +
- 'padding:10px 10px;margin:0 auto;font-size:14px;border-radius:4px;">' + content + '</p></div>';
- elAlertMsg = elWrapper.childNodes[0];
- document.body.appendChild(elAlertMsg);
- } else {
- elAlertMsg.querySelector('p').innerHTML = content;
- elAlertMsg.style.display = 'block';
- }
- window.feHelperAlertMsgTid = window.setTimeout(function () {
- elAlertMsg.style.display = 'none';
- }, 3000);
- };
|