mirror of
https://github.com/CorentinTh/it-tools.git
synced 2025-05-24 02:02:35 -04:00
120 lines
2.8 KiB
TypeScript
120 lines
2.8 KiB
TypeScript
import _ from 'lodash';
|
|
import { useCopy } from '@/composable/copy';
|
|
import type { Difference, ArrayDifference, ObjectDifference } from '../json-diff.types';
|
|
|
|
export const DiffRootViewer = ({ diff }: { diff: Difference }) => {
|
|
return (
|
|
<div class={'diffs-viewer'}>
|
|
<ul>{DiffViewer({ diff, showKeys: false })}</ul>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
const 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 });
|
|
};
|
|
|
|
const 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>
|
|
);
|
|
};
|
|
|
|
const 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>
|
|
);
|
|
};
|
|
|
|
const 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);
|
|
}
|
|
|
|
const 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>
|
|
);
|
|
};
|