├── .editorconfig ├── .gitignore ├── README.md ├── dist ├── app.js ├── background.js ├── devtoolsBackground.html ├── devtoolsBackground.js ├── images │ ├── 128.png │ ├── 16.png │ ├── 32.png │ └── 48.png ├── list-items │ ├── end.svg │ ├── mid.svg │ ├── none.svg │ └── start.svg ├── manifest.json ├── panel.html └── styles.css ├── package-lock.json ├── package.json ├── src ├── app.js └── assets │ ├── background.js │ ├── devtoolsBackground.html │ ├── devtoolsBackground.js │ ├── images │ ├── 128.png │ ├── 16.png │ ├── 32.png │ └── 48.png │ ├── list-items │ ├── end.svg │ ├── mid.svg │ ├── none.svg │ └── start.svg │ ├── manifest.json │ ├── panel.html │ └── styles.css ├── store.data ├── 1280x800.png ├── 128x128.png ├── 440x280.jpg ├── 440x280.png ├── description.txt └── dist.zip └── webpack.config.js /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | 3 | root = true 4 | 5 | [*] 6 | charset = utf-8 7 | indent_style = space 8 | indent_size = 2 9 | end_of_line = lf 10 | insert_final_newline = true 11 | trim_trailing_whitespace = true 12 | 13 | [*.md] 14 | insert_final_newline = false 15 | trim_trailing_whitespace = false 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | JSON-RPC Viewer is an extension to help viewing JSON-RPC requests in a more convenient way than Network tab allows. 2 | You can view a list of requests with method name, params and result/response. 3 | Supports JSON-RPC batch requests from version 1.1.1 4 | 5 | Feature requests, bug reports and pull requests are welcome here: https://github.com/kityan/json-rpc-viewer. 6 | 7 | You can install it from Chrome Web Store: https://chrome.google.com/webstore/detail/json-rpc-viewer/hnmcofcmhpllkdkncnofkjdlpieagngg. -------------------------------------------------------------------------------- /dist/app.js: -------------------------------------------------------------------------------- 1 | /******/ (function(modules) { // webpackBootstrap 2 | /******/ // The module cache 3 | /******/ var installedModules = {}; 4 | /******/ 5 | /******/ // The require function 6 | /******/ function __webpack_require__(moduleId) { 7 | /******/ 8 | /******/ // Check if module is in cache 9 | /******/ if(installedModules[moduleId]) { 10 | /******/ return installedModules[moduleId].exports; 11 | /******/ } 12 | /******/ // Create a new module (and put it into the cache) 13 | /******/ var module = installedModules[moduleId] = { 14 | /******/ i: moduleId, 15 | /******/ l: false, 16 | /******/ exports: {} 17 | /******/ }; 18 | /******/ 19 | /******/ // Execute the module function 20 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); 21 | /******/ 22 | /******/ // Flag the module as loaded 23 | /******/ module.l = true; 24 | /******/ 25 | /******/ // Return the exports of the module 26 | /******/ return module.exports; 27 | /******/ } 28 | /******/ 29 | /******/ 30 | /******/ // expose the modules object (__webpack_modules__) 31 | /******/ __webpack_require__.m = modules; 32 | /******/ 33 | /******/ // expose the module cache 34 | /******/ __webpack_require__.c = installedModules; 35 | /******/ 36 | /******/ // define getter function for harmony exports 37 | /******/ __webpack_require__.d = function(exports, name, getter) { 38 | /******/ if(!__webpack_require__.o(exports, name)) { 39 | /******/ Object.defineProperty(exports, name, { 40 | /******/ configurable: false, 41 | /******/ enumerable: true, 42 | /******/ get: getter 43 | /******/ }); 44 | /******/ } 45 | /******/ }; 46 | /******/ 47 | /******/ // getDefaultExport function for compatibility with non-harmony modules 48 | /******/ __webpack_require__.n = function(module) { 49 | /******/ var getter = module && module.__esModule ? 50 | /******/ function getDefault() { return module['default']; } : 51 | /******/ function getModuleExports() { return module; }; 52 | /******/ __webpack_require__.d(getter, 'a', getter); 53 | /******/ return getter; 54 | /******/ }; 55 | /******/ 56 | /******/ // Object.prototype.hasOwnProperty.call 57 | /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; 58 | /******/ 59 | /******/ // __webpack_public_path__ 60 | /******/ __webpack_require__.p = ""; 61 | /******/ 62 | /******/ // Load entry module and return exports 63 | /******/ return __webpack_require__(__webpack_require__.s = 1); 64 | /******/ }) 65 | /************************************************************************/ 66 | /******/ ([ 67 | /* 0 */ 68 | /***/ (function(module, exports) { 69 | 70 | var g; 71 | 72 | // This works in non-strict mode 73 | g = (function() { 74 | return this; 75 | })(); 76 | 77 | try { 78 | // This works if eval is allowed (see CSP) 79 | g = g || Function("return this")() || (1,eval)("this"); 80 | } catch(e) { 81 | // This works if the window reference is available 82 | if(typeof window === "object") 83 | g = window; 84 | } 85 | 86 | // g can still be undefined, but nothing to do about it... 87 | // We return undefined, instead of nothing here, so it's 88 | // easier to handle this case. if(!global) { ...} 89 | 90 | module.exports = g; 91 | 92 | 93 | /***/ }), 94 | /* 1 */ 95 | /***/ (function(module, __webpack_exports__, __webpack_require__) { 96 | 97 | "use strict"; 98 | Object.defineProperty(__webpack_exports__, "__esModule", { value: true }); 99 | /* WEBPACK VAR INJECTION */(function(setImmediate) {/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_json_formatter_js__ = __webpack_require__(5); 100 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_json_formatter_js___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_json_formatter_js__); 101 | 102 | 103 | const body = document.getElementsByTagName('body') 104 | const left = document.getElementById('left') 105 | const right = document.getElementById('right') 106 | const params = document.getElementById('params') 107 | const table = document.getElementById('table') 108 | const helpPopup = document.getElementById('helpPopup') 109 | const divParamsViewer = document.getElementById('params_json_viewer') 110 | const divResultErrorViewer = document.getElementById('resultError_json_viewer') 111 | const leftResizer = document.getElementById('left_resizer') 112 | const paramsResizer = document.getElementById('params_resizer') 113 | const resetLayoutBtn = document.getElementById('reset_layout') 114 | const opts = {animateOpen: false, animateClose: false} 115 | const currentTheme = chrome.devtools.panels.themeName 116 | 117 | let trClass = 1; 118 | 119 | // add theme class name 120 | if (currentTheme && body.length > 0) { 121 | body[0].classList.add('theme-' + currentTheme) 122 | } 123 | 124 | loadLayout() 125 | 126 | // clear log 127 | document.getElementById('clear').addEventListener('click', () => { 128 | divParamsViewer.innerHTML = '' 129 | divResultErrorViewer.innerHTML = '' 130 | Array.from(table.childNodes).forEach((node, index) => index > 1 && table.removeChild(node)) 131 | }) 132 | 133 | // show help 134 | document.getElementById('help').addEventListener('click', () => helpPopup.classList.remove('hidden')) 135 | document.getElementById('closeHelp').addEventListener('click', () => helpPopup.classList.add('hidden')) 136 | 137 | // process finished request 138 | chrome.devtools.network.onRequestFinished.addListener(request => { 139 | if ( 140 | request.request && 141 | request.request.postData && 142 | request.request.postData.mimeType && 143 | request.request.postData.mimeType.match(/application\/json/) && 144 | request.request.postData.text && request.request.postData.text.match(/jsonrpc/) 145 | ) { 146 | request.getContent(body => { 147 | // [+] add check for spec? 148 | const responseJSON = JSON.parse(body) 149 | const requestJSON = JSON.parse(request.request.postData.text) 150 | // [+] add check for equal length? 151 | 152 | const isBatch = Array.isArray(requestJSON) && Array.isArray(responseJSON) 153 | if (!isBatch) { 154 | addListItem(request, requestJSON, responseJSON) 155 | } else { 156 | const reponseJSONIndex = responseJSON.reduce((obj, item) => { 157 | obj[item.id] = item; 158 | return obj 159 | }, {}) 160 | // [+] add check and warning for: id duplication? absent id? 161 | for (let i = 0; i < requestJSON.length; i++) { 162 | const inBatch = i == 0 ? 'start' : (i == requestJSON.length - 1 ? 'end' : 'mid') 163 | addListItem(request, requestJSON[i], reponseJSONIndex[requestJSON[i].id], inBatch, requestJSON.length) 164 | } 165 | } 166 | 167 | }) 168 | } 169 | }) 170 | 171 | 172 | function addListItem(request, requestJSON, responseJSON, inBatch, batchSize) { 173 | 174 | const tr = document.createElement('tr') 175 | tr.classList.add(trClass > 0 ? 'even' : 'odd') 176 | trClass *= -1 177 | 178 | const td1 = document.createElement('td') 179 | 180 | if (responseJSON) { 181 | td1.classList.add(responseJSON && responseJSON.hasOwnProperty && responseJSON.hasOwnProperty('result') ? 'ok' : 'error') 182 | } else { 183 | td1.classList.add('reponseNotParsed') 184 | } 185 | 186 | const td2 = document.createElement('td') 187 | const td3 = document.createElement('td') 188 | tr.appendChild(td1) 189 | tr.appendChild(td2) 190 | tr.appendChild(td3) 191 | 192 | 193 | const wasScrolledToBottom = left.clientHeight + Math.ceil(left.scrollTop) >= left.scrollHeight 194 | table.appendChild(tr) 195 | if (wasScrolledToBottom) { 196 | setImmediate(() => left.scrollTop = left.scrollHeight - left.clientHeight) 197 | } 198 | 199 | 200 | tr.addEventListener('click', event => { 201 | Array.from(document.getElementsByTagName('tr')).forEach(el => el.classList.remove('selected')) 202 | event.currentTarget.classList.add('selected') 203 | let formatter1 204 | if (requestJSON && requestJSON.hasOwnProperty && requestJSON.hasOwnProperty('params')) { 205 | formatter1 = new __WEBPACK_IMPORTED_MODULE_0_json_formatter_js___default.a(requestJSON.params, 1, opts) 206 | } 207 | // [?] too large responses are not available 208 | let formatter2 209 | if (responseJSON && responseJSON.hasOwnProperty) { 210 | if (responseJSON.hasOwnProperty('result')) { 211 | formatter2 = new __WEBPACK_IMPORTED_MODULE_0_json_formatter_js___default.a(responseJSON.result, 1, opts) 212 | } 213 | if (responseJSON.hasOwnProperty('error')) { 214 | formatter2 = new __WEBPACK_IMPORTED_MODULE_0_json_formatter_js___default.a(responseJSON.error, 1, opts) 215 | } 216 | } 217 | divParamsViewer.innerHTML = '' 218 | if (formatter1) { 219 | divParamsViewer.appendChild(formatter1.render()) 220 | } 221 | divResultErrorViewer.innerHTML = '' 222 | if (formatter2) { 223 | divResultErrorViewer.appendChild(formatter2.render()) 224 | } 225 | }) 226 | 227 | const time = Number.isFinite(request.time) ? Math.round(request.time) : '' 228 | const size = request.response && request.response.content && request.response.content.size 229 | 230 | td1.innerHTML = requestJSON.method 231 | td1.classList.add('methodName') 232 | if (inBatch) { 233 | td1.classList.add('inBatch_' + inBatch) 234 | if (inBatch === 'start') { 235 | td2.innerText = time 236 | td3.innerText = size 237 | } else { 238 | td2.innerText = ' ' 239 | td3.innerText = ' ' 240 | } 241 | } else { 242 | td2.innerText = time 243 | td3.innerText = size 244 | } 245 | 246 | } 247 | 248 | leftResizer.addEventListener('mousedown', function (e) { 249 | document.addEventListener('mousemove', resizeLeftDiv) 250 | document.addEventListener('mouseup', stopResizeLeftDiv) 251 | document.addEventListener('mouseleave', stopResizeLeftDiv) 252 | }) 253 | 254 | function loadLayout() { 255 | const leftWidth = localStorage.getItem('left-width') 256 | const paramsHeight = localStorage.getItem('params-height') 257 | 258 | left.style.width = leftWidth ? leftWidth : '50%'; 259 | params.style.height = paramsHeight ? paramsHeight : '25%'; 260 | 261 | if (leftWidth || paramsHeight) { 262 | resetLayoutBtn.style.display = 'inherit' 263 | } else { 264 | resetLayoutBtn.style.display = 'none' 265 | } 266 | } 267 | 268 | /** 269 | * @param {MouseEvent} e 270 | */ 271 | function resizeLeftDiv(e) { 272 | left.style.width = (e.pageX / body[0].clientWidth) * 100 + '%'; 273 | localStorage.setItem('left-width', left.style.width) 274 | resetLayoutBtn.style.display = 'inherit' 275 | } 276 | 277 | function stopResizeLeftDiv() { 278 | document.removeEventListener('mousemove', resizeLeftDiv) 279 | document.removeEventListener('mouseup', stopResizeLeftDiv) 280 | document.removeEventListener('mouseleave', stopResizeLeftDiv) 281 | } 282 | 283 | paramsResizer.addEventListener('mousedown', function (e) { 284 | document.addEventListener('mousemove', resizeParamsDiv) 285 | document.addEventListener('mouseup', stopResizeParamsDiv) 286 | document.addEventListener('mouseleave', stopResizeParamsDiv) 287 | }) 288 | 289 | /** 290 | * @param {MouseEvent} e 291 | */ 292 | function resizeParamsDiv(e) { 293 | let rightRect = right.getBoundingClientRect() 294 | params.style.height = ((e.pageY - rightRect.top) / rightRect.height) * 100 + '%'; 295 | localStorage.setItem('params-height', params.style.height) 296 | resetLayoutBtn.style.display = 'inherit' 297 | } 298 | 299 | function stopResizeParamsDiv() { 300 | document.removeEventListener('mousemove', resizeParamsDiv) 301 | document.removeEventListener('mouseup', stopResizeParamsDiv) 302 | document.removeEventListener('mouseleave', stopResizeParamsDiv) 303 | } 304 | 305 | resetLayoutBtn.addEventListener('click', function () { 306 | localStorage.removeItem('params-height') 307 | localStorage.removeItem('left-width') 308 | loadLayout() 309 | }) 310 | 311 | /* WEBPACK VAR INJECTION */}.call(__webpack_exports__, __webpack_require__(2).setImmediate)) 312 | 313 | /***/ }), 314 | /* 2 */ 315 | /***/ (function(module, exports, __webpack_require__) { 316 | 317 | /* WEBPACK VAR INJECTION */(function(global) {var scope = (typeof global !== "undefined" && global) || 318 | (typeof self !== "undefined" && self) || 319 | window; 320 | var apply = Function.prototype.apply; 321 | 322 | // DOM APIs, for completeness 323 | 324 | exports.setTimeout = function() { 325 | return new Timeout(apply.call(setTimeout, scope, arguments), clearTimeout); 326 | }; 327 | exports.setInterval = function() { 328 | return new Timeout(apply.call(setInterval, scope, arguments), clearInterval); 329 | }; 330 | exports.clearTimeout = 331 | exports.clearInterval = function(timeout) { 332 | if (timeout) { 333 | timeout.close(); 334 | } 335 | }; 336 | 337 | function Timeout(id, clearFn) { 338 | this._id = id; 339 | this._clearFn = clearFn; 340 | } 341 | Timeout.prototype.unref = Timeout.prototype.ref = function() {}; 342 | Timeout.prototype.close = function() { 343 | this._clearFn.call(scope, this._id); 344 | }; 345 | 346 | // Does not start the time, just sets up the members needed. 347 | exports.enroll = function(item, msecs) { 348 | clearTimeout(item._idleTimeoutId); 349 | item._idleTimeout = msecs; 350 | }; 351 | 352 | exports.unenroll = function(item) { 353 | clearTimeout(item._idleTimeoutId); 354 | item._idleTimeout = -1; 355 | }; 356 | 357 | exports._unrefActive = exports.active = function(item) { 358 | clearTimeout(item._idleTimeoutId); 359 | 360 | var msecs = item._idleTimeout; 361 | if (msecs >= 0) { 362 | item._idleTimeoutId = setTimeout(function onTimeout() { 363 | if (item._onTimeout) 364 | item._onTimeout(); 365 | }, msecs); 366 | } 367 | }; 368 | 369 | // setimmediate attaches itself to the global object 370 | __webpack_require__(3); 371 | // On some exotic environments, it's not clear which object `setimmediate` was 372 | // able to install onto. Search each possibility in the same order as the 373 | // `setimmediate` library. 374 | exports.setImmediate = (typeof self !== "undefined" && self.setImmediate) || 375 | (typeof global !== "undefined" && global.setImmediate) || 376 | (this && this.setImmediate); 377 | exports.clearImmediate = (typeof self !== "undefined" && self.clearImmediate) || 378 | (typeof global !== "undefined" && global.clearImmediate) || 379 | (this && this.clearImmediate); 380 | 381 | /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0))) 382 | 383 | /***/ }), 384 | /* 3 */ 385 | /***/ (function(module, exports, __webpack_require__) { 386 | 387 | /* WEBPACK VAR INJECTION */(function(global, process) {(function (global, undefined) { 388 | "use strict"; 389 | 390 | if (global.setImmediate) { 391 | return; 392 | } 393 | 394 | var nextHandle = 1; // Spec says greater than zero 395 | var tasksByHandle = {}; 396 | var currentlyRunningATask = false; 397 | var doc = global.document; 398 | var registerImmediate; 399 | 400 | function setImmediate(callback) { 401 | // Callback can either be a function or a string 402 | if (typeof callback !== "function") { 403 | callback = new Function("" + callback); 404 | } 405 | // Copy function arguments 406 | var args = new Array(arguments.length - 1); 407 | for (var i = 0; i < args.length; i++) { 408 | args[i] = arguments[i + 1]; 409 | } 410 | // Store and register the task 411 | var task = { callback: callback, args: args }; 412 | tasksByHandle[nextHandle] = task; 413 | registerImmediate(nextHandle); 414 | return nextHandle++; 415 | } 416 | 417 | function clearImmediate(handle) { 418 | delete tasksByHandle[handle]; 419 | } 420 | 421 | function run(task) { 422 | var callback = task.callback; 423 | var args = task.args; 424 | switch (args.length) { 425 | case 0: 426 | callback(); 427 | break; 428 | case 1: 429 | callback(args[0]); 430 | break; 431 | case 2: 432 | callback(args[0], args[1]); 433 | break; 434 | case 3: 435 | callback(args[0], args[1], args[2]); 436 | break; 437 | default: 438 | callback.apply(undefined, args); 439 | break; 440 | } 441 | } 442 | 443 | function runIfPresent(handle) { 444 | // From the spec: "Wait until any invocations of this algorithm started before this one have completed." 445 | // So if we're currently running a task, we'll need to delay this invocation. 446 | if (currentlyRunningATask) { 447 | // Delay by doing a setTimeout. setImmediate was tried instead, but in Firefox 7 it generated a 448 | // "too much recursion" error. 449 | setTimeout(runIfPresent, 0, handle); 450 | } else { 451 | var task = tasksByHandle[handle]; 452 | if (task) { 453 | currentlyRunningATask = true; 454 | try { 455 | run(task); 456 | } finally { 457 | clearImmediate(handle); 458 | currentlyRunningATask = false; 459 | } 460 | } 461 | } 462 | } 463 | 464 | function installNextTickImplementation() { 465 | registerImmediate = function(handle) { 466 | process.nextTick(function () { runIfPresent(handle); }); 467 | }; 468 | } 469 | 470 | function canUsePostMessage() { 471 | // The test against `importScripts` prevents this implementation from being installed inside a web worker, 472 | // where `global.postMessage` means something completely different and can't be used for this purpose. 473 | if (global.postMessage && !global.importScripts) { 474 | var postMessageIsAsynchronous = true; 475 | var oldOnMessage = global.onmessage; 476 | global.onmessage = function() { 477 | postMessageIsAsynchronous = false; 478 | }; 479 | global.postMessage("", "*"); 480 | global.onmessage = oldOnMessage; 481 | return postMessageIsAsynchronous; 482 | } 483 | } 484 | 485 | function installPostMessageImplementation() { 486 | // Installs an event handler on `global` for the `message` event: see 487 | // * https://developer.mozilla.org/en/DOM/window.postMessage 488 | // * http://www.whatwg.org/specs/web-apps/current-work/multipage/comms.html#crossDocumentMessages 489 | 490 | var messagePrefix = "setImmediate$" + Math.random() + "$"; 491 | var onGlobalMessage = function(event) { 492 | if (event.source === global && 493 | typeof event.data === "string" && 494 | event.data.indexOf(messagePrefix) === 0) { 495 | runIfPresent(+event.data.slice(messagePrefix.length)); 496 | } 497 | }; 498 | 499 | if (global.addEventListener) { 500 | global.addEventListener("message", onGlobalMessage, false); 501 | } else { 502 | global.attachEvent("onmessage", onGlobalMessage); 503 | } 504 | 505 | registerImmediate = function(handle) { 506 | global.postMessage(messagePrefix + handle, "*"); 507 | }; 508 | } 509 | 510 | function installMessageChannelImplementation() { 511 | var channel = new MessageChannel(); 512 | channel.port1.onmessage = function(event) { 513 | var handle = event.data; 514 | runIfPresent(handle); 515 | }; 516 | 517 | registerImmediate = function(handle) { 518 | channel.port2.postMessage(handle); 519 | }; 520 | } 521 | 522 | function installReadyStateChangeImplementation() { 523 | var html = doc.documentElement; 524 | registerImmediate = function(handle) { 525 | // Create a 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /dist/devtoolsBackground.js: -------------------------------------------------------------------------------- 1 | var panels = chrome && chrome.devtools && chrome.devtools.panels; 2 | panels.create('JSON-RPC Viewer', 'images/get_started16.png', 'panel.html'); 3 | -------------------------------------------------------------------------------- /dist/images/128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kityan/json-rpc-viewer/15213034f7b04d9f5b2611236f15f660e059a2b5/dist/images/128.png -------------------------------------------------------------------------------- /dist/images/16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kityan/json-rpc-viewer/15213034f7b04d9f5b2611236f15f660e059a2b5/dist/images/16.png -------------------------------------------------------------------------------- /dist/images/32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kityan/json-rpc-viewer/15213034f7b04d9f5b2611236f15f660e059a2b5/dist/images/32.png -------------------------------------------------------------------------------- /dist/images/48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kityan/json-rpc-viewer/15213034f7b04d9f5b2611236f15f660e059a2b5/dist/images/48.png -------------------------------------------------------------------------------- /dist/list-items/end.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /dist/list-items/mid.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /dist/list-items/none.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /dist/list-items/start.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /dist/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "JSON-RPC Viewer", 3 | "version": "1.1.2", 4 | "description": "Convenient way to view JSON-RPC requests", 5 | "manifest_version": 2, 6 | "permissions": [ 7 | 8 | ], 9 | "icons": { 10 | "16": "images/16.png", 11 | "32": "images/32.png", 12 | "48": "images/48.png", 13 | "128": "images/128.png" 14 | }, 15 | "devtools_page": "devtoolsBackground.html" 16 | } 17 | -------------------------------------------------------------------------------- /dist/panel.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 |
14 |
15 |
16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
MethodTimeSize
24 |
25 |
26 |
27 | 38 |
39 | 40 | 58 | 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /dist/styles.css: -------------------------------------------------------------------------------- 1 | html { 2 | height: 100%; 3 | } 4 | 5 | button { 6 | -webkit-tap-highlight-color: rgba(255, 255, 255, 0); 7 | -webkit-tap-highlight-color: transparent; 8 | outline: 0; 9 | border: none; 10 | margin: 0; 11 | padding: 0; 12 | width: auto; 13 | overflow: visible; 14 | background: transparent; 15 | color: inherit; 16 | font: inherit; 17 | text-align: inherit; 18 | cursor: pointer; 19 | text-decoration: underline; 20 | text-decoration-style: dashed; 21 | } 22 | 23 | * { 24 | box-sizing: border-box; 25 | font-family: monospace !important; 26 | font-size: 11px; 27 | } 28 | 29 | body { 30 | margin: 0; 31 | height: 100%; 32 | display: flex; 33 | justify-content: space-between; 34 | flex-direction: column; 35 | } 36 | 37 | 38 | #tableWrapper { 39 | width: 100%; 40 | } 41 | 42 | 43 | #table { 44 | border-collapse: collapse; 45 | width: 100%; 46 | border: 0; 47 | margin: 0; 48 | margin-right: -1px; 49 | } 50 | 51 | #table td { 52 | padding: 3px; 53 | border: 0; 54 | } 55 | 56 | #table td.methodName { 57 | padding-left: 10px !important; 58 | background-repeat: no-repeat; 59 | background-position: 0 0; 60 | /* background-image: url('./list-items/none.svg'); */ 61 | } 62 | 63 | #topmenu { 64 | height: 25px; 65 | min-height: 25px; 66 | color: #000; 67 | display: flex; 68 | justify-content: space-between; 69 | border-bottom: 1px solid #999; 70 | background: #CCC; 71 | align-items: center; 72 | padding: 3px; 73 | } 74 | 75 | #topmenu a { 76 | color: inherit !important; 77 | 78 | } 79 | 80 | button:hover { 81 | color: goldenrod; 82 | text-decoration-style: solid; 83 | } 84 | 85 | button:active { 86 | text-decoration: none; 87 | } 88 | 89 | button#clear { 90 | justify-self: flex-start; 91 | } 92 | 93 | button#help { 94 | justify-self: flex-end; 95 | } 96 | 97 | #panels { 98 | flex-grow: 1; 99 | display: flex; 100 | } 101 | 102 | #left { 103 | width: 50%; 104 | min-width: 5%; 105 | overflow: auto; 106 | } 107 | 108 | #right { 109 | border-left: 1px solid #999; 110 | min-width: 5%; 111 | overflow: auto; 112 | display: flex; 113 | flex-direction: column; 114 | flex-grow: 1; 115 | } 116 | 117 | #params { 118 | min-height: 25px; 119 | max-height: 95%; 120 | display: flex; 121 | flex-direction: column; 122 | justify-content: space-between; 123 | } 124 | 125 | #resultError { 126 | display: flex; 127 | flex-direction: column; 128 | justify-content: space-between; 129 | } 130 | 131 | #resultError_json_viewer, 132 | #params_json_viewer { 133 | overflow: auto; 134 | flex-grow: 1; 135 | padding: 3px; 136 | } 137 | 138 | #left_resizer { 139 | width: 5px; 140 | cursor: col-resize; 141 | } 142 | 143 | #left_resizer:hover { 144 | background-color: #c7c7c7; 145 | } 146 | 147 | #params_resizer { 148 | height: 5px; 149 | cursor: row-resize; 150 | } 151 | #params_resizer:hover { 152 | background-color: #c7c7c7; 153 | } 154 | 155 | tr { 156 | cursor: pointer; 157 | } 158 | 159 | .even { 160 | background: #EEE; 161 | } 162 | 163 | .odd { 164 | background: #FFF; 165 | } 166 | 167 | .selected { 168 | background: lightblue !important; 169 | } 170 | 171 | .header { 172 | height: 25px; 173 | min-height: 25px; 174 | background: #CCC; 175 | color: #000; 176 | padding: 3px; 177 | user-select: none; 178 | } 179 | 180 | tr.header { 181 | vertical-align: middle; 182 | } 183 | div.header { 184 | display: flex; 185 | align-items: center; 186 | } 187 | 188 | .ok { 189 | color: green; 190 | } 191 | 192 | .error { 193 | color: orangered; 194 | } 195 | 196 | .reponseNotParsed { 197 | color: purple; 198 | } 199 | 200 | 201 | #helpPopup { 202 | position: absolute; 203 | width: 100%; 204 | height: 100%; 205 | padding: 30px; 206 | background: rgba(0,0,0,0.5); 207 | display: flex; 208 | } 209 | 210 | #helpPopupContent { 211 | background: #FFF; 212 | padding: 10px; 213 | } 214 | 215 | .hidden { 216 | visibility: hidden; 217 | } 218 | 219 | 220 | .methodName.inBatch_mid { 221 | background-image: url('./list-items/mid.svg') !important; 222 | } 223 | .methodName.inBatch_end { 224 | background-image: url('./list-items/end.svg') !important; 225 | } 226 | .methodName.inBatch_start { 227 | background-image: url('./list-items/start.svg') !important; 228 | } 229 | 230 | .theme-dark .json-formatter-row .json-formatter-key { 231 | color: #999999; 232 | } 233 | 234 | .theme-dark .json-formatter-row, 235 | .theme-dark .json-formatter-row a, 236 | .theme-dark .json-formatter-row a:hover, 237 | .theme-dark .json-formatter-row .json-formatter-bracket { 238 | color: #c3c3ff; 239 | } 240 | 241 | .theme-dark .json-formatter-row .json-formatter-number { 242 | color: #8181ff; 243 | } 244 | 245 | .theme-dark .json-formatter-row .json-formatter-string, .theme-dark .json-formatter-row .json-formatter-stringifiable { 246 | color: #00d200; 247 | } 248 | 249 | .theme-dark .error { 250 | color: #ff4500; 251 | } 252 | 253 | .theme-dark .even { 254 | background: #2b2b2b; 255 | } 256 | 257 | .theme-dark .odd { 258 | background: transparent; 259 | } 260 | 261 | .theme-dark .selected { 262 | background: #424242 !important; 263 | } 264 | 265 | .theme-dark .header, .theme-dark #topmenu { 266 | background-color: #212121; 267 | color: white; 268 | } 269 | 270 | .theme-dark .ok { 271 | color: lightgreen; 272 | } 273 | 274 | .theme-dark #helpPopupContent { 275 | background-color: #2f2f2f; 276 | } 277 | 278 | .theme-dark #helpPopupContent a { 279 | color: #00a0ff; 280 | } 281 | 282 | .theme-dark #left_resizer:hover, .theme-dark #params_resizer:hover { 283 | background-color: #999; 284 | } 285 | 286 | .theme-dark { 287 | color: white; 288 | } 289 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "json-rpc-viewer", 3 | "version": "1.1.2", 4 | "description": "Convenient way to view JSON-RPC requests", 5 | "main": "app.js", 6 | "dependencies": { 7 | "json-formatter-js": "^2.2.1" 8 | }, 9 | "devDependencies": { 10 | "copy-webpack-plugin": "^4.0.1", 11 | "rimraf": "^2.5.4", 12 | "webpack": "^3.0.0" 13 | }, 14 | "scripts": { 15 | "clean": "rimraf dist", 16 | "build": "npm run clean && webpack --config webpack.config.js", 17 | "test": "echo \"Error: no test specified\" && exit 1" 18 | }, 19 | "repository": { 20 | "type": "git", 21 | "url": "git+https://github.com/kityan/json-rpc-viewer.git" 22 | }, 23 | "author": "pavel@kityan.ru", 24 | "license": "MIT", 25 | "bugs": { 26 | "url": "https://github.com/kityan/json-rpc-viewer/issues" 27 | }, 28 | "homepage": "https://github.com/kityan/json-rpc-viewer#readme" 29 | } 30 | -------------------------------------------------------------------------------- /src/app.js: -------------------------------------------------------------------------------- 1 | import JSONFormatter from 'json-formatter-js' 2 | 3 | const body = document.getElementsByTagName('body') 4 | const left = document.getElementById('left') 5 | const right = document.getElementById('right') 6 | const params = document.getElementById('params') 7 | const table = document.getElementById('table') 8 | const helpPopup = document.getElementById('helpPopup') 9 | const divParamsViewer = document.getElementById('params_json_viewer') 10 | const divResultErrorViewer = document.getElementById('resultError_json_viewer') 11 | const leftResizer = document.getElementById('left_resizer') 12 | const paramsResizer = document.getElementById('params_resizer') 13 | const resetLayoutBtn = document.getElementById('reset_layout') 14 | const opts = {animateOpen: false, animateClose: false} 15 | const currentTheme = chrome.devtools.panels.themeName 16 | 17 | let trClass = 1; 18 | 19 | // add theme class name 20 | if (currentTheme && body.length > 0) { 21 | body[0].classList.add('theme-' + currentTheme) 22 | } 23 | 24 | loadLayout() 25 | 26 | // clear log 27 | document.getElementById('clear').addEventListener('click', () => { 28 | divParamsViewer.innerHTML = '' 29 | divResultErrorViewer.innerHTML = '' 30 | Array.from(table.childNodes).forEach((node, index) => index > 1 && table.removeChild(node)) 31 | }) 32 | 33 | // show help 34 | document.getElementById('help').addEventListener('click', () => helpPopup.classList.remove('hidden')) 35 | document.getElementById('closeHelp').addEventListener('click', () => helpPopup.classList.add('hidden')) 36 | 37 | // process finished request 38 | chrome.devtools.network.onRequestFinished.addListener(request => { 39 | if ( 40 | request.request && 41 | request.request.postData && 42 | request.request.postData.mimeType && 43 | request.request.postData.mimeType.match(/application\/json/) && 44 | request.request.postData.text && request.request.postData.text.match(/jsonrpc/) 45 | ) { 46 | request.getContent(body => { 47 | // [+] add check for spec? 48 | const responseJSON = JSON.parse(body) 49 | const requestJSON = JSON.parse(request.request.postData.text) 50 | // [+] add check for equal length? 51 | 52 | const isBatch = Array.isArray(requestJSON) && Array.isArray(responseJSON) 53 | if (!isBatch) { 54 | addListItem(request, requestJSON, responseJSON) 55 | } else { 56 | const reponseJSONIndex = responseJSON.reduce((obj, item) => { 57 | obj[item.id] = item; 58 | return obj 59 | }, {}) 60 | // [+] add check and warning for: id duplication? absent id? 61 | for (let i = 0; i < requestJSON.length; i++) { 62 | const inBatch = i == 0 ? 'start' : (i == requestJSON.length - 1 ? 'end' : 'mid') 63 | addListItem(request, requestJSON[i], reponseJSONIndex[requestJSON[i].id], inBatch, requestJSON.length) 64 | } 65 | } 66 | 67 | }) 68 | } 69 | }) 70 | 71 | 72 | function addListItem(request, requestJSON, responseJSON, inBatch, batchSize) { 73 | 74 | const tr = document.createElement('tr') 75 | tr.classList.add(trClass > 0 ? 'even' : 'odd') 76 | trClass *= -1 77 | 78 | const td1 = document.createElement('td') 79 | 80 | if (responseJSON) { 81 | td1.classList.add(responseJSON && responseJSON.hasOwnProperty && responseJSON.hasOwnProperty('result') ? 'ok' : 'error') 82 | } else { 83 | td1.classList.add('reponseNotParsed') 84 | } 85 | 86 | const td2 = document.createElement('td') 87 | const td3 = document.createElement('td') 88 | tr.appendChild(td1) 89 | tr.appendChild(td2) 90 | tr.appendChild(td3) 91 | 92 | 93 | const wasScrolledToBottom = left.clientHeight + Math.ceil(left.scrollTop) >= left.scrollHeight 94 | table.appendChild(tr) 95 | if (wasScrolledToBottom) { 96 | setImmediate(() => left.scrollTop = left.scrollHeight - left.clientHeight) 97 | } 98 | 99 | 100 | tr.addEventListener('click', event => { 101 | Array.from(document.getElementsByTagName('tr')).forEach(el => el.classList.remove('selected')) 102 | event.currentTarget.classList.add('selected') 103 | let formatter1 104 | if (requestJSON && requestJSON.hasOwnProperty && requestJSON.hasOwnProperty('params')) { 105 | formatter1 = new JSONFormatter(requestJSON.params, 1, opts) 106 | } 107 | // [?] too large responses are not available 108 | let formatter2 109 | if (responseJSON && responseJSON.hasOwnProperty) { 110 | if (responseJSON.hasOwnProperty('result')) { 111 | formatter2 = new JSONFormatter(responseJSON.result, 1, opts) 112 | } 113 | if (responseJSON.hasOwnProperty('error')) { 114 | formatter2 = new JSONFormatter(responseJSON.error, 1, opts) 115 | } 116 | } 117 | divParamsViewer.innerHTML = '' 118 | if (formatter1) { 119 | divParamsViewer.appendChild(formatter1.render()) 120 | } 121 | divResultErrorViewer.innerHTML = '' 122 | if (formatter2) { 123 | divResultErrorViewer.appendChild(formatter2.render()) 124 | } 125 | }) 126 | 127 | const time = Number.isFinite(request.time) ? Math.round(request.time) : '' 128 | const size = request.response && request.response.content && request.response.content.size 129 | 130 | td1.innerHTML = requestJSON.method 131 | td1.classList.add('methodName') 132 | if (inBatch) { 133 | td1.classList.add('inBatch_' + inBatch) 134 | if (inBatch === 'start') { 135 | td2.innerText = time 136 | td3.innerText = size 137 | } else { 138 | td2.innerText = ' ' 139 | td3.innerText = ' ' 140 | } 141 | } else { 142 | td2.innerText = time 143 | td3.innerText = size 144 | } 145 | 146 | } 147 | 148 | leftResizer.addEventListener('mousedown', function (e) { 149 | document.addEventListener('mousemove', resizeLeftDiv) 150 | document.addEventListener('mouseup', stopResizeLeftDiv) 151 | document.addEventListener('mouseleave', stopResizeLeftDiv) 152 | }) 153 | 154 | function loadLayout() { 155 | const leftWidth = localStorage.getItem('left-width') 156 | const paramsHeight = localStorage.getItem('params-height') 157 | 158 | left.style.width = leftWidth ? leftWidth : '50%'; 159 | params.style.height = paramsHeight ? paramsHeight : '25%'; 160 | 161 | if (leftWidth || paramsHeight) { 162 | resetLayoutBtn.style.display = 'inherit' 163 | } else { 164 | resetLayoutBtn.style.display = 'none' 165 | } 166 | } 167 | 168 | /** 169 | * @param {MouseEvent} e 170 | */ 171 | function resizeLeftDiv(e) { 172 | left.style.width = (e.pageX / body[0].clientWidth) * 100 + '%'; 173 | localStorage.setItem('left-width', left.style.width) 174 | resetLayoutBtn.style.display = 'inherit' 175 | } 176 | 177 | function stopResizeLeftDiv() { 178 | document.removeEventListener('mousemove', resizeLeftDiv) 179 | document.removeEventListener('mouseup', stopResizeLeftDiv) 180 | document.removeEventListener('mouseleave', stopResizeLeftDiv) 181 | } 182 | 183 | paramsResizer.addEventListener('mousedown', function (e) { 184 | document.addEventListener('mousemove', resizeParamsDiv) 185 | document.addEventListener('mouseup', stopResizeParamsDiv) 186 | document.addEventListener('mouseleave', stopResizeParamsDiv) 187 | }) 188 | 189 | /** 190 | * @param {MouseEvent} e 191 | */ 192 | function resizeParamsDiv(e) { 193 | let rightRect = right.getBoundingClientRect() 194 | params.style.height = ((e.pageY - rightRect.top) / rightRect.height) * 100 + '%'; 195 | localStorage.setItem('params-height', params.style.height) 196 | resetLayoutBtn.style.display = 'inherit' 197 | } 198 | 199 | function stopResizeParamsDiv() { 200 | document.removeEventListener('mousemove', resizeParamsDiv) 201 | document.removeEventListener('mouseup', stopResizeParamsDiv) 202 | document.removeEventListener('mouseleave', stopResizeParamsDiv) 203 | } 204 | 205 | resetLayoutBtn.addEventListener('click', function () { 206 | localStorage.removeItem('params-height') 207 | localStorage.removeItem('left-width') 208 | loadLayout() 209 | }) 210 | -------------------------------------------------------------------------------- /src/assets/background.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kityan/json-rpc-viewer/15213034f7b04d9f5b2611236f15f660e059a2b5/src/assets/background.js -------------------------------------------------------------------------------- /src/assets/devtoolsBackground.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/assets/devtoolsBackground.js: -------------------------------------------------------------------------------- 1 | var panels = chrome && chrome.devtools && chrome.devtools.panels; 2 | panels.create('JSON-RPC Viewer', 'images/get_started16.png', 'panel.html'); 3 | -------------------------------------------------------------------------------- /src/assets/images/128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kityan/json-rpc-viewer/15213034f7b04d9f5b2611236f15f660e059a2b5/src/assets/images/128.png -------------------------------------------------------------------------------- /src/assets/images/16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kityan/json-rpc-viewer/15213034f7b04d9f5b2611236f15f660e059a2b5/src/assets/images/16.png -------------------------------------------------------------------------------- /src/assets/images/32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kityan/json-rpc-viewer/15213034f7b04d9f5b2611236f15f660e059a2b5/src/assets/images/32.png -------------------------------------------------------------------------------- /src/assets/images/48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kityan/json-rpc-viewer/15213034f7b04d9f5b2611236f15f660e059a2b5/src/assets/images/48.png -------------------------------------------------------------------------------- /src/assets/list-items/end.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/assets/list-items/mid.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/assets/list-items/none.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/assets/list-items/start.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/assets/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "JSON-RPC Viewer", 3 | "version": "1.1.2", 4 | "description": "Convenient way to view JSON-RPC requests", 5 | "manifest_version": 2, 6 | "permissions": [ 7 | 8 | ], 9 | "icons": { 10 | "16": "images/16.png", 11 | "32": "images/32.png", 12 | "48": "images/48.png", 13 | "128": "images/128.png" 14 | }, 15 | "devtools_page": "devtoolsBackground.html" 16 | } 17 | -------------------------------------------------------------------------------- /src/assets/panel.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 |
14 |
15 |
16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
MethodTimeSize
24 |
25 |
26 |
27 | 38 |
39 | 40 | 58 | 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /src/assets/styles.css: -------------------------------------------------------------------------------- 1 | html { 2 | height: 100%; 3 | } 4 | 5 | button { 6 | -webkit-tap-highlight-color: rgba(255, 255, 255, 0); 7 | -webkit-tap-highlight-color: transparent; 8 | outline: 0; 9 | border: none; 10 | margin: 0; 11 | padding: 0; 12 | width: auto; 13 | overflow: visible; 14 | background: transparent; 15 | color: inherit; 16 | font: inherit; 17 | text-align: inherit; 18 | cursor: pointer; 19 | text-decoration: underline; 20 | text-decoration-style: dashed; 21 | } 22 | 23 | * { 24 | box-sizing: border-box; 25 | font-family: monospace !important; 26 | font-size: 11px; 27 | } 28 | 29 | body { 30 | margin: 0; 31 | height: 100%; 32 | display: flex; 33 | justify-content: space-between; 34 | flex-direction: column; 35 | } 36 | 37 | 38 | #tableWrapper { 39 | width: 100%; 40 | } 41 | 42 | 43 | #table { 44 | border-collapse: collapse; 45 | width: 100%; 46 | border: 0; 47 | margin: 0; 48 | margin-right: -1px; 49 | } 50 | 51 | #table td { 52 | padding: 3px; 53 | border: 0; 54 | } 55 | 56 | #table td.methodName { 57 | padding-left: 10px !important; 58 | background-repeat: no-repeat; 59 | background-position: 0 0; 60 | /* background-image: url('./list-items/none.svg'); */ 61 | } 62 | 63 | #topmenu { 64 | height: 25px; 65 | min-height: 25px; 66 | color: #000; 67 | display: flex; 68 | justify-content: space-between; 69 | border-bottom: 1px solid #999; 70 | background: #CCC; 71 | align-items: center; 72 | padding: 3px; 73 | } 74 | 75 | #topmenu a { 76 | color: inherit !important; 77 | 78 | } 79 | 80 | button:hover { 81 | color: goldenrod; 82 | text-decoration-style: solid; 83 | } 84 | 85 | button:active { 86 | text-decoration: none; 87 | } 88 | 89 | button#clear { 90 | justify-self: flex-start; 91 | } 92 | 93 | button#help { 94 | justify-self: flex-end; 95 | } 96 | 97 | #panels { 98 | flex-grow: 1; 99 | display: flex; 100 | } 101 | 102 | #left { 103 | width: 50%; 104 | min-width: 5%; 105 | overflow: auto; 106 | } 107 | 108 | #right { 109 | border-left: 1px solid #999; 110 | min-width: 5%; 111 | overflow: auto; 112 | display: flex; 113 | flex-direction: column; 114 | flex-grow: 1; 115 | } 116 | 117 | #params { 118 | min-height: 25px; 119 | max-height: 95%; 120 | display: flex; 121 | flex-direction: column; 122 | justify-content: space-between; 123 | } 124 | 125 | #resultError { 126 | display: flex; 127 | flex-direction: column; 128 | justify-content: space-between; 129 | } 130 | 131 | #resultError_json_viewer, 132 | #params_json_viewer { 133 | overflow: auto; 134 | flex-grow: 1; 135 | padding: 3px; 136 | } 137 | 138 | #left_resizer { 139 | width: 5px; 140 | cursor: col-resize; 141 | } 142 | 143 | #left_resizer:hover { 144 | background-color: #c7c7c7; 145 | } 146 | 147 | #params_resizer { 148 | height: 5px; 149 | cursor: row-resize; 150 | } 151 | #params_resizer:hover { 152 | background-color: #c7c7c7; 153 | } 154 | 155 | tr { 156 | cursor: pointer; 157 | } 158 | 159 | .even { 160 | background: #EEE; 161 | } 162 | 163 | .odd { 164 | background: #FFF; 165 | } 166 | 167 | .selected { 168 | background: lightblue !important; 169 | } 170 | 171 | .header { 172 | height: 25px; 173 | min-height: 25px; 174 | background: #CCC; 175 | color: #000; 176 | padding: 3px; 177 | user-select: none; 178 | } 179 | 180 | tr.header { 181 | vertical-align: middle; 182 | } 183 | div.header { 184 | display: flex; 185 | align-items: center; 186 | } 187 | 188 | .ok { 189 | color: green; 190 | } 191 | 192 | .error { 193 | color: orangered; 194 | } 195 | 196 | .reponseNotParsed { 197 | color: purple; 198 | } 199 | 200 | 201 | #helpPopup { 202 | position: absolute; 203 | width: 100%; 204 | height: 100%; 205 | padding: 30px; 206 | background: rgba(0,0,0,0.5); 207 | display: flex; 208 | } 209 | 210 | #helpPopupContent { 211 | background: #FFF; 212 | padding: 10px; 213 | } 214 | 215 | .hidden { 216 | visibility: hidden; 217 | } 218 | 219 | 220 | .methodName.inBatch_mid { 221 | background-image: url('./list-items/mid.svg') !important; 222 | } 223 | .methodName.inBatch_end { 224 | background-image: url('./list-items/end.svg') !important; 225 | } 226 | .methodName.inBatch_start { 227 | background-image: url('./list-items/start.svg') !important; 228 | } 229 | 230 | .theme-dark .json-formatter-row .json-formatter-key { 231 | color: #999999; 232 | } 233 | 234 | .theme-dark .json-formatter-row, 235 | .theme-dark .json-formatter-row a, 236 | .theme-dark .json-formatter-row a:hover, 237 | .theme-dark .json-formatter-row .json-formatter-bracket { 238 | color: #c3c3ff; 239 | } 240 | 241 | .theme-dark .json-formatter-row .json-formatter-number { 242 | color: #8181ff; 243 | } 244 | 245 | .theme-dark .json-formatter-row .json-formatter-string, .theme-dark .json-formatter-row .json-formatter-stringifiable { 246 | color: #00d200; 247 | } 248 | 249 | .theme-dark .error { 250 | color: #ff4500; 251 | } 252 | 253 | .theme-dark .even { 254 | background: #2b2b2b; 255 | } 256 | 257 | .theme-dark .odd { 258 | background: transparent; 259 | } 260 | 261 | .theme-dark .selected { 262 | background: #424242 !important; 263 | } 264 | 265 | .theme-dark .header, .theme-dark #topmenu { 266 | background-color: #212121; 267 | color: white; 268 | } 269 | 270 | .theme-dark .ok { 271 | color: lightgreen; 272 | } 273 | 274 | .theme-dark #helpPopupContent { 275 | background-color: #2f2f2f; 276 | } 277 | 278 | .theme-dark #helpPopupContent a { 279 | color: #00a0ff; 280 | } 281 | 282 | .theme-dark #left_resizer:hover, .theme-dark #params_resizer:hover { 283 | background-color: #999; 284 | } 285 | 286 | .theme-dark { 287 | color: white; 288 | } 289 | -------------------------------------------------------------------------------- /store.data/1280x800.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kityan/json-rpc-viewer/15213034f7b04d9f5b2611236f15f660e059a2b5/store.data/1280x800.png -------------------------------------------------------------------------------- /store.data/128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kityan/json-rpc-viewer/15213034f7b04d9f5b2611236f15f660e059a2b5/store.data/128x128.png -------------------------------------------------------------------------------- /store.data/440x280.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kityan/json-rpc-viewer/15213034f7b04d9f5b2611236f15f660e059a2b5/store.data/440x280.jpg -------------------------------------------------------------------------------- /store.data/440x280.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kityan/json-rpc-viewer/15213034f7b04d9f5b2611236f15f660e059a2b5/store.data/440x280.png -------------------------------------------------------------------------------- /store.data/description.txt: -------------------------------------------------------------------------------- 1 | JSON-RPC Viewer is an extension to help viewing JSON-RPC requests in a more convenient way than Network tab allows. 2 | You can view a list of requests with method name, params and result/response. 3 | Supports JSON-RPC batch requests from version 1.1.1 4 | Feature requests, bug reports and pull requests are welcome here: https://github.com/kityan/json-rpc-viewer. 5 | -------------------------------------------------------------------------------- /store.data/dist.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kityan/json-rpc-viewer/15213034f7b04d9f5b2611236f15f660e059a2b5/store.data/dist.zip -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const CopyWebpackPlugin = require('copy-webpack-plugin') 2 | const path = require('path') 3 | 4 | module.exports = function () { 5 | 6 | const config = { 7 | entry: { 8 | app: './src/app.js', 9 | }, 10 | output: { 11 | path: path.join(__dirname, '/dist'), 12 | filename: '[name].js', 13 | }, 14 | resolve: { 15 | modules: ['./node_modules'] 16 | }, 17 | plugins: [ 18 | new CopyWebpackPlugin([ 19 | { 20 | from: './src/assets' 21 | }, 22 | ]), 23 | ] 24 | } 25 | 26 | return config 27 | } 28 | --------------------------------------------------------------------------------