1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
import _ from 'lodash';
import type { ArrayDifference, Difference, ObjectDifference } from '../json-diff.types';
import { useCopy } from '@/composable/copy';
export function DiffRootViewer({ diff }: { diff: Difference }) {
return (
<div class={'diffs-viewer'}>
<ul>{DiffViewer({ diff, showKeys: false })}</ul>
</div>
);
}
function DiffViewer({ diff, showKeys = true }: { diff: Difference; showKeys?: boolean }) {
const { type, status } = diff;
if (status === 'updated') {
return ComparisonViewer({ diff, showKeys });
}
if (type === 'array') {
return ChildrenViewer({ diff, showKeys, showChildrenKeys: false, openTag: '[', closeTag: ']' });
}
if (type === 'object') {
return ChildrenViewer({ diff, showKeys, openTag: '{', closeTag: '}' });
}
return LineDiffViewer({ diff, showKeys });
}
function LineDiffViewer({ diff, showKeys }: { diff: Difference; showKeys?: boolean }) {
const { value, key, status, oldValue } = diff;
const valueToDisplay = status === 'removed' ? oldValue : value;
return (
<li>
<span class={[status, 'result']}>
{showKeys && (
<>
<span class={'key'}>{key}</span>
{': '}
</>
)}
{Value({ value: valueToDisplay, status })}
</span>
,
</li>
);
}
function ComparisonViewer({ diff, showKeys }: { diff: Difference; showKeys?: boolean }) {
const { value, key, oldValue } = diff;
return (
<li class={'updated-line'}>
{showKeys && (
<>
<span class={'key'}>{key}</span>
{': '}
</>
)}
{Value({ value: oldValue, status: 'removed' })}
{Value({ value, status: 'added' })},
</li>
);
}
function ChildrenViewer({
diff,
openTag,
closeTag,
showKeys,
showChildrenKeys = true,
}: {
diff: ArrayDifference | ObjectDifference
showKeys: boolean
showChildrenKeys?: boolean
openTag: string
closeTag: string
}) {
const { children, key, status, type } = diff;
return (
<li>
<div class={[type, status]} style={{ display: 'inline-block' }}>
{showKeys && (
<>
<span class={'key'}>{key}</span>
{': '}
</>
)}
{openTag}
{children.length > 0 && <ul>{children.map(diff => DiffViewer({ diff, showKeys: showChildrenKeys }))}</ul>}
{`${closeTag},`}
</div>
</li>
);
}
function formatValue(value: unknown) {
if (_.isNull(value)) {
return 'null';
}
return JSON.stringify(value);
}
function Value({ value, status }: { value: unknown; status: string }) {
const formatedValue = formatValue(value);
const { copy } = useCopy({ source: formatedValue });
return (
<span class={['value', status]} onClick={copy}>
{formatedValue}
</span>
);
}
|