├── .gitignore
├── art
├── banner.png
└── banner.svg
├── fixture
├── basic.json
└── bootstrap.json
├── license
├── package.json
├── readme.md
└── src
├── cli.js
├── index.html
├── index.js
└── renderer.js
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
--------------------------------------------------------------------------------
/art/banner.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/queckezz/inspect-json/02ffbc2173e954ee766bc75ea2dcf76c5df9fb5b/art/banner.png
--------------------------------------------------------------------------------
/art/banner.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
1067 |
--------------------------------------------------------------------------------
/fixture/basic.json:
--------------------------------------------------------------------------------
1 | {
2 | "id": 1,
3 | "name": "Leanne Graham",
4 | "username": "Bret",
5 | "email": "Sincere@april.biz",
6 | "address": {
7 | "street": "Kulas Light",
8 | "suite": "Apt. 556",
9 | "city": "Gwenborough",
10 | "zipcode": "92998-3874",
11 | "geo": {
12 | "lat": "-37.3159",
13 | "lng": "81.1496"
14 | }
15 | },
16 | "phone": "1-770-736-8031 x56442",
17 | "website": "hildegard.org",
18 | "company": {
19 | "name": "Romaguera-Crona",
20 | "catchPhrase": "Multi-layered client-server neural-net",
21 | "bs": "harness real-time e-markets"
22 | }
23 | }
--------------------------------------------------------------------------------
/fixture/bootstrap.json:
--------------------------------------------------------------------------------
1 | {
2 | "id": 2126244,
3 | "name": "bootstrap",
4 | "full_name": "twbs/bootstrap",
5 | "owner": {
6 | "login": "twbs",
7 | "id": 2918581,
8 | "avatar_url": "https://avatars.githubusercontent.com/u/2918581?v=3",
9 | "gravatar_id": "",
10 | "url": "https://api.github.com/users/twbs",
11 | "html_url": "https://github.com/twbs",
12 | "followers_url": "https://api.github.com/users/twbs/followers",
13 | "following_url": "https://api.github.com/users/twbs/following{/other_user}",
14 | "gists_url": "https://api.github.com/users/twbs/gists{/gist_id}",
15 | "starred_url": "https://api.github.com/users/twbs/starred{/owner}{/repo}",
16 | "subscriptions_url": "https://api.github.com/users/twbs/subscriptions",
17 | "organizations_url": "https://api.github.com/users/twbs/orgs",
18 | "repos_url": "https://api.github.com/users/twbs/repos",
19 | "events_url": "https://api.github.com/users/twbs/events{/privacy}",
20 | "received_events_url": "https://api.github.com/users/twbs/received_events",
21 | "type": "Organization",
22 | "site_admin": false
23 | },
24 | "private": false,
25 | "html_url": "https://github.com/twbs/bootstrap",
26 | "description": "The most popular HTML, CSS, and JavaScript framework for developing responsive, mobile first projects on the web.",
27 | "fork": false,
28 | "url": "https://api.github.com/repos/twbs/bootstrap",
29 | "forks_url": "https://api.github.com/repos/twbs/bootstrap/forks",
30 | "keys_url": "https://api.github.com/repos/twbs/bootstrap/keys{/key_id}",
31 | "collaborators_url": "https://api.github.com/repos/twbs/bootstrap/collaborators{/collaborator}",
32 | "teams_url": "https://api.github.com/repos/twbs/bootstrap/teams",
33 | "hooks_url": "https://api.github.com/repos/twbs/bootstrap/hooks",
34 | "issue_events_url": "https://api.github.com/repos/twbs/bootstrap/issues/events{/number}",
35 | "events_url": "https://api.github.com/repos/twbs/bootstrap/events",
36 | "assignees_url": "https://api.github.com/repos/twbs/bootstrap/assignees{/user}",
37 | "branches_url": "https://api.github.com/repos/twbs/bootstrap/branches{/branch}",
38 | "tags_url": "https://api.github.com/repos/twbs/bootstrap/tags",
39 | "blobs_url": "https://api.github.com/repos/twbs/bootstrap/git/blobs{/sha}",
40 | "git_tags_url": "https://api.github.com/repos/twbs/bootstrap/git/tags{/sha}",
41 | "git_refs_url": "https://api.github.com/repos/twbs/bootstrap/git/refs{/sha}",
42 | "trees_url": "https://api.github.com/repos/twbs/bootstrap/git/trees{/sha}",
43 | "statuses_url": "https://api.github.com/repos/twbs/bootstrap/statuses/{sha}",
44 | "languages_url": "https://api.github.com/repos/twbs/bootstrap/languages",
45 | "stargazers_url": "https://api.github.com/repos/twbs/bootstrap/stargazers",
46 | "contributors_url": "https://api.github.com/repos/twbs/bootstrap/contributors",
47 | "subscribers_url": "https://api.github.com/repos/twbs/bootstrap/subscribers",
48 | "subscription_url": "https://api.github.com/repos/twbs/bootstrap/subscription",
49 | "commits_url": "https://api.github.com/repos/twbs/bootstrap/commits{/sha}",
50 | "git_commits_url": "https://api.github.com/repos/twbs/bootstrap/git/commits{/sha}",
51 | "comments_url": "https://api.github.com/repos/twbs/bootstrap/comments{/number}",
52 | "issue_comment_url": "https://api.github.com/repos/twbs/bootstrap/issues/comments{/number}",
53 | "contents_url": "https://api.github.com/repos/twbs/bootstrap/contents/{+path}",
54 | "compare_url": "https://api.github.com/repos/twbs/bootstrap/compare/{base}...{head}",
55 | "merges_url": "https://api.github.com/repos/twbs/bootstrap/merges",
56 | "archive_url": "https://api.github.com/repos/twbs/bootstrap/{archive_format}{/ref}",
57 | "downloads_url": "https://api.github.com/repos/twbs/bootstrap/downloads",
58 | "issues_url": "https://api.github.com/repos/twbs/bootstrap/issues{/number}",
59 | "pulls_url": "https://api.github.com/repos/twbs/bootstrap/pulls{/number}",
60 | "milestones_url": "https://api.github.com/repos/twbs/bootstrap/milestones{/number}",
61 | "notifications_url": "https://api.github.com/repos/twbs/bootstrap/notifications{?since,all,participating}",
62 | "labels_url": "https://api.github.com/repos/twbs/bootstrap/labels{/name}",
63 | "releases_url": "https://api.github.com/repos/twbs/bootstrap/releases{/id}",
64 | "deployments_url": "https://api.github.com/repos/twbs/bootstrap/deployments",
65 | "created_at": "2011-07-29T21:19:00Z",
66 | "updated_at": "2016-11-24T15:58:44Z",
67 | "pushed_at": "2016-11-24T02:24:54Z",
68 | "git_url": "git://github.com/twbs/bootstrap.git",
69 | "ssh_url": "git@github.com:twbs/bootstrap.git",
70 | "clone_url": "https://github.com/twbs/bootstrap.git",
71 | "svn_url": "https://github.com/twbs/bootstrap",
72 | "homepage": "http://getbootstrap.com",
73 | "size": 215143,
74 | "stargazers_count": 103838,
75 | "watchers_count": 103838,
76 | "language": "JavaScript",
77 | "has_issues": true,
78 | "has_downloads": true,
79 | "has_wiki": false,
80 | "has_pages": true,
81 | "forks_count": 46970,
82 | "mirror_url": null,
83 | "open_issues_count": 402,
84 | "forks": 46970,
85 | "open_issues": 402,
86 | "watchers": 103838,
87 | "default_branch": "v4-dev",
88 | "organization": {
89 | "login": "twbs",
90 | "id": 2918581,
91 | "avatar_url": "https://avatars.githubusercontent.com/u/2918581?v=3",
92 | "gravatar_id": "",
93 | "url": "https://api.github.com/users/twbs",
94 | "html_url": "https://github.com/twbs",
95 | "followers_url": "https://api.github.com/users/twbs/followers",
96 | "following_url": "https://api.github.com/users/twbs/following{/other_user}",
97 | "gists_url": "https://api.github.com/users/twbs/gists{/gist_id}",
98 | "starred_url": "https://api.github.com/users/twbs/starred{/owner}{/repo}",
99 | "subscriptions_url": "https://api.github.com/users/twbs/subscriptions",
100 | "organizations_url": "https://api.github.com/users/twbs/orgs",
101 | "repos_url": "https://api.github.com/users/twbs/repos",
102 | "events_url": "https://api.github.com/users/twbs/events{/privacy}",
103 | "received_events_url": "https://api.github.com/users/twbs/received_events",
104 | "type": "Organization",
105 | "site_admin": false
106 | },
107 | "network_count": 46970,
108 | "subscribers_count": 6602
109 | }
110 |
--------------------------------------------------------------------------------
/license:
--------------------------------------------------------------------------------
1 | (The MIT License)
2 |
3 | Copyright (c) 2016 Fabian Eichenberger
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining
6 | a copy of this software and associated documentation files (the
7 | 'Software'), to deal in the Software without restriction, including
8 | without limitation the rights to use, copy, modify, merge, publish,
9 | distribute, sublicense, and/or sell copies of the Software, and to
10 | permit persons to whom the Software is furnished to do so, subject to
11 | the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be
14 | included in all copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "inspect-json",
3 | "version": "0.2.0",
4 | "description": "Robust manipulation and inspection of JSON data using the already familiar Chromium Devtools",
5 | "main": "src/index.js",
6 | "bin": "src/cli.js",
7 | "scripts": {
8 | "start": "electron ."
9 | },
10 | "repository": "https://github.com/queckezz/electron-json-viewer",
11 | "author": "Fabian Eichenberger ",
12 | "license": "MIT",
13 | "devDependencies": {},
14 | "dependencies": {
15 | "chokidar": "^1.6.1",
16 | "electron": "^1.4.8",
17 | "execa": "^0.5.0",
18 | "get-stdin": "^5.0.1",
19 | "got": "^6.6.3",
20 | "is-url": "^1.2.2",
21 | "minimist": "^1.2.0",
22 | "mz": "^2.6.0"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 |
2 | 
3 |
4 | **Robust manipulation and inspection of JSON data using the already familiar Chromium Devtools** - It allows for *quick* inspection of arbitrary JSON strucures. Allows JSON to be passed in from **URLs**, **Files** and **`process.stdin`**. The JSON can be manipulated while inspecting by accessing `window.json` through the console.
5 |
6 |
7 |
8 | [![npm version][version-image]][version-url]
9 | [![dependency status][david-image]][david-url]
10 | [![license][license-image]][license-url]
11 | [![js standard style][standard-image]][standard-url]
12 | [![downloads per month][downloads-image]][downloads-url]
13 |
14 | ## Installation
15 |
16 | ```
17 | > npm install -g inspect-json
18 | ```
19 |
20 | ## Examples
21 |
22 | Inspect JSON from the following types.
23 |
24 | **File:**
25 |
26 | ```
27 | > inspect-json example.json
28 | ```
29 |
30 | **REST Endpoint:**
31 |
32 | ```
33 | > inspect-json https://api.github.com/users/mbostock
34 | ```
35 |
36 | **Standard Input (CLI):**
37 |
38 | ```
39 | > echo { "test": true } | inspect-json
40 | ```
41 |
42 | **Inspecting webpack output stats:**
43 |
44 | Let's say you have a webpack stats object that you want to analyse. How would you go about doing that? Just pipe it into `inspect-json`
45 |
46 | ```
47 | > webpack --stats | inspect-json
48 | ```
49 |
50 |
51 |
52 | ## License
53 |
54 | [MIT][license-url]
55 |
56 | [version-image]: https://img.shields.io/npm/v/inspect-json.svg?style=flat-square
57 | [version-url]: https://npmjs.org/package/inspect-json
58 |
59 | [downloads-image]: https://img.shields.io/npm/dm/inspect-json.svg?style=flat-square
60 | [downloads-url]: https://npmjs.org/package/inspect-json
61 |
62 | [david-image]: http://img.shields.io/david/queckezz/inspect-json.svg?style=flat-square
63 | [david-url]: https://david-dm.org/queckezz/inspect-json
64 |
65 | [standard-image]: https://img.shields.io/badge/code-standard-brightgreen.svg?style=flat-square
66 | [standard-url]: https://github.com/feross/standard
67 |
68 | [license-image]: http://img.shields.io/npm/l/inspect-json.svg?style=flat-square
69 | [license-url]: ./license
--------------------------------------------------------------------------------
/src/cli.js:
--------------------------------------------------------------------------------
1 | #! /usr/bin/env node
2 | const { readFileSync } = require('fs')
3 | const getStdin = require('get-stdin')
4 | const minimist = require('minimist')
5 | const { join } = require('path')
6 | const execa = require('execa')
7 |
8 | const help = () => `
9 | Usage:
10 | inspect-json [file|url]
11 |
12 | Examples:
13 | https://github.com/queckezz/inspect-json#examples
14 | `
15 |
16 | const mainProcess = join(__dirname, 'index.js')
17 |
18 | const args = minimist(process.argv.slice(2), {
19 | alias: { h: 'help', v: 'version' }
20 | })
21 |
22 | if (args.help) return console.log(help())
23 |
24 | if (args.version) {
25 | const contents = readFileSync(join(__dirname, '../package.json'), 'utf-8')
26 | return console.log(JSON.parse(contents).version)
27 | }
28 |
29 | const source = args._[0]
30 |
31 | if (!source) {
32 | getStdin().then((str) => {
33 | if (str.length == 0) {
34 | return console.log(help())
35 | }
36 | try {
37 | const json = JSON.parse(str)
38 | execa('electron', [mainProcess, JSON.stringify(json)])
39 | } catch (e) {
40 | console.error(e)
41 | }
42 | })
43 | } else {
44 | execa('electron', [mainProcess, source])
45 | }
46 |
--------------------------------------------------------------------------------
/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Electron JSON Viewer
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 |
2 | const { BrowserWindow, app } = require('electron')
3 | const { ipcMain } = require('electron')
4 | const { readFile } = require('mz/fs')
5 | const { watch } = require('chokidar')
6 | const minimist = require('minimist')
7 | const { resolve } = require('path')
8 | const isUrl = require('is-url')
9 | const got = require('got')
10 |
11 | const argv = minimist(process.argv.slice(2))
12 | let win = null
13 |
14 | const emitFromFile = (source, renderer) => {
15 | return readFile(source)
16 | .then(JSON.parse)
17 | .then((json) => {
18 | renderer.send('json', { file: true, source, json })
19 | })
20 | .catch((error) => {
21 | renderer.send('error', { file: true, source, error })
22 | })
23 | }
24 |
25 | const emitFromHttp = (source, renderer) => {
26 | return got(source, { json: true })
27 | .then((res) => res.body)
28 | .then((json) => {
29 | renderer.send('json', { source, json })
30 | })
31 | .catch((error) => {
32 | renderer.send('error', { source, error })
33 | })
34 | }
35 |
36 | app.on('ready', () => {
37 | const source = argv._[0]
38 |
39 | win = new BrowserWindow({
40 | useContentSize: true,
41 | width: 0,
42 | height: 0,
43 | x: 0,
44 | y: 0
45 | })
46 |
47 | const renderer = win.webContents
48 |
49 | win.loadURL(`file://${__dirname}/index.html`)
50 |
51 | win.on('closed', () => {
52 | win = null
53 | })
54 |
55 | renderer.on('did-finish-load', () => {
56 | try {
57 | const json = JSON.parse(source)
58 | renderer.send('json', { source: 'stdin', json })
59 | } catch (e) {
60 | if (isUrl(source)) {
61 | emitFromHttp(source, renderer)
62 | } else {
63 | const fileSource = resolve(process.cwd(), source)
64 | const watcher = watch(fileSource)
65 |
66 | watcher.on('change', () => {
67 | emitFromFile(fileSource, renderer)
68 | })
69 |
70 | emitFromFile(fileSource, renderer)
71 | }
72 | }
73 | })
74 |
75 | renderer.once('devtools-opened', (t) => {
76 | win.hide()
77 | })
78 |
79 | renderer.once('devtools-closed', (t) => {
80 | setImmediate(app.exit)
81 | })
82 |
83 | renderer.openDevTools({ mode: 'undocked' })
84 | })
--------------------------------------------------------------------------------
/src/renderer.js:
--------------------------------------------------------------------------------
1 |
2 | const { ipcRenderer } = require('electron')
3 |
4 | const pad = (str = '') => ' ' + str
5 |
6 | const render = ({ file, source, json, error }) => {
7 | if (window.json || error) {
8 | console.clear()
9 | }
10 |
11 | if (file) {
12 | console.log('%c✔ Reloads on changes', 'color: #94d82d;')
13 | }
14 |
15 | console.log(
16 | `%cInspecting %c${source}`,
17 | 'font-weight: normal; background: #f1f3f5; color: #91a7ff',
18 | 'font-weight: bold; background: #f1f3f5; color: #91a7ff'
19 | )
20 |
21 | console.log(
22 | pad('%c(Also accessible through %cwindow.json)'),
23 | 'color: #adb5bd;',
24 | 'color: #adb5bd; font-weight: bold;'
25 | )
26 |
27 | if (error) {
28 | console.error(error)
29 | } else {
30 | console.log(pad(), json)
31 | }
32 | }
33 |
34 | ipcRenderer.on('json', (event, data) => {
35 | render(data)
36 | window.json = data.json
37 | })
38 |
39 | ipcRenderer.on('error', (event, data) => {
40 | render(data)
41 | })
42 |
--------------------------------------------------------------------------------