diff options
author | 2023-04-22 00:49:03 +0200 | |
---|---|---|
committer | 2023-04-23 15:24:20 +0200 | |
commit | 362f2fa280fdab210074e9a7e01dde6187924d29 (patch) | |
tree | 2a17c13e1db19e0b244cda22eabf8e107218f6b9 /src/tools/json-diff/diff-viewer/diff-viewer.models.tsx | |
parent | 61ece2387f7061d67177ee41c35db572ffeb84a7 (diff) | |
download | it-tools-362f2fa280fdab210074e9a7e01dde6187924d29.tar.gz it-tools-362f2fa280fdab210074e9a7e01dde6187924d29.tar.zst it-tools-362f2fa280fdab210074e9a7e01dde6187924d29.zip |
feat(new-tool): diff of two json objects
Diffstat (limited to 'src/tools/json-diff/diff-viewer/diff-viewer.models.tsx')
-rw-r--r-- | src/tools/json-diff/diff-viewer/diff-viewer.models.tsx | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/src/tools/json-diff/diff-viewer/diff-viewer.models.tsx b/src/tools/json-diff/diff-viewer/diff-viewer.models.tsx new file mode 100644 index 0000000..5a19feb --- /dev/null +++ b/src/tools/json-diff/diff-viewer/diff-viewer.models.tsx @@ -0,0 +1,119 @@ +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> + ); +}; |