diff --git a/dist/client/ui/foldable.js b/dist/client/ui/foldable.js index febf2cc58d7..ce8ff5ccdb8 100644 --- a/dist/client/ui/foldable.js +++ b/dist/client/ui/foldable.js @@ -36,6 +36,10 @@ var _jsonStringifySafe = require('json-stringify-safe'); var _jsonStringifySafe2 = _interopRequireDefault(_jsonStringifySafe); +var _highlight = require('./highlight'); + +var _highlight2 = _interopRequireDefault(_highlight); + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var folderStyle = { @@ -124,11 +128,9 @@ var Foldable = function (_React$Component) { this.state.collapsed ? '►' : '▼' ) ), - _react2.default.createElement( - 'div', - { ref: 'foldable-content', style: folderContentStyle }, - content - ) + _react2.default.createElement('div', { ref: 'foldable-content', style: folderContentStyle, + dangerouslySetInnerHTML: { __html: (0, _highlight2.default)(content) } + }) ); } }]); diff --git a/dist/client/ui/highlight.js b/dist/client/ui/highlight.js new file mode 100644 index 00000000000..233b59b71b5 --- /dev/null +++ b/dist/client/ui/highlight.js @@ -0,0 +1,40 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = highlight; +/** + * Parses the JSON string and adds styling and class based on whether + * a part is string, number, undefined, null or key. Also removes quotes + * from keys. + * + * @param data A stringified JSON + * @returns {string} String with styling + */ +function highlight(data) { + var json = data.replace(/&/g, '&').replace(//g, '>'); + var regex = /("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g; // eslint-disable-line + return json.replace(regex, function (match) { + var className = 'number'; + var style = void 0; + var result = match; + if (/^"/.test(result)) { + if (/:$/.test(result)) { + className = 'key'; + style = 'color:#800080'; + result = match.replace(/"/g, ''); + } else { + className = 'string'; + style = 'color:#a31515'; + } + } else if (/true|false/.test(result)) { + className = 'boolean'; + style = 'color:#066066'; + } else if (/null|undefined/.test(result)) { + className = 'null'; + style = 'color:#a31515'; + } + return '' + result + ''; + }); +} \ No newline at end of file diff --git a/src/client/ui/__tests__/foldable.js b/src/client/ui/__tests__/foldable.js index 63910ee7197..69b67e94747 100644 --- a/src/client/ui/__tests__/foldable.js +++ b/src/client/ui/__tests__/foldable.js @@ -12,7 +12,7 @@ describe('', function () { args: 'things', }; - const compactString = '{"name":"test action","args":"things"}'; + const compactString = '{name:"test action",args:"things"}'; const wrap = mount(); const content = wrap.ref('foldable-content'); @@ -25,7 +25,7 @@ describe('', function () { args: 'things', }; - const fullString = '{\n "name": "test action",\n "args": "things"\n}'; + const fullString = '{\n name: "test action",\n args: "things"\n}'; const wrap = mount(); const toggle = wrap.ref('foldable-toggle'); diff --git a/src/client/ui/__tests__/highlight.js b/src/client/ui/__tests__/highlight.js new file mode 100644 index 00000000000..c7ed3e24d96 --- /dev/null +++ b/src/client/ui/__tests__/highlight.js @@ -0,0 +1,21 @@ +const { describe, it } = global; +import { expect } from 'chai'; +import highlight from '../highlight'; + +describe('highlight', function () { + it('should remove quotes from keys and add correct colour', function () { + const data = '{ "name": "react-storybook" }'; + const expected = '{ name: "react-storybook" }'; // eslint-disable-line + expect(highlight(data)).to.equal(expected); + }); + + it('should preserve new lines also', function () { + const data = '{\n "name": "test action",\n "args": "things"\n}'; + const expected = '{\n ' + + 'name: ' + + '"test action",\n ' + + 'args: ' + + '"things"\n}'; + expect(highlight(data)).to.equal(expected); + }); +}); diff --git a/src/client/ui/foldable.js b/src/client/ui/foldable.js index 291ed4bb22e..49b10d3bd45 100644 --- a/src/client/ui/foldable.js +++ b/src/client/ui/foldable.js @@ -1,5 +1,6 @@ import React from 'react'; import stringify from 'json-stringify-safe'; +import highlight from './highlight'; const folderStyle = { display: 'block', @@ -70,9 +71,9 @@ class Foldable extends React.Component { { this.state.collapsed ? '►' : '▼' } - -
- { content } +
); diff --git a/src/client/ui/highlight.js b/src/client/ui/highlight.js new file mode 100644 index 00000000000..bba93bd35aa --- /dev/null +++ b/src/client/ui/highlight.js @@ -0,0 +1,34 @@ +/** + * Parses the JSON string and adds styling and class based on whether + * a part is string, number, undefined, null or key. Also removes quotes + * from keys. + * + * @param data A stringified JSON + * @returns {string} String with styling + */ +export default function highlight(data) { + const json = data.replace(/&/g, '&').replace(//g, '>'); + const regex = /("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g; // eslint-disable-line + return json.replace(regex, (match) => { + let className = 'number'; + let style; + let result = match; + if (/^"/.test(result)) { + if (/:$/.test(result)) { + className = 'key'; + style = 'color:#800080'; + result = match.replace(/"/g, ''); + } else { + className = 'string'; + style = 'color:#a31515'; + } + } else if (/true|false/.test(result)) { + className = 'boolean'; + style = 'color:#066066'; + } else if (/null|undefined/.test(result)) { + className = 'null'; + style = 'color:#a31515'; + } + return `${result}`; + }); +}