├── .babelrc
├── .eslintrc
├── .gitignore
├── .jshintrc
├── .npmignore
├── .travis.yml
├── HEAD
├── HISTORY.md
├── LICENSE
├── README.md
├── build
├── react-object-inspector.js
└── react-object-inspector.map
├── example
├── App.js
├── bundle.js
├── index.html
└── index.js
├── karma.conf.js
├── package.json
├── server.js
├── src
├── ObjectDescription.js
├── ObjectInspector.js
├── ObjectPreview.js
└── objectStyles.js
├── test
├── index.js
└── objectDescription-test.js
├── webpack.config.js
└── webpack.prod.config.js
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "stage": 0
3 | }
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "ecmaFeatures": {
3 | "jsx": true,
4 | "modules": true
5 | },
6 | "env": {
7 | "browser": true,
8 | "node": true
9 | },
10 | "parser": "babel-eslint",
11 | "rules": {
12 | // "quotes": [2, "single"],
13 | // "strict": [2, "never"],
14 | "no-var": 0,
15 | "react/jsx-uses-react": 2,
16 | "react/jsx-uses-vars": 2,
17 | "react/react-in-jsx-scope": 2
18 | },
19 | "plugins": [
20 | "react"
21 | ]
22 | }
23 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | npm-debug.log
3 | .DS_Store
4 | jsconfig.json
5 |
6 | react-codemod
7 | dev
8 | lib
9 | gh-pages/
10 |
--------------------------------------------------------------------------------
/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "node": true,
3 | "browser": true,
4 | "esnext": true,
5 | "newcap": false
6 | }
7 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | .eslintrc
2 | .gitignore
3 | .npmignore
4 | jsconfig.json
5 |
6 | react-codemod
7 | dev
8 | gh-pages
9 |
10 | build/
11 | example
12 | server.js
13 | src/
14 | webpack.config.js
15 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - "4"
4 | - "5"
5 | script:
6 | - npm run lint
7 | - npm test
8 | - npm run build
9 | before_install:
10 | - "export DISPLAY=:99.0"
11 | - "sh -e /etc/init.d/xvfb start"
--------------------------------------------------------------------------------
/HEAD:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xyc/react-object-inspector/d76a18474524c3721809abb309032ce5af102aa6/HEAD
--------------------------------------------------------------------------------
/HISTORY.md:
--------------------------------------------------------------------------------
1 | ## 0.2.0 (11/26/2015)
2 | - issue #4: inline styles
3 | - issue #5: Initial expanded paths
4 |
5 | ## 0.1.6 (10/26/2015)
6 | - Upgrade to React 0.14
7 |
8 | ## 0.1.5 (09/10/2015)
9 | - Display dates in string form
10 | - Resolve issue #6 "undefined" is rendered as Object
11 |
12 | ## 0.1.0 (08/06/2015)
13 | - Initial release.
14 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Xiaoyi Chen
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [DEPRECATION WARNING] future development will be at https://github.com/xyc/react-inspector
2 |
3 | react-object-inspector
4 | =====================
5 |
6 | [](https://travis-ci.org/xyc/react-object-inspector)
7 | [](https://www.npmjs.com/package/react-object-inspector)
8 | [](https://www.npmjs.com/package/react-object-inspector)
9 |
10 | Simple object inspector made with [React](http://facebook.github.io/react/) styled similarly to [Chrome DevTools](https://developer.chrome.com/devtools). You can use this tool to inspect Javascript Objects as an alternative to `
JSON.stringify(data, null, 2)
`. Check out the playground [here](http://xyc.github.io/react-object-inspector/)
11 |
12 | 
13 |
14 | Tree state is saved at root. If you click to expand some elements in the hierarchy, the state will be preserved after the element is unmounted.
15 |
16 | ### Install
17 |
18 | NPM:
19 | ```sh
20 | npm install react-object-inspector
21 | ```
22 |
23 | Starting from 0.2.0, react-object-inspector uses inline styles and you don't need to include any additional CSS files.
24 |
25 | ## API
26 | #### <ObjectInspector />
27 | The component accepts the following props:
28 | #### `data`: the Javascript object you would like to inspect
29 |
30 | #### `name`: specify the name of the root node, default to `undefined`
31 |
32 | #### `initialExpandedPaths`: an array containing all the paths that should be expanded when the component is initialized.
33 | - A path is a dot separated string like `root.foo.bar`
34 | - By default you can refer to root's path as `'root'`, or the name prop if name is defined
35 | - For example, `['root']` expands the first level nodes
36 | - `['myCustomName']` can also expand the first level nodes if the component is setup as ``.
37 | - `['root.foo.bar']` expands the path `root.foo.bar` if `root.foo.bar` is an existing property
38 | - You can use wildcard to expand all paths on a specific level
39 | - For example, to expand all first level and second level nodes, use `['root', 'root.*']`
40 |
41 |
42 | ### Usage
43 | ```js
44 | import ObjectInspector from 'react-object-inspector';
45 | let data = { /* ... */ };
46 |
47 | React.render(
48 | ,
49 | document.getElementById('objectInspector')
50 | );
51 | ```
52 | One common usage is embedding this in a component's render() method to provide a view for its props/state.
53 |
54 | ### Install the example
55 | ```sh
56 | npm install && npm start
57 | ```
58 | Open http://localhost:3000/example/index.html
59 |
--------------------------------------------------------------------------------
/build/react-object-inspector.js:
--------------------------------------------------------------------------------
1 | (function webpackUniversalModuleDefinition(root, factory) {
2 | if(typeof exports === 'object' && typeof module === 'object')
3 | module.exports = factory(require("react"));
4 | else if(typeof define === 'function' && define.amd)
5 | define(["react"], factory);
6 | else if(typeof exports === 'object')
7 | exports["ObjectInspector"] = factory(require("react"));
8 | else
9 | root["ObjectInspector"] = factory(root["React"]);
10 | })(this, function(__WEBPACK_EXTERNAL_MODULE_1__) {
11 | return /******/ (function(modules) { // webpackBootstrap
12 | /******/ // The module cache
13 | /******/ var installedModules = {};
14 | /******/
15 | /******/ // The require function
16 | /******/ function __webpack_require__(moduleId) {
17 | /******/
18 | /******/ // Check if module is in cache
19 | /******/ if(installedModules[moduleId])
20 | /******/ return installedModules[moduleId].exports;
21 | /******/
22 | /******/ // Create a new module (and put it into the cache)
23 | /******/ var module = installedModules[moduleId] = {
24 | /******/ exports: {},
25 | /******/ id: moduleId,
26 | /******/ loaded: false
27 | /******/ };
28 | /******/
29 | /******/ // Execute the module function
30 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
31 | /******/
32 | /******/ // Flag the module as loaded
33 | /******/ module.loaded = true;
34 | /******/
35 | /******/ // Return the exports of the module
36 | /******/ return module.exports;
37 | /******/ }
38 | /******/
39 | /******/
40 | /******/ // expose the modules object (__webpack_modules__)
41 | /******/ __webpack_require__.m = modules;
42 | /******/
43 | /******/ // expose the module cache
44 | /******/ __webpack_require__.c = installedModules;
45 | /******/
46 | /******/ // __webpack_public_path__
47 | /******/ __webpack_require__.p = "build/";
48 | /******/
49 | /******/ // Load entry module and return exports
50 | /******/ return __webpack_require__(0);
51 | /******/ })
52 | /************************************************************************/
53 | /******/ ([
54 | /* 0 */
55 | /***/ function(module, exports, __webpack_require__) {
56 |
57 | 'use strict';
58 |
59 | Object.defineProperty(exports, '__esModule', {
60 | value: true
61 | });
62 |
63 | var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
64 |
65 | var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
66 |
67 | var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } };
68 |
69 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
70 |
71 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
72 |
73 | function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
74 |
75 | var _react = __webpack_require__(1);
76 |
77 | var _react2 = _interopRequireDefault(_react);
78 |
79 | var _ObjectDescription = __webpack_require__(2);
80 |
81 | var _ObjectDescription2 = _interopRequireDefault(_ObjectDescription);
82 |
83 | var _ObjectPreview = __webpack_require__(4);
84 |
85 | var _ObjectPreview2 = _interopRequireDefault(_ObjectPreview);
86 |
87 | // Constants
88 |
89 | // Styles
90 |
91 | var _objectStyles = __webpack_require__(3);
92 |
93 | var _objectStyles2 = _interopRequireDefault(_objectStyles);
94 |
95 | var DEFAULT_ROOT_PATH = 'root';
96 | var styles = {
97 | base: {
98 | fontFamily: 'Menlo, monospace',
99 | fontSize: '11px',
100 | lineHeight: '14px',
101 | cursor: 'default'
102 | },
103 | propertyNodesContainer: {
104 | paddingLeft: '12px'
105 | },
106 | unselectable: {
107 | WebkitTouchCallout: 'none',
108 | WebkitUserSelect: 'none',
109 | KhtmlUserSelect: 'none',
110 | MozUserSelect: 'none',
111 | msUserSelect: 'none',
112 | OUserSelect: 'none',
113 | userSelect: 'none'
114 | },
115 | expandControl: {
116 | color: '#6e6e6e',
117 | fontSize: '10px',
118 | marginRight: '3px',
119 | whiteSpace: 'pre'
120 | },
121 | property: {
122 | paddingTop: '2px'
123 | }
124 | };
125 |
126 | var ObjectInspector = (function (_Component) {
127 | _inherits(ObjectInspector, _Component);
128 |
129 | _createClass(ObjectInspector, null, [{
130 | key: 'defaultProps',
131 | // path is dot separated property names to reach the current node
132 | value: {
133 | name: void 0,
134 | data: undefined,
135 | initialExpandedPaths: undefined,
136 | depth: 0,
137 | path: DEFAULT_ROOT_PATH
138 | },
139 | enumerable: true
140 | }]);
141 |
142 | function ObjectInspector(props) {
143 | var _this = this;
144 |
145 | _classCallCheck(this, ObjectInspector);
146 |
147 | _get(Object.getPrototypeOf(ObjectInspector.prototype), 'constructor', this).call(this, props);
148 |
149 | if (props.depth === 0) {
150 | this.state = { expandedPaths: {} };
151 | this.state.expandedPaths[props.path] = false;
152 |
153 | // initialize expandedPaths with initialExpandedPaths
154 | if (typeof props.initialExpandedPaths !== 'undefined') {
155 | props.initialExpandedPaths.map(function (expandedPath) {
156 | if (typeof expandedPath === 'string') {
157 | (function () {
158 | var wildcardPathToPaths = function wildcardPathToPaths(curObject, curPath, i) {
159 | var WILDCARD = "*";
160 | if (i === names.length) {
161 | paths.push(curPath);
162 | return;
163 | }
164 | var name = names[i];
165 | if (i === 0) {
166 | if (name === props.name || name === DEFAULT_ROOT_PATH || name === WILDCARD) {
167 | wildcardPathToPaths(curObject, 'root', i + 1);
168 | }
169 | } else {
170 | if (name === WILDCARD) {
171 | for (var propertyName in curObject) {
172 | if (curObject.hasOwnProperty(propertyName)) {
173 | var propertyValue = curObject[propertyName];
174 | if (ObjectInspector.isExpandable(propertyValue)) {
175 | wildcardPathToPaths(propertyValue, curPath + '.' + propertyName, i + 1);
176 | } else {
177 | continue;
178 | }
179 | }
180 | }
181 | } else {
182 | var propertyValue = curObject[name];
183 | if (ObjectInspector.isExpandable(propertyValue)) {
184 | wildcardPathToPaths(propertyValue, curPath + '.' + name, i + 1);
185 | }
186 | }
187 | }
188 | };
189 |
190 | var names = expandedPath.split('.'); // wildcard names
191 | var paths = [];
192 |
193 | wildcardPathToPaths(props.data, '', 0);
194 |
195 | paths.map(function (path) {
196 | _this.state.expandedPaths[path] = true;
197 | });
198 | })();
199 | }
200 | });
201 | }
202 | }
203 | }
204 |
205 | _createClass(ObjectInspector, [{
206 | key: 'getExpanded',
207 | value: function getExpanded(path) {
208 | var expandedPaths = this.state.expandedPaths;
209 | if (typeof expandedPaths[path] !== 'undefined') {
210 | return expandedPaths[path];
211 | }
212 | return false;
213 | }
214 | }, {
215 | key: 'setExpanded',
216 | value: function setExpanded(path, expanded) {
217 | var expandedPaths = this.state.expandedPaths;
218 | expandedPaths[path] = expanded;
219 | this.setState({ expandedPaths: expandedPaths });
220 | }
221 | }, {
222 | key: 'handleClick',
223 | value: function handleClick() {
224 | // console.log(this.props.data);
225 | if (ObjectInspector.isExpandable(this.props.data)) {
226 | if (this.props.depth > 0) {
227 | this.props.setExpanded(this.props.path, !this.props.getExpanded(this.props.path));
228 | } else {
229 | this.setExpanded(this.props.path, !this.getExpanded(this.props.path));
230 | }
231 | }
232 | }
233 | }, {
234 | key: 'componentWillMount',
235 | value: function componentWillMount() {
236 | if (typeof _react2['default'].initializeTouchEvents === 'function') {
237 | _react2['default'].initializeTouchEvents(true);
238 | }
239 | }
240 | }, {
241 | key: 'render',
242 | value: function render() {
243 |
244 | var data = this.props.data;
245 | var name = this.props.name;
246 |
247 | var setExpanded = this.props.depth === 0 ? this.setExpanded.bind(this) : this.props.setExpanded;
248 | var getExpanded = this.props.depth === 0 ? this.getExpanded.bind(this) : this.props.getExpanded;
249 | var expanded = getExpanded(this.props.path);
250 |
251 | var expandGlyph = ObjectInspector.isExpandable(data) ? expanded ? '▼' : '▶' : this.props.depth === 0 ? '' // unnamed root node
252 | : ' ';
253 |
254 | var propertyNodesContainer = undefined;
255 | if (expanded) {
256 | var propertyNodes = [];
257 |
258 | for (var propertyName in data) {
259 | var propertyValue = data[propertyName];
260 | if (data.hasOwnProperty(propertyName)) {
261 | propertyNodes.push(_react2['default'].createElement(ObjectInspector, { getExpanded: getExpanded,
262 | setExpanded: setExpanded,
263 | path: this.props.path + '.' + propertyName,
264 | depth: this.props.depth + 1,
265 | key: propertyName,
266 | name: propertyName,
267 | data: propertyValue }));
268 | }
269 | }
270 | propertyNodesContainer = _react2['default'].createElement(
271 | 'div',
272 | { style: styles.propertyNodesContainer },
273 | propertyNodes
274 | );
275 | }
276 |
277 | return _react2['default'].createElement(
278 | 'div',
279 | { style: styles.base },
280 | _react2['default'].createElement(
281 | 'span',
282 | { style: styles.property, onClick: this.handleClick.bind(this) },
283 | _react2['default'].createElement(
284 | 'span',
285 | { style: _extends({}, styles.expandControl, styles.unselectable) },
286 | expandGlyph
287 | ),
288 | (function () {
289 | if (typeof name !== 'undefined') {
290 | return _react2['default'].createElement(
291 | 'span',
292 | null,
293 | _react2['default'].createElement(
294 | 'span',
295 | { style: _objectStyles2['default'].name },
296 | name
297 | ),
298 | _react2['default'].createElement(
299 | 'span',
300 | null,
301 | ': '
302 | ),
303 | _react2['default'].createElement(_ObjectDescription2['default'], { object: data })
304 | );
305 | } else {
306 | return _react2['default'].createElement(_ObjectPreview2['default'], { object: data });
307 | }
308 | })()
309 | ),
310 | propertyNodesContainer
311 | );
312 | }
313 | }], [{
314 | key: 'isExpandable',
315 | value: function isExpandable(data) {
316 | return typeof data === 'object' && data !== null && Object.keys(data).length > 0;
317 | }
318 | }]);
319 |
320 | return ObjectInspector;
321 | })(_react.Component);
322 |
323 | exports['default'] = ObjectInspector;
324 | module.exports = exports['default'];
325 | // initial paths of the nodes that are visible
326 |
327 | /***/ },
328 | /* 1 */
329 | /***/ function(module, exports) {
330 |
331 | module.exports = __WEBPACK_EXTERNAL_MODULE_1__;
332 |
333 | /***/ },
334 | /* 2 */
335 | /***/ function(module, exports, __webpack_require__) {
336 |
337 | 'use strict';
338 |
339 | Object.defineProperty(exports, '__esModule', {
340 | value: true
341 | });
342 |
343 | var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
344 |
345 | var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } };
346 |
347 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
348 |
349 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
350 |
351 | function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
352 |
353 | var _react = __webpack_require__(1);
354 |
355 | var _react2 = _interopRequireDefault(_react);
356 |
357 | // Styles
358 |
359 | var _objectStyles = __webpack_require__(3);
360 |
361 | var _objectStyles2 = _interopRequireDefault(_objectStyles);
362 |
363 | /**
364 | * A short description of the object
365 | */
366 |
367 | var ObjectDescription = (function (_Component) {
368 | _inherits(ObjectDescription, _Component);
369 |
370 | function ObjectDescription() {
371 | _classCallCheck(this, ObjectDescription);
372 |
373 | _get(Object.getPrototypeOf(ObjectDescription.prototype), 'constructor', this).apply(this, arguments);
374 | }
375 |
376 | _createClass(ObjectDescription, [{
377 | key: 'render',
378 | value: function render() {
379 | var object = this.props.object;
380 | switch (typeof object) {
381 | case 'number':
382 | return _react2['default'].createElement(
383 | 'span',
384 | { style: _objectStyles2['default'].value.number },
385 | object
386 | );
387 | case 'string':
388 | return _react2['default'].createElement(
389 | 'span',
390 | { style: _objectStyles2['default'].value.string },
391 | '"',
392 | object,
393 | '"'
394 | );
395 | case 'boolean':
396 | return _react2['default'].createElement(
397 | 'span',
398 | { style: _objectStyles2['default'].value.boolean },
399 | String(object)
400 | );
401 | case 'undefined':
402 | return _react2['default'].createElement(
403 | 'span',
404 | { style: _objectStyles2['default'].value.undefined },
405 | 'undefined'
406 | );
407 | case 'object':
408 | if (object === null) {
409 | return _react2['default'].createElement(
410 | 'span',
411 | { style: _objectStyles2['default'].value['null'] },
412 | 'null'
413 | );
414 | }
415 | if (object instanceof Date) {
416 | return _react2['default'].createElement(
417 | 'span',
418 | null,
419 | object.toString()
420 | );
421 | }
422 | if (Array.isArray(object)) {
423 | return _react2['default'].createElement(
424 | 'span',
425 | null,
426 | 'Array[' + object.length + ']'
427 | );
428 | }
429 | return _react2['default'].createElement(
430 | 'span',
431 | null,
432 | 'Object'
433 | );
434 | case 'function':
435 | return _react2['default'].createElement(
436 | 'span',
437 | null,
438 | _react2['default'].createElement(
439 | 'span',
440 | { style: _objectStyles2['default'].value['function'].keyword },
441 | 'function'
442 | ),
443 | _react2['default'].createElement(
444 | 'span',
445 | { style: _objectStyles2['default'].value['function'].name },
446 | ' ',
447 | object.name,
448 | '()'
449 | )
450 | );
451 | case 'symbol':
452 | return _react2['default'].createElement(
453 | 'span',
454 | { style: _objectStyles2['default'].value.symbol },
455 | 'Symbol()'
456 | );
457 | default:
458 | return _react2['default'].createElement('span', null);
459 | }
460 | }
461 | }]);
462 |
463 | return ObjectDescription;
464 | })(_react.Component);
465 |
466 | exports['default'] = ObjectDescription;
467 | module.exports = exports['default'];
468 |
469 | /***/ },
470 | /* 3 */
471 | /***/ function(module, exports) {
472 |
473 | 'use strict';
474 |
475 | Object.defineProperty(exports, '__esModule', {
476 | value: true
477 | });
478 | exports['default'] = {
479 | name: {
480 | color: 'rgb(136, 19, 145)'
481 | },
482 | value: {
483 | 'null': {
484 | color: 'rgb(128, 128, 128)'
485 | },
486 | undefined: {
487 | color: 'rgb(128, 128, 128)'
488 | },
489 | string: {
490 | color: 'rgb(196, 26, 22)'
491 | },
492 | symbol: {
493 | color: 'rgb(196, 26, 22)'
494 | },
495 | number: {
496 | color: 'rgb(28, 0, 207)'
497 | },
498 | boolean: {
499 | color: 'rgb(28, 0, 207)'
500 | },
501 | 'function': {
502 | keyword: {
503 | color: 'rgb(170, 13, 145)',
504 | fontStyle: 'italic'
505 | },
506 | name: {
507 | fontStyle: 'italic'
508 | }
509 | }
510 | }
511 | };
512 | module.exports = exports['default'];
513 |
514 | /***/ },
515 | /* 4 */
516 | /***/ function(module, exports, __webpack_require__) {
517 |
518 | 'use strict';
519 |
520 | Object.defineProperty(exports, '__esModule', {
521 | value: true
522 | });
523 |
524 | var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
525 |
526 | var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } };
527 |
528 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
529 |
530 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
531 |
532 | function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
533 |
534 | var _react = __webpack_require__(1);
535 |
536 | var _react2 = _interopRequireDefault(_react);
537 |
538 | var _ObjectDescription = __webpack_require__(2);
539 |
540 | var _ObjectDescription2 = _interopRequireDefault(_ObjectDescription);
541 |
542 | // Styles
543 |
544 | var _objectStyles = __webpack_require__(3);
545 |
546 | var _objectStyles2 = _interopRequireDefault(_objectStyles);
547 |
548 | var styles = {
549 | preview: {
550 | fontStyle: 'italic'
551 | }
552 | };
553 |
554 | function intersperse(arr, sep) {
555 | if (arr.length === 0) {
556 | return [];
557 | }
558 |
559 | return arr.slice(1).reduce(function (xs, x, i) {
560 | return xs.concat([sep, x]);
561 | }, [arr[0]]);
562 | }
563 |
564 | /**
565 | * A preview of the object on root level node
566 | */
567 |
568 | var ObjectPreview = (function (_Component) {
569 | _inherits(ObjectPreview, _Component);
570 |
571 | function ObjectPreview() {
572 | _classCallCheck(this, ObjectPreview);
573 |
574 | _get(Object.getPrototypeOf(ObjectPreview.prototype), 'constructor', this).apply(this, arguments);
575 | }
576 |
577 | _createClass(ObjectPreview, [{
578 | key: 'render',
579 | value: function render() {
580 | var object = this.props.object;
581 | if (typeof object !== 'object' || object === null) {
582 | return _react2['default'].createElement(_ObjectDescription2['default'], { object: object });
583 | }
584 |
585 | if (Array.isArray(object)) {
586 | return _react2['default'].createElement(
587 | 'span',
588 | { style: styles.preview },
589 | '[',
590 | intersperse(object.map(function (element, index) {
591 | return _react2['default'].createElement(_ObjectDescription2['default'], { key: index, object: element });
592 | }), ", "),
593 | ']'
594 | );
595 | } else if (object instanceof Date) {
596 | return _react2['default'].createElement(
597 | 'span',
598 | null,
599 | object.toString()
600 | );
601 | } else {
602 | var propertyNodes = [];
603 | for (var propertyName in object) {
604 | var propertyValue = object[propertyName];
605 | if (object.hasOwnProperty(propertyName)) {
606 | var ellipsis = undefined;
607 | if (propertyNodes.length === this.props.maxProperties - 1 && Object.keys(object).length > this.props.maxProperties) {
608 | ellipsis = _react2['default'].createElement(
609 | 'span',
610 | { key: 'ellipsis' },
611 | '…'
612 | );
613 | }
614 | propertyNodes.push(_react2['default'].createElement(
615 | 'span',
616 | { key: propertyName },
617 | _react2['default'].createElement(
618 | 'span',
619 | { style: _objectStyles2['default'].name },
620 | propertyName
621 | ),
622 | ': ',
623 | _react2['default'].createElement(_ObjectDescription2['default'], { object: propertyValue }),
624 | ellipsis
625 | ));
626 | if (ellipsis) break;
627 | }
628 | }
629 |
630 | return _react2['default'].createElement(
631 | 'span',
632 | { style: styles.preview },
633 | 'Object {',
634 | intersperse(propertyNodes, ", "),
635 | '}'
636 | );
637 | }
638 | }
639 | }], [{
640 | key: 'defaultProps',
641 | // maximum properties displayed in preview
642 | value: {
643 | maxProperties: 5
644 | },
645 | enumerable: true
646 | }]);
647 |
648 | return ObjectPreview;
649 | })(_react.Component);
650 |
651 | exports['default'] = ObjectPreview;
652 | module.exports = exports['default'];
653 |
654 | /***/ }
655 | /******/ ])
656 | });
657 | ;
658 | //# sourceMappingURL=react-object-inspector.map
--------------------------------------------------------------------------------
/build/react-object-inspector.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["webpack:///webpack/universalModuleDefinition","webpack:///webpack/bootstrap b7d41dad084c183d9993","webpack:///./src/ObjectInspector.js","webpack:///external {\"root\":\"React\",\"commonjs2\":\"react\",\"commonjs\":\"react\",\"amd\":\"react\"}","webpack:///./src/ObjectDescription.js","webpack:///./src/objectStyles.js","webpack:///./src/ObjectPreview.js"],"names":[],"mappings":"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","file":"react-object-inspector.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory(require(\"react\"));\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([\"react\"], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"ObjectInspector\"] = factory(require(\"react\"));\n\telse\n\t\troot[\"ObjectInspector\"] = factory(root[\"React\"]);\n})(this, function(__WEBPACK_EXTERNAL_MODULE_1__) {\nreturn \n\n\n/** WEBPACK FOOTER **\n ** webpack/universalModuleDefinition\n **/"," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId])\n \t\t\treturn installedModules[moduleId].exports;\n\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\texports: {},\n \t\t\tid: moduleId,\n \t\t\tloaded: false\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.loaded = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"build/\";\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(0);\n\n\n\n/** WEBPACK FOOTER **\n ** webpack/bootstrap b7d41dad084c183d9993\n **/","import React, { Component } from 'react';\n\nimport ObjectDescription from './ObjectDescription';\nimport ObjectPreview from './ObjectPreview';\n\n// Constants\nconst DEFAULT_ROOT_PATH='root';\n\n// Styles\nimport objectStyles from './objectStyles';\nconst styles = {\n base: {\n fontFamily: 'Menlo, monospace',\n fontSize: '11px',\n lineHeight: '14px',\n cursor: 'default',\n },\n propertyNodesContainer: {\n paddingLeft: '12px',\n },\n unselectable: {\n WebkitTouchCallout: 'none',\n WebkitUserSelect: 'none',\n KhtmlUserSelect: 'none',\n MozUserSelect: 'none',\n msUserSelect: 'none',\n OUserSelect: 'none',\n userSelect: 'none',\n },\n expandControl: {\n color: '#6e6e6e',\n fontSize: '10px',\n marginRight: '3px',\n whiteSpace: 'pre',\n },\n property: {\n paddingTop: '2px',\n },\n};\n\nexport default class ObjectInspector extends Component {\n\n propTypes: {\n name: PropTypes.string,\n data: PropTypes.object,\n initialExpandedPaths: PropTypes.array, // initial paths of the nodes that are visible\n depth: PropTypes.number.isRequired,\n path: PropTypes.string // path is dot separated property names to reach the current node\n }\n\n static defaultProps = {\n name: void 0,\n data: undefined,\n initialExpandedPaths: undefined,\n depth: 0,\n path: DEFAULT_ROOT_PATH\n }\n\n constructor(props) {\n super(props);\n\n if(props.depth === 0){\n this.state = {expandedPaths: {}};\n this.state.expandedPaths[props.path] = false;\n\n // initialize expandedPaths with initialExpandedPaths\n if(typeof props.initialExpandedPaths !== 'undefined'){\n props.initialExpandedPaths.map((expandedPath)=>{\n if(typeof expandedPath === 'string'){\n const names = expandedPath.split('.'); // wildcard names\n const paths = [];\n function wildcardPathToPaths(curObject, curPath, i){\n const WILDCARD = \"*\";\n if(i === names.length){\n paths.push(curPath);\n return;\n }\n const name = names[i];\n if(i === 0){\n if(name === props.name || name === DEFAULT_ROOT_PATH || name === WILDCARD){\n wildcardPathToPaths(curObject, 'root', i + 1);\n }\n }\n else{\n if(name === WILDCARD){\n for(const propertyName in curObject){\n if(curObject.hasOwnProperty(propertyName)){\n const propertyValue = curObject[propertyName];\n if(ObjectInspector.isExpandable(propertyValue)){\n wildcardPathToPaths(propertyValue, curPath + '.' + propertyName, i + 1);\n }\n else{\n continue;\n }\n }\n }\n }\n else{\n const propertyValue = curObject[name];\n if(ObjectInspector.isExpandable(propertyValue)){\n wildcardPathToPaths(propertyValue, curPath + '.' + name, i + 1);\n }\n }\n }\n }\n wildcardPathToPaths(props.data, '', 0);\n\n paths.map((path)=>{\n this.state.expandedPaths[path] = true;\n })\n }\n });\n }\n }\n }\n\n static isExpandable(data){\n return (typeof data === 'object' && data !== null && Object.keys(data).length > 0);\n }\n\n getExpanded(path){\n const expandedPaths = this.state.expandedPaths;\n if (typeof expandedPaths[path] !== 'undefined') {\n return expandedPaths[path];\n }\n return false;\n }\n\n setExpanded(path, expanded){\n const expandedPaths = this.state.expandedPaths;\n expandedPaths[path] = expanded;\n this.setState({expandedPaths: expandedPaths});\n }\n\n handleClick() {\n // console.log(this.props.data);\n if (ObjectInspector.isExpandable(this.props.data)) {\n if (this.props.depth > 0) {\n this.props.setExpanded(this.props.path, !this.props.getExpanded(this.props.path));\n }\n else{\n this.setExpanded(this.props.path, !this.getExpanded(this.props.path));\n }\n }\n }\n\n componentWillMount(){\n if (typeof React.initializeTouchEvents === 'function') {\n React.initializeTouchEvents(true);\n }\n }\n\n render() {\n\n const data = this.props.data;\n const name = this.props.name;\n\n const setExpanded = (this.props.depth === 0) ? (this.setExpanded.bind(this)) : this.props.setExpanded;\n const getExpanded = (this.props.depth === 0) ? (this.getExpanded.bind(this)) : this.props.getExpanded;\n const expanded = getExpanded(this.props.path);\n\n const expandGlyph = ObjectInspector.isExpandable(data) ? (expanded ? '▼'\n : '▶')\n : (this.props.depth === 0 ? '' // unnamed root node\n : ' ');\n\n let propertyNodesContainer;\n if(expanded){\n let propertyNodes = [];\n\n for(let propertyName in data){\n const propertyValue = data[propertyName];\n if(data.hasOwnProperty(propertyName)){\n propertyNodes.push();\n }\n }\n propertyNodesContainer = ({propertyNodes}
);\n }\n\n return (\n \n \n {expandGlyph}\n {(() => {\n if (typeof name !== 'undefined') {\n return (\n {name}\n : \n \n );\n }\n else{\n return ();\n }\n })()}\n \n {propertyNodesContainer}\n
\n );\n }\n}\n\n\n\n/** WEBPACK FOOTER **\n ** ./src/ObjectInspector.js\n **/","module.exports = __WEBPACK_EXTERNAL_MODULE_1__;\n\n\n/*****************\n ** WEBPACK FOOTER\n ** external {\"root\":\"React\",\"commonjs2\":\"react\",\"commonjs\":\"react\",\"amd\":\"react\"}\n ** module id = 1\n ** module chunks = 0\n **/","import React, { Component } from 'react';\n\n// Styles\nimport objectStyles from './objectStyles';\n\n/**\n * A short description of the object\n */\nexport default class ObjectDescription extends Component{\n render() {\n const object = this.props.object;\n switch (typeof object){\n case 'number':\n return ({object});\n case 'string':\n return ("{object}");\n case 'boolean':\n return ({String(object)});\n case 'undefined':\n return (undefined);\n case 'object':\n if(object === null){\n return (null)\n }\n if(object instanceof Date){\n return ({object.toString()});\n }\n if(Array.isArray(object)){\n return ({`Array[${object.length}]`});\n }\n return (Object);\n case 'function':\n return (\n function\n {object.name}()\n );\n case 'symbol':\n return (Symbol())\n default:\n return ();\n }\n }\n}\n\n\n\n/** WEBPACK FOOTER **\n ** ./src/ObjectDescription.js\n **/","export default {\n name: {\n color: 'rgb(136, 19, 145)',\n },\n value: {\n null: {\n color: 'rgb(128, 128, 128)',\n },\n undefined: {\n color: 'rgb(128, 128, 128)',\n },\n string: {\n color: 'rgb(196, 26, 22)',\n },\n symbol: {\n color: 'rgb(196, 26, 22)',\n },\n number: {\n color: 'rgb(28, 0, 207)',\n },\n boolean: {\n color: 'rgb(28, 0, 207)',\n },\n function: {\n keyword: {\n color: 'rgb(170, 13, 145)',\n fontStyle: 'italic',\n },\n name: {\n fontStyle: 'italic',\n },\n },\n },\n};\n\n\n\n/** WEBPACK FOOTER **\n ** ./src/objectStyles.js\n **/","import React, { Component } from 'react';\n\nimport ObjectDescription from './ObjectDescription';\n\n// Styles\nimport objectStyles from './objectStyles';\nconst styles = {\n preview: {\n fontStyle: 'italic',\n }\n}\n\nfunction intersperse(arr, sep){\n if (arr.length === 0) {\n return [];\n }\n\n return arr.slice(1).reduce(function(xs, x, i) {\n return xs.concat([sep, x]);\n }, [arr[0]]);\n}\n\n/**\n * A preview of the object on root level node\n */\nexport default class ObjectPreview extends Component {\n propTypes: {\n maxProperties: PropTypes.number; // maximum properties displayed in preview\n }\n\n static defaultProps = {\n maxProperties: 5\n }\n\n render() {\n const object = this.props.object;\n if (typeof object !== 'object' || object === null) {\n return ();\n }\n\n if (Array.isArray(object)) {\n return [\n {intersperse(object.map(function(element, index){\n return ()\n }), \", \")}\n ];\n }\n else if (object instanceof Date) {\n return {object.toString()};\n }\n else {\n let propertyNodes = [];\n for(let propertyName in object){\n const propertyValue = object[propertyName];\n if(object.hasOwnProperty(propertyName)){\n let ellipsis;\n if (propertyNodes.length === (this.props.maxProperties - 1)\n && Object.keys(object).length > this.props.maxProperties) {\n ellipsis = (…);\n }\n propertyNodes.push(\n \n {propertyName}\n : \n \n {ellipsis}\n \n );\n if(ellipsis)\n break;\n }\n }\n\n return (\n {'Object {'}\n {intersperse(propertyNodes, \", \")}\n {'}'}\n );\n }\n }\n}\n\n\n\n/** WEBPACK FOOTER **\n ** ./src/ObjectPreview.js\n **/"],"sourceRoot":""}
--------------------------------------------------------------------------------
/example/App.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 |
3 | import ObjectInspector from '../src/ObjectInspector';
4 |
5 | function testFunction(){
6 | console.log("hello world");
7 | }
8 |
9 | export default class App extends Component {
10 |
11 | render() {
12 | const testObject = {
13 | "id": 2,
14 | "name": "An ice sculpture",
15 | // "price": 12.50,
16 | "tags": ["cold", "ice"],
17 | "dimensions": {
18 | "length": 7.0,
19 | "width": 12.0,
20 | "height": 9.5
21 | },
22 | "warehouseLocation": {
23 | "latitude": -78.75,
24 | "longitude": 20.4
25 | }
26 | };
27 |
28 | const test2 = {"employees":[
29 | {"firstName":"John", "lastName":"Doe", "fullTime": true},
30 | {"firstName":"Anna", "lastName":"Smith"},
31 | {"firstName":"Peter", "lastName":"Jones"}
32 | ]};
33 |
34 | const test3 = {
35 | "a1": 1,
36 | "a2": "A2",
37 | "a3": true,
38 | "a4": undefined,
39 | "a5": {
40 | "a5-1": null,
41 | "a5-2": ["a5-2-1", "a5-2-2"],
42 | "a5-3": {}
43 | },
44 | "a6": function(){
45 | console.log("hello world")
46 | },
47 | "a7": new Date("2005-04-03")
48 | };
49 |
50 | const test4 = {
51 | "login": "defunkt",
52 | "id": 2,
53 | "avatar_url": "https://avatars.githubusercontent.com/u/2?v=3",
54 | "gravatar_id": "",
55 | "url": "https://api.github.com/users/defunkt",
56 | "html_url": "https://github.com/defunkt",
57 | "followers_url": "https://api.github.com/users/defunkt/followers",
58 | "following_url": "https://api.github.com/users/defunkt/following{/other_user}",
59 | "gists_url": "https://api.github.com/users/defunkt/gists{/gist_id}",
60 | "starred_url": "https://api.github.com/users/defunkt/starred{/owner}{/repo}",
61 | "subscriptions_url": "https://api.github.com/users/defunkt/subscriptions",
62 | "organizations_url": "https://api.github.com/users/defunkt/orgs",
63 | "repos_url": "https://api.github.com/users/defunkt/repos",
64 | "events_url": "https://api.github.com/users/defunkt/events{/privacy}",
65 | "received_events_url": "https://api.github.com/users/defunkt/received_events",
66 | "type": "User",
67 | "site_admin": true,
68 | "name": "Chris Wanstrath",
69 | "company": "GitHub",
70 | "blog": "http://chriswanstrath.com/",
71 | "location": "San Francisco",
72 | "email": "chris@github.com",
73 | "hireable": true,
74 | "bio": null,
75 | "public_repos": 108,
76 | "public_gists": 280,
77 | "followers": 14509,
78 | "following": 208,
79 | "created_at": "2007-10-20T05:24:19Z",
80 | "updated_at": "2015-08-03T18:05:52Z"
81 | };
82 |
83 | const test5 = {
84 | "glossary": {
85 | "title": "example glossary",
86 | "GlossDiv": {
87 | "title": "S",
88 | "GlossList": {
89 | "GlossEntry": {
90 | "ID": "SGML",
91 | "SortAs": "SGML",
92 | "GlossTerm": "Standard Generalized Markup Language",
93 | "Acronym": "SGML",
94 | "Abbrev": "ISO 8879:1986",
95 | "GlossDef": {
96 | "para": "A meta-markup language, used to create markup languages such as DocBook.",
97 | "GlossSeeAlso": ["GML", "XML"]
98 | },
99 | "GlossSee": "markup"
100 | }
101 | }
102 | }
103 | }
104 | };
105 |
106 | // {
107 | // "a": function(){
108 | // // iife ajax call
109 | // }
110 | // }
111 |
112 | const testObjects = [undefined, testFunction, null, true, false, "testString", 42, NaN, Symbol('foo'), testObject, test2, test3, test4, test5, [], ["a"], ["a", 1], new Date()];
113 |
114 | return (
115 |
116 | {(() => {
117 | // https://facebook.github.io/react/tips/if-else-in-JSX.html
118 | return testObjects.map(function(object, index){
119 | return (
120 |
121 |
122 |
123 |
);
124 | });
125 | })()}
126 |
127 | );
128 | }
129 | }
130 |
--------------------------------------------------------------------------------
/example/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Sample App
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/example/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './App';
4 |
5 | ReactDOM.render(, document.getElementById('root'));
6 |
--------------------------------------------------------------------------------
/karma.conf.js:
--------------------------------------------------------------------------------
1 | // Karma configuration
2 | // Generated on Sun Sep 13 2015 21:58:59 GMT-0700 (PDT)
3 |
4 |
5 | var path = require('path');
6 |
7 | var webpackConfig = {
8 | module: {
9 | loaders: [
10 | {
11 | test: /\.(js|jsx)$/, loader: 'babel', include: [path.resolve('./src'), path.resolve('./test')],
12 | },
13 | ]
14 | }
15 | };
16 |
17 | module.exports = function(config) {
18 | config.set({
19 |
20 | // base path that will be used to resolve all patterns (eg. files, exclude)
21 | basePath: '',
22 |
23 |
24 | // frameworks to use
25 | // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
26 | frameworks: ['jasmine'],
27 |
28 |
29 | // list of files / patterns to load in the browser
30 | files: [
31 | 'test/index.js'
32 | ],
33 |
34 |
35 | // list of files to exclude
36 | exclude: [
37 | ],
38 |
39 | webpack: webpackConfig,
40 | webpackMiddleware: {
41 | noInfo: true
42 | },
43 |
44 | // preprocess matching files before serving them to the browser
45 | // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
46 | preprocessors: {
47 | 'test/index.js': ['webpack'], // run the test bundle through webpack plugin
48 | },
49 |
50 | plugins: [
51 | 'karma-jasmine',
52 | 'karma-phantomjs-launcher',
53 | 'karma-firefox-launcher',
54 | require("karma-webpack")
55 | ],
56 |
57 |
58 | // test results reporter to use
59 | // possible values: 'dots', 'progress'
60 | // available reporters: https://npmjs.org/browse/keyword/karma-reporter
61 | reporters: ['progress'],
62 |
63 |
64 | // web server port
65 | port: 9876,
66 |
67 |
68 | // enable / disable colors in the output (reporters and logs)
69 | colors: true,
70 |
71 |
72 | // level of logging
73 | // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
74 | logLevel: config.LOG_INFO,
75 |
76 |
77 | // enable / disable watching file and executing tests whenever any file changes
78 | autoWatch: true,
79 |
80 |
81 | // start these browsers
82 | // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
83 | browsers: ['PhantomJS', 'Firefox'],
84 |
85 |
86 | // Continuous Integration mode
87 | // if true, Karma captures browsers, runs the tests and exits
88 | singleRun: false
89 | })
90 | }
91 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-object-inspector",
3 | "version": "0.2.1",
4 | "description": "Simple object inspector styled similarly to Chrome DevTools",
5 | "main": "lib/ObjectInspector.js",
6 | "directories": {
7 | "example": "example"
8 | },
9 | "scripts": {
10 | "start": "node server.js",
11 | "build": "babel src --out-dir lib && webpack --config webpack.prod.config.js",
12 | "lint": "eslint lib",
13 | "test": "karma start ./karma.conf.js --single-run",
14 | "clean": "rimraf lib",
15 | "prerelease": "npm run lint && npm run test && npm run clean && npm run build",
16 | "release": ""
17 | },
18 | "repository": {
19 | "type": "git",
20 | "url": "https://github.com/xyc/react-object-inspector.git"
21 | },
22 | "keywords": [
23 | "react",
24 | "reactjs",
25 | "object",
26 | "object-inspector",
27 | "object-inspector",
28 | "treeview",
29 | "tree-view",
30 | "tree",
31 | "view",
32 | "inspector",
33 | "react-component",
34 | "ui"
35 | ],
36 | "author": "Xiaoyi Chen (http://github.com/xyc)",
37 | "license": "MIT",
38 | "bugs": {
39 | "url": "https://github.com/xyc/react-object-inspector/issues"
40 | },
41 | "homepage": "https://github.com/xyc/react-object-inspector",
42 | "devDependencies": {
43 | "babel": "^5.5.8",
44 | "babel-core": "^5.6.18",
45 | "babel-eslint": "^4.1.0",
46 | "babel-loader": "^5.1.4",
47 | "core-js": "^1.1.4",
48 | "css-loader": "^0.23.0",
49 | "es5-shim": "^4.2.0",
50 | "eslint": "^1.7.1",
51 | "eslint-plugin-react": "^2.3.0",
52 | "jasmine-core": "^2.3.4",
53 | "karma": "^0.13.9",
54 | "karma-firefox-launcher": "^0.1.6",
55 | "karma-jasmine": "^0.3.6",
56 | "karma-phantomjs-launcher": "^0.2.1",
57 | "karma-webpack": "^1.7.0",
58 | "phantomjs": "^1.9.18",
59 | "react": "^0.14.2",
60 | "react-addons-test-utils": "^0.14.2",
61 | "react-dom": "^0.14.2",
62 | "react-hot-loader": "^1.2.7",
63 | "style-loader": "^0.13.0",
64 | "rimraf": "^2.4.4",
65 | "webpack": "^1.9.6",
66 | "webpack-dev-server": "^1.8.2"
67 | },
68 | "peerDependencies": {
69 | "react": "^0.14.0"
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/server.js:
--------------------------------------------------------------------------------
1 | var webpack = require('webpack');
2 | var WebpackDevServer = require('webpack-dev-server');
3 | var config = require('./webpack.config');
4 |
5 | new WebpackDevServer(webpack(config), {
6 | publicPath: config.output.publicPath,
7 | hot: true,
8 | historyApiFallback: true
9 | }).listen(3000, 'localhost', function (err, result) {
10 | if (err) {
11 | console.log(err);
12 | }
13 |
14 | console.log('Listening at localhost:3000');
15 | });
16 |
--------------------------------------------------------------------------------
/src/ObjectDescription.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 |
3 | // Styles
4 | import objectStyles from './objectStyles';
5 |
6 | /**
7 | * A short description of the object
8 | */
9 | export default class ObjectDescription extends Component{
10 | render() {
11 | const object = this.props.object;
12 | switch (typeof object){
13 | case 'number':
14 | return ({object});
15 | case 'string':
16 | return ("{object}");
17 | case 'boolean':
18 | return ({String(object)});
19 | case 'undefined':
20 | return (undefined);
21 | case 'object':
22 | if(object === null){
23 | return (null)
24 | }
25 | if(object instanceof Date){
26 | return ({object.toString()});
27 | }
28 | if(Array.isArray(object)){
29 | return ({`Array[${object.length}]`});
30 | }
31 | return (Object);
32 | case 'function':
33 | return (
34 | function
35 | {object.name}()
36 | );
37 | case 'symbol':
38 | return (Symbol())
39 | default:
40 | return ();
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/ObjectInspector.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 |
3 | import ObjectDescription from './ObjectDescription';
4 | import ObjectPreview from './ObjectPreview';
5 |
6 | // Constants
7 | const DEFAULT_ROOT_PATH='root';
8 |
9 | // Styles
10 | import objectStyles from './objectStyles';
11 | const styles = {
12 | base: {
13 | fontFamily: 'Menlo, monospace',
14 | fontSize: '11px',
15 | lineHeight: '14px',
16 | cursor: 'default',
17 | },
18 | propertyNodesContainer: {
19 | paddingLeft: '12px',
20 | },
21 | unselectable: {
22 | WebkitTouchCallout: 'none',
23 | WebkitUserSelect: 'none',
24 | KhtmlUserSelect: 'none',
25 | MozUserSelect: 'none',
26 | msUserSelect: 'none',
27 | OUserSelect: 'none',
28 | userSelect: 'none',
29 | },
30 | expandControl: {
31 | color: '#6e6e6e',
32 | fontSize: '10px',
33 | marginRight: '3px',
34 | whiteSpace: 'pre',
35 | },
36 | property: {
37 | paddingTop: '2px',
38 | },
39 | };
40 |
41 | export default class ObjectInspector extends Component {
42 |
43 | propTypes: {
44 | name: PropTypes.string,
45 | data: PropTypes.object,
46 | initialExpandedPaths: PropTypes.array, // initial paths of the nodes that are visible
47 | depth: PropTypes.number.isRequired,
48 | path: PropTypes.string // path is dot separated property names to reach the current node
49 | }
50 |
51 | static defaultProps = {
52 | name: void 0,
53 | data: undefined,
54 | initialExpandedPaths: undefined,
55 | depth: 0,
56 | path: DEFAULT_ROOT_PATH
57 | }
58 |
59 | constructor(props) {
60 | super(props);
61 |
62 | if(props.depth === 0){
63 | this.state = {expandedPaths: {}};
64 | this.state.expandedPaths[props.path] = false;
65 |
66 | // initialize expandedPaths with initialExpandedPaths
67 | if(typeof props.initialExpandedPaths !== 'undefined'){
68 | props.initialExpandedPaths.map((expandedPath)=>{
69 | if(typeof expandedPath === 'string'){
70 | const names = expandedPath.split('.'); // wildcard names
71 | const paths = [];
72 | function wildcardPathToPaths(curObject, curPath, i){
73 | const WILDCARD = "*";
74 | if(i === names.length){
75 | paths.push(curPath);
76 | return;
77 | }
78 | const name = names[i];
79 | if(i === 0){
80 | if(name === props.name || name === DEFAULT_ROOT_PATH || name === WILDCARD){
81 | wildcardPathToPaths(curObject, 'root', i + 1);
82 | }
83 | }
84 | else{
85 | if(name === WILDCARD){
86 | for(const propertyName in curObject){
87 | if(curObject.hasOwnProperty(propertyName)){
88 | const propertyValue = curObject[propertyName];
89 | if(ObjectInspector.isExpandable(propertyValue)){
90 | wildcardPathToPaths(propertyValue, curPath + '.' + propertyName, i + 1);
91 | }
92 | else{
93 | continue;
94 | }
95 | }
96 | }
97 | }
98 | else{
99 | const propertyValue = curObject[name];
100 | if(ObjectInspector.isExpandable(propertyValue)){
101 | wildcardPathToPaths(propertyValue, curPath + '.' + name, i + 1);
102 | }
103 | }
104 | }
105 | }
106 | wildcardPathToPaths(props.data, '', 0);
107 |
108 | paths.map((path)=>{
109 | this.state.expandedPaths[path] = true;
110 | })
111 | }
112 | });
113 | }
114 | }
115 | }
116 |
117 | static isExpandable(data){
118 | return (typeof data === 'object' && data !== null && Object.keys(data).length > 0);
119 | }
120 |
121 | getExpanded(path){
122 | const expandedPaths = this.state.expandedPaths;
123 | if (typeof expandedPaths[path] !== 'undefined') {
124 | return expandedPaths[path];
125 | }
126 | return false;
127 | }
128 |
129 | setExpanded(path, expanded){
130 | const expandedPaths = this.state.expandedPaths;
131 | expandedPaths[path] = expanded;
132 | this.setState({expandedPaths: expandedPaths});
133 | }
134 |
135 | handleClick() {
136 | // console.log(this.props.data);
137 | if (ObjectInspector.isExpandable(this.props.data)) {
138 | if (this.props.depth > 0) {
139 | this.props.setExpanded(this.props.path, !this.props.getExpanded(this.props.path));
140 | }
141 | else{
142 | this.setExpanded(this.props.path, !this.getExpanded(this.props.path));
143 | }
144 | }
145 | }
146 |
147 | componentWillMount(){
148 | if (typeof React.initializeTouchEvents === 'function') {
149 | React.initializeTouchEvents(true);
150 | }
151 | }
152 |
153 | render() {
154 |
155 | const data = this.props.data;
156 | const name = this.props.name;
157 |
158 | const setExpanded = (this.props.depth === 0) ? (this.setExpanded.bind(this)) : this.props.setExpanded;
159 | const getExpanded = (this.props.depth === 0) ? (this.getExpanded.bind(this)) : this.props.getExpanded;
160 | const expanded = getExpanded(this.props.path);
161 |
162 | const expandGlyph = ObjectInspector.isExpandable(data) ? (expanded ? '▼'
163 | : '▶')
164 | : (this.props.depth === 0 ? '' // unnamed root node
165 | : ' ');
166 |
167 | let propertyNodesContainer;
168 | if(expanded){
169 | let propertyNodes = [];
170 |
171 | for(let propertyName in data){
172 | const propertyValue = data[propertyName];
173 | if(data.hasOwnProperty(propertyName)){
174 | propertyNodes.push();
181 | }
182 | }
183 | propertyNodesContainer = ({propertyNodes}
);
184 | }
185 |
186 | return (
187 |
188 |
189 | {expandGlyph}
190 | {(() => {
191 | if (typeof name !== 'undefined') {
192 | return (
193 | {name}
194 | :
195 |
196 | );
197 | }
198 | else{
199 | return ();
200 | }
201 | })()}
202 |
203 | {propertyNodesContainer}
204 |
205 | );
206 | }
207 | }
208 |
--------------------------------------------------------------------------------
/src/ObjectPreview.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 |
3 | import ObjectDescription from './ObjectDescription';
4 |
5 | // Styles
6 | import objectStyles from './objectStyles';
7 | const styles = {
8 | preview: {
9 | fontStyle: 'italic',
10 | }
11 | }
12 |
13 | function intersperse(arr, sep){
14 | if (arr.length === 0) {
15 | return [];
16 | }
17 |
18 | return arr.slice(1).reduce(function(xs, x, i) {
19 | return xs.concat([sep, x]);
20 | }, [arr[0]]);
21 | }
22 |
23 | /**
24 | * A preview of the object on root level node
25 | */
26 | export default class ObjectPreview extends Component {
27 | propTypes: {
28 | maxProperties: PropTypes.number; // maximum properties displayed in preview
29 | }
30 |
31 | static defaultProps = {
32 | maxProperties: 5
33 | }
34 |
35 | render() {
36 | const object = this.props.object;
37 | if (typeof object !== 'object' || object === null) {
38 | return ();
39 | }
40 |
41 | if (Array.isArray(object)) {
42 | return [
43 | {intersperse(object.map(function(element, index){
44 | return ()
45 | }), ", ")}
46 | ];
47 | }
48 | else if (object instanceof Date) {
49 | return {object.toString()};
50 | }
51 | else {
52 | let propertyNodes = [];
53 | for(let propertyName in object){
54 | const propertyValue = object[propertyName];
55 | if(object.hasOwnProperty(propertyName)){
56 | let ellipsis;
57 | if (propertyNodes.length === (this.props.maxProperties - 1)
58 | && Object.keys(object).length > this.props.maxProperties) {
59 | ellipsis = (…);
60 | }
61 | propertyNodes.push(
62 |
63 | {propertyName}
64 | :
65 |
66 | {ellipsis}
67 |
68 | );
69 | if(ellipsis)
70 | break;
71 | }
72 | }
73 |
74 | return (
75 | {'Object {'}
76 | {intersperse(propertyNodes, ", ")}
77 | {'}'}
78 | );
79 | }
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/src/objectStyles.js:
--------------------------------------------------------------------------------
1 | export default {
2 | name: {
3 | color: 'rgb(136, 19, 145)',
4 | },
5 | value: {
6 | null: {
7 | color: 'rgb(128, 128, 128)',
8 | },
9 | undefined: {
10 | color: 'rgb(128, 128, 128)',
11 | },
12 | string: {
13 | color: 'rgb(196, 26, 22)',
14 | },
15 | symbol: {
16 | color: 'rgb(196, 26, 22)',
17 | },
18 | number: {
19 | color: 'rgb(28, 0, 207)',
20 | },
21 | boolean: {
22 | color: 'rgb(28, 0, 207)',
23 | },
24 | function: {
25 | keyword: {
26 | color: 'rgb(170, 13, 145)',
27 | fontStyle: 'italic',
28 | },
29 | name: {
30 | fontStyle: 'italic',
31 | },
32 | },
33 | },
34 | };
35 |
--------------------------------------------------------------------------------
/test/index.js:
--------------------------------------------------------------------------------
1 | // http://kentor.me/posts/testing-react-and-flux-applications-with-karma-and-webpack/
2 | // ES5 shims for Function.prototype.bind, Object.prototype.keys, etc.
3 | // require('core-js/es5');
4 | require('es5-shim');
5 |
6 | var context = require.context('./', true, /-test\.js$/);
7 | context.keys().forEach(context);
8 |
--------------------------------------------------------------------------------
/test/objectDescription-test.js:
--------------------------------------------------------------------------------
1 | import React, {PropTypes} from 'react';
2 | import ReactDOM from 'react-dom';
3 | import TestUtils from 'react-addons-test-utils';
4 |
5 | const ObjectDescription = require('../src/ObjectDescription');
6 |
7 | describe('ObjectDescription', () => {
8 |
9 | beforeEach(() => {
10 |
11 | });
12 |
13 | it('should render number', () => {
14 | const desc = TestUtils.renderIntoDocument();
15 | const span = TestUtils.findRenderedDOMComponentWithTag(desc, 'span');
16 |
17 | expect(ReactDOM.findDOMNode(span).textContent).toBe("0");
18 | });
19 |
20 | it('should render string with quotes', () => {
21 | const desc = TestUtils.renderIntoDocument();
22 | const span = TestUtils.findRenderedDOMComponentWithTag(desc, 'span');
23 |
24 | expect(ReactDOM.findDOMNode(span).textContent).toBe("\"octocat\"");
25 | });
26 |
27 | it('should render boolean', () => {
28 | for(let value of [true, false]){
29 | const desc = TestUtils.renderIntoDocument();
30 | const span = TestUtils.findRenderedDOMComponentWithTag(desc, 'span');
31 |
32 | expect(ReactDOM.findDOMNode(span).textContent).toBe(value.toString());
33 | }
34 | });
35 |
36 | it('should render undefined', () => {
37 | const desc = TestUtils.renderIntoDocument();
38 | const span = TestUtils.findRenderedDOMComponentWithTag(desc, 'span');
39 |
40 | expect(ReactDOM.findDOMNode(span).textContent).toBe("undefined");
41 | });
42 |
43 | it('shoudl render null', () => {
44 | const desc = TestUtils.renderIntoDocument();
45 | const span = TestUtils.findRenderedDOMComponentWithTag(desc, 'span');
46 |
47 | expect(ReactDOM.findDOMNode(span).textContent).toBe("null");
48 | });
49 |
50 | it('should display date correctly', () => {
51 | const dateString = 'December 17, 1995 03:24:00';
52 | const date = new Date(dateString);
53 | const desc = TestUtils.renderIntoDocument();
54 | const span = TestUtils.findRenderedDOMComponentWithTag(desc, 'span');
55 |
56 | expect(ReactDOM.findDOMNode(span).textContent).toBe((new Date(dateString)).toString());
57 | });
58 |
59 | it('should render array with length information', () => {
60 | const desc = TestUtils.renderIntoDocument();
61 | const span = TestUtils.findRenderedDOMComponentWithTag(desc, 'span');
62 |
63 | expect(ReactDOM.findDOMNode(span).textContent).toBe("Array[5]");
64 | });
65 |
66 | it('should render an empty object', () => {
67 | const desc = TestUtils.renderIntoDocument();
68 | const span = TestUtils.findRenderedDOMComponentWithTag(desc, 'span');
69 |
70 | expect(ReactDOM.findDOMNode(span).textContent).toBe("Object");
71 | });
72 |
73 | it('should render a simple object', () => {
74 | const desc = TestUtils.renderIntoDocument();
75 | const span = TestUtils.findRenderedDOMComponentWithTag(desc, 'span');
76 |
77 | expect(ReactDOM.findDOMNode(span).textContent).toBe("Object");
78 | });
79 |
80 | it('should render an anonymous function', () => {
81 | const desc = TestUtils.renderIntoDocument();
82 | const spans = TestUtils.scryRenderedDOMComponentsWithTag(desc, 'span');
83 |
84 | expect(spans.length).toBe(3);
85 | });
86 |
87 | it('should render a named function', () => {
88 | const desc = TestUtils.renderIntoDocument();
89 | const spans = TestUtils.scryRenderedDOMComponentsWithTag(desc, 'span');
90 |
91 | expect(spans.length).toBe(3);
92 | expect(ReactDOM.findDOMNode(spans[0]).textContent).toBe("function\xa0id()");
93 | });
94 |
95 | // Need phantomjs 2
96 | // it('symbol', () => {
97 | // const desc = TestUtils.renderIntoDocument();
98 | // const span = TestUtils.findRenderedDOMComponentWithTag(desc, 'span');
99 | //
100 | // expect(React.findDOMNode(span).textContent).toBe("Symbol()");
101 | // });
102 |
103 | });
104 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var webpack = require('webpack');
3 |
4 | module.exports = {
5 | devtool: 'eval',
6 | entry: [
7 | 'webpack-dev-server/client?http://localhost:3000',
8 | 'webpack/hot/only-dev-server',
9 | './example/index.js'
10 | ],
11 | output: {
12 | path: path.join(__dirname, 'example'),
13 | filename: 'bundle.js',
14 | publicPath: '/static/'
15 | },
16 | plugins: [
17 | new webpack.HotModuleReplacementPlugin(),
18 | new webpack.NoErrorsPlugin()
19 | ],
20 | resolve: {
21 | extensions: ['', '.js', '.jsx', '.css']
22 | },
23 | module: {
24 | loaders: [
25 | {
26 | test: /\.(js|jsx)$/,
27 | loaders: ['react-hot', 'babel'],
28 | include: [path.join(__dirname, 'src'), path.join(__dirname, 'example')]
29 | },
30 | ]
31 | }
32 | };
33 |
--------------------------------------------------------------------------------
/webpack.prod.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 |
3 | var config = {
4 | devtool: 'sourcemap',
5 | entry: {
6 | index: './src/ObjectInspector.js',
7 | },
8 | output: {
9 | path: path.join(__dirname, 'build'),
10 | publicPath: 'build/',
11 | filename: 'react-object-inspector.js',
12 | sourceMapFilename: 'react-object-inspector.map',
13 | library: 'ObjectInspector',
14 | libraryTarget: 'umd',
15 | },
16 | module: {
17 | loaders: [{
18 | test: /\.(js|jsx)/,
19 | loader: 'babel',
20 | },
21 | ],
22 | },
23 | plugins: [],
24 | resolve: {
25 | extensions: ['', '.js', '.jsx'],
26 | },
27 | externals: {
28 | 'react': {
29 | root: 'React',
30 | commonjs2: 'react',
31 | commonjs: 'react',
32 | amd: 'react',
33 | },
34 | },
35 | };
36 |
37 | module.exports = config;
38 |
--------------------------------------------------------------------------------