Skip to content

Commit d2e75d6

Browse files
authored
feat: enhance function dataType (#81)
1 parent 52c02e2 commit d2e75d6

File tree

4 files changed

+214
-23
lines changed

4 files changed

+214
-23
lines changed

examples/basic/pages/index.tsx

+13-1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ const avatar = 'https://i.imgur.com/1bX5QH6.jpg'
2626
function aPlusB (a: number, b: number) {
2727
return a + b
2828
}
29+
const aPlusBConst = function (a: number, b: number) {
30+
return a + b
31+
}
2932

3033
const loopObject = {
3134
foo: 1,
@@ -71,7 +74,16 @@ const example = {
7174
'second-child': false,
7275
'last-child': null
7376
},
74-
fn: aPlusB,
77+
function: aPlusB,
78+
constFunction: aPlusBConst,
79+
anonymousFunction: function (a: number, b: number) {
80+
return a + b
81+
},
82+
shortFunction: (arg1: any, arg2: any) => console.log(arg1, arg2),
83+
shortLongFunction: (arg1: any, arg2: any) => {
84+
console.log(arg1, arg2)
85+
return '123'
86+
},
7587
string_number: '1234',
7688
timer: 0,
7789
avatar,

src/components/DataKeyPair.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ export const DataKeyPair: React.FC<DataKeyPairProps> = (props) => {
4747
}
4848
return propsEditable
4949
}, [path, propsEditable, storeEditable, value])
50-
const [tempValue, setTempValue] = useState(value)
50+
const [tempValue, setTempValue] = useState(typeof value === 'function' ? () => value : value)
5151
const depth = path.length
5252
const key = path[depth - 1]
5353
const hoverPath = useJsonViewerStore(store => store.hoverPath)
@@ -114,7 +114,7 @@ export const DataKeyPair: React.FC<DataKeyPairProps> = (props) => {
114114
try {
115115
copy(
116116
JSON.stringify(
117-
value,
117+
typeof value === 'function' ? value.toString() : value,
118118
null,
119119
' '
120120
)

src/components/DataTypes/Function.tsx

+40-19
Original file line numberDiff line numberDiff line change
@@ -8,39 +8,55 @@ import { DataTypeLabel } from '../DataTypeLabel'
88
const functionBody = (func: Function) => {
99
const funcString = func.toString()
1010

11-
return funcString.substring(
12-
funcString.indexOf('{', funcString.indexOf(')')) + 1,
13-
funcString.lastIndexOf('}')
14-
)
11+
let isUsualFunction = true;
12+
let parenthesisPos = funcString.indexOf(')');
13+
let arrowPos = funcString.indexOf('=>');
14+
if (arrowPos !== -1 && arrowPos > parenthesisPos) {
15+
isUsualFunction = false
16+
}
17+
if (isUsualFunction) {
18+
return funcString.substring(
19+
funcString.indexOf('{', parenthesisPos) + 1,
20+
funcString.lastIndexOf('}')
21+
)
22+
}
23+
24+
return funcString.substring(funcString.indexOf('=>') + 2)
1525
}
1626

1727
const functionName = (func: Function) => {
18-
return func.toString()
19-
.slice(9, -1)
20-
.replace(/\{[\s\S]+/, '')
28+
let funcString = func.toString();
29+
const isUsualFunction = funcString.indexOf('function') !== -1
30+
if (isUsualFunction) {
31+
return funcString.substring(8, funcString.indexOf('{')).trim();
32+
}
33+
34+
return funcString.substring(0, funcString.indexOf('=>') + 2).trim()
2135
}
2236

2337
const lb = '{'
2438
const rb = '}'
2539

2640
export const PreFunctionType: React.FC<DataItemProps<Function>> = (props) => {
2741
return (
28-
<Box
29-
component='span' className='data-object-start'
30-
sx={{
31-
letterSpacing: 0.5
32-
}}
33-
>
42+
<>
3443
<DataTypeLabel dataType='function'/>
35-
{functionName(props.value)}
36-
{lb}
37-
</Box>
44+
<Box
45+
component='span' className='data-function-start'
46+
sx={{
47+
letterSpacing: 0.5,
48+
}}
49+
>
50+
{functionName(props.value)}
51+
{' '}{lb}
52+
</Box>
53+
</>
3854
)
3955
}
4056

4157
export const PostFunctionType: React.FC<DataItemProps<Function>> = () => {
4258
return (
43-
<Box component='span' className='data-object-end'>
59+
<Box component='span' className='data-function-end'>
4460
{rb}
4561
</Box>
4662
)
@@ -60,10 +76,15 @@ export const FunctionType: React.FC<DataItemProps<Function>> = (props) => {
6076
{props.inspect
6177
? functionBody(props.value)
6278
: (
63-
<Box component='span' className='data-object-body'>
79+
<Box component='span' className='data-function-body'
80+
onClick={() => props.setInspect(true)}
81+
sx={{
82+
'&:hover': {cursor: 'pointer'}
83+
}}
84+
>
6485
...
6586
</Box>
66-
)
87+
)
6788
}
6889
</Box>
6990
)

tests/index.test.tsx

+159-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {fireEvent, render, screen} from '@testing-library/react'
1+
import { fireEvent, render, screen } from '@testing-library/react'
22
import { expectTypeOf } from 'expect-type'
33
import React from 'react'
44
import { describe, expect, it } from 'vitest'
@@ -281,3 +281,161 @@ describe('Expand elements by click on dots', () => {
281281
})
282282
})
283283

284+
285+
describe('test functions', () => {
286+
const func1 = function (...args: any[]) {
287+
console.log(args)
288+
return '111';
289+
}
290+
291+
function func2(...args: any[]) {
292+
console.log(args)
293+
return '222';
294+
}
295+
296+
const dataProvider = [
297+
[
298+
function (...args: any) {
299+
console.log(args)
300+
return '333';
301+
},
302+
`(...args) {`,
303+
`
304+
console.log(args);
305+
return "333";
306+
`
307+
],
308+
[
309+
func1,
310+
`(...args) {`,
311+
`
312+
console.log(args);
313+
return "111";
314+
`
315+
],
316+
[
317+
func2,
318+
`func2(...args) {`,
319+
`
320+
console.log(args);
321+
return "222";
322+
`
323+
],
324+
[
325+
(...args:any) => console.log('555'),
326+
`(...args) => {`,
327+
` console.log("555")`
328+
],
329+
[
330+
(...args:any) => {
331+
console.log(args)
332+
return '666'
333+
},
334+
`(...args) => {`,
335+
` {
336+
console.log(args);
337+
return "666";
338+
}`
339+
],
340+
[
341+
function (a: number, b: number) {
342+
throw Error('Be careful to use the function just as value in useState() hook')
343+
}
344+
,
345+
`(a, b) {`,
346+
`
347+
throw Error("Be careful to use the function just as value in useState() hook");
348+
`
349+
],
350+
[
351+
({prop1, prop2, ...other}:any) => {
352+
console.log(prop1, prop2, other)
353+
return '777'
354+
},
355+
`({
356+
prop1,
357+
prop2,
358+
...other
359+
}) => {`,
360+
` {
361+
console.log(prop1, prop2, other);
362+
return "777";
363+
}`
364+
],
365+
[
366+
{
367+
func: ({prop1, prop2, ...other}:any) => {
368+
console.log(prop1, prop2, other)
369+
return '777'
370+
}
371+
},
372+
`({
373+
prop1,
374+
prop2,
375+
...other
376+
}) => {`,
377+
` {
378+
console.log(prop1, prop2, other);
379+
return "777";
380+
}`
381+
],
382+
[
383+
// @ts-ignore
384+
(function(e,n){return e+n}),
385+
`(e, n) {`,
386+
`
387+
return e + n;
388+
`
389+
],
390+
]
391+
for (let iteration of dataProvider) {
392+
it('render', () => {
393+
const {container} = render(
394+
<JsonViewer
395+
rootName={false}
396+
value={iteration[0]}
397+
/>
398+
)
399+
expect(container.children.length).eq(1)
400+
const functionName = container.getElementsByClassName('data-function-start')
401+
expect(functionName.length).eq(1)
402+
expect(functionName[0].textContent).eq(iteration[1])
403+
404+
const functionBody = container.getElementsByClassName('data-function')
405+
expect(functionBody.length).eq(1)
406+
expect(functionBody[0].textContent).eq(iteration[2])
407+
});
408+
}
409+
})
410+
411+
describe('Expand function by click on dots', () => {
412+
it('render', () => {
413+
const {container, rerender} = render(
414+
<JsonViewer
415+
rootName={false}
416+
value={(e:any) => console.log('it works')}
417+
defaultInspectDepth={0}
418+
/>
419+
)
420+
421+
let elements = container.getElementsByClassName('data-function-body');
422+
expect(elements.length).eq(1)
423+
expect(elements[0].textContent).eq('...')
424+
fireEvent.click(elements[0])
425+
426+
rerender(
427+
<JsonViewer
428+
rootName={false}
429+
value={(e:any) => console.log('it works')}
430+
defaultInspectDepth={0}
431+
/>
432+
)
433+
elements = container.getElementsByClassName('data-function-body');
434+
expect(elements.length).eq(0)
435+
436+
elements = container.getElementsByClassName('data-function');
437+
expect(elements.length).eq(1)
438+
expect(elements[0].children.length).eq(0)
439+
expect(elements[0].textContent).not.eq('...')
440+
})
441+
})

0 commit comments

Comments
 (0)