From 392fa791ca3ab493696138e41d4bbe83d983087c Mon Sep 17 00:00:00 2001 From: Kiko Beats Date: Fri, 27 Sep 2024 15:10:48 +0200 Subject: [PATCH 1/3] chore(release): 1.23.3 --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d17e98..14205ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +### [1.23.3](https://github.com/microlinkhq/react-json-view/compare/v1.23.2...v1.23.3) (2024-09-27) + + +### Bug Fixes + +* function call ([86bbd60](https://github.com/microlinkhq/react-json-view/commit/86bbd60caef8d80b812a45c8ea9326df62fcb02f)) + ### [1.23.2](https://github.com/microlinkhq/react-json-view/compare/v1.23.1...v1.23.2) (2024-09-22) diff --git a/package.json b/package.json index 9475ae5..989c6e7 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "@microlink/react-json-view", "description": "Interactive react component for displaying javascript arrays and JSON objects.", "homepage": "https://github.com/microlinkhq/react-json-view", - "version": "1.23.2", + "version": "1.23.3", "main": "dist/main.js", "author": { "name": "Mac Gainor" From 94409ea682a380f9a868dabcef443c053f3fe3be Mon Sep 17 00:00:00 2001 From: Kiko Beats Date: Wed, 23 Oct 2024 10:02:17 +0200 Subject: [PATCH 2/3] build: relint the project --- .editorconfig | 20 + .eslintrc.json | 20 - .github/workflows/main.yml | 38 +- .prettierrc.json | 15 - CHANGELOG.md | 18 +- CONTRIBUTING.md | 6 +- README.md | 111 ++- demo/dist/index.html | 101 +- demo/src/js/components/Demo.js | 905 +++++++++--------- demo/src/js/entry.js | 18 +- demo/src/js/helpers/Code.js | 34 +- demo/src/js/index.js | 16 +- demo/src/style/scss/_variables.scss | 10 +- demo/src/style/scss/global.scss | 28 +- demo/src/style/scss/rjv-demo.scss | 62 +- dev-server/dist/index.html | 35 +- dev-server/src/index.js | 508 +++++----- docker/README.md | 85 +- index.d.ts | 125 ++- package.json | 49 +- src/js/components/ArrayGroup.js | 252 +++-- src/js/components/CopyToClipboard.js | 230 +++-- src/js/components/DataTypes/Boolean.js | 28 +- src/js/components/DataTypes/DataTypeLabel.js | 29 +- src/js/components/DataTypes/DataTypes.js | 22 +- src/js/components/DataTypes/Date.js | 46 +- src/js/components/DataTypes/Float.js | 28 +- src/js/components/DataTypes/Function.js | 141 ++- src/js/components/DataTypes/Integer.js | 28 +- src/js/components/DataTypes/Nan.js | 12 +- src/js/components/DataTypes/Null.js | 12 +- src/js/components/DataTypes/Object.js | 568 ++++++----- src/js/components/DataTypes/Regexp.js | 28 +- src/js/components/DataTypes/String.js | 124 ++- src/js/components/DataTypes/Undefined.js | 12 +- src/js/components/JsonViewer.js | 60 +- .../ObjectKeyModal/AddKeyRequest.js | 79 +- .../ObjectKeyModal/ObjectKeyModal.js | 166 ++-- src/js/components/ObjectName.js | 78 +- src/js/components/ToggleIcons.js | 109 +-- src/js/components/ValidationFailure.js | 54 +- src/js/components/VariableEditor.js | 885 +++++++++-------- src/js/components/VariableMeta.js | 260 +++-- src/js/components/icons.js | 460 ++++----- src/js/helpers/dispatcher.js | 6 +- src/js/helpers/parseInput.js | 139 ++- src/js/helpers/stringifyVariable.js | 64 +- src/js/helpers/util.js | 96 +- src/js/index.js | 481 +++++----- src/js/stores/ObjectAttributes.js | 219 +++-- src/js/themes/base16/rjv-themes.js | 78 +- src/js/themes/getStyle.js | 790 ++++++++------- src/js/themes/styleConstants.js | 140 +-- src/style/scss/global.scss | 82 +- test/testHelpers/requireSources.js | 48 +- test/tests/js/Index-test.js | 234 +++-- test/tests/js/components/ArrayGroup-test.js | 220 ++--- .../js/components/CopyToClipboard-test.js | 56 +- .../js/components/DataTypes/Boolean-test.js | 95 +- .../DataTypes/DataTypeLabel-test.js | 56 +- .../js/components/DataTypes/Date-test.js | 56 +- .../js/components/DataTypes/Float-test.js | 56 +- .../js/components/DataTypes/Function-test.js | 140 +-- .../js/components/DataTypes/Integer-test.js | 58 +- .../tests/js/components/DataTypes/Nan-test.js | 44 +- .../js/components/DataTypes/Null-test.js | 44 +- .../js/components/DataTypes/Object-test.js | 746 +++++++-------- .../js/components/DataTypes/Regex-test.js | 58 +- .../js/components/DataTypes/String-test.js | 122 ++- .../js/components/DataTypes/Undefined-test.js | 48 +- .../ObjectKeyModal/AddKeyRequest-test.js | 60 +- .../ObjectKeyModal/ObjectKeyModal-test.js | 342 ++++--- test/tests/js/components/ObjectName-test.js | 151 ++- test/tests/js/components/ToggleIcons-test.js | 108 +-- .../js/components/ValidationFailure-test.js | 114 +-- .../js/components/VariableEditor-test.js | 666 +++++++------ test/tests/js/components/VariableMeta-test.js | 181 ++-- test/tests/js/components/icons-test.js | 140 +-- test/tests/js/helpers/Util-test.js | 234 ++--- test/tests/js/helpers/parseInput-test.js | 100 +- .../js/helpers/stringifyVariable-test.js | 166 ++-- test/tests/js/stores/ObjectAttributes-test.js | 44 +- test/tests/js/themes/getStyle-test.js | 44 +- webpack/webpack.config-demo.js | 122 +-- webpack/webpack.config-dev.js | 38 +- webpack/webpack.config.js | 58 +- 86 files changed, 6302 insertions(+), 6357 deletions(-) create mode 100644 .editorconfig delete mode 100644 .eslintrc.json delete mode 100644 .prettierrc.json diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..0f2eb81 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,20 @@ +# https://editorconfig.org + +root = true + +[*] +indent_style = space +indent_size = 2 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true +max_line_length = 80 +indent_brace_style = 1TBS +spaces_around_operators = true +quote_type = auto + +[package.json] +indent_style = space +indent_size = 2 +a \ No newline at end of file diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index e1d47ae..0000000 --- a/.eslintrc.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "plugins": ["react", "prettier"], - "rules": { - "prettier/prettier": "error", - "import/no-anonymous-default-export": "off", - "egegeg": "off" - }, - "parser":"@babel/eslint-parser", - "parserOptions": { - "sourceType": "module", - "ecmaVersion": 6, - "ecmaFeatures": { - "experimentalObjectRestSpread": true - } - }, - "env": { - "es6": true, - "node": true - } -} diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 97c1765..ce472aa 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,24 +1,24 @@ name: test on: - push: - branches: - - master - pull_request: - branches: - - master + push: + branches: + - master + pull_request: + branches: + - master jobs: - test: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: lts/* - - name: Install - run: npm install --no-package-lock --force - - name: Test - run: npm test + test: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: lts/* + - name: Install + run: npm install --no-package-lock --force + - name: Test + run: npm test diff --git a/.prettierrc.json b/.prettierrc.json deleted file mode 100644 index cdccb6c..0000000 --- a/.prettierrc.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "tabWidth": 4, - "printWidth": 80, - "singleQuote": true, - "trailingComma": "none", - "bracketSpacing": true, - "jsxBracketSameLine": false, - "parser": "babel", - "semi": true, - "requirePragma": false, - "proseWrap": "preserve", - "arrowParens": "avoid", - "eslintIntegration": false, - "endOfLine": "auto" -} \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 14205ca..afc3394 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,34 +4,30 @@ All notable changes to this project will be documented in this file. See [standa ### [1.23.3](https://github.com/microlinkhq/react-json-view/compare/v1.23.2...v1.23.3) (2024-09-27) - ### Bug Fixes -* function call ([86bbd60](https://github.com/microlinkhq/react-json-view/commit/86bbd60caef8d80b812a45c8ea9326df62fcb02f)) +- function call ([86bbd60](https://github.com/microlinkhq/react-json-view/commit/86bbd60caef8d80b812a45c8ea9326df62fcb02f)) ### [1.23.2](https://github.com/microlinkhq/react-json-view/compare/v1.23.1...v1.23.2) (2024-09-22) - ### Bug Fixes -* add legacy ssl flag ([4005834](https://github.com/microlinkhq/react-json-view/commit/4005834bb4234ddfdef66f2173a53a686641cb21)) +- add legacy ssl flag ([4005834](https://github.com/microlinkhq/react-json-view/commit/4005834bb4234ddfdef66f2173a53a686641cb21)) ### [1.23.1](https://github.com/microlinkhq/react-json-view/compare/v1.23.0...v1.23.1) (2024-07-02) ## [1.23.0](https://github.com/microlinkhq/react-json-view/compare/v1.22.2...v1.23.0) (2023-10-26) - ### Features -* **dev server:** add example of name as jsx element ([84ada17](https://github.com/microlinkhq/react-json-view/commit/84ada17617ad1df0e748e5cf6383f9cdcefa6e02)) -* **json viewer:** add handling namespace when is an react object ([e11b60a](https://github.com/microlinkhq/react-json-view/commit/e11b60af87fa1755554cb5c846d1d49ea12d131e)) -* **types:** add JSX.Element as name prop type ([ebd8aed](https://github.com/microlinkhq/react-json-view/commit/ebd8aed8246742ebc41776a8a0bb489b8e711138)) - +- **dev server:** add example of name as jsx element ([84ada17](https://github.com/microlinkhq/react-json-view/commit/84ada17617ad1df0e748e5cf6383f9cdcefa6e02)) +- **json viewer:** add handling namespace when is an react object ([e11b60a](https://github.com/microlinkhq/react-json-view/commit/e11b60af87fa1755554cb5c846d1d49ea12d131e)) +- **types:** add JSX.Element as name prop type ([ebd8aed](https://github.com/microlinkhq/react-json-view/commit/ebd8aed8246742ebc41776a8a0bb489b8e711138)) ### Bug Fixes -* add missed devDeps in new create-react-app ([5275cd4](https://github.com/microlinkhq/react-json-view/commit/5275cd446f7d4202b06f4a0d048092066a6b5f5b)) -* **json viewer:** add support for functional components ([f478f55](https://github.com/microlinkhq/react-json-view/commit/f478f55aa2b9dbe730f9638485d9c584ccbbcc45)) +- add missed devDeps in new create-react-app ([5275cd4](https://github.com/microlinkhq/react-json-view/commit/5275cd446f7d4202b06f4a0d048092066a6b5f5b)) +- **json viewer:** add support for functional components ([f478f55](https://github.com/microlinkhq/react-json-view/commit/f478f55aa2b9dbe730f9638485d9c584ccbbcc45)) ### [1.22.2](https://github.com/microlinkhq/react-json-view/compare/v1.22.1...v1.22.2) (2022-06-27) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e2e9b6b..74f71a9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,7 +8,8 @@ npm install --save-dev # run the dev server with hot reloading npm run dev ``` -Webpack Dev Server should automatically open up http://localhost:2000 in your web browser. If it does not, open a browser and navigate to port 2000. The hot reloader will automatically reload when files are modified in the `/src/` directory. + +Webpack Dev Server should automatically open up http://localhost:2000 in your web browser. If it does not, open a browser and navigate to port 2000. The hot reloader will automatically reload when files are modified in the `/src/` directory. ## Run the Production Build @@ -16,6 +17,7 @@ Webpack Dev Server should automatically open up http://localhost:2000 in your we # run the build (note: you may need to use `sudo` priveledges to run the build successfully) npm run build ``` + Please add tests for your code before posting a pull request. You can run the test suite with `npm run test` or `npm run test:watch` to automatically reload when files are modified. @@ -24,4 +26,4 @@ You can run the test suite with `npm run test` or `npm run test:watch` to automa I recommend using docker for development because it enforces environmental consistency. -For information about contributing with Docker, see the [README in ./docker](https://github.com/microlinkhq/react-json-view/blob/master/docker/README.md#contributing-to-this-project-using-docker). \ No newline at end of file +For information about contributing with Docker, see the [README in ./docker](https://github.com/microlinkhq/react-json-view/blob/master/docker/README.md#contributing-to-this-project-using-docker). diff --git a/README.md b/README.md index f65eca8..6b67595 100644 --- a/README.md +++ b/README.md @@ -1,37 +1,45 @@ ![alt text](https://raw.githubusercontent.com/microlinkhq/react-json-view/master/doc/rjv-icon-alt.png) -[![npm](https://img.shields.io/npm/v/%40microlink%2Freact-json-view.svg)](https://www.npmjs.com/package/@microlink/react-json-view) [![npm](https://img.shields.io/npm/l/%40microlink%2Freact-json-view.svg -)](https://github.com/microlinkhq/react-json-view/blob/master/LICENSE) [![Build Status](https://github.com/microlinkhq/react-json-view/workflows/test/badge.svg)](https://github.com/microlinkhq/react-json-view/actions/workflows/main.yml?query=branch%3Amaster) +[![npm](https://img.shields.io/npm/v/%40microlink%2Freact-json-view.svg)](https://www.npmjs.com/package/@microlink/react-json-view) [![npm](https://img.shields.io/npm/l/%40microlink%2Freact-json-view.svg)](https://github.com/microlinkhq/react-json-view/blob/master/LICENSE) [![Build Status](https://github.com/microlinkhq/react-json-view/workflows/test/badge.svg)](https://github.com/microlinkhq/react-json-view/actions/workflows/main.yml?query=branch%3Amaster) # react-json-view + RJV is a React component for displaying and editing javascript **arrays** and **JSON objects**. -This component provides a responsive interface for displaying arrays or JSON in a web browser. NPM offers a distribution of the source that's transpiled to ES5; so you can include this component with *any web-based javascript application*. +This component provides a responsive interface for displaying arrays or JSON in a web browser. NPM offers a distribution of the source that's transpiled to ES5; so you can include this component with _any web-based javascript application_. [Check out the Interactive Demo](https://react-json-view.microlink.io/) - ### Implementation Example + ```js // import the react-json-view component import ReactJson from '@microlink/react-json-view' // use the component in your app! - +; ``` ### Output Examples + #### Default Theme -![alt text](https://raw.githubusercontent.com/microlinkhq/react-json-view/master/doc/output-example-15.png "Output Example 1") + +![alt text](https://raw.githubusercontent.com/microlinkhq/react-json-view/master/doc/output-example-15.png 'Output Example 1') + #### Hopscotch Theme, with Triangle Icons: -![alt text](https://raw.githubusercontent.com/microlinkhq/react-json-view/master/doc/output-example-14.png "Output Example 2") + +![alt text](https://raw.githubusercontent.com/microlinkhq/react-json-view/master/doc/output-example-14.png 'Output Example 2') ### Installation Instructions + Install this component with [NPM](https://www.npmjs.com/package/@microlink/react-json-view). + ```shell npm install --save @microlink/react-json-view ``` + Or add to your package.json config file: + ```json "dependencies": { "@microlink/react-json-view": "latest" @@ -39,68 +47,79 @@ Or add to your package.json config file: ``` ### Props -Name|Type|Default|Description -|:---|:---|:---|:--- -`src`|`JSON Object`|None|This property contains your input JSON -`name`|`string`|`JSX.Element` or `false`|"root"|Contains the name of your root node. Use `null` or `false` for no name. -`theme`|`string`|"rjv-default"|RJV supports base-16 themes. Check out the list of supported themes [in the demo](https://react-json-view.microlink.io/). A custom "rjv-default" theme applies by default. -`style`|`object`|`{}`|Style attributes for react-json-view container. Explicit style attributes will override attributes provided by a theme. -`iconStyle`|`string`|"circle"| Style of expand/collapse icons. Accepted values are "circle", triangle" or "square". -`indentWidth`|`integer`|4|Set the indent-width for nested objects -`collapsed`|`boolean` or `integer`|`false`|When set to `true`, all nodes will be collapsed by default. Use an integer value to collapse at a particular depth. -`collapseStringsAfterLength`|`integer`|`false`|When an integer value is assigned, strings will be cut off at that length. Collapsed strings are followed by an ellipsis. String content can be expanded and collapsed by clicking on the string value. -`shouldCollapse`|`(field)=>{}`|`false`|Callback function to provide control over what objects and arrays should be collapsed by default. An object is passed to the callback containing `name`, `src`, `type` ("array" or "object") and `namespace`. -`groupArraysAfterLength`|`integer`|`100`|When an integer value is assigned, arrays will be displayed in groups by count of the value. Groups are displayed with bracket notation and can be expanded and collapsed by clicking on the brackets. -`enableClipboard`|`boolean` or `(copy)=>{}`|`true`|When prop is not `false`, the user can copy objects and arrays to clipboard by clicking on the clipboard icon. Copy callbacks are supported. -`displayObjectSize`|`boolean`|`true`|When set to `true`, objects and arrays are labeled with size -`displayDataTypes`|`boolean`|`true`|When set to `true`, data type labels prefix values -`onEdit`|`(edit)=>{}`|`false`|When a callback function is passed in, `edit` functionality is enabled. The callback is invoked before edits are completed. Returning `false` from `onEdit` will prevent the change from being made. [see: onEdit docs](#onedit-onadd-and-ondelete-interaction) -`onAdd`|`(add)=>{}`|`false`|When a callback function is passed in, `add` functionality is enabled. The callback is invoked before additions are completed. Returning `false` from `onAdd` will prevent the change from being made. [see: onAdd docs](#onedit-onadd-and-ondelete-interaction) -`defaultValue`|`string \|number \|boolean \|array \|object`|`null`|Sets the default value to be used when adding an item to json -`onDelete`|`(delete)=>{}`|`false`|When a callback function is passed in, `delete` functionality is enabled. The callback is invoked before deletions are completed. Returning `false` from `onDelete` will prevent the change from being made. [see: onDelete docs](#onedit-onadd-and-ondelete-interaction) -`onSelect`|`(select)=>{}`|`false`|When a function is passed in, clicking a value triggers the `onSelect` method to be called. -`sortKeys`|`boolean`|`false`|set to true to sort object keys -`quotesOnKeys`|`boolean`|`true`|set to false to remove quotes from keys (eg. `"name":` vs. `name:`) -`validationMessage`|`string`|"Validation Error"|Custom message for validation failures to `onEdit`, `onAdd`, or `onDelete` callbacks -`displayArrayKey`|`boolean`|`true`|When set to `true`, the index of the elements prefix values + +| Name | Type | Default | Description | +| :--------------------------- | :------------------------------------------- | :----------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------- | +| `src` | `JSON Object` | None | This property contains your input JSON | +| `name` | `string` | `JSX.Element` or `false` | "root" | Contains the name of your root node. Use `null` or `false` for no name. | +| `theme` | `string` | "rjv-default" | RJV supports base-16 themes. Check out the list of supported themes [in the demo](https://react-json-view.microlink.io/). A custom "rjv-default" theme applies by default. | +| `style` | `object` | `{}` | Style attributes for react-json-view container. Explicit style attributes will override attributes provided by a theme. | +| `iconStyle` | `string` | "circle" | Style of expand/collapse icons. Accepted values are "circle", triangle" or "square". | +| `indentWidth` | `integer` | 4 | Set the indent-width for nested objects | +| `collapsed` | `boolean` or `integer` | `false` | When set to `true`, all nodes will be collapsed by default. Use an integer value to collapse at a particular depth. | +| `collapseStringsAfterLength` | `integer` | `false` | When an integer value is assigned, strings will be cut off at that length. Collapsed strings are followed by an ellipsis. String content can be expanded and collapsed by clicking on the string value. | +| `shouldCollapse` | `(field)=>{}` | `false` | Callback function to provide control over what objects and arrays should be collapsed by default. An object is passed to the callback containing `name`, `src`, `type` ("array" or "object") and `namespace`. | +| `groupArraysAfterLength` | `integer` | `100` | When an integer value is assigned, arrays will be displayed in groups by count of the value. Groups are displayed with bracket notation and can be expanded and collapsed by clicking on the brackets. | +| `enableClipboard` | `boolean` or `(copy)=>{}` | `true` | When prop is not `false`, the user can copy objects and arrays to clipboard by clicking on the clipboard icon. Copy callbacks are supported. | +| `displayObjectSize` | `boolean` | `true` | When set to `true`, objects and arrays are labeled with size | +| `displayDataTypes` | `boolean` | `true` | When set to `true`, data type labels prefix values | +| `onEdit` | `(edit)=>{}` | `false` | When a callback function is passed in, `edit` functionality is enabled. The callback is invoked before edits are completed. Returning `false` from `onEdit` will prevent the change from being made. [see: onEdit docs](#onedit-onadd-and-ondelete-interaction) | +| `onAdd` | `(add)=>{}` | `false` | When a callback function is passed in, `add` functionality is enabled. The callback is invoked before additions are completed. Returning `false` from `onAdd` will prevent the change from being made. [see: onAdd docs](#onedit-onadd-and-ondelete-interaction) | +| `defaultValue` | `string \|number \|boolean \|array \|object` | `null` | Sets the default value to be used when adding an item to json | +| `onDelete` | `(delete)=>{}` | `false` | When a callback function is passed in, `delete` functionality is enabled. The callback is invoked before deletions are completed. Returning `false` from `onDelete` will prevent the change from being made. [see: onDelete docs](#onedit-onadd-and-ondelete-interaction) | +| `onSelect` | `(select)=>{}` | `false` | When a function is passed in, clicking a value triggers the `onSelect` method to be called. | +| `sortKeys` | `boolean` | `false` | set to true to sort object keys | +| `quotesOnKeys` | `boolean` | `true` | set to false to remove quotes from keys (eg. `"name":` vs. `name:`) | +| `validationMessage` | `string` | "Validation Error" | Custom message for validation failures to `onEdit`, `onAdd`, or `onDelete` callbacks | +| `displayArrayKey` | `boolean` | `true` | When set to `true`, the index of the elements prefix values | ### Features -* `onEdit`, `onAdd` and `onDelete` props allow users to edit the `src` variable -* Object, array, string and function values can be collapsed and expanded -* Object and array nodes display length -* Object and array nodes support a "Copy to Clipboard" feature -* String values can be truncated after a specified length -* Arrays can be subgrouped after a specified length -* Base-16 Theme Support -* When `onEdit` is enabled: - * `Ctrl/Cmd+Click` Edit Mode - * `Ctrl/Cmd+Enter` Submit + +- `onEdit`, `onAdd` and `onDelete` props allow users to edit the `src` variable +- Object, array, string and function values can be collapsed and expanded +- Object and array nodes display length +- Object and array nodes support a "Copy to Clipboard" feature +- String values can be truncated after a specified length +- Arrays can be subgrouped after a specified length +- Base-16 Theme Support +- When `onEdit` is enabled: + - `Ctrl/Cmd+Click` Edit Mode + - `Ctrl/Cmd+Enter` Submit ### Customizing Style + #### Stock Themes + RJV now supports base-16 themes! You can specify a `theme` name or object when you instantiate your rjv component. + ```jsx - + ``` + Check out the list of supported themes [in the component demo](https://react-json-view.microlink.io/). #### Monokai theme example -![alt text](https://raw.githubusercontent.com/microlinkhq/react-json-view/master/doc/output-example-monokai-2.png "Base-16 Theme Example") + +![alt text](https://raw.githubusercontent.com/microlinkhq/react-json-view/master/doc/output-example-monokai-2.png 'Base-16 Theme Example') #### Solarized theme example -![alt text](https://raw.githubusercontent.com/microlinkhq/react-json-view/master/doc/output-example-solarized-2.png "Base-16 Theme Example") + +![alt text](https://raw.githubusercontent.com/microlinkhq/react-json-view/master/doc/output-example-solarized-2.png 'Base-16 Theme Example') #### Use Your Own Theme + You can supply your own base-16 theme object. To better understand custom themes, take a look at [my example implementation](https://github.com/microlinkhq/react-json-view/blob/7c154b9a7d83ea89dce2c171ebdf4d163ff49233/dev-server/src/index.js#L135) and the [base-16 theme styling guidelines](https://github.com/chriskempson/base16/blob/master/styling.md). ### onEdit, onAdd and onDelete Interaction -Pass callback methods to `onEdit`, `onAdd` and `onDelete` props. Your method will be invoked when a user attempts to update your `src` object. + +Pass callback methods to `onEdit`, `onAdd` and `onDelete` props. Your method will be invoked when a user attempts to update your `src` object. The following object will be passed to your method: + ```js { updated_src: src, //new src value @@ -111,4 +130,4 @@ The following object will be passed to your method: } ``` -Returning `false` from a callback method will prevent the src from being affected. \ No newline at end of file +Returning `false` from a callback method will prevent the src from being affected. diff --git a/demo/dist/index.html b/demo/dist/index.html index 5a21a00..8cb97d9 100644 --- a/demo/dist/index.html +++ b/demo/dist/index.html @@ -2,28 +2,49 @@ RJV Demo - - - - + + + + - - + + -
-
- - - + - \ No newline at end of file + diff --git a/demo/src/js/components/Demo.js b/demo/src/js/components/Demo.js index 8a1b341..b6a85e8 100644 --- a/demo/src/js/components/Demo.js +++ b/demo/src/js/components/Demo.js @@ -1,483 +1,480 @@ -import React from 'react'; -import ReactSelect from 'react-select'; -import ReactJson from './../../../../src/js/index'; -import GitHubButton from 'react-github-button'; +import React from 'react' +import ReactSelect from 'react-select' +import ReactJson from './../../../../src/js/index' +import GitHubButton from 'react-github-button' -import Code from './../helpers/Code'; -import './../../style/scss/rjv-demo.scss'; -import 'react-select/dist/react-select.css'; -import 'react-github-button/assets/style.css'; +import Code from './../helpers/Code' +import './../../style/scss/rjv-demo.scss' +import 'react-select/dist/react-select.css' +import 'react-github-button/assets/style.css' //index entrypoint component class Demo extends React.PureComponent { - constructor(props) { - super(props); - this.state = { - ...Demo.defaultProps, - src: this.getExampleJson() - }; + constructor (props) { + super(props) + this.state = { + ...Demo.defaultProps, + src: this.getExampleJson() } + } - static defaultProps = { - theme: 'monokai', - src: null, - collapsed: false, - collapseStringsAfter: 15, - onAdd: true, - onEdit: true, - onDelete: true, - displayObjectSize: true, - enableClipboard: true, - indentWidth: 4, - displayDataTypes: true, - iconStyle: 'triangle' - }; + static defaultProps = { + theme: 'monokai', + src: null, + collapsed: false, + collapseStringsAfter: 15, + onAdd: true, + onEdit: true, + onDelete: true, + displayObjectSize: true, + enableClipboard: true, + indentWidth: 4, + displayDataTypes: true, + iconStyle: 'triangle' + } - render() { - const { - src, - collapseStringsAfter, - onAdd, - onEdit, - onDelete, - displayObjectSize, - enableClipboard, - theme, - iconStyle, - collapsed, - indentWidth, - displayDataTypes - } = this.state; - const style = { - padding: '10px', - borderRadius: '3px', - margin: '10px 0px' - }; + render () { + const { + src, + collapseStringsAfter, + onAdd, + onEdit, + onDelete, + displayObjectSize, + enableClipboard, + theme, + iconStyle, + collapsed, + indentWidth, + displayDataTypes + } = this.state + const style = { + padding: '10px', + borderRadius: '3px', + margin: '10px 0px' + } - return ( -
-
-
react-json-view
-
component demo
- { - window.open( - 'https://github.com/microlinkhq/react-json-view', - '_blank' - ); - }} - /> - -
- { - console.log(e); - this.setState({ src: e.updated_src }); - } - : false - } - onDelete={ - onDelete - ? e => { - console.log(e); - this.setState({ src: e.updated_src }); - } - : false - } - onAdd={ - onAdd - ? e => { - console.log(e); - this.setState({ src: e.updated_src }); - } - : false - } - displayObjectSize={displayObjectSize} - enableClipboard={enableClipboard} - indentWidth={indentWidth} - displayDataTypes={displayDataTypes} - iconStyle={iconStyle} - /> + return ( +
+
+
react-json-view
+
component demo
+ { + window.open( + 'https://github.com/microlinkhq/react-json-view', + '_blank' + ) + }} + /> + +
+ { + console.log(e) + this.setState({ src: e.updated_src }) + } + : false + } + onDelete={ + onDelete + ? e => { + console.log(e) + this.setState({ src: e.updated_src }) + } + : false + } + onAdd={ + onAdd + ? e => { + console.log(e) + this.setState({ src: e.updated_src }) + } + : false + } + displayObjectSize={displayObjectSize} + enableClipboard={enableClipboard} + indentWidth={indentWidth} + displayDataTypes={displayDataTypes} + iconStyle={iconStyle} + /> -
-
-
Theme:
- {this.getThemeInput(theme)} -
-
-
Icon Style:
- {this.getIconStyleInput(iconStyle)} -
-
-
Enable Edit:
- {this.getEditInput(onEdit)} -
-
-
Enable Add:
- {this.getAddInput(onAdd)} -
-
-
Enable Delete:
- {this.getDeleteInput(onDelete)} -
-
-
Enable Clipboard:
- {this.getEnableClipboardInput(enableClipboard)} -
-
+
+
+
Theme:
+ {this.getThemeInput(theme)} +
+
+
Icon Style:
+ {this.getIconStyleInput(iconStyle)} +
+
+
Enable Edit:
+ {this.getEditInput(onEdit)} +
+
+
Enable Add:
+ {this.getAddInput(onAdd)} +
+
+
Enable Delete:
+ {this.getDeleteInput(onDelete)} +
+
+
Enable Clipboard:
+ {this.getEnableClipboardInput(enableClipboard)} +
+
-
-
-
Display Data Types:
- {this.getDataTypesInput(displayDataTypes)} -
-
-
Display Object Size:
- {this.getObjectSizeInput(displayObjectSize)} -
-
-
Indent Width:
- {this.getIndentWidthInput(indentWidth)} -
-
-
Collapsed:
- {this.getCollapsedInput(collapsed)} -
-
-
- Collapse Strings After Length: -
- {this.getCollapsedStringsInput(collapseStringsAfter)} -
-
+
+
+
Display Data Types:
+ {this.getDataTypesInput(displayDataTypes)} +
+
+
Display Object Size:
+ {this.getObjectSizeInput(displayObjectSize)} +
+
+
Indent Width:
+ {this.getIndentWidthInput(indentWidth)} +
+
+
Collapsed:
+ {this.getCollapsedInput(collapsed)} +
+
+
Collapse Strings After Length:
+ {this.getCollapsedStringsInput(collapseStringsAfter)} +
+
- {this.getNotes(onEdit, onAdd)} -
- ); - } + {this.getNotes(onEdit, onAdd)} +
+ ) + } - getNotes = (on_edit_enabled, on_add_enabled) => { - let notes = []; - if (on_edit_enabled) { - notes.push( - - To edit a value, try ctrl/cmd + click enter - edit mode - - ); - notes.push( - - When editing a value, try ctrl/cmd + Enter to - submit changes - - ); - notes.push( - - When editing a value, try Escape key to cancel - - ); - } - if (on_add_enabled) { - notes.push( - - When adding a new key, try Enter to submit - - ); - notes.push( - - When adding a new key, try Escape to cancel - - ); - } + getNotes = (on_edit_enabled, on_add_enabled) => { + let notes = [] + if (on_edit_enabled) { + notes.push( + + To edit a value, try ctrl/cmd + click enter edit mode + + ) + notes.push( + + When editing a value, try ctrl/cmd + Enter to submit + changes + + ) + notes.push( + + When editing a value, try Escape key to cancel + + ) + } + if (on_add_enabled) { + notes.push( + + When adding a new key, try Enter to submit + + ) + notes.push( + + When adding a new key, try Escape to cancel + + ) + } - if (notes.length === 0) { - return null; - } + if (notes.length === 0) { + return null + } - return ( -
- Keyboard Shortcuts -
    - {notes.map(note => { - return
  • {note}
  • ; - })} -
-
- ); - }; + return ( +
+ Keyboard Shortcuts +
    + {notes.map(note => { + return
  • {note}
  • + })} +
+
+ ) + } - getIconStyleInput = iconStyle => { - return ( - { - this.set('iconStyle', val); - }} - /> - ); - }; + getIconStyleInput = iconStyle => { + return ( + { + this.set('iconStyle', val) + }} + /> + ) + } - getEditInput = onEdit => { - return ( - { - this.set('onEdit', val); - }} - /> - ); - }; + getEditInput = onEdit => { + return ( + { + this.set('onEdit', val) + }} + /> + ) + } - getAddInput = onAdd => { - return ( - { - this.set('onAdd', val); - }} - /> - ); - }; + getAddInput = onAdd => { + return ( + { + this.set('onAdd', val) + }} + /> + ) + } - getDeleteInput = onDelete => { - return ( - { - this.set('onDelete', val); - }} - /> - ); - }; + getDeleteInput = onDelete => { + return ( + { + this.set('onDelete', val) + }} + /> + ) + } - getEnableClipboardInput = enableClipboard => { - return ( - { - this.set('enableClipboard', val); - }} - /> - ); - }; + getEnableClipboardInput = enableClipboard => { + return ( + { + this.set('enableClipboard', val) + }} + /> + ) + } - getObjectSizeInput = displayObjectSize => { - return ( - { - this.set('displayObjectSize', val); - }} - /> - ); - }; + getObjectSizeInput = displayObjectSize => { + return ( + { + this.set('displayObjectSize', val) + }} + /> + ) + } - getDataTypesInput = displayDataTypes => { - return ( - { - this.set('displayDataTypes', val); - }} - /> - ); - }; + getDataTypesInput = displayDataTypes => { + return ( + { + this.set('displayDataTypes', val) + }} + /> + ) + } - getCollapsedStringsInput = collapseStringsAfter => { - return ( - { - this.set('collapseStringsAfter', val); - }} - /> - ); - }; + getCollapsedStringsInput = collapseStringsAfter => { + return ( + { + this.set('collapseStringsAfter', val) + }} + /> + ) + } - getCollapsedInput = collapsed => { - return ( - { - this.set('collapsed', val); - }} - /> - ); - }; + getCollapsedInput = collapsed => { + return ( + { + this.set('collapsed', val) + }} + /> + ) + } - getIndentWidthInput = indentWidth => { - return ( - { - this.set('indentWidth', val); - }} - /> - ); - }; + getIndentWidthInput = indentWidth => { + return ( + { + this.set('indentWidth', val) + }} + /> + ) + } - getThemeInput = theme => { - return ( - { - this.set('theme', val); - }} - /> - ); - }; + getThemeInput = theme => { + return ( + { + this.set('theme', val) + }} + /> + ) + } - set = (field, value) => { - let state = {}; - state[field] = value.value; - this.setState(state); - }; + set = (field, value) => { + let state = {} + state[field] = value.value + this.setState(state) + } - //just a function to get an example JSON object - getExampleJson = () => { - return { - string: 'this is a test string', - integer: 42, - array: [1, 2, 3, 'test', NaN], - float: 3.14159, - undefined: undefined, - object: { - 'first-child': true, - 'second-child': false, - 'last-child': null - }, - string_number: '1234', - date: new Date() - }; - }; + //just a function to get an example JSON object + getExampleJson = () => { + return { + string: 'this is a test string', + integer: 42, + array: [1, 2, 3, 'test', NaN], + float: 3.14159, + undefined: undefined, + object: { + 'first-child': true, + 'second-child': false, + 'last-child': null + }, + string_number: '1234', + date: new Date() + } + } } -export default Demo; +export default Demo diff --git a/demo/src/js/entry.js b/demo/src/js/entry.js index 5635084..883f8dc 100644 --- a/demo/src/js/entry.js +++ b/demo/src/js/entry.js @@ -1,14 +1,14 @@ -import ReactDom from 'react-dom'; -import Index from './index'; +import ReactDom from 'react-dom' +import Index from './index' -require('./../style/scss/global.scss'); +require('./../style/scss/global.scss') -const app = document.getElementById('mac-react-container'); +const app = document.getElementById('mac-react-container') //app entrypoint ReactDom.render( -
- -
, - app -); +
+ +
, + app +) diff --git a/demo/src/js/helpers/Code.js b/demo/src/js/helpers/Code.js index c3c3aca..ca72c3d 100644 --- a/demo/src/js/helpers/Code.js +++ b/demo/src/js/helpers/Code.js @@ -1,19 +1,21 @@ import React from 'react' export default class extends React.PureComponent { - - render () { - return
- {this.props.children} -
- } - -} \ No newline at end of file + render () { + return ( +
+ {this.props.children} +
+ ) + } +} diff --git a/demo/src/js/index.js b/demo/src/js/index.js index 4155fb7..adb22c8 100644 --- a/demo/src/js/index.js +++ b/demo/src/js/index.js @@ -1,11 +1,11 @@ -import React from 'react'; -import ReactJsonDemo from './components/Demo'; +import React from 'react' +import ReactJsonDemo from './components/Demo' //index entrypoint component -export default function Demo() { - return ( -
- -
- ); +export default function Demo () { + return ( +
+ +
+ ) } diff --git a/demo/src/style/scss/_variables.scss b/demo/src/style/scss/_variables.scss index 9b92f56..aefd24d 100644 --- a/demo/src/style/scss/_variables.scss +++ b/demo/src/style/scss/_variables.scss @@ -1,18 +1,18 @@ -$component-background-color:#fff; -$component-font-family: "Open Sans"; +$component-background-color: #fff; +$component-font-family: 'Open Sans'; //global color theme $blue: #01a1dd; $pale-blue: #f0fafe; $dark-blue: #337ab7; -$dark-blue-shaded: #0088BB; +$dark-blue-shaded: #0088bb; $green: #458832; -$pale-green: #D9F6C8; +$pale-green: #d9f6c8; // $orange: #FFA347; $orange: #eeb211; $black: #333; $white: #fff; -$off-white: #F4F4F4; +$off-white: #f4f4f4; $grey: #898989; $dark-grey: #555; $light-grey: #ddd; diff --git a/demo/src/style/scss/global.scss b/demo/src/style/scss/global.scss index 68392d6..6a4aa3f 100644 --- a/demo/src/style/scss/global.scss +++ b/demo/src/style/scss/global.scss @@ -2,18 +2,18 @@ @import '_variables'; #mac-react-container { - font-family: "Open Sans"; - padding: 20px; + font-family: 'Open Sans'; + padding: 20px; - .header-1 { - font-size: 28px; - margin-right: 5px; - margin-bottom: 3px; - } - .header-2 { - font-size: 22px; - margin-right: 5px; - margin-bottom: 5px; - font-style: italic; - } -} \ No newline at end of file + .header-1 { + font-size: 28px; + margin-right: 5px; + margin-bottom: 3px; + } + .header-2 { + font-size: 22px; + margin-right: 5px; + margin-bottom: 5px; + font-style: italic; + } +} diff --git a/demo/src/style/scss/rjv-demo.scss b/demo/src/style/scss/rjv-demo.scss index 7f7d128..d6fbbdf 100644 --- a/demo/src/style/scss/rjv-demo.scss +++ b/demo/src/style/scss/rjv-demo.scss @@ -1,38 +1,38 @@ .rjv-demo { - .rjv-settings, - .rjv-source { - vertical-align: top; - display: inline-block; - margin-top: 5px; - margin-right: 10px; - min-width: 300px; - max-width: 400px; - .rjv-input { - margin-bottom: 5px; - .rjv-label { - font-size: 14px; - font-weight: bold; - // font-style: italic; - } - } + .rjv-settings, + .rjv-source { + vertical-align: top; + display: inline-block; + margin-top: 5px; + margin-right: 10px; + min-width: 300px; + max-width: 400px; + .rjv-input { + margin-bottom: 5px; + .rjv-label { + font-size: 14px; + font-weight: bold; + // font-style: italic; + } } + } - .rjv-header { - position: relative; + .rjv-header { + position: relative; - .rjv-logo { - width: 100px; - position: absolute; - right: 0px; - top: 0px; - cursor: pointer; - } + .rjv-logo { + width: 100px; + position: absolute; + right: 0px; + top: 0px; + cursor: pointer; + } - .github-btn { - display: block; - position: absolute; - right: 0px; - top: 48px; - } + .github-btn { + display: block; + position: absolute; + right: 0px; + top: 48px; } + } } diff --git a/dev-server/dist/index.html b/dev-server/dist/index.html index aeae8d9..945bb6e 100644 --- a/dev-server/dist/index.html +++ b/dev-server/dist/index.html @@ -2,27 +2,38 @@ react-json-view - + - - + + diff --git a/dev-server/src/index.js b/dev-server/src/index.js index e01fbae..58e2699 100644 --- a/dev-server/src/index.js +++ b/dev-server/src/index.js @@ -1,294 +1,296 @@ -'use strict'; +'use strict' //import react and reactDom for browser rendering -import React from 'react'; -import ReactDom from 'react-dom'; +import React from 'react' +import ReactDom from 'react-dom' -import Moment from 'moment'; +import Moment from 'moment' //import the react-json-view component (installed with npm) -import JsonViewer from './../../src/js/index'; +import JsonViewer from './../../src/js/index' //render 2 different examples of the react-json-view component ReactDom.render( -
- {/* just pass in your JSON to the src attribute */} - { - console.log('edit callback', e); - if (e.new_value == 'error') { - return false; - } - }} - onDelete={e => { - console.log('delete callback', e); - }} - onAdd={e => { - console.log('add callback', e); - if (e.new_value == 'error') { - return false; - } - }} - onSelect={e => { - console.log('select callback', e); - console.log(e.namespace); - }} - displayObjectSize={true} - name={'dev-server'} - enableClipboard={copy => { - console.log('you copied to clipboard!', copy); - }} - shouldCollapse={({ src, namespace, type }) => { - if (type === 'array' && src.indexOf('test') > -1) { - return true; - } else if (namespace.indexOf('moment') > -1) { - return true; - } - return false; - }} - defaultValue="" - /> +
+ {/* just pass in your JSON to the src attribute */} + { + console.log('edit callback', e) + if (e.new_value == 'error') { + return false + } + }} + onDelete={e => { + console.log('delete callback', e) + }} + onAdd={e => { + console.log('add callback', e) + if (e.new_value == 'error') { + return false + } + }} + onSelect={e => { + console.log('select callback', e) + console.log(e.namespace) + }} + displayObjectSize={true} + name={'dev-server'} + enableClipboard={copy => { + console.log('you copied to clipboard!', copy) + }} + shouldCollapse={({ src, namespace, type }) => { + if (type === 'array' && src.indexOf('test') > -1) { + return true + } else if (namespace.indexOf('moment') > -1) { + return true + } + return false + }} + defaultValue='' + /> -
+
- {/* use a base16 theme */} - { - console.log(e); - if (e.new_value === 'error') { - return false; - } - }} - onDelete={e => { - console.log(e); - }} - onAdd={e => { - console.log(e); - if (e.new_value === 'error') { - return false; - } - }} - name={false} - iconStyle="triangle" - shouldCollapse={({ src, type }) => - type === 'object' && - src.constructor && - src.constructor.name === 'Moment' - } - selectOnFocus - /> + {/* use a base16 theme */} + { + console.log(e) + if (e.new_value === 'error') { + return false + } + }} + onDelete={e => { + console.log(e) + }} + onAdd={e => { + console.log(e) + if (e.new_value === 'error') { + return false + } + }} + name={false} + iconStyle='triangle' + shouldCollapse={({ src, type }) => + type === 'object' && + src.constructor && + src.constructor.name === 'Moment' + } + selectOnFocus + /> -
+
- {/* initialize this one with a name and default collapsed */} - + {/* initialize this one with a name and default collapsed */} + -
+
- {/* initialize this one with a name and default collapsed */} - + {/* initialize this one with a name and default collapsed */} + -
+
- {/* initialize an example with a long string */} - + {/* initialize an example with a long string */} + -
+
- {/*demo array support*/} - { - console.log(edit); - }} - /> + {/*demo array support*/} + { + console.log(edit) + }} + /> -
+
- {/* custom theme example */} - - namespace.indexOf('moment') > -1 - } - theme={{ - base00: 'white', - base01: '#ddd', - base02: '#ddd', - base03: '#444', - base04: 'purple', - base05: '#444', - base06: '#444', - base07: '#444', - base08: '#444', - base09: 'rgba(70, 70, 230, 1)', - base0A: 'rgba(70, 70, 230, 1)', - base0B: 'rgba(70, 70, 230, 1)', - base0C: 'rgba(70, 70, 230, 1)', - base0D: 'rgba(70, 70, 230, 1)', - base0E: 'rgba(70, 70, 230, 1)', - base0F: 'rgba(70, 70, 230, 1)' - }} - /> + {/* custom theme example */} + + namespace.indexOf('moment') > -1 + } + theme={{ + base00: 'white', + base01: '#ddd', + base02: '#ddd', + base03: '#444', + base04: 'purple', + base05: '#444', + base06: '#444', + base07: '#444', + base08: '#444', + base09: 'rgba(70, 70, 230, 1)', + base0A: 'rgba(70, 70, 230, 1)', + base0B: 'rgba(70, 70, 230, 1)', + base0C: 'rgba(70, 70, 230, 1)', + base0D: 'rgba(70, 70, 230, 1)', + base0E: 'rgba(70, 70, 230, 1)', + base0F: 'rgba(70, 70, 230, 1)' + }} + /> - + - {/* Name as colored react component */} - React Element as name} - src={getExampleJson2()} - /> -
, - document.getElementById('app-container') -); + {/* Name as colored react component */} + + React Element as name + + } + src={getExampleJson2()} + /> +
, + document.getElementById('app-container') +) /*-------------------------------------------------------------------------*/ /* the following functions just contain test json data for display */ /*-------------------------------------------------------------------------*/ //just a function to get an example JSON object -function getExampleJson1() { - return { - string: 'this is a test string', - integer: 42, - empty_array: [], - empty_object: {}, - array: [1, 2, 3, 'test'], - float: -2.757, - undefined_var: undefined, - parent: { - sibling1: true, - sibling2: false, - sibling3: null, - isString: value => { - if (typeof value === 'string') { - return 'string'; - } else { - return 'other'; - } - } - }, - string_number: '1234', - date: new Date(), - moment: Moment(), - regexp: /[0-9]/gi - }; +function getExampleJson1 () { + return { + string: 'this is a test string', + integer: 42, + empty_array: [], + empty_object: {}, + array: [1, 2, 3, 'test'], + float: -2.757, + undefined_var: undefined, + parent: { + sibling1: true, + sibling2: false, + sibling3: null, + isString: value => { + if (typeof value === 'string') { + return 'string' + } else { + return 'other' + } + } + }, + string_number: '1234', + date: new Date(), + moment: Moment(), + regexp: /[0-9]/gi + } } //and another a function to get an example JSON object -function getExampleJson2() { - return { - normalized: { - '1-grams': { - body: 1, - testing: 1 - }, - '2-grams': { - 'testing body': 1 - }, - '3-grams': {} - }, - noun_phrases: { - body: 1 - }, - lemmatized: { - '1-grams': { - test: 1, - body: 1 - }, - '2-grams': { - 'test body': 1 - }, - '3-grams': {} - }, - dependency: { - '1-grams': { - testingVERBROOTtestingVERB: 1, - bodyNOUNdobjtestingVERB: 1 - }, - '2-grams': { - 'testingVERBROOTtestingVERB bodyNOUNdobjtestingVERB': 1 - }, - '3-grams': {} - } - }; +function getExampleJson2 () { + return { + normalized: { + '1-grams': { + body: 1, + testing: 1 + }, + '2-grams': { + 'testing body': 1 + }, + '3-grams': {} + }, + noun_phrases: { + body: 1 + }, + lemmatized: { + '1-grams': { + test: 1, + body: 1 + }, + '2-grams': { + 'test body': 1 + }, + '3-grams': {} + }, + dependency: { + '1-grams': { + testingVERBROOTtestingVERB: 1, + bodyNOUNdobjtestingVERB: 1 + }, + '2-grams': { + 'testingVERBROOTtestingVERB bodyNOUNdobjtestingVERB': 1 + }, + '3-grams': {} + } + } } -function getExampleJson3() { - return { - example_information: - 'this example has the collapsed prop set to true and the indentWidth prop is set to 8', - default_collapsed: true, - collapsed_array: [ - 'you expanded me', - 'try collapsing and expanding the root node', - 'i will still be expanded', - { - leaf_node: true - } - ] - }; +function getExampleJson3 () { + return { + example_information: + 'this example has the collapsed prop set to true and the indentWidth prop is set to 8', + default_collapsed: true, + collapsed_array: [ + 'you expanded me', + 'try collapsing and expanding the root node', + 'i will still be expanded', + { + leaf_node: true + } + ] + } } -function getExampleJson4() { - const large_array = new Array(225).fill( - 'this is a large array full of items' - ); +function getExampleJson4 () { + const large_array = new Array(225).fill('this is a large array full of items') - large_array.push(getExampleArray()); + large_array.push(getExampleArray()) - large_array.push(new Array(75).fill(Math.random())); + large_array.push(new Array(75).fill(Math.random())) - return large_array; + return large_array } -function getExampleArray() { - return [ - 'you can also display arrays!', - new Date(), - 1, - 2, - 3, - { - pretty_cool: true - } - ]; +function getExampleArray () { + return [ + 'you can also display arrays!', + new Date(), + 1, + 2, + 3, + { + pretty_cool: true + } + ] } diff --git a/docker/README.md b/docker/README.md index e1bdc2e..3432c79 100644 --- a/docker/README.md +++ b/docker/README.md @@ -1,24 +1,28 @@ ### Contributing to this Project Using Docker + #### Run the Dev Server + To use Docker to run the source code in a local development environment: - 1. Clone this repo - 2. Build the docker image - * `cd react-json-view` - * `./docker/build-container.sh` - * *note:* you may need to use `sudo` to run docker commands - 3. Run the docker container on port 2000. This will run the webpack-dev-server with hot-reloading enabled. - * `./docker/dev-server.sh` - * *note:* you may need to use `sudo` to run the server file - 4. Open port 2000 in your browser - * navigate to localhost:2000 - -Your source code will be mounted inside the docker container. The container is built on the latest `Node:slim` image. + +1. Clone this repo +2. Build the docker image + - `cd react-json-view` + - `./docker/build-container.sh` + - _note:_ you may need to use `sudo` to run docker commands +3. Run the docker container on port 2000. This will run the webpack-dev-server with hot-reloading enabled. + - `./docker/dev-server.sh` + - _note:_ you may need to use `sudo` to run the server file +4. Open port 2000 in your browser + - navigate to localhost:2000 + +Your source code will be mounted inside the docker container. The container is built on the latest `Node:slim` image. Webpack-dev-server is running in the container and hot-reloading when changes are made locally. All node modules are installed within the container, so make sure to rebuild your container if you make changes to package.json (see step 2, above). #### Run the Production Build + ```bash cd react-json-view # build the rjv container @@ -27,12 +31,11 @@ cd react-json-view ./docker/build-dist.sh ``` - ### Motivation for adding Docker to your Development Stack -**PSA:** You do not need to use Docker to contribute to this project. If you're not interested in using a container for development, you can ignore this directory. +**PSA:** You do not need to use Docker to contribute to this project. If you're not interested in using a container for development, you can ignore this directory. -You can contribute to this project with or without using Docker. This README is here to describe _how_ to use Docker when contributing and _why_ you would benefit. +You can contribute to this project with or without using Docker. This README is here to describe _how_ to use Docker when contributing and _why_ you would benefit. #### What is Docker? @@ -47,48 +50,50 @@ for example, the container used with this project has the following composition: ``` #### Motivations for Docker - * _environmental consistency_ - * this means I can completely replicate an environment for any build, on any machine - * _portability_ - * it's easy to define an environment and share it with other developers. - * I don't need to list steps for installing software - I can just write and share a dockerfile - * _module fatigue_ - * I can easily add/update/remove frameworks or node modules without worrying about messing up my file system. All packages are confined within a container, which I can easily update, rebuild or remove. + +- _environmental consistency_ + - this means I can completely replicate an environment for any build, on any machine +- _portability_ + - it's easy to define an environment and share it with other developers. + - I don't need to list steps for installing software - I can just write and share a dockerfile +- _module fatigue_ + - I can easily add/update/remove frameworks or node modules without worrying about messing up my file system. All packages are confined within a container, which I can easily update, rebuild or remove. #### RJV Docker Workflow -the `Dockerfile` defines exactly how a container should be composed for an application. Any docker-integrated workflow starts here. +the `Dockerfile` defines exactly how a container should be composed for an application. Any docker-integrated workflow starts here. Here is the [RJV Dockerfile](https://github.com/microlinkhq/react-json-view/blob/master/Dockerfile) -Notice [here](https://github.com/microlinkhq/react-json-view/blob/master/Dockerfile#L1) that my container is built on top of a node container. If you track down that node container on docker-hub, you'll see that it's built on top of a debian container. Also notice that `node_modules` are installed directly into my container [here](https://github.com/microlinkhq/react-json-view/blob/master/Dockerfile#L6-L7). +Notice [here](https://github.com/microlinkhq/react-json-view/blob/master/Dockerfile#L1) that my container is built on top of a node container. If you track down that node container on docker-hub, you'll see that it's built on top of a debian container. Also notice that `node_modules` are installed directly into my container [here](https://github.com/microlinkhq/react-json-view/blob/master/Dockerfile#L6-L7). When I run `./docker/build-container.sh`, docker produces a container including all the `node_modules` listed in my `package.json` file. When I run `./docker/dev-server.sh`, a few things happen: - 1. docker [runs my container and mounts some source files](https://github.com/microlinkhq/react-json-view/blob/master/docker/dev-server.sh#L16-L20) into the container - * "mounting" is like a soft copy. my files are linked inside the container's file system so local edits propagate to the container. - 2. docker [exposes a port](https://github.com/microlinkhq/react-json-view/blob/master/docker/dev-server.sh#L23) on the container - * this allows me to configure my app to listen and respond to to traffic at http://localhost:2000 - * the port is arbitrary - 3. An [entrypoint will be invoked](https://github.com/microlinkhq/react-json-view/blob/master/docker/dev-server.sh#L24) once the container is running - * With my container up and running, the [entrypoint simply runs webpack dev server](https://github.com/microlinkhq/react-json-view/blob/master/entrypoints/dev-server.sh#L6). -If you understand those steps, then you'll understand any of the docker scripts in `/docker/`. They do the same thing as the dev-server script but call different entrypoints. +1. docker [runs my container and mounts some source files](https://github.com/microlinkhq/react-json-view/blob/master/docker/dev-server.sh#L16-L20) into the container + - "mounting" is like a soft copy. my files are linked inside the container's file system so local edits propagate to the container. +2. docker [exposes a port](https://github.com/microlinkhq/react-json-view/blob/master/docker/dev-server.sh#L23) on the container + - this allows me to configure my app to listen and respond to to traffic at http://localhost:2000 + - the port is arbitrary +3. An [entrypoint will be invoked](https://github.com/microlinkhq/react-json-view/blob/master/docker/dev-server.sh#L24) once the container is running + - With my container up and running, the [entrypoint simply runs webpack dev server](https://github.com/microlinkhq/react-json-view/blob/master/entrypoints/dev-server.sh#L6). + +If you understand those steps, then you'll understand any of the docker scripts in `/docker/`. They do the same thing as the dev-server script but call different entrypoints. -here is a workflow comparison with and without docker: +here is a workflow comparison with and without docker: -Task|Without Docker|With Docker -|:---|:---|:--- -install node modules|update package.json
`npm install --save-dev`|update package.json
`./docker/build-container.sh` -run dev server|`npm run dev:hot`|`./docker/dev-server.sh` -run build|`npm run build`|`./docker/build.sh` +| Task | Without Docker | With Docker | +| :------------------- | :----------------------------------------------- | :---------------------------------------------------- | +| install node modules | update package.json
`npm install --save-dev` | update package.json
`./docker/build-container.sh` | +| run dev server | `npm run dev:hot` | `./docker/dev-server.sh` | +| run build | `npm run build` | `./docker/build.sh` | #### is it worth it? -`/docker/` and `/entrypoint/` scripts come with some overhead. Is it really worth the work? +`/docker/` and `/entrypoint/` scripts come with some overhead. Is it really worth the work? -Remember the problems that docker is solving. Without docker, I have to be much more skeptical when testing contributions from the community. +Remember the problems that docker is solving. Without docker, I have to be much more skeptical when testing contributions from the community. What if a contributor is using a different version of node or npm? What if a contributor has a global package installed that's affecting the behavior of their code? diff --git a/index.d.ts b/index.d.ts index cf0564d..d08ea65 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,4 +1,4 @@ -import * as React from 'react'; +import * as React from 'react' export interface ReactJsonViewProps { /** @@ -6,46 +6,46 @@ export interface ReactJsonViewProps { * * Required. */ - src: object; + src: object /** * Contains the name of your root node. Use null or false for no name. * * Default: "root" */ - name?: React.JSX.Element | string | null | false; + name?: React.JSX.Element | string | null | false /** * RJV supports base-16 themes. Check out the list of supported themes in the demo. * A custom "rjv-default" theme applies by default. * * Default: "rjv-default" */ - theme?: ThemeKeys | ThemeObject; + theme?: ThemeKeys | ThemeObject /** * Style attributes for react-json-view container. * Explicit style attributes will override attributes provided by a theme. * * Default: "rjv-default" */ - style?: React.CSSProperties; + style?: React.CSSProperties /** * Style of expand/collapse icons. Accepted values are "circle", triangle" or "square". * * Default: {} */ - iconStyle?: 'circle' | 'triangle' | 'square'; + iconStyle?: 'circle' | 'triangle' | 'square' /** * Set the indent-width for nested objects. * * Default: 4 */ - indentWidth?: number; + indentWidth?: number /** * When set to true, all nodes will be collapsed by default. * Use an integer value to collapse at a particular depth. * * Default: false */ - collapsed?: boolean | number; + collapsed?: boolean | number /** * When an integer value is assigned, strings will be cut off at that length. * Collapsed strings are followed by an ellipsis. @@ -53,52 +53,52 @@ export interface ReactJsonViewProps { * * Default: false */ - collapseStringsAfterLength?: number | false; + collapseStringsAfterLength?: number | false /** * Callback function to provide control over what objects and arrays should be collapsed by default. * An object is passed to the callback containing name, src, type ("array" or "object") and namespace. * * Default: false */ - shouldCollapse?: false | ((field: CollapsedFieldProps) => boolean); + shouldCollapse?: false | ((field: CollapsedFieldProps) => boolean) /** * When an integer value is assigned, arrays will be displayed in groups by count of the value. * Groups are displayed with brakcet notation and can be expanded and collapsed by clickong on the brackets. * * Default: 100 */ - groupArraysAfterLength?: number; + groupArraysAfterLength?: number /** * When prop is not false, the user can copy objects and arrays to clipboard by clicking on the clipboard icon. * Copy callbacks are supported. * * Default: true */ - enableClipboard?: boolean | ((copy: OnCopyProps) => void); + enableClipboard?: boolean | ((copy: OnCopyProps) => void) /** * When set to true, objects and arrays are labeled with size. * * Default: true */ - displayObjectSize?: boolean; + displayObjectSize?: boolean /** * When set to true, data type labels prefix values. * * Default: true */ - displayDataTypes?: boolean; + displayDataTypes?: boolean /** * When set to true, the index of the elements prefix values * * Default: true */ - displayArrayKey?: boolean; + displayArrayKey?: boolean /** * set to false to remove quotes from keys (eg. "name": vs. name:) * * Default: true */ - quotesOnKeys?: boolean; + quotesOnKeys?: boolean /** * When a callback function is passed in, edit functionality is enabled. * The callback is invoked before edits are completed. Returning false @@ -106,7 +106,7 @@ export interface ReactJsonViewProps { * * Default: false */ - onEdit?: ((edit: InteractionProps) => false | any) | false; + onEdit?: ((edit: InteractionProps) => false | any) | false /** * When a callback function is passed in, add functionality is enabled. * The callback is invoked before additions are completed. @@ -114,7 +114,7 @@ export interface ReactJsonViewProps { * * Default: false */ - onAdd?: ((add: InteractionProps) => false | any) | false; + onAdd?: ((add: InteractionProps) => false | any) | false /** * When a callback function is passed in, delete functionality is enabled. * The callback is invoked before deletions are completed. @@ -122,146 +122,145 @@ export interface ReactJsonViewProps { * * Default: false */ - onDelete?: ((del: InteractionProps) => false | any) | false; + onDelete?: ((del: InteractionProps) => false | any) | false /** * When a function is passed in, clicking a value triggers the onSelect method to be called. * * Default: false */ - onSelect?: ((select: OnSelectProps) => void) | false; + onSelect?: ((select: OnSelectProps) => void) | false /** * Custom message for validation failures to onEdit, onAdd, or onDelete callbacks. * * Default: "Validation Error" */ - validationMessage?: string; + validationMessage?: string /** * Set to true to sort object keys. * * Default: false */ - sortKeys?: boolean; + sortKeys?: boolean /** * Set to a value to be used as defaultValue when adding new key to json * * Default: null */ - defaultValue?: TypeDefaultValue | TypeDefaultValue[] | null; + defaultValue?: TypeDefaultValue | TypeDefaultValue[] | null /** * Whether to select the textarea contents on edit * * Default: false */ - selectOnFocus?: boolean; + selectOnFocus?: boolean /** * The key modifier to be combined with a click on JSON values to edit them * * Default: (e) => e.metaKey || e.ctrlKey */ - keyModifier?: (event: Event, type: 'edit' | 'submit') => boolean; + keyModifier?: (event: Event, type: 'edit' | 'submit') => boolean } export interface OnCopyProps { /** * The JSON tree source object */ - src: object; + src: object /** * List of keys. */ - namespace: Array; + namespace: Array /** * The last key in the namespace array. */ - name: string | null; + name: string | null } export interface CollapsedFieldProps { /** * The name of the entry. */ - name: string | null; + name: string | null /** * The corresponding JSON subtree. */ - src: object; + src: object /** * The type of src. Can only be "array" or "object". */ - type: 'array' | 'object'; + type: 'array' | 'object' /** * The scopes above the current entry. */ - namespace: Array; + namespace: Array } export interface InteractionProps { /** * The updated subtree of the JSON tree. */ - updated_src: object; + updated_src: object /** * The existing subtree of the JSON tree. */ - existing_src: object; + existing_src: object /** * The key of the entry that is interacted with. */ - name: string | null; + name: string | null /** * List of keys. */ - namespace: Array; + namespace: Array /** * The original value of the entry that is interacted with. */ - existing_value: object | string | number | boolean | null; + existing_value: object | string | number | boolean | null /** * The updated value of the entry that is interacted with. */ - new_value?: object | string | number | boolean | null; + new_value?: object | string | number | boolean | null } export interface OnSelectProps { /** * The name of the currently selected entry. */ - name: string | null; + name: string | null /** * The value of the currently selected entry. */ - value: object | string | number | boolean | null; + value: object | string | number | boolean | null /** * The type of the value. For "number" type, it will be replaced with the more * accurate types: "float", "integer", or "nan". */ - type: string; + type: string /** * List of keys representing the scopes above the selected entry. */ - namespace: Array; - + namespace: Array } -export type TypeDefaultValue = string | number | boolean | object; +export type TypeDefaultValue = string | number | boolean | object export interface ThemeObject { - base00: string; - base01: string; - base02: string; - base03: string; - base04: string; - base05: string; - base06: string; - base07: string; - base08: string; - base09: string; - base0A: string; - base0B: string; - base0C: string; - base0D: string; - base0E: string; - base0F: string; + base00: string + base01: string + base02: string + base03: string + base04: string + base05: string + base06: string + base07: string + base08: string + base09: string + base0A: string + base0B: string + base0C: string + base0D: string + base0E: string + base0F: string } export type ThemeKeys = @@ -301,7 +300,7 @@ export type ThemeKeys = | 'threezerotwofour' | 'tomorrow' | 'tube' - | 'twilight'; + | 'twilight' -declare const ReactJson: React.ComponentType; -export default ReactJson; +declare const ReactJson: React.ComponentType +export default ReactJson diff --git a/package.json b/package.json index 989c6e7..4ec2462 100644 --- a/package.json +++ b/package.json @@ -215,33 +215,38 @@ "@babel/plugin-syntax-class-properties": "~7.12.1", "@babel/plugin-syntax-jsx": "~7.12.1", "@babel/register": "7.12.10", + "@commitlint/cli": "latest", + "@commitlint/config-conventional": "latest", + "@ksmithut/prettier-standard": "latest", "@types/react": "^18.2.20", + "babel-loader": "8.4.1", + "babel-plugin-istanbul": "6.1.1", "babel-plugin-react-html-attrs": "~2.1.0", + "babel-preset-react-app": "10.0.1", "chai": "~4.2.0", "cheerio": "1.0.0-rc.3", "css-loader": "~4.3.0", "enzyme": "~3.11.0", "enzyme-adapter-react-16": "~1.15.5", - "eslint": "~7.16.0", - "eslint-plugin-prettier": "~3.3.1", - "eslint-plugin-react": "~7.21.5", "github-generate-release": "latest", "html-webpack-plugin": "^4.5.2", "ignore-styles": "~5.0.1", "jsdom": "~16.4.0", "mocha": "~8.2.1", "moment": "~2.29.1", + "nano-staged": "latest", "nyc": "~15.1.0", "prettier": "~2.2.1", "react": "~16.14.0", "react-dom": "~16.14.0", "react-github-button": "~0.1.11", - "react-scripts": "~5.0.1", "react-select": "~1.1.0", "react-test-renderer": "~16.14.0", "sass": "~1.47.0", "sass-loader": "~10.1.1", + "simple-git-hooks": "latest", "sinon": "~9.2.3", + "standard": "latest", "standard-version": "latest", "style-loader": "~1.3.0", "typescript": "^4.5.4", @@ -259,8 +264,7 @@ "build": "NODE_OPTIONS=--openssl-legacy-provider NODE_ENV=production webpack --config webpack/webpack.config.js --progress", "build:demo": "NODE_ENV=production webpack --node-env production --config webpack/webpack.config-demo.js --progress", "dev": "NODE_ENV=development webpack-dev-server --config webpack/webpack.config-dev.js --open", - "lint": "NODE_ENV=test ./node_modules/.bin/eslint src", - "lint-fixup": "NODE_ENV=test ./node_modules/.bin/eslint src --ext .js,.jsx --fix", + "lint": "standard", "modules:debug": "./docker/debug.sh", "modules:size-analyzer": "webpack --config webpack/webpack.config.js --json | webpack-bundle-size-analyzer", "modules:tree": "webpack --config webpack/webpack.config.js --json ", @@ -275,8 +279,41 @@ "test:watch": "NODE_ENV=test nyc mocha -w test/**/*-test.js" }, "license": "MIT", + "commitlint": { + "extends": [ + "@commitlint/config-conventional" + ], + "rules": { + "body-max-line-length": [ + 0 + ] + } + }, + "nano-staged": { + "*.js": [ + "prettier-standard", + "standard --fix" + ], + "package.json": [ + "finepack" + ] + }, "peerDependencies": { "react": ">= 15", "react-dom": ">= 15" + }, + "simple-git-hooks": { + "commit-msg": "npx commitlint --edit", + "pre-commit": "npx nano-staged" + }, + "standard": { + "ignore": [ + "demo/dist", + "dev-server" + ], + "globals": [ + "describe", + "it" + ] } } diff --git a/src/js/components/ArrayGroup.js b/src/js/components/ArrayGroup.js index deae3f8..1d9b228 100644 --- a/src/js/components/ArrayGroup.js +++ b/src/js/components/ArrayGroup.js @@ -1,149 +1,145 @@ -import React from 'react'; -import Theme from './../themes/getStyle'; +import React from 'react' +import Theme from './../themes/getStyle' -import VariableMeta from './VariableMeta'; -import ObjectName from './ObjectName'; -import ObjectComponent from './DataTypes/Object'; +import VariableMeta from './VariableMeta' +import ObjectName from './ObjectName' +import ObjectComponent from './DataTypes/Object' -//icons -import { CollapsedIcon, ExpandedIcon } from './ToggleIcons'; +// icons +import { CollapsedIcon, ExpandedIcon } from './ToggleIcons' -//single indent is 5px -const SINGLE_INDENT = 5; +// single indent is 5px +const SINGLE_INDENT = 5 export default class extends React.PureComponent { - constructor(props) { - super(props); - this.state = { - expanded: [] - }; + constructor (props) { + super(props) + this.state = { + expanded: [] } + } - toggleCollapsed = i => { - const newExpanded = []; - for (const j in this.state.expanded) { - newExpanded.push(this.state.expanded[j]); - } - newExpanded[i] = !newExpanded[i]; - this.setState({ - expanded: newExpanded - }); - }; - - getExpandedIcon(i) { - const { theme, iconStyle } = this.props; + toggleCollapsed = i => { + const newExpanded = [] + for (const j in this.state.expanded) { + newExpanded.push(this.state.expanded[j]) + } + newExpanded[i] = !newExpanded[i] + this.setState({ + expanded: newExpanded + }) + } - if (this.state.expanded[i]) { - return ; - } + getExpandedIcon (i) { + const { theme, iconStyle } = this.props - return ; + if (this.state.expanded[i]) { + return } - render() { - const { - src, - groupArraysAfterLength, - depth, - name, - theme, - jsvRoot, - namespace, - parent_type, - ...rest - } = this.props; + return + } - let object_padding_left = 0; + render () { + const { + src, + groupArraysAfterLength, + depth, + name, + theme, + jsvRoot, + namespace, + parent_type, + ...rest + } = this.props - const array_group_padding_left = this.props.indentWidth * SINGLE_INDENT; + let object_padding_left = 0 - if (!jsvRoot) { - object_padding_left = this.props.indentWidth * SINGLE_INDENT; - } + const array_group_padding_left = this.props.indentWidth * SINGLE_INDENT - const size = groupArraysAfterLength; - const groups = Math.ceil(src.length / size); + if (!jsvRoot) { + object_padding_left = this.props.indentWidth * SINGLE_INDENT + } - return ( -
- + const size = groupArraysAfterLength + const groups = Math.ceil(src.length / size) - - - - {[...Array(groups)].map((_, i) => ( + return ( +
+ + + + + + {[...Array(groups)].map((_, i) => ( +
+ +
{ + this.toggleCollapsed(i) + }} + > + {this.getExpandedIcon(i)} +
+ {this.state.expanded[i] + ? ( + + ) + : ( + { + this.toggleCollapsed(i) + }} + class='array-group-brace' + > + [
- -
{ - this.toggleCollapsed(i); - }} - > - {this.getExpandedIcon(i)} -
- {this.state.expanded[i] ? ( - - ) : ( - { - this.toggleCollapsed(i); - }} - class="array-group-brace" - > - [ - - ] - - )} -
+ + {i * size} + {' - '} + {i * size + size > src.length + ? src.length + : i * size + size} +
- ))} -
- ); - } + ] + + )} + +
+ ))} +
+ ) + } } diff --git a/src/js/components/CopyToClipboard.js b/src/js/components/CopyToClipboard.js index 49746ca..34cabaa 100644 --- a/src/js/components/CopyToClipboard.js +++ b/src/js/components/CopyToClipboard.js @@ -1,131 +1,127 @@ -import React from 'react'; +import React from 'react' -import { toType } from './../helpers/util'; +import { toType } from './../helpers/util' -//clipboard icon -import { Clippy } from './icons'; +// clipboard icon +import { Clippy } from './icons' -//theme -import Theme from './../themes/getStyle'; +// theme +import Theme from './../themes/getStyle' export default class extends React.PureComponent { - constructor(props) { - super(props); - this.state = { - copied: false - }; + constructor (props) { + super(props) + this.state = { + copied: false } + } - copiedTimer = null; + copiedTimer = null - componentWillUnmount() { - if (this.copiedTimer) { - clearTimeout(this.copiedTimer); - this.copiedTimer = null; - } + componentWillUnmount () { + if (this.copiedTimer) { + clearTimeout(this.copiedTimer) + this.copiedTimer = null + } + } + + copyToClipboardFallback = textToCopy => { + const textArea = document.createElement('textarea') + textArea.value = textToCopy + document.body.appendChild(textArea) + textArea.select() + document.execCommand('copy') + document.body.removeChild(textArea) + } + + handleCopy = () => { + const { clickCallback, src, namespace } = this.props + + const textToCopy = JSON.stringify(this.clipboardValue(src), null, ' ') + + if (navigator.clipboard) { + navigator.clipboard.writeText(textToCopy).catch(() => { + // Fallback for non-secure contexts (i.e. http) + this.copyToClipboardFallback(textToCopy) + }) + } else { + // Fallback for old browsers and test environments + this.copyToClipboardFallback(textToCopy) } - copyToClipboardFallback = (textToCopy) => { - const textArea = document.createElement('textarea'); - textArea.value = textToCopy; - document.body.appendChild(textArea); - textArea.select(); - document.execCommand('copy'); - document.body.removeChild(textArea); + this.copiedTimer = setTimeout(() => { + this.setState({ + copied: false + }) + }, 5500) + + this.setState({ copied: true }, () => { + if (typeof clickCallback !== 'function') { + return + } + + clickCallback({ + src, + namespace, + name: namespace[namespace.length - 1] + }) + }) + } + + getClippyIcon = () => { + const { theme } = this.props + + if (this.state.copied) { + return ( + + + ✔ + + ) } - handleCopy = () => { - const { clickCallback, src, namespace } = this.props; - - const textToCopy = JSON.stringify( - this.clipboardValue(src), - null, - ' ' - ); - - if (navigator.clipboard) { - navigator.clipboard.writeText(textToCopy).catch(() => { - // Fallback for non-secure contexts (i.e. http) - this.copyToClipboardFallback(textToCopy); - }); - } else { - // Fallback for old browsers and test environments - this.copyToClipboardFallback(textToCopy); - }; - - this.copiedTimer = setTimeout(() => { - this.setState({ - copied: false - }); - }, 5500); - - this.setState({ copied: true }, () => { - if (typeof clickCallback !== 'function') { - return; - } - - clickCallback({ - src: src, - namespace: namespace, - name: namespace[namespace.length - 1] - }); - }); - }; - - getClippyIcon = () => { - const { theme } = this.props; - - if (this.state.copied) { - return ( - - - ✔ - - ); - } - - return ; - }; - - clipboardValue = value => { - const type = toType(value); - switch (type) { - case 'function': - case 'regexp': - return value.toString(); - default: - return value; - } - }; - - render() { - const { src, theme, hidden, rowHovered } = this.props; - let style = Theme(theme, 'copy-to-clipboard').style; - let display = 'inline'; - - if (hidden) { - display = 'none'; - } - - return ( - - - {this.getClippyIcon()} - - - ); + return + } + + clipboardValue = value => { + const type = toType(value) + switch (type) { + case 'function': + case 'regexp': + return value.toString() + default: + return value } + } + + render () { + const { src, theme, hidden, rowHovered } = this.props + const style = Theme(theme, 'copy-to-clipboard').style + let display = 'inline' + + if (hidden) { + display = 'none' + } + + return ( + + + {this.getClippyIcon()} + + + ) + } } diff --git a/src/js/components/DataTypes/Boolean.js b/src/js/components/DataTypes/Boolean.js index 886d332..ab7d4ca 100644 --- a/src/js/components/DataTypes/Boolean.js +++ b/src/js/components/DataTypes/Boolean.js @@ -1,19 +1,19 @@ -import React from 'react'; -import DataTypeLabel from './DataTypeLabel'; +import React from 'react' +import DataTypeLabel from './DataTypeLabel' -//theme -import Theme from './../../themes/getStyle'; +// theme +import Theme from './../../themes/getStyle' export default class extends React.PureComponent { - render() { - const type_name = 'bool'; - const { props } = this; + render () { + const type_name = 'bool' + const { props } = this - return ( -
- - {props.value ? 'true' : 'false'} -
- ); - } + return ( +
+ + {props.value ? 'true' : 'false'} +
+ ) + } } diff --git a/src/js/components/DataTypes/DataTypeLabel.js b/src/js/components/DataTypes/DataTypeLabel.js index 5b61fdc..001f3e7 100644 --- a/src/js/components/DataTypes/DataTypeLabel.js +++ b/src/js/components/DataTypes/DataTypeLabel.js @@ -1,21 +1,18 @@ -import React from 'react'; +import React from 'react' -//theme -import Theme from './../../themes/getStyle'; +// theme +import Theme from './../../themes/getStyle' export default class extends React.PureComponent { - render() { - const { rjvId, type_name, displayDataTypes, theme } = this.props; - if (displayDataTypes) { - return ( - - {type_name} - - ); - } - return null; + render () { + const { rjvId, type_name, displayDataTypes, theme } = this.props + if (displayDataTypes) { + return ( + + {type_name} + + ) } + return null + } } diff --git a/src/js/components/DataTypes/DataTypes.js b/src/js/components/DataTypes/DataTypes.js index de5c501..56223dd 100644 --- a/src/js/components/DataTypes/DataTypes.js +++ b/src/js/components/DataTypes/DataTypes.js @@ -1,11 +1,11 @@ -export { default as JsonBoolean } from './Boolean'; -export { default as JsonDate } from './Date'; -export { default as JsonFloat } from './Float'; -export { default as JsonFunction } from './Function'; -export { default as JsonNan } from './Nan'; -export { default as JsonNull } from './Null'; -export { default as JsonInteger } from './Integer'; -export { default as JsonObject } from './Object'; -export { default as JsonRegexp } from './Regexp'; -export { default as JsonString } from './String'; -export { default as JsonUndefined } from './Undefined'; +export { default as JsonBoolean } from './Boolean' +export { default as JsonDate } from './Date' +export { default as JsonFloat } from './Float' +export { default as JsonFunction } from './Function' +export { default as JsonNan } from './Nan' +export { default as JsonNull } from './Null' +export { default as JsonInteger } from './Integer' +export { default as JsonObject } from './Object' +export { default as JsonRegexp } from './Regexp' +export { default as JsonString } from './String' +export { default as JsonUndefined } from './Undefined' diff --git a/src/js/components/DataTypes/Date.js b/src/js/components/DataTypes/Date.js index 662d755..bf10c1a 100644 --- a/src/js/components/DataTypes/Date.js +++ b/src/js/components/DataTypes/Date.js @@ -1,28 +1,28 @@ -import React from 'react'; -import DataTypeLabel from './DataTypeLabel'; +import React from 'react' +import DataTypeLabel from './DataTypeLabel' -//theme -import Theme from './../../themes/getStyle'; +// theme +import Theme from './../../themes/getStyle' export default class extends React.PureComponent { - render() { - const type_name = 'date'; - const { props } = this; - const display_options = { - weekday: 'short', - year: 'numeric', - month: 'short', - day: 'numeric', - hour: '2-digit', - minute: '2-digit' - }; - return ( -
- - - {props.value.toLocaleTimeString('en-us', display_options)} - -
- ); + render () { + const type_name = 'date' + const { props } = this + const display_options = { + weekday: 'short', + year: 'numeric', + month: 'short', + day: 'numeric', + hour: '2-digit', + minute: '2-digit' } + return ( +
+ + + {props.value.toLocaleTimeString('en-us', display_options)} + +
+ ) + } } diff --git a/src/js/components/DataTypes/Float.js b/src/js/components/DataTypes/Float.js index 68bab7a..0105817 100644 --- a/src/js/components/DataTypes/Float.js +++ b/src/js/components/DataTypes/Float.js @@ -1,18 +1,18 @@ -import React from 'react'; -import DataTypeLabel from './DataTypeLabel'; +import React from 'react' +import DataTypeLabel from './DataTypeLabel' -//theme -import Theme from './../../themes/getStyle'; +// theme +import Theme from './../../themes/getStyle' export default class extends React.PureComponent { - render() { - const type_name = 'float'; - const { props } = this; - return ( -
- - {this.props.value} -
- ); - } + render () { + const type_name = 'float' + const { props } = this + return ( +
+ + {this.props.value} +
+ ) + } } diff --git a/src/js/components/DataTypes/Function.js b/src/js/components/DataTypes/Function.js index 473afe9..39290de 100644 --- a/src/js/components/DataTypes/Function.js +++ b/src/js/components/DataTypes/Function.js @@ -1,82 +1,79 @@ -import React from 'react'; -import DataTypeLabel from './DataTypeLabel'; +import React from 'react' +import DataTypeLabel from './DataTypeLabel' -//theme -import Theme from './../../themes/getStyle'; +// theme +import Theme from './../../themes/getStyle' -//attribute store for storing collapsed state -import AttributeStore from './../../stores/ObjectAttributes'; +// attribute store for storing collapsed state +import AttributeStore from './../../stores/ObjectAttributes' export default class extends React.PureComponent { - constructor(props) { - super(props); - this.state = { - collapsed: AttributeStore.get( - props.rjvId, - props.namespace, - 'collapsed', - true - ) - }; + constructor (props) { + super(props) + this.state = { + collapsed: AttributeStore.get( + props.rjvId, + props.namespace, + 'collapsed', + true + ) } + } - toggleCollapsed = () => { - this.setState( - { - collapsed: !this.state.collapsed - }, - () => { - // will be called after setState takes effect. - AttributeStore.set( - this.props.rjvId, - this.props.namespace, - 'collapsed', - this.state.collapsed - ); - } - ); - }; + toggleCollapsed = () => { + this.setState( + { + collapsed: !this.state.collapsed + }, + () => { + // will be called after setState takes effect. + AttributeStore.set( + this.props.rjvId, + this.props.namespace, + 'collapsed', + this.state.collapsed + ) + } + ) + } - render() { - const type_name = 'function'; - const { props } = this; - const { collapsed } = this.state; + render () { + const type_name = 'function' + const { props } = this + const { collapsed } = this.state - return ( -
- - - {this.getFunctionDisplay(collapsed)} - -
- ); - } + return ( +
+ + + {this.getFunctionDisplay(collapsed)} + +
+ ) + } - getFunctionDisplay = collapsed => { - const { props } = this; - if (collapsed) { - return ( - - {this.props.value - .toString() - .slice(9, -1) - .replace(/\{[\s\S]+/, '')} - - {'{'} - ... - {'}'} - - - ); - } else { - return this.props.value.toString().slice(9, -1); - } - }; + getFunctionDisplay = collapsed => { + const { props } = this + if (collapsed) { + return ( + + {this.props.value + .toString() + .slice(9, -1) + .replace(/\{[\s\S]+/, '')} + + {'{'} + ... + {'}'} + + + ) + } else { + return this.props.value.toString().slice(9, -1) + } + } } diff --git a/src/js/components/DataTypes/Integer.js b/src/js/components/DataTypes/Integer.js index 21d173d..86d04d4 100644 --- a/src/js/components/DataTypes/Integer.js +++ b/src/js/components/DataTypes/Integer.js @@ -1,18 +1,18 @@ -import React from 'react'; -import DataTypeLabel from './DataTypeLabel'; +import React from 'react' +import DataTypeLabel from './DataTypeLabel' -//theme -import Theme from './../../themes/getStyle'; +// theme +import Theme from './../../themes/getStyle' export default class extends React.PureComponent { - render() { - const type_name = 'int'; - const { props } = this; - return ( -
- - {this.props.value} -
- ); - } + render () { + const type_name = 'int' + const { props } = this + return ( +
+ + {this.props.value} +
+ ) + } } diff --git a/src/js/components/DataTypes/Nan.js b/src/js/components/DataTypes/Nan.js index ddc1aa9..6412f1e 100644 --- a/src/js/components/DataTypes/Nan.js +++ b/src/js/components/DataTypes/Nan.js @@ -1,10 +1,10 @@ -import React from 'react'; +import React from 'react' -//theme -import Theme from './../../themes/getStyle'; +// theme +import Theme from './../../themes/getStyle' export default class extends React.PureComponent { - render() { - return
NaN
; - } + render () { + return
NaN
+ } } diff --git a/src/js/components/DataTypes/Null.js b/src/js/components/DataTypes/Null.js index 005729f..b603bb1 100644 --- a/src/js/components/DataTypes/Null.js +++ b/src/js/components/DataTypes/Null.js @@ -1,10 +1,10 @@ -import React from 'react'; +import React from 'react' -//theme -import Theme from './../../themes/getStyle'; +// theme +import Theme from './../../themes/getStyle' export default class extends React.PureComponent { - render() { - return
NULL
; - } + render () { + return
NULL
+ } } diff --git a/src/js/components/DataTypes/Object.js b/src/js/components/DataTypes/Object.js index 4c7cb93..d3c1b90 100644 --- a/src/js/components/DataTypes/Object.js +++ b/src/js/components/DataTypes/Object.js @@ -1,328 +1,318 @@ -import React from 'react'; -import { polyfill } from 'react-lifecycles-compat'; -import { toType } from './../../helpers/util'; +import React from 'react' +import { polyfill } from 'react-lifecycles-compat' +import { toType } from './../../helpers/util' -//data type components -import { JsonObject } from './DataTypes'; +// data type components +import { JsonObject } from './DataTypes' -import VariableEditor from './../VariableEditor'; -import VariableMeta from './../VariableMeta'; -import ArrayGroup from './../ArrayGroup'; -import ObjectName from './../ObjectName'; +import VariableEditor from './../VariableEditor' +import VariableMeta from './../VariableMeta' +import ArrayGroup from './../ArrayGroup' +import ObjectName from './../ObjectName' -//attribute store -import AttributeStore from './../../stores/ObjectAttributes'; +// attribute store +import AttributeStore from './../../stores/ObjectAttributes' -//icons -import { CollapsedIcon, ExpandedIcon } from './../ToggleIcons'; +// icons +import { CollapsedIcon, ExpandedIcon } from './../ToggleIcons' -//theme -import Theme from './../../themes/getStyle'; +// theme +import Theme from './../../themes/getStyle' -//increment 1 with each nested object & array -const DEPTH_INCREMENT = 1; -//single indent is 5px -const SINGLE_INDENT = 5; +// increment 1 with each nested object & array +const DEPTH_INCREMENT = 1 +// single indent is 5px +const SINGLE_INDENT = 5 class RjvObject extends React.PureComponent { - constructor(props) { - super(props); - const state = RjvObject.getState(props); - this.state = { - ...state, - prevProps: {} - }; + constructor (props) { + super(props) + const state = RjvObject.getState(props) + this.state = { + ...state, + prevProps: {} } + } - static getState = props => { - const size = Object.keys(props.src).length; - const expanded = - (props.collapsed === false || - (props.collapsed !== true && props.collapsed > props.depth)) && - (!props.shouldCollapse || - props.shouldCollapse({ - name: props.name, - src: props.src, - type: toType(props.src), - namespace: props.namespace - }) === false) && - //initialize closed if object has no items - size !== 0; - const state = { - expanded: AttributeStore.get( - props.rjvId, - props.namespace, - 'expanded', - expanded - ), - object_type: props.type === 'array' ? 'array' : 'object', - parent_type: props.type === 'array' ? 'array' : 'object', - size, - hovered: false - }; - return state; - }; + static getState = props => { + const size = Object.keys(props.src).length + const expanded = + (props.collapsed === false || + (props.collapsed !== true && props.collapsed > props.depth)) && + (!props.shouldCollapse || + props.shouldCollapse({ + name: props.name, + src: props.src, + type: toType(props.src), + namespace: props.namespace + }) === false) && + // initialize closed if object has no items + size !== 0 + const state = { + expanded: AttributeStore.get( + props.rjvId, + props.namespace, + 'expanded', + expanded + ), + object_type: props.type === 'array' ? 'array' : 'object', + parent_type: props.type === 'array' ? 'array' : 'object', + size, + hovered: false + } + return state + } - static getDerivedStateFromProps(nextProps, prevState) { - const { prevProps } = prevState; - if ( - nextProps.src !== prevProps.src || - nextProps.collapsed !== prevProps.collapsed || - nextProps.name !== prevProps.name || - nextProps.namespace !== prevProps.namespace || - nextProps.rjvId !== prevProps.rjvId - ) { - const newState = RjvObject.getState(nextProps); - return { - ...newState, - prevProps: nextProps - }; - } - return null; + static getDerivedStateFromProps (nextProps, prevState) { + const { prevProps } = prevState + if ( + nextProps.src !== prevProps.src || + nextProps.collapsed !== prevProps.collapsed || + nextProps.name !== prevProps.name || + nextProps.namespace !== prevProps.namespace || + nextProps.rjvId !== prevProps.rjvId + ) { + const newState = RjvObject.getState(nextProps) + return { + ...newState, + prevProps: nextProps + } } + return null + } - toggleCollapsed = () => { - this.setState( - { - expanded: !this.state.expanded - }, - () => { - AttributeStore.set( - this.props.rjvId, - this.props.namespace, - 'expanded', - this.state.expanded - ); - } - ); - }; + toggleCollapsed = () => { + this.setState( + { + expanded: !this.state.expanded + }, + () => { + AttributeStore.set( + this.props.rjvId, + this.props.namespace, + 'expanded', + this.state.expanded + ) + } + ) + } - getObjectContent = (depth, src, props) => { - return ( -
-
- {this.renderObjectContents(src, props)} -
-
- ); - }; + getObjectContent = (depth, src, props) => { + return ( +
+
+ {this.renderObjectContents(src, props)} +
+
+ ) + } - getEllipsis = () => { - const { size } = this.state; + getEllipsis = () => { + const { size } = this.state - if (size === 0) { - //don't render an ellipsis when an object has no items - return null; - } else { - return ( -
- ... -
- ); - } - }; + if (size === 0) { + // don't render an ellipsis when an object has no items + return null + } else { + return ( +
+ ... +
+ ) + } + } - getObjectMetaData = src => { - const { rjvId, theme } = this.props; - const { size, hovered } = this.state; - return ( - - ); - }; + getObjectMetaData = src => { + const { rjvId, theme } = this.props + const { size, hovered } = this.state + return + } - getBraceStart(object_type, expanded) { - const { src, theme, iconStyle, parent_type } = this.props; + getBraceStart (object_type, expanded) { + const { src, theme, iconStyle, parent_type } = this.props - if (parent_type === 'array_group') { - return ( - - - {object_type === 'array' ? '[' : '{'} - - {expanded ? this.getObjectMetaData(src) : null} - - ); - } + if (parent_type === 'array_group') { + return ( + + + {object_type === 'array' ? '[' : '{'} + + {expanded ? this.getObjectMetaData(src) : null} + + ) + } + + const IconComponent = expanded ? ExpandedIcon : CollapsedIcon + + return ( + + { + this.toggleCollapsed() + }} + {...Theme(theme, 'brace-row')} + > +
+ +
+ + + {object_type === 'array' ? '[' : '{'} + +
+ {expanded ? this.getObjectMetaData(src) : null} +
+ ) + } - const IconComponent = expanded ? ExpandedIcon : CollapsedIcon; + render () { + // `indentWidth` and `collapsed` props will + // perpetuate to children via `...rest` + const { + depth, + src, + namespace, + name, + type, + parent_type, + theme, + jsvRoot, + iconStyle, + ...rest + } = this.props - return ( - - { - this.toggleCollapsed(); - }} - {...Theme(theme, 'brace-row')} - > -
- -
- - - {object_type === 'array' ? '[' : '{'} - -
- {expanded ? this.getObjectMetaData(src) : null} -
- ); + const { object_type, expanded } = this.state + + const styles = {} + if (!jsvRoot && parent_type !== 'array_group') { + styles.paddingLeft = this.props.indentWidth * SINGLE_INDENT + } else if (parent_type === 'array_group') { + styles.borderLeft = 0 + styles.display = 'inline' } - render() { - // `indentWidth` and `collapsed` props will - // perpetuate to children via `...rest` - const { - depth, - src, - namespace, - name, - type, - parent_type, + return ( +
this.setState({ ...this.state, hovered: true })} + onMouseLeave={() => this.setState({ ...this.state, hovered: false })} + {...Theme(theme, jsvRoot ? 'jsv-root' : 'objectKeyVal', styles)} + > + {this.getBraceStart(object_type, expanded)} + {expanded + ? this.getObjectContent(depth, src, { theme, - jsvRoot, iconStyle, ...rest - } = this.props; - - const { object_type, expanded } = this.state; + }) + : this.getEllipsis()} + + + {object_type === 'array' ? ']' : '}'} + + {expanded ? null : this.getObjectMetaData(src)} + +
+ ) + } - let styles = {}; - if (!jsvRoot && parent_type !== 'array_group') { - styles.paddingLeft = this.props.indentWidth * SINGLE_INDENT; - } else if (parent_type === 'array_group') { - styles.borderLeft = 0; - styles.display = 'inline'; - } - - return ( -
- this.setState({ ...this.state, hovered: true }) - } - onMouseLeave={() => - this.setState({ ...this.state, hovered: false }) - } - {...Theme(theme, jsvRoot ? 'jsv-root' : 'objectKeyVal', styles)} - > - {this.getBraceStart(object_type, expanded)} - {expanded - ? this.getObjectContent(depth, src, { - theme, - iconStyle, - ...rest - }) - : this.getEllipsis()} - - - {object_type === 'array' ? ']' : '}'} - - {expanded ? null : this.getObjectMetaData(src)} - -
- ); + renderObjectContents = (variables, props) => { + const { + depth, + parent_type, + index_offset, + groupArraysAfterLength, + namespace + } = this.props + const { object_type } = this.state + const elements = [] + let variable + let keys = Object.keys(variables || {}) + if (this.props.sortKeys && object_type !== 'array') { + keys = keys.sort() } - renderObjectContents = (variables, props) => { - const { - depth, - parent_type, - index_offset, - groupArraysAfterLength, - namespace - } = this.props; - const { object_type } = this.state; - let elements = [], - variable; - let keys = Object.keys(variables || {}); - if (this.props.sortKeys && object_type !== 'array') { - keys = keys.sort(); - } - - keys.forEach(name => { - variable = new JsonVariable(name, variables[name]); + keys.forEach(name => { + variable = new JsonVariable(name, variables[name]) - if (parent_type === 'array_group' && index_offset) { - variable.name = parseInt(variable.name) + index_offset; - } - if (!variables.hasOwnProperty(name)) { - return; - } else if (variable.type === 'object') { - elements.push( - - ); - } else if (variable.type === 'array') { - let ObjectComponent = JsonObject; + if (parent_type === 'array_group' && index_offset) { + variable.name = parseInt(variable.name) + index_offset + } + if (!variables.hasOwnProperty(name)) { + } else if (variable.type === 'object') { + elements.push( + + ) + } else if (variable.type === 'array') { + let ObjectComponent = JsonObject - if ( - groupArraysAfterLength && - variable.value.length > groupArraysAfterLength - ) { - ObjectComponent = ArrayGroup; - } + if ( + groupArraysAfterLength && + variable.value.length > groupArraysAfterLength + ) { + ObjectComponent = ArrayGroup + } - elements.push( - - ); - } else { - elements.push( - - ); - } - }); + elements.push( + + ) + } else { + elements.push( + + ) + } + }) - return elements; - }; + return elements + } } -//just store name, value and type with a variable +// just store name, value and type with a variable class JsonVariable { - constructor(name, value) { - this.name = name; - this.value = value; - this.type = toType(value); - } + constructor (name, value) { + this.name = name + this.value = value + this.type = toType(value) + } } -polyfill(RjvObject); +polyfill(RjvObject) -//export component -export default RjvObject; +// export component +export default RjvObject diff --git a/src/js/components/DataTypes/Regexp.js b/src/js/components/DataTypes/Regexp.js index 17af70a..cf2753c 100644 --- a/src/js/components/DataTypes/Regexp.js +++ b/src/js/components/DataTypes/Regexp.js @@ -1,18 +1,18 @@ -import React from 'react'; -import DataTypeLabel from './DataTypeLabel'; +import React from 'react' +import DataTypeLabel from './DataTypeLabel' -//theme -import Theme from './../../themes/getStyle'; +// theme +import Theme from './../../themes/getStyle' export default class extends React.PureComponent { - render() { - const type_name = 'regexp'; - const { props } = this; - return ( -
- - {this.props.value.toString()} -
- ); - } + render () { + const type_name = 'regexp' + const { props } = this + return ( +
+ + {this.props.value.toString()} +
+ ) + } } diff --git a/src/js/components/DataTypes/String.js b/src/js/components/DataTypes/String.js index cef5fc3..29454e5 100644 --- a/src/js/components/DataTypes/String.js +++ b/src/js/components/DataTypes/String.js @@ -1,74 +1,70 @@ -import React from 'react'; -import DataTypeLabel from './DataTypeLabel'; -import { toType } from './../../helpers/util'; +import React from 'react' +import DataTypeLabel from './DataTypeLabel' +import { toType } from './../../helpers/util' -//theme -import Theme from './../../themes/getStyle'; +// theme +import Theme from './../../themes/getStyle' -//attribute store for storing collapsed state -import AttributeStore from './../../stores/ObjectAttributes'; +// attribute store for storing collapsed state +import AttributeStore from './../../stores/ObjectAttributes' export default class extends React.PureComponent { - constructor(props) { - super(props); - this.state = { - collapsed: AttributeStore.get( - props.rjvId, - props.namespace, - 'collapsed', - true - ) - }; + constructor (props) { + super(props) + this.state = { + collapsed: AttributeStore.get( + props.rjvId, + props.namespace, + 'collapsed', + true + ) } + } - toggleCollapsed = () => { - this.setState( - { - collapsed: !this.state.collapsed - }, - () => { - AttributeStore.set( - this.props.rjvId, - this.props.namespace, - 'collapsed', - this.state.collapsed - ); - } - ); - }; + toggleCollapsed = () => { + this.setState( + { + collapsed: !this.state.collapsed + }, + () => { + AttributeStore.set( + this.props.rjvId, + this.props.namespace, + 'collapsed', + this.state.collapsed + ) + } + ) + } - render() { - const type_name = 'string'; - const { collapsed } = this.state; - const { props } = this; - const { collapseStringsAfterLength, theme } = props; - let { value } = props; - let collapsible = toType(collapseStringsAfterLength) === 'integer'; - let style = { style: { cursor: 'default' } }; + render () { + const type_name = 'string' + const { collapsed } = this.state + const { props } = this + const { collapseStringsAfterLength, theme } = props + let { value } = props + const collapsible = toType(collapseStringsAfterLength) === 'integer' + const style = { style: { cursor: 'default' } } - if (collapsible && value.length > collapseStringsAfterLength) { - style.style.cursor = 'pointer'; - if (this.state.collapsed) { - value = ( - - {value.substring(0, collapseStringsAfterLength)} - ... - - ); - } - } - - return ( -
- - - "{value}" - -
- ); + if (collapsible && value.length > collapseStringsAfterLength) { + style.style.cursor = 'pointer' + if (this.state.collapsed) { + value = ( + + {value.substring(0, collapseStringsAfterLength)} + ... + + ) + } } + + return ( +
+ + + "{value}" + +
+ ) + } } diff --git a/src/js/components/DataTypes/Undefined.js b/src/js/components/DataTypes/Undefined.js index 534132f..b9fd2db 100644 --- a/src/js/components/DataTypes/Undefined.js +++ b/src/js/components/DataTypes/Undefined.js @@ -1,10 +1,10 @@ -import React from 'react'; +import React from 'react' -//theme -import Theme from './../../themes/getStyle'; +// theme +import Theme from './../../themes/getStyle' export default class extends React.PureComponent { - render() { - return
undefined
; - } + render () { + return
undefined
+ } } diff --git a/src/js/components/JsonViewer.js b/src/js/components/JsonViewer.js index 5ddebc2..ab0df68 100644 --- a/src/js/components/JsonViewer.js +++ b/src/js/components/JsonViewer.js @@ -1,37 +1,33 @@ -import React from 'react'; -import JsonObject from './DataTypes/Object'; -import ArrayGroup from './ArrayGroup'; +import React from 'react' +import JsonObject from './DataTypes/Object' +import ArrayGroup from './ArrayGroup' export default class extends React.PureComponent { - render = () => { - const { props } = this; - let namespace = [props.name]; - let ObjectComponent = JsonObject; - if (typeof props.name === 'object' && !Array.isArray(props.name)) { - // Support Classes and Functional Components - const ComponentName = props.name?.displayName || props.name?.name || props.name?.type?.name; - namespace = [ComponentName || 'Anonymous']; - } + render = () => { + const { props } = this + let namespace = [props.name] + let ObjectComponent = JsonObject + if (typeof props.name === 'object' && !Array.isArray(props.name)) { + // Support Classes and Functional Components + const ComponentName = + props.name?.displayName || props.name?.name || props.name?.type?.name + namespace = [ComponentName || 'Anonymous'] + } - if ( - Array.isArray(props.src) && - props.groupArraysAfterLength && - props.src.length > props.groupArraysAfterLength - ) { - ObjectComponent = ArrayGroup; - } + if ( + Array.isArray(props.src) && + props.groupArraysAfterLength && + props.src.length > props.groupArraysAfterLength + ) { + ObjectComponent = ArrayGroup + } - return ( -
-
- -
-
- ); - }; + return ( +
+
+ +
+
+ ) + } } diff --git a/src/js/components/ObjectKeyModal/AddKeyRequest.js b/src/js/components/ObjectKeyModal/AddKeyRequest.js index 65eb7b0..62933b0 100644 --- a/src/js/components/ObjectKeyModal/AddKeyRequest.js +++ b/src/js/components/ObjectKeyModal/AddKeyRequest.js @@ -1,48 +1,45 @@ -import React from 'react'; -import dispatcher from './../../helpers/dispatcher'; -import ObjectAttributes from './../../stores/ObjectAttributes'; -import ObjectKeyModal from './ObjectKeyModal'; +import React from 'react' +import dispatcher from './../../helpers/dispatcher' +import ObjectAttributes from './../../stores/ObjectAttributes' +import ObjectKeyModal from './ObjectKeyModal' -//global theme -import Theme from './../../themes/getStyle'; +// global theme +import Theme from './../../themes/getStyle' -//this input appears when adding a new value to an object +// this input appears when adding a new value to an object export default class extends React.PureComponent { - render() { - const { active, theme, rjvId } = this.props; + render () { + const { active, theme, rjvId } = this.props - return active ? ( - - ) : null; - } + return active + ? ( + + ) + : null + } - isValid = input => { - const { rjvId } = this.props; - const request = ObjectAttributes.get( - rjvId, - 'action', - 'new-key-request' - ); - return ( - input != '' && - Object.keys(request.existing_value).indexOf(input) === -1 - ); - }; + isValid = input => { + const { rjvId } = this.props + const request = ObjectAttributes.get(rjvId, 'action', 'new-key-request') + return ( + input != '' && Object.keys(request.existing_value).indexOf(input) === -1 + ) + } - submit = input => { - const { rjvId } = this.props; - let request = ObjectAttributes.get(rjvId, 'action', 'new-key-request'); - request.new_value = { ...request.existing_value }; - request.new_value[input] = this.props.defaultValue; - dispatcher.dispatch({ - name: 'VARIABLE_ADDED', - rjvId: rjvId, - data: request - }); - }; + submit = input => { + const { rjvId } = this.props + const request = ObjectAttributes.get(rjvId, 'action', 'new-key-request') + request.new_value = { ...request.existing_value } + request.new_value[input] = this.props.defaultValue + dispatcher.dispatch({ + name: 'VARIABLE_ADDED', + rjvId, + data: request + }) + } } diff --git a/src/js/components/ObjectKeyModal/ObjectKeyModal.js b/src/js/components/ObjectKeyModal/ObjectKeyModal.js index 6738915..f340e7c 100644 --- a/src/js/components/ObjectKeyModal/ObjectKeyModal.js +++ b/src/js/components/ObjectKeyModal/ObjectKeyModal.js @@ -1,93 +1,95 @@ -import React from 'react'; -import dispatcher from './../../helpers/dispatcher'; +import React from 'react' +import dispatcher from './../../helpers/dispatcher' -import { CheckCircle, Add as Cancel } from './../icons'; +import { CheckCircle, Add as Cancel } from './../icons' -//global theme -import Theme from './../../themes/getStyle'; +// global theme +import Theme from './../../themes/getStyle' -//this input appears when adding a new value to an object +// this input appears when adding a new value to an object export default class extends React.PureComponent { - constructor(props) { - super(props); - this.state = { - input: props.input ? props.input : '' - }; + constructor (props) { + super(props) + this.state = { + input: props.input ? props.input : '' } + } - render() { - const { theme, rjvId, isValid } = this.props; - const { input } = this.state; + render () { + const { theme, rjvId, isValid } = this.props + const { input } = this.state - const valid = isValid(input); + const valid = isValid(input) - return ( -
-
{ - e.stopPropagation(); - }} - > -
Key Name:
-
- el && el.focus()} - spellCheck={false} - value={input} - placeholder="..." - onChange={e => { - this.setState({ - input: e.target.value - }); - }} - onKeyPress={e => { - if (valid && e.key === 'Enter') { - this.submit(); - } else if (e.key === 'Escape') { - this.closeModal(); - } - }} - /> - {valid ? ( - this.submit()} - /> - ) : null} -
- - { - dispatcher.dispatch({ - rjvId: rjvId, - name: 'RESET' - }); - }} - /> - -
-
- ); - } + return ( +
+
{ + e.stopPropagation() + }} + > +
Key Name:
+
+ el && el.focus()} + spellCheck={false} + value={input} + placeholder='...' + onChange={e => { + this.setState({ + input: e.target.value + }) + }} + onKeyPress={e => { + if (valid && e.key === 'Enter') { + this.submit() + } else if (e.key === 'Escape') { + this.closeModal() + } + }} + /> + {valid + ? ( + this.submit()} + /> + ) + : null} +
+ + { + dispatcher.dispatch({ + rjvId, + name: 'RESET' + }) + }} + /> + +
+
+ ) + } - closeModal = () => { - dispatcher.dispatch({ - rjvId: this.props.rjvId, - name: 'RESET' - }); - }; + closeModal = () => { + dispatcher.dispatch({ + rjvId: this.props.rjvId, + name: 'RESET' + }) + } - submit = () => { - this.props.submit(this.state.input); - }; + submit = () => { + this.props.submit(this.state.input) + } } diff --git a/src/js/components/ObjectName.js b/src/js/components/ObjectName.js index c1cfaac..301d6f7 100644 --- a/src/js/components/ObjectName.js +++ b/src/js/components/ObjectName.js @@ -1,44 +1,42 @@ -import React from 'react'; -import Theme from './../themes/getStyle'; +import React from 'react' +import Theme from './../themes/getStyle' -export default function getObjectName(props) { - const { - parent_type, - namespace, - quotesOnKeys, - theme, - jsvRoot, - name, - displayArrayKey - } = props; +export default function getObjectName (props) { + const { + parent_type, + namespace, + quotesOnKeys, + theme, + jsvRoot, + name, + displayArrayKey + } = props - const display_name = props.name ? props.name : ''; + const display_name = props.name ? props.name : '' - if (jsvRoot && (name === false || name === null)) { - return ; - } else if (parent_type == 'array') { - return displayArrayKey ? ( - - {display_name} - : - - ) : ( - - ); - } else { - return ( - - - {quotesOnKeys && ( - " - )} - {display_name} - {quotesOnKeys && ( - " - )} - - : - - ); - } + if (jsvRoot && (name === false || name === null)) { + return + } else if (parent_type == 'array') { + return displayArrayKey + ? ( + + {display_name} + : + + ) + : ( + + ) + } else { + return ( + + + {quotesOnKeys && "} + {display_name} + {quotesOnKeys && "} + + : + + ) + } } diff --git a/src/js/components/ToggleIcons.js b/src/js/components/ToggleIcons.js index 2ad3412..9ded049 100644 --- a/src/js/components/ToggleIcons.js +++ b/src/js/components/ToggleIcons.js @@ -1,65 +1,56 @@ -import React from 'react'; -import Theme from './../themes/getStyle'; +import React from 'react' +import Theme from './../themes/getStyle' import { - CircleMinus, - CirclePlus, - SquareMinus, - SquarePlus, - ArrowRight, - ArrowDown -} from './icons'; + CircleMinus, + CirclePlus, + SquareMinus, + SquarePlus, + ArrowRight, + ArrowDown +} from './icons' -export function ExpandedIcon(props) { - const { theme, iconStyle } = props; - switch (iconStyle) { - case 'triangle': - return ( - - ); - case 'square': - return ( - - ); - default: - return ( - - ); - } +export function ExpandedIcon (props) { + const { theme, iconStyle } = props + switch (iconStyle) { + case 'triangle': + return ( + + ) + case 'square': + return ( + + ) + default: + return ( + + ) + } } -export function CollapsedIcon(props) { - const { theme, iconStyle } = props; - switch (iconStyle) { - case 'triangle': - return ( - - ); - case 'square': - return ( - - ); - default: - return ( - - ); - } +export function CollapsedIcon (props) { + const { theme, iconStyle } = props + switch (iconStyle) { + case 'triangle': + return ( + + ) + case 'square': + return ( + + ) + default: + return ( + + ) + } } diff --git a/src/js/components/ValidationFailure.js b/src/js/components/ValidationFailure.js index ea2981a..d4537ae 100644 --- a/src/js/components/ValidationFailure.js +++ b/src/js/components/ValidationFailure.js @@ -1,33 +1,33 @@ -import React from 'react'; -import dispatcher from './../helpers/dispatcher'; -import ObjectAttributes from './../stores/ObjectAttributes'; +import React from 'react' +import dispatcher from './../helpers/dispatcher' +import ObjectAttributes from './../stores/ObjectAttributes' -import { Add as Clear } from './icons'; +import { Add as Clear } from './icons' -//global theme -import Theme from './../themes/getStyle'; +// global theme +import Theme from './../themes/getStyle' -//this input appears when adding a new value to an object +// this input appears when adding a new value to an object export default class extends React.PureComponent { - render() { - const { message, active, theme, rjvId } = this.props; + render () { + const { message, active, theme, rjvId } = this.props - return active ? ( -
{ - dispatcher.dispatch({ - rjvId: rjvId, - name: 'RESET' - }); - }} - > - - {message} - - -
- ) : null; - } + return active + ? ( +
{ + dispatcher.dispatch({ + rjvId, + name: 'RESET' + }) + }} + > + {message} + +
+ ) + : null + } } diff --git a/src/js/components/VariableEditor.js b/src/js/components/VariableEditor.js index 1811977..56cbb84 100644 --- a/src/js/components/VariableEditor.js +++ b/src/js/components/VariableEditor.js @@ -1,476 +1,465 @@ -import React from 'react'; -import AutosizeTextarea from 'react-textarea-autosize'; +import React from 'react' +import AutosizeTextarea from 'react-textarea-autosize' -import { toType } from './../helpers/util'; -import dispatcher from './../helpers/dispatcher'; -import parseInput from './../helpers/parseInput'; -import stringifyVariable from './../helpers/stringifyVariable'; -import CopyToClipboard from './CopyToClipboard'; +import { toType } from './../helpers/util' +import dispatcher from './../helpers/dispatcher' +import parseInput from './../helpers/parseInput' +import stringifyVariable from './../helpers/stringifyVariable' +import CopyToClipboard from './CopyToClipboard' -//data type components +// data type components import { - JsonBoolean, - JsonDate, - JsonFloat, - JsonFunction, - JsonInteger, - JsonNan, - JsonNull, - JsonRegexp, - JsonString, - JsonUndefined -} from './DataTypes/DataTypes'; + JsonBoolean, + JsonDate, + JsonFloat, + JsonFunction, + JsonInteger, + JsonNan, + JsonNull, + JsonRegexp, + JsonString, + JsonUndefined +} from './DataTypes/DataTypes' -//clibboard icon -import { Edit, CheckCircle, RemoveCircle as Remove } from './icons'; +// clibboard icon +import { Edit, CheckCircle, RemoveCircle as Remove } from './icons' -//theme -import Theme from './../themes/getStyle'; +// theme +import Theme from './../themes/getStyle' class VariableEditor extends React.PureComponent { - constructor(props) { - super(props); - this.state = { - editMode: false, - editValue: '', - hovered: false, - renameKey: false, - parsedInput: { - type: false, - value: null - } - }; + constructor (props) { + super(props) + this.state = { + editMode: false, + editValue: '', + hovered: false, + renameKey: false, + parsedInput: { + type: false, + value: null + } } + } - render() { - const { - variable, - singleIndent, - type, - theme, - namespace, - indentWidth, - enableClipboard, - onEdit, - onDelete, - onSelect, - displayArrayKey, - quotesOnKeys, - keyModifier - } = this.props; - const { editMode } = this.state; - return ( -
- this.setState({ ...this.state, hovered: true }) - } - onMouseLeave={() => - this.setState({ ...this.state, hovered: false }) - } - class="variable-row" - key={variable.name} - > - {type == 'array' ? ( - displayArrayKey ? ( - - {variable.name} -
:
-
- ) : null - ) : ( - - - {!!quotesOnKeys && ( - " - )} - - {variable.name} - - {!!quotesOnKeys && ( - " - )} - - : - + render () { + const { + variable, + singleIndent, + type, + theme, + namespace, + indentWidth, + enableClipboard, + onEdit, + onDelete, + onSelect, + displayArrayKey, + quotesOnKeys, + keyModifier + } = this.props + const { editMode } = this.state + return ( +
this.setState({ ...this.state, hovered: true })} + onMouseLeave={() => this.setState({ ...this.state, hovered: false })} + class='variable-row' + key={variable.name} + > + {type == 'array' + ? ( + displayArrayKey + ? ( + + {variable.name} +
:
+
+ ) + : null + ) + : ( + + + {!!quotesOnKeys && ( + " )} -
{ - let location = [...namespace]; - if ( - keyModifier(e, 'edit') && - onEdit !== false - ) { - this.prepopInput(variable); - } else if (onSelect !== false) { - location.shift(); - onSelect({ - ...variable, - namespace: location - }); - } - } - } - {...Theme(theme, 'variableValue', { - cursor: onSelect === false ? 'default' : 'pointer' - })} - > - {this.getValue(variable, editMode)} -
- {enableClipboard ? ( -
- ); - } + {variable.name} + {!!quotesOnKeys && ( + " + )} + + : + + )} +
{ + const location = [...namespace] + if (keyModifier(e, 'edit') && onEdit !== false) { + this.prepopInput(variable) + } else if (onSelect !== false) { + location.shift() + onSelect({ + ...variable, + namespace: location + }) + } + } + } + {...Theme(theme, 'variableValue', { + cursor: onSelect === false ? 'default' : 'pointer' + })} + > + {this.getValue(variable, editMode)} +
+ {enableClipboard + ? ( +
+ ) + } - getEditIcon = () => { - const { variable, theme } = this.props; + getEditIcon = () => { + const { variable, theme } = this.props - return ( -
- { - this.prepopInput(variable); - }} - /> -
- ); - }; + return ( +
+ { + this.prepopInput(variable) + }} + /> +
+ ) + } - prepopInput = variable => { - if (this.props.onEdit !== false) { - const stringifiedValue = stringifyVariable(variable.value); - const detected = parseInput(stringifiedValue); - this.setState({ - editMode: true, - editValue: stringifiedValue, - parsedInput: { - type: detected.type, - value: detected.value - } - }); + prepopInput = variable => { + if (this.props.onEdit !== false) { + const stringifiedValue = stringifyVariable(variable.value) + const detected = parseInput(stringifiedValue) + this.setState({ + editMode: true, + editValue: stringifiedValue, + parsedInput: { + type: detected.type, + value: detected.value } - }; + }) + } + } - getRemoveIcon = () => { - const { variable, namespace, theme, rjvId } = this.props; + getRemoveIcon = () => { + const { variable, namespace, theme, rjvId } = this.props - return ( -
- { - dispatcher.dispatch({ - name: 'VARIABLE_REMOVED', - rjvId: rjvId, - data: { - name: variable.name, - namespace: namespace, - existing_value: variable.value, - variable_removed: true - } - }); - }} - /> -
- ); - }; + return ( +
+ { + dispatcher.dispatch({ + name: 'VARIABLE_REMOVED', + rjvId, + data: { + name: variable.name, + namespace, + existing_value: variable.value, + variable_removed: true + } + }) + }} + /> +
+ ) + } - getValue = (variable, editMode) => { - const type = editMode ? false : variable.type; - const { props } = this; - switch (type) { - case false: - return this.getEditInput(); - case 'string': - return ; - case 'integer': - return ; - case 'float': - return ; - case 'boolean': - return ; - case 'function': - return ; - case 'null': - return ; - case 'nan': - return ; - case 'undefined': - return ; - case 'date': - return ; - case 'regexp': - return ; - default: - // catch-all for types that weren't anticipated - return ( -
- {JSON.stringify(variable.value)} -
- ); - } - }; + getValue = (variable, editMode) => { + const type = editMode ? false : variable.type + const { props } = this + switch (type) { + case false: + return this.getEditInput() + case 'string': + return + case 'integer': + return + case 'float': + return + case 'boolean': + return + case 'function': + return + case 'null': + return + case 'nan': + return + case 'undefined': + return + case 'date': + return + case 'regexp': + return + default: + // catch-all for types that weren't anticipated + return
{JSON.stringify(variable.value)}
+ } + } - getEditInput = () => { - const { keyModifier, selectOnFocus, theme } = this.props; - const { editValue } = this.state; + getEditInput = () => { + const { keyModifier, selectOnFocus, theme } = this.props + const { editValue } = this.state - return ( -
- { - if (input) { - input[!selectOnFocus ? 'focus' : 'select'](); - } - }} - value={editValue} - class="variable-editor" - onChange={event => { - const value = event.target.value; - const detected = parseInput(value); - this.setState({ - editValue: value, - parsedInput: { - type: detected.type, - value: detected.value - } - }); - }} - onKeyDown={e => { - switch (e.key) { - case 'Escape': { - this.setState({ - editMode: false, - editValue: '' - }); - break; - } - case 'Enter': { - if (keyModifier(e, 'submit')) { - this.submitEdit(true); - } - break; - } - } - e.stopPropagation(); - }} - placeholder="update this value" - minRows={2} - {...Theme(theme, 'edit-input')} - /> -
- { - if (e) { - e.stopPropagation(); - } + return ( +
+ { + if (input) { + input[!selectOnFocus ? 'focus' : 'select']() + } + }} + value={editValue} + class='variable-editor' + onChange={event => { + const value = event.target.value + const detected = parseInput(value) + this.setState({ + editValue: value, + parsedInput: { + type: detected.type, + value: detected.value + } + }) + }} + onKeyDown={e => { + switch (e.key) { + case 'Escape': { + this.setState({ + editMode: false, + editValue: '' + }) + break + } + case 'Enter': { + if (keyModifier(e, 'submit')) { + this.submitEdit(true) + } + break + } + } + e.stopPropagation() + }} + placeholder='update this value' + minRows={2} + {...Theme(theme, 'edit-input')} + /> +
+ { + if (e) { + e.stopPropagation() + } - this.setState({ editMode: false, editValue: '' }); - }} - /> - { - if (e) { - e.stopPropagation(); - } + this.setState({ editMode: false, editValue: '' }) + }} + /> + { + if (e) { + e.stopPropagation() + } - this.submitEdit(); - }} - /> -
{this.showDetected()}
-
-
- ); - }; + this.submitEdit() + }} + /> +
{this.showDetected()}
+
+
+ ) + } - submitEdit = submit_detected => { - const { variable, namespace, rjvId } = this.props; - const { editValue, parsedInput } = this.state; - let new_value = editValue; - if (submit_detected && parsedInput.type) { - new_value = parsedInput.value; - } - this.setState({ - editMode: false - }); - dispatcher.dispatch({ - name: 'VARIABLE_UPDATED', - rjvId: rjvId, - data: { - name: variable.name, - namespace: namespace, - existing_value: variable.value, - new_value: new_value, - variable_removed: false - } - }); - }; + submitEdit = submit_detected => { + const { variable, namespace, rjvId } = this.props + const { editValue, parsedInput } = this.state + let new_value = editValue + if (submit_detected && parsedInput.type) { + new_value = parsedInput.value + } + this.setState({ + editMode: false + }) + dispatcher.dispatch({ + name: 'VARIABLE_UPDATED', + rjvId, + data: { + name: variable.name, + namespace, + existing_value: variable.value, + new_value, + variable_removed: false + } + }) + } - showDetected = () => { - const { theme, variable, namespace, rjvId } = this.props; - const { type, value } = this.state.parsedInput; - const detected = this.getDetectedInput(); - if (detected) { - return ( -
-
- {detected} - { - if (e) { - e.stopPropagation(); - } + showDetected = () => { + const { theme, variable, namespace, rjvId } = this.props + const { type, value } = this.state.parsedInput + const detected = this.getDetectedInput() + if (detected) { + return ( +
+
+ {detected} + { + if (e) { + e.stopPropagation() + } - this.submitEdit(true); - }} - /> -
-
- ); - } - }; + this.submitEdit(true) + }} + /> +
+
+ ) + } + } - getDetectedInput = () => { - const { parsedInput } = this.state; - const { type, value } = parsedInput; - const { props } = this; - const { theme } = props; + getDetectedInput = () => { + const { parsedInput } = this.state + const { type, value } = parsedInput + const { props } = this + const { theme } = props - if (type !== false) { - switch (type.toLowerCase()) { - case 'object': - return ( - - - {'{'} - - - ... - - - {'}'} - - - ); - case 'array': - return ( - - - {'['} - - - ... - - - {']'} - - - ); - case 'string': - return ; - case 'integer': - return ; - case 'float': - return ; - case 'boolean': - return ; - case 'function': - return ; - case 'null': - return ; - case 'nan': - return ; - case 'undefined': - return ; - case 'date': - return ; - } - } - }; + if (type !== false) { + switch (type.toLowerCase()) { + case 'object': + return ( + + + {'{'} + + + ... + + + {'}'} + + + ) + case 'array': + return ( + + + [ + + + ... + + + ] + + + ) + case 'string': + return + case 'integer': + return + case 'float': + return + case 'boolean': + return + case 'function': + return + case 'null': + return + case 'nan': + return + case 'undefined': + return + case 'date': + return + } + } + } } -//export component -export default VariableEditor; +// export component +export default VariableEditor diff --git a/src/js/components/VariableMeta.js b/src/js/components/VariableMeta.js index d6f6da7..17d5e85 100644 --- a/src/js/components/VariableMeta.js +++ b/src/js/components/VariableMeta.js @@ -1,143 +1,139 @@ -import React from 'react'; -import dispatcher from './../helpers/dispatcher'; +import React from 'react' +import dispatcher from './../helpers/dispatcher' -import CopyToClipboard from './CopyToClipboard'; -import { toType } from './../helpers/util'; +import CopyToClipboard from './CopyToClipboard' +import { toType } from './../helpers/util' -//icons -import { RemoveCircle as Remove, AddCircle as Add } from './icons'; +// icons +import { RemoveCircle as Remove, AddCircle as Add } from './icons' -//theme -import Theme from './../themes/getStyle'; +// theme +import Theme from './../themes/getStyle' export default class extends React.PureComponent { - getObjectSize = () => { - const { size, theme, displayObjectSize } = this.props; - if (displayObjectSize) { - return ( - - {size} item{size === 1 ? '' : 's'} - - ); - } - }; + getObjectSize = () => { + const { size, theme, displayObjectSize } = this.props + if (displayObjectSize) { + return ( + + {size} item{size === 1 ? '' : 's'} + + ) + } + } - getAddAttribute = rowHovered => { - const { theme, namespace, name, src, rjvId, depth } = this.props; + getAddAttribute = rowHovered => { + const { theme, namespace, name, src, rjvId, depth } = this.props - return ( - - { - const request = { - name: depth > 0 ? name : null, - namespace: namespace.splice( - 0, - namespace.length - 1 - ), - existing_value: src, - variable_removed: false, - key_name: null - }; - if (toType(src) === 'object') { - dispatcher.dispatch({ - name: 'ADD_VARIABLE_KEY_REQUEST', - rjvId: rjvId, - data: request - }); - } else { - dispatcher.dispatch({ - name: 'VARIABLE_ADDED', - rjvId: rjvId, - data: { - ...request, - new_value: [...src, null] - } - }); - } - }} - /> - - ); - }; + return ( + + { + const request = { + name: depth > 0 ? name : null, + namespace: namespace.splice(0, namespace.length - 1), + existing_value: src, + variable_removed: false, + key_name: null + } + if (toType(src) === 'object') { + dispatcher.dispatch({ + name: 'ADD_VARIABLE_KEY_REQUEST', + rjvId, + data: request + }) + } else { + dispatcher.dispatch({ + name: 'VARIABLE_ADDED', + rjvId, + data: { + ...request, + new_value: [...src, null] + } + }) + } + }} + /> + + ) + } - getRemoveObject = rowHovered => { - const { theme, hover, namespace, name, src, rjvId } = this.props; + getRemoveObject = rowHovered => { + const { theme, hover, namespace, name, src, rjvId } = this.props - //don't allow deleting of root node - if (namespace.length === 1) { - return; - } - return ( - - { - dispatcher.dispatch({ - name: 'VARIABLE_REMOVED', - rjvId: rjvId, - data: { - name: name, - namespace: namespace.splice( - 0, - namespace.length - 1 - ), - existing_value: src, - variable_removed: true - } - }); - }} - /> - - ); - }; + // don't allow deleting of root node + if (namespace.length === 1) { + return + } + return ( + + { + dispatcher.dispatch({ + name: 'VARIABLE_REMOVED', + rjvId, + data: { + name, + namespace: namespace.splice(0, namespace.length - 1), + existing_value: src, + variable_removed: true + } + }) + }} + /> + + ) + } - render = () => { - const { - theme, - onDelete, - onAdd, - enableClipboard, - src, - namespace, - rowHovered - } = this.props; - return ( - - ); - }; + render = () => { + const { + theme, + onDelete, + onAdd, + enableClipboard, + src, + namespace, + rowHovered + } = this.props + return ( + + ) + } } diff --git a/src/js/components/icons.js b/src/js/components/icons.js index 863eb9e..0f5e41f 100644 --- a/src/js/components/icons.js +++ b/src/js/components/icons.js @@ -1,282 +1,282 @@ -import React from 'react'; +import React from 'react' -const DEFAULT_WIDTH = 24; -const DEFAULT_HEIGHT = 24; -const DEFAULT_COLOR = '#000000'; +const DEFAULT_WIDTH = 24 +const DEFAULT_HEIGHT = 24 +const DEFAULT_COLOR = '#000000' export class CircleMinus extends React.PureComponent { - render() { - const { props } = this; - const { style, ...rest } = props; + render () { + const { props } = this + const { style, ...rest } = props - return ( - - - - - - ); - } + return ( + + + + + + ) + } } export class CirclePlus extends React.PureComponent { - render() { - const { props } = this; - const { style, ...rest } = props; + render () { + const { props } = this + const { style, ...rest } = props - return ( - - - - - - ); - } + return ( + + + + + + ) + } } export class SquareMinus extends React.PureComponent { - render() { - const { props } = this; - const { style, ...rest } = props; - const svgStyle = getIconStyle(style).style; + render () { + const { props } = this + const { style, ...rest } = props + const svgStyle = getIconStyle(style).style - return ( - - - - - - ); - } + return ( + + + + + + ) + } } export class SquarePlus extends React.PureComponent { - render() { - const { props } = this; - const { style, ...rest } = props; - const svgStyle = getIconStyle(style).style; + render () { + const { props } = this + const { style, ...rest } = props + const svgStyle = getIconStyle(style).style - return ( - - - - - - ); - } + return ( + + + + + + ) + } } export class ArrowRight extends React.PureComponent { - render() { - const { props } = this; - const { style, ...rest } = props; + render () { + const { props } = this + const { style, ...rest } = props - return ( - - - - - - ); - } + return ( + + + + + + ) + } } export class ArrowDown extends React.PureComponent { - render() { - const { props } = this; - const { style, ...rest } = props; + render () { + const { props } = this + const { style, ...rest } = props - return ( - - - - - - ); - } + return ( + + + + + + ) + } } export class Clippy extends React.PureComponent { - render() { - const { props } = this; - const { style, ...rest } = props; + render () { + const { props } = this + const { style, ...rest } = props - return ( - - - - - - - - ); - } + return ( + + + + + + + + ) + } } export class RemoveCircle extends React.PureComponent { - render() { - const { props } = this; - const { style, ...rest } = props; + render () { + const { props } = this + const { style, ...rest } = props - return ( - - - - - - - - ); - } + return ( + + + + + + + + ) + } } export class AddCircle extends React.PureComponent { - render() { - const { props } = this; - const { style, ...rest } = props; + render () { + const { props } = this + const { style, ...rest } = props - return ( - - - - - - - - ); - } + return ( + + + + + + + + ) + } } export class Add extends React.PureComponent { - render() { - const { props } = this; - const { style, ...rest } = props; + render () { + const { props } = this + const { style, ...rest } = props - return ( - - - - - - - - ); - } + return ( + + + + + + + + ) + } } export class Edit extends React.PureComponent { - render() { - const { props } = this; - const { style, ...rest } = props; + render () { + const { props } = this + const { style, ...rest } = props - return ( - - - - - - - - ); - } + return ( + + + + + + + + ) + } } export class CheckCircle extends React.PureComponent { - render() { - const { props } = this; - const { style, ...rest } = props; + render () { + const { props } = this + const { style, ...rest } = props - return ( - - - - - - - - ); - } + return ( + + + + + + + + ) + } } -function getIconStyle(style) { - if (!style) { - style = {}; +function getIconStyle (style) { + if (!style) { + style = {} + } + return { + style: { + verticalAlign: 'middle', + ...style, + color: style.color ? style.color : DEFAULT_COLOR, + height: '1em', + width: '1em' } - return { - style: { - verticalAlign: 'middle', - ...style, - color: style.color ? style.color : DEFAULT_COLOR, - height: '1em', - width: '1em' - } - }; + } } diff --git a/src/js/helpers/dispatcher.js b/src/js/helpers/dispatcher.js index 586532f..7e47273 100644 --- a/src/js/helpers/dispatcher.js +++ b/src/js/helpers/dispatcher.js @@ -1,3 +1,3 @@ -import { Dispatcher } from 'flux'; -const dispatcher = new Dispatcher(); -export default dispatcher; +import { Dispatcher } from 'flux' +const dispatcher = new Dispatcher() +export default dispatcher diff --git a/src/js/helpers/parseInput.js b/src/js/helpers/parseInput.js index 8eeb36c..da0c451 100644 --- a/src/js/helpers/parseInput.js +++ b/src/js/helpers/parseInput.js @@ -1,79 +1,76 @@ -export default function parseInput(input) { - //following code is to make a best guess at - //the type for a variable being submitted. +export default function parseInput (input) { + // following code is to make a best guess at + // the type for a variable being submitted. - //we are working with a serialized data representation - input = input.trim(); - try { - input = JSON.stringify(JSON.parse(input)); - if (input[0] === '[') { - //array - return formatResponse('array', JSON.parse(input)); - } else if (input[0] === '{') { - //object - return formatResponse('object', JSON.parse(input)); - } else if ( - input.match(/\-?\d+\.\d+/) && - input.match(/\-?\d+\.\d+/)[0] === input - ) { - //float - return formatResponse('float', parseFloat(input)); - } else if ( - input.match(/\-?\d+e-\d+/) && - input.match(/\-?\d+e-\d+/)[0] === input - ) { - //scientific float - return formatResponse('float', Number(input)); - } else if ( - input.match(/\-?\d+/) && - input.match(/\-?\d+/)[0] === input - ) { - //integer - return formatResponse('integer', parseInt(input)); - } else if ( - input.match(/\-?\d+e\+\d+/) && - input.match(/\-?\d+e\+\d+/)[0] === input - ) { - //scientific integer - return formatResponse('integer', Number(input)); - } - } catch (e) { - // no-op + // we are working with a serialized data representation + input = input.trim() + try { + input = JSON.stringify(JSON.parse(input)) + if (input[0] === '[') { + // array + return formatResponse('array', JSON.parse(input)) + } else if (input[0] === '{') { + // object + return formatResponse('object', JSON.parse(input)) + } else if ( + input.match(/\-?\d+\.\d+/) && + input.match(/\-?\d+\.\d+/)[0] === input + ) { + // float + return formatResponse('float', parseFloat(input)) + } else if ( + input.match(/\-?\d+e-\d+/) && + input.match(/\-?\d+e-\d+/)[0] === input + ) { + // scientific float + return formatResponse('float', Number(input)) + } else if (input.match(/\-?\d+/) && input.match(/\-?\d+/)[0] === input) { + // integer + return formatResponse('integer', parseInt(input)) + } else if ( + input.match(/\-?\d+e\+\d+/) && + input.match(/\-?\d+e\+\d+/)[0] === input + ) { + // scientific integer + return formatResponse('integer', Number(input)) } + } catch (e) { + // no-op + } - //run in case input was not serializable - input = input.toLowerCase(); - switch (input) { - case 'undefined': { - return formatResponse('undefined', undefined); - } - case 'nan': { - return formatResponse('nan', NaN); - } - case 'null': { - return formatResponse('null', null); - } - case 'true': { - return formatResponse('boolean', true); - } - case 'false': { - return formatResponse('boolean', false); - } - default: { - //check to see if this is a date - input = Date.parse(input); - if (input) { - return formatResponse('date', new Date(input)); - } - } + // run in case input was not serializable + input = input.toLowerCase() + switch (input) { + case 'undefined': { + return formatResponse('undefined', undefined) } + case 'nan': { + return formatResponse('nan', NaN) + } + case 'null': { + return formatResponse('null', null) + } + case 'true': { + return formatResponse('boolean', true) + } + case 'false': { + return formatResponse('boolean', false) + } + default: { + // check to see if this is a date + input = Date.parse(input) + if (input) { + return formatResponse('date', new Date(input)) + } + } + } - return formatResponse(false, null); + return formatResponse(false, null) } -function formatResponse(type, value) { - return { - type: type, - value: value - }; +function formatResponse (type, value) { + return { + type, + value + } } diff --git a/src/js/helpers/stringifyVariable.js b/src/js/helpers/stringifyVariable.js index adfa035..4d912b2 100644 --- a/src/js/helpers/stringifyVariable.js +++ b/src/js/helpers/stringifyVariable.js @@ -1,36 +1,36 @@ -import { toType } from './util'; +import { toType } from './util' export default value => { - const type = toType(value); - let string_value; - switch (type) { - case 'undefined': { - string_value = 'undefined'; - break; - } - case 'nan': - string_value = 'NaN'; - break; - case 'string': - string_value = value; - break; - case 'date': - string_value = value.toString(); - break; - case 'function': - string_value = value.toString(); - break; - case 'regexp': - string_value = value.toString(); - break; - default: { - try { - string_value = JSON.stringify(value, null, ' '); - } catch (e) { - string_value = ''; - } - } + const type = toType(value) + let string_value + switch (type) { + case 'undefined': { + string_value = 'undefined' + break } + case 'nan': + string_value = 'NaN' + break + case 'string': + string_value = value + break + case 'date': + string_value = value.toString() + break + case 'function': + string_value = value.toString() + break + case 'regexp': + string_value = value.toString() + break + default: { + try { + string_value = JSON.stringify(value, null, ' ') + } catch (e) { + string_value = '' + } + } + } - return string_value; -}; + return string_value +} diff --git a/src/js/helpers/util.js b/src/js/helpers/util.js index 50ab518..a11ea83 100644 --- a/src/js/helpers/util.js +++ b/src/js/helpers/util.js @@ -1,55 +1,55 @@ -//returns a string "type" of input object -export function toType(obj) { - let type = getType(obj); - // some extra disambiguation for numbers - if (type === 'number') { - if (isNaN(obj)) { - type = 'nan'; - } else if ((obj | 0) != obj) { - //bitwise OR produces integers - type = 'float'; - } else { - type = 'integer'; - } +// returns a string "type" of input object +export function toType (obj) { + let type = getType(obj) + // some extra disambiguation for numbers + if (type === 'number') { + if (isNaN(obj)) { + type = 'nan' + } else if ((obj | 0) != obj) { + // bitwise OR produces integers + type = 'float' + } else { + type = 'integer' } - return type; + } + return type } -//source: http://stackoverflow.com/questions/7390426/better-way-to-get-type-of-a-javascript-variable/7390612#7390612 -function getType(obj) { - return {}.toString - .call(obj) - .match(/\s([a-zA-Z]+)/)[1] - .toLowerCase(); +// source: http://stackoverflow.com/questions/7390426/better-way-to-get-type-of-a-javascript-variable/7390612#7390612 +function getType (obj) { + return {}.toString + .call(obj) + .match(/\s([a-zA-Z]+)/)[1] + .toLowerCase() } -//validation for base-16 themes -export function isTheme(theme) { - const theme_keys = [ - 'base00', - 'base01', - 'base02', - 'base03', - 'base04', - 'base05', - 'base06', - 'base07', - 'base08', - 'base09', - 'base0A', - 'base0B', - 'base0C', - 'base0D', - 'base0E', - 'base0F' - ]; - if (toType(theme) === 'object') { - for (var i = 0; i < theme_keys.length; i++) { - if (!(theme_keys[i] in theme)) { - return false; - } - } - return true; +// validation for base-16 themes +export function isTheme (theme) { + const theme_keys = [ + 'base00', + 'base01', + 'base02', + 'base03', + 'base04', + 'base05', + 'base06', + 'base07', + 'base08', + 'base09', + 'base0A', + 'base0B', + 'base0C', + 'base0D', + 'base0E', + 'base0F' + ] + if (toType(theme) === 'object') { + for (let i = 0; i < theme_keys.length; i++) { + if (!(theme_keys[i] in theme)) { + return false + } } - return false; + return true + } + return false } diff --git a/src/js/index.js b/src/js/index.js index 410d0f6..1a9733b 100644 --- a/src/js/index.js +++ b/src/js/index.js @@ -1,269 +1,270 @@ -import React from 'react'; -import { polyfill } from 'react-lifecycles-compat'; -import JsonViewer from './components/JsonViewer'; -import AddKeyRequest from './components/ObjectKeyModal/AddKeyRequest'; -import ValidationFailure from './components/ValidationFailure'; -import { toType, isTheme } from './helpers/util'; -import ObjectAttributes from './stores/ObjectAttributes'; +import React from 'react' +import { polyfill } from 'react-lifecycles-compat' +import JsonViewer from './components/JsonViewer' +import AddKeyRequest from './components/ObjectKeyModal/AddKeyRequest' +import ValidationFailure from './components/ValidationFailure' +import { toType, isTheme } from './helpers/util' +import ObjectAttributes from './stores/ObjectAttributes' -//global theme -import Theme from './themes/getStyle'; +// global theme +import Theme from './themes/getStyle' -//forward src through to JsonObject component +// forward src through to JsonObject component class ReactJsonView extends React.PureComponent { - constructor(props) { - super(props); - this.state = { - //listen to request to add/edit a key to an object - addKeyRequest: false, - editKeyRequest: false, - validationFailure: false, - src: ReactJsonView.defaultProps.src, - name: ReactJsonView.defaultProps.name, - theme: ReactJsonView.defaultProps.theme, - validationMessage: ReactJsonView.defaultProps.validationMessage, - // the state object also needs to remember the prev prop values, because we need to compare - // old and new props in getDerivedStateFromProps(). - prevSrc: ReactJsonView.defaultProps.src, - prevName: ReactJsonView.defaultProps.name, - prevTheme: ReactJsonView.defaultProps.theme - }; + constructor (props) { + super(props) + this.state = { + // listen to request to add/edit a key to an object + addKeyRequest: false, + editKeyRequest: false, + validationFailure: false, + src: ReactJsonView.defaultProps.src, + name: ReactJsonView.defaultProps.name, + theme: ReactJsonView.defaultProps.theme, + validationMessage: ReactJsonView.defaultProps.validationMessage, + // the state object also needs to remember the prev prop values, because we need to compare + // old and new props in getDerivedStateFromProps(). + prevSrc: ReactJsonView.defaultProps.src, + prevName: ReactJsonView.defaultProps.name, + prevTheme: ReactJsonView.defaultProps.theme } + } - //reference id for this instance - rjvId = Date.now().toString(); + // reference id for this instance + rjvId = Date.now().toString() - //all acceptable props and default values - static defaultProps = { - src: {}, - name: 'root', - theme: 'rjv-default', - collapsed: false, - collapseStringsAfterLength: false, - shouldCollapse: false, - sortKeys: false, - quotesOnKeys: true, - groupArraysAfterLength: 100, - indentWidth: 4, - enableClipboard: true, - displayObjectSize: true, - displayDataTypes: true, - onEdit: false, - onDelete: false, - onAdd: false, - onSelect: false, - iconStyle: 'triangle', - style: {}, - validationMessage: 'Validation Error', - defaultValue: null, - displayArrayKey: true, - selectOnFocus: false, - keyModifier: e => e.metaKey || e.ctrlKey - }; + // all acceptable props and default values + static defaultProps = { + src: {}, + name: 'root', + theme: 'rjv-default', + collapsed: false, + collapseStringsAfterLength: false, + shouldCollapse: false, + sortKeys: false, + quotesOnKeys: true, + groupArraysAfterLength: 100, + indentWidth: 4, + enableClipboard: true, + displayObjectSize: true, + displayDataTypes: true, + onEdit: false, + onDelete: false, + onAdd: false, + onSelect: false, + iconStyle: 'triangle', + style: {}, + validationMessage: 'Validation Error', + defaultValue: null, + displayArrayKey: true, + selectOnFocus: false, + keyModifier: e => e.metaKey || e.ctrlKey + } - // will trigger whenever setState() is called, or parent passes in new props. - static getDerivedStateFromProps(nextProps, prevState) { - if ( - nextProps.src !== prevState.prevSrc || - nextProps.name !== prevState.prevName || - nextProps.theme !== prevState.prevTheme - ) { - // if we pass in new props, we re-validate - const newPartialState = { - src: nextProps.src, - name: nextProps.name, - theme: nextProps.theme, - validationMessage: nextProps.validationMessage, - prevSrc: nextProps.src, - prevName: nextProps.name, - prevTheme: nextProps.theme - }; - return ReactJsonView.validateState(newPartialState); - } - return null; + // will trigger whenever setState() is called, or parent passes in new props. + static getDerivedStateFromProps (nextProps, prevState) { + if ( + nextProps.src !== prevState.prevSrc || + nextProps.name !== prevState.prevName || + nextProps.theme !== prevState.prevTheme + ) { + // if we pass in new props, we re-validate + const newPartialState = { + src: nextProps.src, + name: nextProps.name, + theme: nextProps.theme, + validationMessage: nextProps.validationMessage, + prevSrc: nextProps.src, + prevName: nextProps.name, + prevTheme: nextProps.theme + } + return ReactJsonView.validateState(newPartialState) } + return null + } - componentDidMount() { - // initialize - ObjectAttributes.set(this.rjvId, 'global', 'src', this.state.src); - // bind to events - const listeners = this.getListeners(); - for (const i in listeners) { - ObjectAttributes.on(i + '-' + this.rjvId, listeners[i]); - } - //reset key request to false once it's observed - this.setState({ - addKeyRequest: false, - editKeyRequest: false - }); + componentDidMount () { + // initialize + ObjectAttributes.set(this.rjvId, 'global', 'src', this.state.src) + // bind to events + const listeners = this.getListeners() + for (const i in listeners) { + ObjectAttributes.on(i + '-' + this.rjvId, listeners[i]) } + // reset key request to false once it's observed + this.setState({ + addKeyRequest: false, + editKeyRequest: false + }) + } - componentDidUpdate(prevProps, prevState) { - //reset key request to false once it's observed - if (prevState.addKeyRequest !== false) { - this.setState({ - addKeyRequest: false - }); - } - if (prevState.editKeyRequest !== false) { - this.setState({ - editKeyRequest: false - }); - } - if (prevProps.src !== this.state.src) { - ObjectAttributes.set(this.rjvId, 'global', 'src', this.state.src); - } + componentDidUpdate (prevProps, prevState) { + // reset key request to false once it's observed + if (prevState.addKeyRequest !== false) { + this.setState({ + addKeyRequest: false + }) } + if (prevState.editKeyRequest !== false) { + this.setState({ + editKeyRequest: false + }) + } + if (prevProps.src !== this.state.src) { + ObjectAttributes.set(this.rjvId, 'global', 'src', this.state.src) + } + } - componentWillUnmount() { - const listeners = this.getListeners(); - for (const i in listeners) { - ObjectAttributes.removeListener(i + '-' + this.rjvId, listeners[i]); - } + componentWillUnmount () { + const listeners = this.getListeners() + for (const i in listeners) { + ObjectAttributes.removeListener(i + '-' + this.rjvId, listeners[i]) } + } - getListeners = () => { - return { - reset: this.resetState, - 'variable-update': this.updateSrc, - 'add-key-request': this.addKeyRequest - }; - }; - //make sure props are passed in as expected - static validateState = state => { - const validatedState = {}; - //make sure theme is valid - if (toType(state.theme) === 'object' && !isTheme(state.theme)) { - console.error( - 'react-json-view error:', - 'theme prop must be a theme name or valid base-16 theme object.', - 'defaulting to "rjv-default" theme' - ); - validatedState.theme = 'rjv-default'; - } - //make sure `src` prop is valid - if (toType(state.src) !== 'object' && toType(state.src) !== 'array') { - console.error( - 'react-json-view error:', - 'src property must be a valid json object' - ); - validatedState.name = 'ERROR'; - validatedState.src = { - message: 'src property must be a valid json object' - }; - } - return { - // get the original state - ...state, - // override the original state - ...validatedState - }; - }; + getListeners = () => { + return { + reset: this.resetState, + 'variable-update': this.updateSrc, + 'add-key-request': this.addKeyRequest + } + } - render() { - const { - validationFailure, - validationMessage, - addKeyRequest, - theme, - src, - name - } = this.state; + // make sure props are passed in as expected + static validateState = state => { + const validatedState = {} + // make sure theme is valid + if (toType(state.theme) === 'object' && !isTheme(state.theme)) { + console.error( + 'react-json-view error:', + 'theme prop must be a theme name or valid base-16 theme object.', + 'defaulting to "rjv-default" theme' + ) + validatedState.theme = 'rjv-default' + } + // make sure `src` prop is valid + if (toType(state.src) !== 'object' && toType(state.src) !== 'array') { + console.error( + 'react-json-view error:', + 'src property must be a valid json object' + ) + validatedState.name = 'ERROR' + validatedState.src = { + message: 'src property must be a valid json object' + } + } + return { + // get the original state + ...state, + // override the original state + ...validatedState + } + } - const { style, defaultValue } = this.props; + render () { + const { + validationFailure, + validationMessage, + addKeyRequest, + theme, + src, + name + } = this.state - return ( -
- - - -
- ); - } + const { style, defaultValue } = this.props - updateSrc = () => { - const { - name, - namespace, - new_value, - existing_value, - variable_removed, - updated_src, - type - } = ObjectAttributes.get(this.rjvId, 'action', 'variable-update'); - const { onEdit, onDelete, onAdd } = this.props; + return ( +
+ + + +
+ ) + } - const { src } = this.state; + updateSrc = () => { + const { + name, + namespace, + new_value, + existing_value, + variable_removed, + updated_src, + type + } = ObjectAttributes.get(this.rjvId, 'action', 'variable-update') + const { onEdit, onDelete, onAdd } = this.props - let result; + const { src } = this.state - const on_edit_payload = { - existing_src: src, - new_value: new_value, - updated_src: updated_src, - name: name, - namespace: namespace, - existing_value: existing_value - }; + let result - switch (type) { - case 'variable-added': - result = onAdd(on_edit_payload); - break; - case 'variable-edited': - result = onEdit(on_edit_payload); - break; - case 'variable-removed': - result = onDelete(on_edit_payload); - break; - } + const on_edit_payload = { + existing_src: src, + new_value, + updated_src, + name, + namespace, + existing_value + } - if (result !== false) { - ObjectAttributes.set(this.rjvId, 'global', 'src', updated_src); - this.setState({ - src: updated_src - }); - } else { - this.setState({ - validationFailure: true - }); - } - }; + switch (type) { + case 'variable-added': + result = onAdd(on_edit_payload) + break + case 'variable-edited': + result = onEdit(on_edit_payload) + break + case 'variable-removed': + result = onDelete(on_edit_payload) + break + } + + if (result !== false) { + ObjectAttributes.set(this.rjvId, 'global', 'src', updated_src) + this.setState({ + src: updated_src + }) + } else { + this.setState({ + validationFailure: true + }) + } + } - addKeyRequest = () => { - this.setState({ - addKeyRequest: true - }); - }; + addKeyRequest = () => { + this.setState({ + addKeyRequest: true + }) + } - resetState = () => { - this.setState({ - validationFailure: false, - addKeyRequest: false - }); - }; + resetState = () => { + this.setState({ + validationFailure: false, + addKeyRequest: false + }) + } } -polyfill(ReactJsonView); +polyfill(ReactJsonView) -export default ReactJsonView; +export default ReactJsonView diff --git a/src/js/stores/ObjectAttributes.js b/src/js/stores/ObjectAttributes.js index a3f1aaf..303d38b 100644 --- a/src/js/stores/ObjectAttributes.js +++ b/src/js/stores/ObjectAttributes.js @@ -1,127 +1,122 @@ -import { EventEmitter } from 'events'; -import dispatcher from './../helpers/dispatcher'; -import { toType } from './../helpers/util'; +import { EventEmitter } from 'events' +import dispatcher from './../helpers/dispatcher' +import { toType } from './../helpers/util' -//store persistent display attributes for objects and arrays +// store persistent display attributes for objects and arrays class ObjectAttributes extends EventEmitter { - objects = {}; + objects = {} - set = (rjvId, name, key, value) => { - if (this.objects[rjvId] === undefined) { - this.objects[rjvId] = {}; - } - if (this.objects[rjvId][name] === undefined) { - this.objects[rjvId][name] = {}; - } - this.objects[rjvId][name][key] = value; - }; + set = (rjvId, name, key, value) => { + if (this.objects[rjvId] === undefined) { + this.objects[rjvId] = {} + } + if (this.objects[rjvId][name] === undefined) { + this.objects[rjvId][name] = {} + } + this.objects[rjvId][name][key] = value + } - get = (rjvId, name, key, default_value) => { - if ( - this.objects[rjvId] === undefined || - this.objects[rjvId][name] === undefined || - this.objects[rjvId][name][key] == undefined - ) { - return default_value; - } - return this.objects[rjvId][name][key]; - }; + get = (rjvId, name, key, default_value) => { + if ( + this.objects[rjvId] === undefined || + this.objects[rjvId][name] === undefined || + this.objects[rjvId][name][key] == undefined + ) { + return default_value + } + return this.objects[rjvId][name][key] + } - handleAction = action => { - const { rjvId, data, name } = action; - switch (name) { - case 'RESET': - this.emit('reset-' + rjvId); - break; - case 'VARIABLE_UPDATED': - action.data.updated_src = this.updateSrc(rjvId, data); - this.set(rjvId, 'action', 'variable-update', { - ...data, - type: 'variable-edited' - }); - this.emit('variable-update-' + rjvId); - break; - case 'VARIABLE_REMOVED': - action.data.updated_src = this.updateSrc(rjvId, data); - this.set(rjvId, 'action', 'variable-update', { - ...data, - type: 'variable-removed' - }); - this.emit('variable-update-' + rjvId); - break; - case 'VARIABLE_ADDED': - action.data.updated_src = this.updateSrc(rjvId, data); - this.set(rjvId, 'action', 'variable-update', { - ...data, - type: 'variable-added' - }); - this.emit('variable-update-' + rjvId); - break; - case 'ADD_VARIABLE_KEY_REQUEST': - this.set(rjvId, 'action', 'new-key-request', data); - this.emit('add-key-request-' + rjvId); - break; - } - }; + handleAction = action => { + const { rjvId, data, name } = action + switch (name) { + case 'RESET': + this.emit('reset-' + rjvId) + break + case 'VARIABLE_UPDATED': + action.data.updated_src = this.updateSrc(rjvId, data) + this.set(rjvId, 'action', 'variable-update', { + ...data, + type: 'variable-edited' + }) + this.emit('variable-update-' + rjvId) + break + case 'VARIABLE_REMOVED': + action.data.updated_src = this.updateSrc(rjvId, data) + this.set(rjvId, 'action', 'variable-update', { + ...data, + type: 'variable-removed' + }) + this.emit('variable-update-' + rjvId) + break + case 'VARIABLE_ADDED': + action.data.updated_src = this.updateSrc(rjvId, data) + this.set(rjvId, 'action', 'variable-update', { + ...data, + type: 'variable-added' + }) + this.emit('variable-update-' + rjvId) + break + case 'ADD_VARIABLE_KEY_REQUEST': + this.set(rjvId, 'action', 'new-key-request', data) + this.emit('add-key-request-' + rjvId) + break + } + } - updateSrc = (rjvId, request) => { - let { - name, - namespace, - new_value, - existing_value, - variable_removed - } = request; + updateSrc = (rjvId, request) => { + const { name, namespace, new_value, existing_value, variable_removed } = + request - namespace.shift(); + namespace.shift() - //deepy copy src - let src = this.get(rjvId, 'global', 'src'); - //deep copy of src variable - let updated_src = this.deepCopy(src, [...namespace]); + // deepy copy src + const src = this.get(rjvId, 'global', 'src') + // deep copy of src variable + let updated_src = this.deepCopy(src, [...namespace]) - //point at current index - let walk = updated_src; - for (const idx of namespace) { - walk = walk[idx]; - } + // point at current index + let walk = updated_src + for (const idx of namespace) { + walk = walk[idx] + } - if (variable_removed) { - if (toType(walk) == 'array') { - walk.splice(name, 1); - } else { - delete walk[name]; - } - } else { - //update copied variable at specified namespace - if (name !== null) { - walk[name] = new_value; - } else { - updated_src = new_value; - } - } + if (variable_removed) { + if (toType(walk) == 'array') { + walk.splice(name, 1) + } else { + delete walk[name] + } + } else { + // update copied variable at specified namespace + if (name !== null) { + walk[name] = new_value + } else { + updated_src = new_value + } + } - this.set(rjvId, 'global', 'src', updated_src); + this.set(rjvId, 'global', 'src', updated_src) - return updated_src; - }; + return updated_src + } - deepCopy = (src, copy_namespace) => { - const type = toType(src); - let result; - let idx = copy_namespace.shift(); - if (type == 'array') { - result = [...src]; - } else if (type == 'object') { - result = { ...src }; - } - if (idx !== undefined) { - result[idx] = this.deepCopy(src[idx], copy_namespace); - } - return result; - }; + deepCopy = (src, copy_namespace) => { + const type = toType(src) + let result + const idx = copy_namespace.shift() + if (type == 'array') { + result = [...src] + } else if (type == 'object') { + result = { ...src } + } + if (idx !== undefined) { + result[idx] = this.deepCopy(src[idx], copy_namespace) + } + return result + } } -const attributeStore = new ObjectAttributes(); -dispatcher.register(attributeStore.handleAction.bind(attributeStore)); -export default attributeStore; +const attributeStore = new ObjectAttributes() +dispatcher.register(attributeStore.handleAction.bind(attributeStore)) +export default attributeStore diff --git a/src/js/themes/base16/rjv-themes.js b/src/js/themes/base16/rjv-themes.js index 96a2139..8dac891 100644 --- a/src/js/themes/base16/rjv-themes.js +++ b/src/js/themes/base16/rjv-themes.js @@ -1,42 +1,42 @@ export const rjv_default = { - scheme: 'rjv-default', - author: 'mac gainor', - //transparent main background - base00: 'rgba(0, 0, 0, 0)', - base01: 'rgb(245, 245, 245)', - base02: 'rgb(235, 235, 235)', - base03: '#93a1a1', - base04: 'rgba(0, 0, 0, 0.3)', - base05: '#586e75', - base06: '#073642', - base07: '#002b36', - base08: '#d33682', - base09: '#cb4b16', - base0A: '#dc322f', - base0B: '#859900', - base0C: '#6c71c4', - base0D: '#586e75', - base0E: '#2aa198', - base0F: '#268bd2' -}; + scheme: 'rjv-default', + author: 'mac gainor', + // transparent main background + base00: 'rgba(0, 0, 0, 0)', + base01: 'rgb(245, 245, 245)', + base02: 'rgb(235, 235, 235)', + base03: '#93a1a1', + base04: 'rgba(0, 0, 0, 0.3)', + base05: '#586e75', + base06: '#073642', + base07: '#002b36', + base08: '#d33682', + base09: '#cb4b16', + base0A: '#dc322f', + base0B: '#859900', + base0C: '#6c71c4', + base0D: '#586e75', + base0E: '#2aa198', + base0F: '#268bd2' +} export const rjv_grey = { - scheme: 'rjv-grey', - author: 'mac gainor', - base00: 'rgba(1, 1, 1, 0)', - base01: 'rgba(1, 1, 1, 0.1)', - base02: 'rgba(0, 0, 0, 0.2)', - base03: 'rgba(1, 1, 1, 0.3)', - base04: 'rgba(0, 0, 0, 0.4)', - base05: 'rgba(1, 1, 1, 0.5)', - base06: 'rgba(1, 1, 1, 0.6)', - base07: 'rgba(1, 1, 1, 0.7)', - base08: 'rgba(1, 1, 1, 0.8)', - base09: 'rgba(1, 1, 1, 0.8)', - base0A: 'rgba(1, 1, 1, 0.8)', - base0B: 'rgba(1, 1, 1, 0.8)', - base0C: 'rgba(1, 1, 1, 0.8)', - base0D: 'rgba(1, 1, 1, 0.8)', - base0E: 'rgba(1, 1, 1, 0.8)', - base0F: 'rgba(1, 1, 1, 0.8)' -}; + scheme: 'rjv-grey', + author: 'mac gainor', + base00: 'rgba(1, 1, 1, 0)', + base01: 'rgba(1, 1, 1, 0.1)', + base02: 'rgba(0, 0, 0, 0.2)', + base03: 'rgba(1, 1, 1, 0.3)', + base04: 'rgba(0, 0, 0, 0.4)', + base05: 'rgba(1, 1, 1, 0.5)', + base06: 'rgba(1, 1, 1, 0.6)', + base07: 'rgba(1, 1, 1, 0.7)', + base08: 'rgba(1, 1, 1, 0.8)', + base09: 'rgba(1, 1, 1, 0.8)', + base0A: 'rgba(1, 1, 1, 0.8)', + base0B: 'rgba(1, 1, 1, 0.8)', + base0C: 'rgba(1, 1, 1, 0.8)', + base0D: 'rgba(1, 1, 1, 0.8)', + base0E: 'rgba(1, 1, 1, 0.8)', + base0F: 'rgba(1, 1, 1, 0.8)' +} diff --git a/src/js/themes/getStyle.js b/src/js/themes/getStyle.js index 2ee98f7..b05affd 100644 --- a/src/js/themes/getStyle.js +++ b/src/js/themes/getStyle.js @@ -1,409 +1,405 @@ -import { rjv_default, rjv_grey } from './base16/rjv-themes'; -import constants from './styleConstants'; -import { createStyling } from 'react-base16-styling'; +import { rjv_default, rjv_grey } from './base16/rjv-themes' +import constants from './styleConstants' +import { createStyling } from 'react-base16-styling' const colorMap = theme => ({ - backgroundColor: theme.base00, - ellipsisColor: theme.base09, - braceColor: theme.base07, - expandedIcon: theme.base0D, - collapsedIcon: theme.base0E, - keyColor: theme.base07, - arrayKeyColor: theme.base0C, - objectSize: theme.base04, - copyToClipboard: theme.base0F, - copyToClipboardCheck: theme.base0D, - objectBorder: theme.base02, - dataTypes: { - boolean: theme.base0E, - date: theme.base0D, - float: theme.base0B, - function: theme.base0D, - integer: theme.base0F, - string: theme.base09, - nan: theme.base08, - null: theme.base0A, - undefined: theme.base05, - regexp: theme.base0A, - background: theme.base02 - }, - editVariable: { - editIcon: theme.base0E, - cancelIcon: theme.base09, - removeIcon: theme.base09, - addIcon: theme.base0E, - checkIcon: theme.base0E, - background: theme.base01, - color: theme.base0A, - border: theme.base07 - }, - addKeyModal: { - background: theme.base05, - border: theme.base04, - color: theme.base0A, - labelColor: theme.base01 - }, - validationFailure: { - background: theme.base09, - iconColor: theme.base01, - fontColor: theme.base01 - } -}); + backgroundColor: theme.base00, + ellipsisColor: theme.base09, + braceColor: theme.base07, + expandedIcon: theme.base0D, + collapsedIcon: theme.base0E, + keyColor: theme.base07, + arrayKeyColor: theme.base0C, + objectSize: theme.base04, + copyToClipboard: theme.base0F, + copyToClipboardCheck: theme.base0D, + objectBorder: theme.base02, + dataTypes: { + boolean: theme.base0E, + date: theme.base0D, + float: theme.base0B, + function: theme.base0D, + integer: theme.base0F, + string: theme.base09, + nan: theme.base08, + null: theme.base0A, + undefined: theme.base05, + regexp: theme.base0A, + background: theme.base02 + }, + editVariable: { + editIcon: theme.base0E, + cancelIcon: theme.base09, + removeIcon: theme.base09, + addIcon: theme.base0E, + checkIcon: theme.base0E, + background: theme.base01, + color: theme.base0A, + border: theme.base07 + }, + addKeyModal: { + background: theme.base05, + border: theme.base04, + color: theme.base0A, + labelColor: theme.base01 + }, + validationFailure: { + background: theme.base09, + iconColor: theme.base01, + fontColor: theme.base01 + } +}) const getDefaultThemeStyling = theme => { - const colors = colorMap(theme); + const colors = colorMap(theme) - return { - 'app-container': { - fontFamily: constants.globalFontFamily, - cursor: constants.globalCursor, - backgroundColor: colors.backgroundColor, - position: 'relative' - }, - ellipsis: { - display: 'inline-block', - color: colors.ellipsisColor, - fontSize: constants.ellipsisFontSize, - lineHeight: constants.ellipsisLineHeight, - cursor: constants.ellipsisCursor - }, - 'brace-row': { - display: 'inline-block', - cursor: 'pointer' - }, - brace: { - display: 'inline-block', - cursor: constants.braceCursor, - fontWeight: constants.braceFontWeight, - color: colors.braceColor - }, - 'expanded-icon': { - color: colors.expandedIcon - }, - 'collapsed-icon': { - color: colors.collapsedIcon - }, - colon: { - display: 'inline-block', - margin: constants.keyMargin, - color: colors.keyColor, - verticalAlign: 'top' - }, - objectKeyVal: (component, variable_style) => { - return { - style: { - paddingTop: constants.keyValPaddingTop, - paddingRight: constants.keyValPaddingRight, - paddingBottom: constants.keyValPaddingBottom, - borderLeft: - constants.keyValBorderLeft + ' ' + colors.objectBorder, - ':hover': { - paddingLeft: variable_style.paddingLeft - 1 + 'px', - borderLeft: - constants.keyValBorderHover + - ' ' + - colors.objectBorder - }, - ...variable_style - } - }; - }, - 'object-key-val-no-border': { - padding: constants.keyValPadding - }, - 'pushed-content': { - marginLeft: constants.pushedContentMarginLeft - }, - variableValue: (component, variable_style) => { - return { - style: { - display: 'inline-block', - paddingRight: constants.variableValuePaddingRight, - position: 'relative', - ...variable_style - } - }; - }, - 'object-name': { - display: 'inline-block', - color: colors.keyColor, - letterSpacing: constants.keyLetterSpacing, - fontStyle: constants.keyFontStyle, - verticalAlign: constants.keyVerticalAlign, - opacity: constants.keyOpacity, - ':hover': { - opacity: constants.keyOpacityHover - } - }, - 'array-key': { - display: 'inline-block', - color: colors.arrayKeyColor, - letterSpacing: constants.keyLetterSpacing, - fontStyle: constants.keyFontStyle, - verticalAlign: constants.keyVerticalAlign, - opacity: constants.keyOpacity, - ':hover': { - opacity: constants.keyOpacityHover - } - }, - 'object-size': { - color: colors.objectSize, - borderRadius: constants.objectSizeBorderRadius, - fontStyle: constants.objectSizeFontStyle, - margin: constants.objectSizeMargin, - cursor: 'default' - }, - 'data-type-label': { - fontSize: constants.dataTypeFontSize, - marginRight: constants.dataTypeMarginRight, - opacity: constants.datatypeOpacity - }, - boolean: { - display: 'inline-block', - color: colors.dataTypes.boolean - }, - date: { - display: 'inline-block', - color: colors.dataTypes.date - }, - 'date-value': { - marginLeft: constants.dateValueMarginLeft - }, - float: { - display: 'inline-block', - color: colors.dataTypes.float - }, - function: { - display: 'inline-block', - color: colors.dataTypes['function'], - cursor: 'pointer', - whiteSpace: 'pre-line' - }, - 'function-value': { - fontStyle: 'italic' - }, - integer: { - display: 'inline-block', - color: colors.dataTypes.integer - }, - string: { - display: 'inline-block', - color: colors.dataTypes.string - }, - nan: { - display: 'inline-block', - color: colors.dataTypes.nan, - fontSize: constants.nanFontSize, - fontWeight: constants.nanFontWeight, - backgroundColor: colors.dataTypes.background, - padding: constants.nanPadding, - borderRadius: constants.nanBorderRadius - }, - null: { - display: 'inline-block', - color: colors.dataTypes.null, - fontSize: constants.nullFontSize, - fontWeight: constants.nullFontWeight, - backgroundColor: colors.dataTypes.background, - padding: constants.nullPadding, - borderRadius: constants.nullBorderRadius - }, - undefined: { - display: 'inline-block', - color: colors.dataTypes.undefined, - fontSize: constants.undefinedFontSize, - padding: constants.undefinedPadding, - borderRadius: constants.undefinedBorderRadius, - backgroundColor: colors.dataTypes.background - }, - regexp: { - display: 'inline-block', - color: colors.dataTypes.regexp - }, - 'copy-to-clipboard': { - cursor: constants.clipboardCursor - }, - 'copy-icon': { - color: colors.copyToClipboard, - fontSize: constants.iconFontSize, - marginRight: constants.iconMarginRight, - verticalAlign: 'top' - }, - 'copy-icon-copied': { - color: colors.copyToClipboardCheck, - marginLeft: constants.clipboardCheckMarginLeft - }, - 'array-group-meta-data': { - display: 'inline-block', - padding: constants.arrayGroupMetaPadding - }, - 'object-meta-data': { - display: 'inline-block', - padding: constants.metaDataPadding - }, - 'icon-container': { - display: 'inline-block', - width: constants.iconContainerWidth - }, - tooltip: { - padding: constants.tooltipPadding - }, - removeVarIcon: { - verticalAlign: 'top', - display: 'inline-block', - color: colors.editVariable.removeIcon, - cursor: constants.iconCursor, - fontSize: constants.iconFontSize, - marginRight: constants.iconMarginRight - }, - addVarIcon: { - verticalAlign: 'top', - display: 'inline-block', - color: colors.editVariable.addIcon, - cursor: constants.iconCursor, - fontSize: constants.iconFontSize, - marginRight: constants.iconMarginRight - }, - editVarIcon: { - verticalAlign: 'top', - display: 'inline-block', - color: colors.editVariable.editIcon, - cursor: constants.iconCursor, - fontSize: constants.iconFontSize, - marginRight: constants.iconMarginRight - }, - 'edit-icon-container': { - display: 'inline-block', - verticalAlign: 'top' - }, - 'check-icon': { - display: 'inline-block', - cursor: constants.iconCursor, - color: colors.editVariable.checkIcon, - fontSize: constants.iconFontSize, - paddingRight: constants.iconPaddingRight - }, - 'cancel-icon': { - display: 'inline-block', - cursor: constants.iconCursor, - color: colors.editVariable.cancelIcon, - fontSize: constants.iconFontSize, - paddingRight: constants.iconPaddingRight - }, - 'edit-input': { - display: 'inline-block', - minWidth: constants.editInputMinWidth, - borderRadius: constants.editInputBorderRadius, - backgroundColor: colors.editVariable.background, - color: colors.editVariable.color, - padding: constants.editInputPadding, - marginRight: constants.editInputMarginRight, - fontFamily: constants.editInputFontFamily - }, - 'detected-row': { - paddingTop: constants.detectedRowPaddingTop - }, - 'key-modal-request': { - position: constants.addKeyCoverPosition, - top: constants.addKeyCoverPositionPx, - left: constants.addKeyCoverPositionPx, - right: constants.addKeyCoverPositionPx, - bottom: constants.addKeyCoverPositionPx, - backgroundColor: constants.addKeyCoverBackground - }, - 'key-modal': { - width: constants.addKeyModalWidth, - backgroundColor: colors.addKeyModal.background, - marginLeft: constants.addKeyModalMargin, - marginRight: constants.addKeyModalMargin, - padding: constants.addKeyModalPadding, - borderRadius: constants.addKeyModalRadius, - marginTop: '15px', - position: 'relative' - }, - 'key-modal-label': { - color: colors.addKeyModal.labelColor, - marginLeft: '2px', - marginBottom: '5px', - fontSize: '11px' - }, - 'key-modal-input-container': { - overflow: 'hidden' - }, - 'key-modal-input': { - width: '100%', - padding: '3px 6px', - fontFamily: 'monospace', - color: colors.addKeyModal.color, - border: 'none', - boxSizing: 'border-box', - borderRadius: '2px' - }, - 'key-modal-cancel': { - backgroundColor: colors.editVariable.removeIcon, - position: 'absolute', - top: '0px', - right: '0px', - borderRadius: '0px 3px 0px 3px', - cursor: 'pointer' - }, - 'key-modal-cancel-icon': { - color: colors.addKeyModal.labelColor, - fontSize: constants.iconFontSize, - transform: 'rotate(45deg)' - }, - 'key-modal-submit': { - color: colors.editVariable.addIcon, - fontSize: constants.iconFontSize, - position: 'absolute', - right: '2px', - top: '3px', - cursor: 'pointer' - }, - 'function-ellipsis': { - display: 'inline-block', - color: colors.ellipsisColor, - fontSize: constants.ellipsisFontSize, - lineHeight: constants.ellipsisLineHeight, - cursor: constants.ellipsisCursor - }, - 'validation-failure': { - float: 'right', - padding: '3px 6px', - borderRadius: '2px', - cursor: 'pointer', - color: colors.validationFailure.fontColor, - backgroundColor: colors.validationFailure.background - }, - 'validation-failure-label': { - marginRight: '6px' - }, - 'validation-failure-clear': { - position: 'relative', - verticalAlign: 'top', - cursor: 'pointer', - color: colors.validationFailure.iconColor, - fontSize: constants.iconFontSize, - transform: 'rotate(45deg)' + return { + 'app-container': { + fontFamily: constants.globalFontFamily, + cursor: constants.globalCursor, + backgroundColor: colors.backgroundColor, + position: 'relative' + }, + ellipsis: { + display: 'inline-block', + color: colors.ellipsisColor, + fontSize: constants.ellipsisFontSize, + lineHeight: constants.ellipsisLineHeight, + cursor: constants.ellipsisCursor + }, + 'brace-row': { + display: 'inline-block', + cursor: 'pointer' + }, + brace: { + display: 'inline-block', + cursor: constants.braceCursor, + fontWeight: constants.braceFontWeight, + color: colors.braceColor + }, + 'expanded-icon': { + color: colors.expandedIcon + }, + 'collapsed-icon': { + color: colors.collapsedIcon + }, + colon: { + display: 'inline-block', + margin: constants.keyMargin, + color: colors.keyColor, + verticalAlign: 'top' + }, + objectKeyVal: (component, variable_style) => { + return { + style: { + paddingTop: constants.keyValPaddingTop, + paddingRight: constants.keyValPaddingRight, + paddingBottom: constants.keyValPaddingBottom, + borderLeft: constants.keyValBorderLeft + ' ' + colors.objectBorder, + ':hover': { + paddingLeft: variable_style.paddingLeft - 1 + 'px', + borderLeft: constants.keyValBorderHover + ' ' + colors.objectBorder + }, + ...variable_style } - }; -}; + } + }, + 'object-key-val-no-border': { + padding: constants.keyValPadding + }, + 'pushed-content': { + marginLeft: constants.pushedContentMarginLeft + }, + variableValue: (component, variable_style) => { + return { + style: { + display: 'inline-block', + paddingRight: constants.variableValuePaddingRight, + position: 'relative', + ...variable_style + } + } + }, + 'object-name': { + display: 'inline-block', + color: colors.keyColor, + letterSpacing: constants.keyLetterSpacing, + fontStyle: constants.keyFontStyle, + verticalAlign: constants.keyVerticalAlign, + opacity: constants.keyOpacity, + ':hover': { + opacity: constants.keyOpacityHover + } + }, + 'array-key': { + display: 'inline-block', + color: colors.arrayKeyColor, + letterSpacing: constants.keyLetterSpacing, + fontStyle: constants.keyFontStyle, + verticalAlign: constants.keyVerticalAlign, + opacity: constants.keyOpacity, + ':hover': { + opacity: constants.keyOpacityHover + } + }, + 'object-size': { + color: colors.objectSize, + borderRadius: constants.objectSizeBorderRadius, + fontStyle: constants.objectSizeFontStyle, + margin: constants.objectSizeMargin, + cursor: 'default' + }, + 'data-type-label': { + fontSize: constants.dataTypeFontSize, + marginRight: constants.dataTypeMarginRight, + opacity: constants.datatypeOpacity + }, + boolean: { + display: 'inline-block', + color: colors.dataTypes.boolean + }, + date: { + display: 'inline-block', + color: colors.dataTypes.date + }, + 'date-value': { + marginLeft: constants.dateValueMarginLeft + }, + float: { + display: 'inline-block', + color: colors.dataTypes.float + }, + function: { + display: 'inline-block', + color: colors.dataTypes.function, + cursor: 'pointer', + whiteSpace: 'pre-line' + }, + 'function-value': { + fontStyle: 'italic' + }, + integer: { + display: 'inline-block', + color: colors.dataTypes.integer + }, + string: { + display: 'inline-block', + color: colors.dataTypes.string + }, + nan: { + display: 'inline-block', + color: colors.dataTypes.nan, + fontSize: constants.nanFontSize, + fontWeight: constants.nanFontWeight, + backgroundColor: colors.dataTypes.background, + padding: constants.nanPadding, + borderRadius: constants.nanBorderRadius + }, + null: { + display: 'inline-block', + color: colors.dataTypes.null, + fontSize: constants.nullFontSize, + fontWeight: constants.nullFontWeight, + backgroundColor: colors.dataTypes.background, + padding: constants.nullPadding, + borderRadius: constants.nullBorderRadius + }, + undefined: { + display: 'inline-block', + color: colors.dataTypes.undefined, + fontSize: constants.undefinedFontSize, + padding: constants.undefinedPadding, + borderRadius: constants.undefinedBorderRadius, + backgroundColor: colors.dataTypes.background + }, + regexp: { + display: 'inline-block', + color: colors.dataTypes.regexp + }, + 'copy-to-clipboard': { + cursor: constants.clipboardCursor + }, + 'copy-icon': { + color: colors.copyToClipboard, + fontSize: constants.iconFontSize, + marginRight: constants.iconMarginRight, + verticalAlign: 'top' + }, + 'copy-icon-copied': { + color: colors.copyToClipboardCheck, + marginLeft: constants.clipboardCheckMarginLeft + }, + 'array-group-meta-data': { + display: 'inline-block', + padding: constants.arrayGroupMetaPadding + }, + 'object-meta-data': { + display: 'inline-block', + padding: constants.metaDataPadding + }, + 'icon-container': { + display: 'inline-block', + width: constants.iconContainerWidth + }, + tooltip: { + padding: constants.tooltipPadding + }, + removeVarIcon: { + verticalAlign: 'top', + display: 'inline-block', + color: colors.editVariable.removeIcon, + cursor: constants.iconCursor, + fontSize: constants.iconFontSize, + marginRight: constants.iconMarginRight + }, + addVarIcon: { + verticalAlign: 'top', + display: 'inline-block', + color: colors.editVariable.addIcon, + cursor: constants.iconCursor, + fontSize: constants.iconFontSize, + marginRight: constants.iconMarginRight + }, + editVarIcon: { + verticalAlign: 'top', + display: 'inline-block', + color: colors.editVariable.editIcon, + cursor: constants.iconCursor, + fontSize: constants.iconFontSize, + marginRight: constants.iconMarginRight + }, + 'edit-icon-container': { + display: 'inline-block', + verticalAlign: 'top' + }, + 'check-icon': { + display: 'inline-block', + cursor: constants.iconCursor, + color: colors.editVariable.checkIcon, + fontSize: constants.iconFontSize, + paddingRight: constants.iconPaddingRight + }, + 'cancel-icon': { + display: 'inline-block', + cursor: constants.iconCursor, + color: colors.editVariable.cancelIcon, + fontSize: constants.iconFontSize, + paddingRight: constants.iconPaddingRight + }, + 'edit-input': { + display: 'inline-block', + minWidth: constants.editInputMinWidth, + borderRadius: constants.editInputBorderRadius, + backgroundColor: colors.editVariable.background, + color: colors.editVariable.color, + padding: constants.editInputPadding, + marginRight: constants.editInputMarginRight, + fontFamily: constants.editInputFontFamily + }, + 'detected-row': { + paddingTop: constants.detectedRowPaddingTop + }, + 'key-modal-request': { + position: constants.addKeyCoverPosition, + top: constants.addKeyCoverPositionPx, + left: constants.addKeyCoverPositionPx, + right: constants.addKeyCoverPositionPx, + bottom: constants.addKeyCoverPositionPx, + backgroundColor: constants.addKeyCoverBackground + }, + 'key-modal': { + width: constants.addKeyModalWidth, + backgroundColor: colors.addKeyModal.background, + marginLeft: constants.addKeyModalMargin, + marginRight: constants.addKeyModalMargin, + padding: constants.addKeyModalPadding, + borderRadius: constants.addKeyModalRadius, + marginTop: '15px', + position: 'relative' + }, + 'key-modal-label': { + color: colors.addKeyModal.labelColor, + marginLeft: '2px', + marginBottom: '5px', + fontSize: '11px' + }, + 'key-modal-input-container': { + overflow: 'hidden' + }, + 'key-modal-input': { + width: '100%', + padding: '3px 6px', + fontFamily: 'monospace', + color: colors.addKeyModal.color, + border: 'none', + boxSizing: 'border-box', + borderRadius: '2px' + }, + 'key-modal-cancel': { + backgroundColor: colors.editVariable.removeIcon, + position: 'absolute', + top: '0px', + right: '0px', + borderRadius: '0px 3px 0px 3px', + cursor: 'pointer' + }, + 'key-modal-cancel-icon': { + color: colors.addKeyModal.labelColor, + fontSize: constants.iconFontSize, + transform: 'rotate(45deg)' + }, + 'key-modal-submit': { + color: colors.editVariable.addIcon, + fontSize: constants.iconFontSize, + position: 'absolute', + right: '2px', + top: '3px', + cursor: 'pointer' + }, + 'function-ellipsis': { + display: 'inline-block', + color: colors.ellipsisColor, + fontSize: constants.ellipsisFontSize, + lineHeight: constants.ellipsisLineHeight, + cursor: constants.ellipsisCursor + }, + 'validation-failure': { + float: 'right', + padding: '3px 6px', + borderRadius: '2px', + cursor: 'pointer', + color: colors.validationFailure.fontColor, + backgroundColor: colors.validationFailure.background + }, + 'validation-failure-label': { + marginRight: '6px' + }, + 'validation-failure-clear': { + position: 'relative', + verticalAlign: 'top', + cursor: 'pointer', + color: colors.validationFailure.iconColor, + fontSize: constants.iconFontSize, + transform: 'rotate(45deg)' + } + } +} const getStyle = theme => { - let rjv_theme = rjv_default; - if (theme === false || theme === 'none') { - rjv_theme = rjv_grey; - } + let rjv_theme = rjv_default + if (theme === false || theme === 'none') { + rjv_theme = rjv_grey + } - return createStyling(getDefaultThemeStyling, { defaultBase16: rjv_theme })( - theme - ); -}; + return createStyling(getDefaultThemeStyling, { defaultBase16: rjv_theme })( + theme + ) +} -export default function style(theme, component, args) { - if (!theme) { - console.error('theme has not been set'); - } +export default function style (theme, component, args) { + if (!theme) { + console.error('theme has not been set') + } - return getStyle(theme)(component, args); + return getStyle(theme)(component, args) } diff --git a/src/js/themes/styleConstants.js b/src/js/themes/styleConstants.js index 5182417..98c1ba6 100644 --- a/src/js/themes/styleConstants.js +++ b/src/js/themes/styleConstants.js @@ -1,95 +1,95 @@ export default { - white: '#fff', - black: '#000', - transparent: 'rgba(1, 1, 1, 0)', + white: '#fff', + black: '#000', + transparent: 'rgba(1, 1, 1, 0)', - globalFontFamily: 'monospace', - globalCursor: 'default', + globalFontFamily: 'monospace', + globalCursor: 'default', - indentBlockWidth: '5px', + indentBlockWidth: '5px', - braceFontWeight: 'bold', - braceCursor: 'pointer', + braceFontWeight: 'bold', + braceCursor: 'pointer', - ellipsisFontSize: '18px', - ellipsisLineHeight: '10px', - ellipsisCursor: 'pointer', + ellipsisFontSize: '18px', + ellipsisLineHeight: '10px', + ellipsisCursor: 'pointer', - keyMargin: '0px 5px', - keyLetterSpacing: '0.5px', - keyFontStyle: 'none', - keyBorderRadius: '3px', - keyColonWeight: 'bold', - keyVerticalAlign: 'top', - keyOpacity: '0.85', - keyOpacityHover: '1', + keyMargin: '0px 5px', + keyLetterSpacing: '0.5px', + keyFontStyle: 'none', + keyBorderRadius: '3px', + keyColonWeight: 'bold', + keyVerticalAlign: 'top', + keyOpacity: '0.85', + keyOpacityHover: '1', - keyValPaddingTop: '3px', - keyValPaddingBottom: '3px', - keyValPaddingRight: '5px', - keyValBorderLeft: '1px solid', - keyValBorderHover: '2px solid', - keyValPaddingHover: '3px 5px 3px 4px', + keyValPaddingTop: '3px', + keyValPaddingBottom: '3px', + keyValPaddingRight: '5px', + keyValBorderLeft: '1px solid', + keyValBorderHover: '2px solid', + keyValPaddingHover: '3px 5px 3px 4px', - pushedContentMarginLeft: '6px', + pushedContentMarginLeft: '6px', - variableValuePaddingRight: '6px', + variableValuePaddingRight: '6px', - nullFontSize: '11px', - nullFontWeight: 'bold', - nullPadding: '1px 2px', - nullBorderRadius: '3px', + nullFontSize: '11px', + nullFontWeight: 'bold', + nullPadding: '1px 2px', + nullBorderRadius: '3px', - nanFontSize: '11px', - nanFontWeight: 'bold', - nanPadding: '1px 2px', - nanBorderRadius: '3px', + nanFontSize: '11px', + nanFontWeight: 'bold', + nanPadding: '1px 2px', + nanBorderRadius: '3px', - undefinedFontSize: '11px', - undefinedFontWeight: 'bold', - undefinedPadding: '1px 2px', - undefinedBorderRadius: '3px', + undefinedFontSize: '11px', + undefinedFontWeight: 'bold', + undefinedPadding: '1px 2px', + undefinedBorderRadius: '3px', - dataTypeFontSize: '11px', - dataTypeMarginRight: '4px', - datatypeOpacity: '0.8', + dataTypeFontSize: '11px', + dataTypeMarginRight: '4px', + datatypeOpacity: '0.8', - objectSizeBorderRadius: '3px', - objectSizeFontStyle: 'italic', - objectSizeMargin: '0px 6px 0px 0px', + objectSizeBorderRadius: '3px', + objectSizeFontStyle: 'italic', + objectSizeMargin: '0px 6px 0px 0px', - clipboardCursor: 'pointer', - clipboardCheckMarginLeft: '-12px', + clipboardCursor: 'pointer', + clipboardCheckMarginLeft: '-12px', - metaDataPadding: '0px 0px 0px 10px', + metaDataPadding: '0px 0px 0px 10px', - arrayGroupMetaPadding: '0px 0px 0px 4px', + arrayGroupMetaPadding: '0px 0px 0px 4px', - iconContainerWidth: '17px', + iconContainerWidth: '17px', - tooltipPadding: '4px', + tooltipPadding: '4px', - editInputMinWidth: '130px', - editInputBorderRadius: '2px', - editInputPadding: '5px', - editInputMarginRight: '4px', - editInputFontFamily: 'monospace', + editInputMinWidth: '130px', + editInputBorderRadius: '2px', + editInputPadding: '5px', + editInputMarginRight: '4px', + editInputFontFamily: 'monospace', - iconCursor: 'pointer', - iconFontSize: '15px', - iconPaddingRight: '1px', + iconCursor: 'pointer', + iconFontSize: '15px', + iconPaddingRight: '1px', - dateValueMarginLeft: '2px', + dateValueMarginLeft: '2px', - iconMarginRight: '3px', + iconMarginRight: '3px', - detectedRowPaddingTop: '3px', + detectedRowPaddingTop: '3px', - addKeyCoverBackground: 'rgba(255, 255, 255, 0.3)', - addKeyCoverPosition: 'absolute', - addKeyCoverPositionPx: '0px', - addKeyModalWidth: '200px', - addKeyModalMargin: 'auto', - addKeyModalPadding: '10px', - addKeyModalRadius: '3px' -}; + addKeyCoverBackground: 'rgba(255, 255, 255, 0.3)', + addKeyCoverPosition: 'absolute', + addKeyCoverPositionPx: '0px', + addKeyModalWidth: '200px', + addKeyModalMargin: 'auto', + addKeyModalPadding: '10px', + addKeyModalRadius: '3px' +} diff --git a/src/style/scss/global.scss b/src/style/scss/global.scss index a7a2d2d..5e482ec 100644 --- a/src/style/scss/global.scss +++ b/src/style/scss/global.scss @@ -1,50 +1,50 @@ .react-json-view { - min-height: 96px; - word-break: break-all; - -ms-word-break: break-all; + min-height: 96px; + word-break: break-all; + -ms-word-break: break-all; - .copy-to-clipboard-container { - vertical-align: top; - display: none; - } - .click-to-add { - display: none; - } - .click-to-remove { - display: none; - } - .click-to-edit { - display: none; - } + .copy-to-clipboard-container { + vertical-align: top; + display: none; + } + .click-to-add { + display: none; + } + .click-to-remove { + display: none; + } + .click-to-edit { + display: none; + } - .object-key-val { - &:hover > span > .object-meta-data { - & > .copy-to-clipboard-container { - display: inline-block; - } - & > .click-to-add { - display: inline-block; - } - & > .click-to-remove { - display: inline-block; - } - } + .object-key-val { + &:hover > span > .object-meta-data { + & > .copy-to-clipboard-container { + display: inline-block; + } + & > .click-to-add { + display: inline-block; + } + & > .click-to-remove { + display: inline-block; + } } + } - .variable-row { - &:hover { - & .copy-to-clipboard-container { - display: inline-block; - } - } + .variable-row { + &:hover { + & .copy-to-clipboard-container { + display: inline-block; + } } + } - .object-content .variable-row { - &:hover .click-to-remove { - display: inline-block; - } - &:hover .click-to-edit { - display: inline-block; - } + .object-content .variable-row { + &:hover .click-to-remove { + display: inline-block; + } + &:hover .click-to-edit { + display: inline-block; } + } } diff --git a/test/testHelpers/requireSources.js b/test/testHelpers/requireSources.js index d61fdd6..39a9c66 100644 --- a/test/testHelpers/requireSources.js +++ b/test/testHelpers/requireSources.js @@ -1,32 +1,32 @@ -import register from 'ignore-styles'; -register(['.sass', '.scss']); -import './../../src/js/index'; +import register from 'ignore-styles' +import './../../src/js/index' -import Adapter from 'enzyme-adapter-react-16'; -import { configure } from 'enzyme'; -import jsdom from 'jsdom'; +import Adapter from 'enzyme-adapter-react-16' +import { configure } from 'enzyme' +import jsdom from 'jsdom' +register(['.sass', '.scss']) -//https://stackoverflow.com/questions/46896639/ensure-a-dom-environment-is-loaded-for-enzyme -function setUpDomEnvironment() { - const { JSDOM } = jsdom; - const dom = new JSDOM(''); - const { window } = dom; +// https://stackoverflow.com/questions/46896639/ensure-a-dom-environment-is-loaded-for-enzyme +function setUpDomEnvironment () { + const { JSDOM } = jsdom + const dom = new JSDOM('') + const { window } = dom - global.window = window; - global.document = window.document; - global.navigator = { - userAgent: 'node.js' - }; - copyProps(window, global); + global.window = window + global.document = window.document + global.navigator = { + userAgent: 'node.js' + } + copyProps(window, global) } -function copyProps(src, target) { - const props = Object.getOwnPropertyNames(src) - .filter(prop => typeof target[prop] === 'undefined') - .map(prop => Object.getOwnPropertyDescriptor(src, prop)); - Object.defineProperties(target, props); +function copyProps (src, target) { + const props = Object.getOwnPropertyNames(src) + .filter(prop => typeof target[prop] === 'undefined') + .map(prop => Object.getOwnPropertyDescriptor(src, prop)) + Object.defineProperties(target, props) } -setUpDomEnvironment(); +setUpDomEnvironment() -configure({ adapter: new Adapter() }); +configure({ adapter: new Adapter() }) diff --git a/test/tests/js/Index-test.js b/test/tests/js/Index-test.js index 046bf7f..ed409bb 100644 --- a/test/tests/js/Index-test.js +++ b/test/tests/js/Index-test.js @@ -1,133 +1,131 @@ -import React from "react" -import { render, mount } from "enzyme" -import sinon from "sinon" -import { expect } from "chai" -import { JSDOM } from "jsdom" +import React from 'react' +import { render, mount } from 'enzyme' +import sinon from 'sinon' +import { expect } from 'chai' +import { JSDOM } from 'jsdom' -import Index from "./../../../src/js/index" +import Index from './../../../src/js/index' const { window } = new JSDOM() global.window = window global.document = window.document -describe("", function() { - const rjvId = 1 +describe('', function () { + const rjvId = 1 - it("check data type labels from index", function() { - const wrapper = render( - {}, - obj: { - arrChild: [1, 2, "three"], - objChild: { - one: 1, - two: "two" - } - }, - arr: [[1, "two"], { one: "one", two: 2 }], - regexp: /[0-9]/gi - }} - /> - ) - expect(wrapper.find(".data-type-label")).to.have.length(14) - expect(wrapper.find(".data-type-label")).to.have.length(14) - }) + it('check data type labels from index', function () { + const wrapper = render( + {}, + obj: { + arrChild: [1, 2, 'three'], + objChild: { + one: 1, + two: 'two' + } + }, + arr: [[1, 'two'], { one: 'one', two: 2 }], + regexp: /[0-9]/gi + }} + /> + ) + expect(wrapper.find('.data-type-label')).to.have.length(14) + expect(wrapper.find('.data-type-label')).to.have.length(14) + }) - it("check object-size labels from index", function() { - const wrapper = mount( - {}, - obj: { - arrChild: [1, 2, "three"], - objChild: { - one: 1, - two: "two" - } - }, - arr: [[1, "two"], { one: "one", two: 2 }], - regexp: /[0-9]/gi - }} - displayObjectSize={true} - displayDataTypes={true} - enableClipboard={false} - /> - ) - expect(wrapper.find(".object-size")).to.have.length(7) + it('check object-size labels from index', function () { + const wrapper = mount( + {}, + obj: { + arrChild: [1, 2, 'three'], + objChild: { + one: 1, + two: 'two' + } + }, + arr: [[1, 'two'], { one: 'one', two: 2 }], + regexp: /[0-9]/gi + }} + displayObjectSize + displayDataTypes + enableClipboard={false} + /> + ) + expect(wrapper.find('.object-size')).to.have.length(7) - wrapper.setProps({ displayObjectSize: false }) - expect(wrapper.find(".object-size")).to.have.length(0) - }) + wrapper.setProps({ displayObjectSize: false }) + expect(wrapper.find('.object-size')).to.have.length(0) + }) - it("src replaced with error message (ERROR OUTPUT EXPECTED)", function() { - const wrapper = render( - - ) - expect(wrapper.find(".data-type-label")).to.have.length(1) - }) + it('src replaced with error message (ERROR OUTPUT EXPECTED)', function () { + const wrapper = render( + + ) + expect(wrapper.find('.data-type-label')).to.have.length(1) + }) - it("make sure copy to clipboard is displayed all properties", function() { - const wrapper = render( - - ) - expect(wrapper.find(".copy-to-clipboard-container")).to.have.length(7) - }) + it('make sure copy to clipboard is displayed all properties', function () { + const wrapper = render( + + ) + expect(wrapper.find('.copy-to-clipboard-container')).to.have.length(7) + }) - it("index test getDerivedStateFromProps", function() { - sinon.spy(Index, "getDerivedStateFromProps") - // mount() will cause getDerivedStateFromProps to be called twice. - // 1. before first render() - // 2. result of setState() in componentDidMount() - const wrapper = mount() - expect(wrapper.find(".data-type-label")).to.have.length(1) - // setProps() will cause getDerivedStateFromProps to be called once. - wrapper.setProps({ src: { test1: true, test2: false } }) - // in total, it was called thrice. - expect(Index.getDerivedStateFromProps.calledThrice).to.equal( - true - ) - }) + it('index test getDerivedStateFromProps', function () { + sinon.spy(Index, 'getDerivedStateFromProps') + // mount() will cause getDerivedStateFromProps to be called twice. + // 1. before first render() + // 2. result of setState() in componentDidMount() + const wrapper = mount() + expect(wrapper.find('.data-type-label')).to.have.length(1) + // setProps() will cause getDerivedStateFromProps to be called once. + wrapper.setProps({ src: { test1: true, test2: false } }) + // in total, it was called thrice. + expect(Index.getDerivedStateFromProps.calledThrice).to.equal(true) + }) - it("index can have ArrayGroup root component", function() { - const wrapper = render( - - ) - expect(wrapper.find(".array-group")).to.have.length(3) - }) + it('index can have ArrayGroup root component', function () { + const wrapper = render( + + ) + expect(wrapper.find('.array-group')).to.have.length(3) + }) - it("length is correct even if an object has a length property", function () { - const wrapper = render( - - ) - expect(wrapper.find(".object-size")).to.have.length(1) - }) + it('length is correct even if an object has a length property', function () { + const wrapper = render( + + ) + expect(wrapper.find('.object-size')).to.have.length(1) + }) }) diff --git a/test/tests/js/components/ArrayGroup-test.js b/test/tests/js/components/ArrayGroup-test.js index 7295be4..9c4749b 100644 --- a/test/tests/js/components/ArrayGroup-test.js +++ b/test/tests/js/components/ArrayGroup-test.js @@ -1,113 +1,113 @@ -import React from 'react'; -import { render, shallow, mount } from 'enzyme'; -import { expect } from 'chai'; +import React from 'react' +import { render, shallow, mount } from 'enzyme' +import { expect } from 'chai' -import ArrayGroup from './../../../../src/js/components/ArrayGroup'; -import JsonObject from './../../../../src/js/components/DataTypes/Object'; -import JsonString from './../../../../src/js/components/DataTypes/String'; +import ArrayGroup from './../../../../src/js/components/ArrayGroup' +import JsonObject from './../../../../src/js/components/DataTypes/Object' +import JsonString from './../../../../src/js/components/DataTypes/String' describe('', function () { - var large_array = new Array(15).fill('test'); - - it('ArrayGroup mount', function () { - const wrapper = render( - - ); - - expect(wrapper.find('.array-group').length).to.equal(3); - }); - - it('ArrayGroup expands and collapses', function () { - const wrapper = shallow( - - ); - - wrapper.find('.array-group-brace').first().simulate('click'); - - expect(wrapper.state().expanded[0]).to.equal(true); - - wrapper - .find('.array-group') - .first() - .find('.icon-container') - .simulate('click'); - - expect(wrapper.state().expanded[0]).to.equal(false); - }); - - it('ArrayGroup displays arrays on expansion', function () { - const wrapper = mount( - - ); - - wrapper.setState({ expanded: { 0: true } }); - - expect(wrapper.find(JsonObject).length).to.equal(1); - - expect(wrapper.find(JsonObject).find(JsonString).length).to.equal(5); - }); - - it('ArrayGroup paginates groups accurately', function () { - var test_array = new Array(17).fill('test'); - - const wrapper = mount( - - ); - - expect(wrapper.find('.array-group').length).to.equal(4); - - wrapper.setState({ expanded: { 3: true } }); - - expect( - wrapper.find('.array-group').last().find(JsonString).length - ).to.equal(2); - }); - - it('ArrayGroup renders at root', function () { - const wrapper = render( - - ); - - expect(wrapper.find('.array-group').length).to.equal(3); - }); -}); + const large_array = new Array(15).fill('test') + + it('ArrayGroup mount', function () { + const wrapper = render( + + ) + + expect(wrapper.find('.array-group').length).to.equal(3) + }) + + it('ArrayGroup expands and collapses', function () { + const wrapper = shallow( + + ) + + wrapper.find('.array-group-brace').first().simulate('click') + + expect(wrapper.state().expanded[0]).to.equal(true) + + wrapper + .find('.array-group') + .first() + .find('.icon-container') + .simulate('click') + + expect(wrapper.state().expanded[0]).to.equal(false) + }) + + it('ArrayGroup displays arrays on expansion', function () { + const wrapper = mount( + + ) + + wrapper.setState({ expanded: { 0: true } }) + + expect(wrapper.find(JsonObject).length).to.equal(1) + + expect(wrapper.find(JsonObject).find(JsonString).length).to.equal(5) + }) + + it('ArrayGroup paginates groups accurately', function () { + const test_array = new Array(17).fill('test') + + const wrapper = mount( + + ) + + expect(wrapper.find('.array-group').length).to.equal(4) + + wrapper.setState({ expanded: { 3: true } }) + + expect( + wrapper.find('.array-group').last().find(JsonString).length + ).to.equal(2) + }) + + it('ArrayGroup renders at root', function () { + const wrapper = render( + + ) + + expect(wrapper.find('.array-group').length).to.equal(3) + }) +}) diff --git a/test/tests/js/components/CopyToClipboard-test.js b/test/tests/js/components/CopyToClipboard-test.js index 937aab3..7543968 100644 --- a/test/tests/js/components/CopyToClipboard-test.js +++ b/test/tests/js/components/CopyToClipboard-test.js @@ -1,32 +1,32 @@ -import React from "react" -import { shallow, mount } from "enzyme" -import { expect } from "chai" +import React from 'react' +import { shallow, mount } from 'enzyme' +import { expect } from 'chai' -import CopyToClipboard from "./../../../../src/js/components/CopyToClipboard" +import CopyToClipboard from './../../../../src/js/components/CopyToClipboard' -describe("", function() { - it("CopyToClipboard clipboard should exist", function() { - const wrapper = shallow( -