Skip to content

Commit a72086a

Browse files
authored
Merge pull request #87 from truongthanh1303/feat/show-comma-option
feat: show comma option
2 parents bc355f3 + bdb3907 commit a72086a

File tree

11 files changed

+316
-11
lines changed

11 files changed

+316
-11
lines changed

README.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ npm install @microlink/react-json-view --save
3939
```js
4040
import ReactJsonView from '@microlink/react-json-view'
4141

42-
<ReactJsonView src={{
42+
<ReactJsonView
43+
src={{
4344
string: 'this is a test string',
4445
integer: 42,
4546
array: [1, 2, 3, 'test', NaN],
@@ -53,7 +54,9 @@ import ReactJsonView from '@microlink/react-json-view'
5354
string_number: '1234',
5455
date: new Date(),
5556
bigNumber: new BigNumber('0.0060254656709730629123')
56-
}} />
57+
}}
58+
showComma
59+
/>
5760
```
5861

5962
### API
@@ -84,6 +87,7 @@ import ReactJsonView from '@microlink/react-json-view'
8487
| `displayArrayKey` | `boolean` | `true` | When set to `true`, the index of the elements prefix values. |
8588
| `escapeStrings` | `boolean` | `true` | When set to `true`, strings sequences such as \n, \t, \r, \f will be escaped. |
8689
| `bigNumber` | `Class` | `null` | A custom class for handling large numbers. The class should have a constructor that accepts a numeric string/value and a `name` property for display purposes. You can use existing libraries like `bignumber.js`, `decimal.js`, `big.js`, or provide your own implementation. |
90+
| `showComma` | `boolean` | `true` | When set to `true`, commas are displayed between object properties and array elements for better readability. Interactive tools (clipboard, edit, delete icons) appear after the comma when hovering over JSON elements. |
8791

8892
#### Callbacks
8993

dev-server/src/index.js

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,53 @@ ReactDom.render(
6464
return false
6565
}}
6666
defaultValue=''
67+
showComma={true}
68+
/>
69+
70+
<br />
71+
72+
{/* Same example without commas for comparison */}
73+
<JsonViewer
74+
bigNumber={BigNumber}
75+
sortKeys
76+
style={{ padding: '30px', backgroundColor: 'white' }}
77+
src={getExampleJson1()}
78+
quotesOnKeys={false}
79+
collapseStringsAfterLength={12}
80+
onEdit={e => {
81+
console.log('edit callback', e)
82+
if (e.new_value == 'error') {
83+
return false
84+
}
85+
}}
86+
onDelete={e => {
87+
console.log('delete callback', e)
88+
}}
89+
onAdd={e => {
90+
console.log('add callback', e)
91+
if (e.new_value == 'error') {
92+
return false
93+
}
94+
}}
95+
onSelect={e => {
96+
console.log('select callback', e)
97+
console.log(e.namespace)
98+
}}
99+
displayObjectSize={true}
100+
name={'dev-server (no commas)'}
101+
enableClipboard={copy => {
102+
console.log('you copied to clipboard!', copy)
103+
}}
104+
shouldCollapse={({ src, namespace, type }) => {
105+
if (type === 'array' && src.indexOf('test') > -1) {
106+
return true
107+
} else if (namespace.indexOf('moment') > -1) {
108+
return true
109+
}
110+
return false
111+
}}
112+
defaultValue=''
113+
showComma={false}
67114
/>
68115

69116
<br />
@@ -98,6 +145,7 @@ ReactDom.render(
98145
src.constructor.name === 'Moment'
99146
}
100147
selectOnFocus
148+
showComma={true}
101149
/>
102150

103151
<br />

src/js/components/ArrayGroup.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ export default class extends React.PureComponent {
109109
type='array'
110110
parent_type='array_group'
111111
theme={theme}
112+
showComma={this.props.showComma}
113+
isLast={i === groups - 1}
112114
{...rest}
113115
/>
114116
)

src/js/components/DataTypes/Object.js

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,6 @@ class RjvObject extends React.PureComponent {
144144
<span {...Theme(theme, 'brace')}>
145145
{object_type === 'array' ? '[' : '{'}
146146
</span>
147-
{expanded ? this.getObjectMetaData(src) : null}
148147
</span>
149148
)
150149
}
@@ -167,7 +166,6 @@ class RjvObject extends React.PureComponent {
167166
{object_type === 'array' ? '[' : '{'}
168167
</span>
169168
</span>
170-
{expanded ? this.getObjectMetaData(src) : null}
171169
</span>
172170
)
173171
}
@@ -185,6 +183,8 @@ class RjvObject extends React.PureComponent {
185183
theme,
186184
jsvRoot,
187185
iconStyle,
186+
showComma,
187+
isLast,
188188
...rest
189189
} = this.props
190190

@@ -222,8 +222,13 @@ class RjvObject extends React.PureComponent {
222222
>
223223
{object_type === 'array' ? ']' : '}'}
224224
</span>
225-
{expanded ? null : this.getObjectMetaData(src)}
226225
</span>
226+
{showComma && !isLast && !jsvRoot && (
227+
<span {...Theme(theme, 'comma')}>
228+
,
229+
</span>
230+
)}
231+
{this.getObjectMetaData(src)}
227232
</div>
228233
)
229234
}
@@ -234,7 +239,8 @@ class RjvObject extends React.PureComponent {
234239
parent_type,
235240
index_offset,
236241
groupArraysAfterLength,
237-
namespace
242+
namespace,
243+
showComma,
238244
} = this.props
239245
const { object_type } = this.state
240246
const elements = []
@@ -244,8 +250,9 @@ class RjvObject extends React.PureComponent {
244250
keys = keys.sort()
245251
}
246252

247-
keys.forEach(name => {
253+
keys.forEach((name, index) => {
248254
variable = new JsonVariable(name, variables[name], props.bigNumber)
255+
const isLast = index === keys.length - 1
249256

250257
if (parent_type === 'array_group' && index_offset) {
251258
variable.name = parseInt(variable.name) + index_offset
@@ -260,6 +267,8 @@ class RjvObject extends React.PureComponent {
260267
src={variable.value}
261268
namespace={namespace.concat(variable.name)}
262269
parent_type={object_type}
270+
isLast={isLast}
271+
showComma={showComma}
263272
{...props}
264273
/>
265274
)
@@ -282,6 +291,8 @@ class RjvObject extends React.PureComponent {
282291
namespace={namespace.concat(variable.name)}
283292
type='array'
284293
parent_type={object_type}
294+
isLast={isLast}
295+
showComma={showComma}
285296
{...props}
286297
/>
287298
)
@@ -294,6 +305,8 @@ class RjvObject extends React.PureComponent {
294305
singleIndent={SINGLE_INDENT}
295306
namespace={namespace}
296307
type={this.props.type}
308+
isLast={isLast}
309+
showComma={showComma}
297310
{...props}
298311
/>
299312
)

src/js/components/VariableEditor.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,9 @@ class VariableEditor extends React.PureComponent {
5757
onSelect,
5858
displayArrayKey,
5959
quotesOnKeys,
60-
keyModifier
60+
keyModifier,
61+
showComma,
62+
isLast
6163
} = this.props
6264
const { editMode } = this.state
6365
return (
@@ -126,6 +128,11 @@ class VariableEditor extends React.PureComponent {
126128
>
127129
{this.getValue(variable, editMode)}
128130
</div>
131+
{showComma && !isLast && (
132+
<span {...Theme(theme, 'comma')}>
133+
,
134+
</span>
135+
)}
129136
{enableClipboard
130137
? (
131138
<CopyToClipboard

src/js/index.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ class ReactJsonView extends React.PureComponent {
6060
displayArrayKey: true,
6161
selectOnFocus: false,
6262
keyModifier: e => e.metaKey || e.ctrlKey,
63-
bigNumber: null
63+
bigNumber: null,
64+
showComma: true
6465
}
6566

6667
// will trigger whenever setState() is called, or parent passes in new props.

src/js/themes/getStyle.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,13 @@ const getDefaultThemeStyling = theme => {
386386
color: colors.validationFailure.iconColor,
387387
fontSize: constants.iconFontSize,
388388
transform: 'rotate(45deg)'
389+
},
390+
comma: {
391+
display: 'inline-block',
392+
color: constants.commaColor,
393+
fontSize: constants.commaFontSize,
394+
marginRight: constants.commaMarginRight,
395+
cursor: 'default'
389396
}
390397
}
391398
}

src/js/themes/styleConstants.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,5 +91,9 @@ export default {
9191
addKeyModalWidth: '200px',
9292
addKeyModalMargin: 'auto',
9393
addKeyModalPadding: '10px',
94-
addKeyModalRadius: '3px'
95-
}
94+
addKeyModalRadius: '3px',
95+
96+
commaColor: '#666',
97+
commaFontSize: '12px',
98+
commaMarginRight: '4px'
99+
};

test/tests/js/Index-test.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,4 +128,48 @@ describe('<Index />', function () {
128128
)
129129
expect(wrapper.find('.object-size')).to.have.length(1)
130130
})
131+
132+
it('should show commas when showComma is true', function () {
133+
const wrapper = render(
134+
<Index
135+
src={{
136+
first: 'first property',
137+
second: 'second property',
138+
third: 'third property'
139+
}}
140+
showComma
141+
/>
142+
)
143+
// Check that commas are present in the rendered output
144+
expect(wrapper.text()).to.include(',')
145+
})
146+
147+
it('should not show commas when showComma is false', function () {
148+
const wrapper = render(
149+
<Index
150+
src={{
151+
first: 'first property',
152+
second: 'second property',
153+
third: 'third property'
154+
}}
155+
showComma={false}
156+
/>
157+
)
158+
// Check that commas are not present in the rendered output
159+
expect(wrapper.text()).to.not.include(',')
160+
})
161+
162+
it('should default to showing commas when showComma is not specified', function () {
163+
const wrapper = render(
164+
<Index
165+
src={{
166+
first: 'first property',
167+
second: 'second property',
168+
third: 'third property'
169+
}}
170+
/>
171+
)
172+
// Check that commas are present by default
173+
expect(wrapper.text()).to.include(',')
174+
})
131175
})

test/tests/js/components/DataTypes/Object-test.js

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,4 +373,97 @@ describe('<JsonObject />', function () {
373373
)
374374
expect(wrapper.text()).to.equal('"":{"d":"d""b":"b""a":"a""c":"c"}')
375375
})
376+
377+
it('Object should show comma when showComma is true and not last element', function () {
378+
let src = {
379+
prop1: 1,
380+
prop2: 2
381+
}
382+
383+
const wrapper = shallow(
384+
<JsonObject
385+
src={src}
386+
theme='rjv-default'
387+
namespace={['root']}
388+
rjvId={rjvId}
389+
showComma
390+
isLast={false}
391+
collapsed={false}
392+
indentWidth={1}
393+
depth={1}
394+
type='object'
395+
/>
396+
)
397+
expect(wrapper.find('span').someWhere(node => node.text() === ',')).to.be.true
398+
})
399+
400+
it('Object should not show comma when showComma is false', function () {
401+
let src = {
402+
prop1: 1,
403+
prop2: 2
404+
}
405+
406+
const wrapper = shallow(
407+
<JsonObject
408+
src={src}
409+
theme='rjv-default'
410+
namespace={['root']}
411+
rjvId={rjvId}
412+
showComma={false}
413+
isLast={false}
414+
collapsed={false}
415+
indentWidth={1}
416+
depth={1}
417+
type='object'
418+
/>
419+
)
420+
expect(wrapper.find('span').someWhere(node => node.text() === ',')).to.be.false
421+
})
422+
423+
it('Object should not show comma when isLast is true', function () {
424+
let src = {
425+
prop1: 1,
426+
prop2: 2
427+
}
428+
429+
const wrapper = shallow(
430+
<JsonObject
431+
src={src}
432+
theme='rjv-default'
433+
namespace={['root']}
434+
rjvId={rjvId}
435+
showComma
436+
isLast
437+
collapsed={false}
438+
indentWidth={1}
439+
depth={1}
440+
type='object'
441+
/>
442+
)
443+
expect(wrapper.find('span').someWhere(node => node.text() === ',')).to.be.false
444+
})
445+
446+
it('Object should not show comma when jsvRoot is true', function () {
447+
let src = {
448+
prop1: 1,
449+
prop2: 2
450+
}
451+
452+
const wrapper = shallow(
453+
<JsonObject
454+
src={src}
455+
theme='rjv-default'
456+
namespace={['root']}
457+
rjvId={rjvId}
458+
showComma
459+
isLast={false}
460+
jsvRoot
461+
collapsed={false}
462+
indentWidth={1}
463+
depth={1}
464+
type='object'
465+
/>
466+
)
467+
expect(wrapper.find('span').someWhere(node => node.text() === ',')).to.be.false
468+
})
376469
})

0 commit comments

Comments
 (0)