Repository: RexSkz/json-diff-kit Branch: main Commit: 8025c5e482fc Files: 75 Total size: 182.5 KB Directory structure: gitextract_zb8i52eb/ ├── .editorconfig ├── .eslintignore ├── .eslintrc.cjs ├── .github/ │ └── workflows/ │ ├── pages.yml │ └── test.yml ├── .gitignore ├── .npmignore ├── .npmrc ├── .stylelintrc.js ├── .swcrc ├── LICENSE ├── README.md ├── bin/ │ ├── examples/ │ │ ├── after.json │ │ ├── before.json │ │ └── output.diff │ └── jsondiff.cjs ├── jest.config.js ├── package.json ├── playground/ │ ├── docs.less │ ├── docs.tsx │ ├── generated-code.tsx │ ├── index.less │ ├── index.tsx │ ├── initial-values.ts │ ├── js-stringify.ts │ ├── label.less │ ├── label.tsx │ ├── playground.less │ └── playground.tsx ├── rollup.config.cli.mjs ├── rollup.config.mjs ├── rollup.config.pages.mjs ├── src/ │ ├── cli/ │ │ ├── index.ts │ │ ├── show-in-terminal.ts │ │ └── write-to-file.ts │ ├── declares.d.ts │ ├── differ.spec.ts │ ├── differ.ts │ ├── index.ts │ ├── utils/ │ │ ├── array-bracket-utils.ts │ │ ├── calculate-placeholder-height.ts │ │ ├── clean-fields.ts │ │ ├── cmp.spec.ts │ │ ├── cmp.ts │ │ ├── concat.spec.ts │ │ ├── concat.ts │ │ ├── detect-circular.ts │ │ ├── diff-array-compare-key.ts │ │ ├── diff-array-lcs.ts │ │ ├── diff-array-normal.ts │ │ ├── diff-object-with-array-support.ts │ │ ├── diff-object.ts │ │ ├── find-visible-lines.ts │ │ ├── format-value.spec.ts │ │ ├── format-value.ts │ │ ├── get-inline-diff.ts │ │ ├── get-inline-syntax-highlight.ts │ │ ├── get-segments.ts │ │ ├── get-type.spec.ts │ │ ├── get-type.ts │ │ ├── is-equal.ts │ │ ├── pretty-append-lines.ts │ │ ├── segment-util.ts │ │ ├── shallow-similarity.spec.ts │ │ ├── shallow-similarity.ts │ │ ├── sort-inner-arrays.spec.ts │ │ ├── sort-inner-arrays.ts │ │ ├── sort-keys.ts │ │ ├── stringify.spec.ts │ │ └── stringify.ts │ ├── viewer-monokai.less │ ├── viewer.less │ └── viewer.tsx ├── tsconfig.build.json └── tsconfig.json ================================================ FILE CONTENTS ================================================ ================================================ FILE: .editorconfig ================================================ root = true [*] insert_final_newline = true charset = utf-8 trim_trailing_whitespace = true end_of_line = lf [*.{ts,js,json}] indent_style = space indent_size = 2 ================================================ FILE: .eslintignore ================================================ dist/ node_modules/ typings/ ================================================ FILE: .eslintrc.cjs ================================================ module.exports = { parser: '@typescript-eslint/parser', parserOptions: { project: true, tsconfigRootDir: __dirname, }, extends: [ 'plugin:rexskz/default', ], globals: { __VERSION__: 'readonly', }, }; ================================================ FILE: .github/workflows/pages.yml ================================================ name: GitHub Pages on: push: branches: - main jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v1 - run: | git config user.name "Rex Zeng" git config user.email "rex@rexskz.info" git checkout -b gh-pages npm install -g pnpm pnpm i pnpm build:pages echo "json-diff-kit.js.org" > docs/CNAME git add docs -f git commit -m Pages git remote set-url origin "https://x-access-token:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" git push -f origin gh-pages env: GITHUB_TOKEN: ${{ secrets.github_token }} ================================================ FILE: .github/workflows/test.yml ================================================ name: Unit Test on: push: branches: - main jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v1 - run: | npm install -g pnpm pnpm i pnpm test curl -Os https://uploader.codecov.io/latest/linux/codecov chmod +x codecov ./codecov env: GITHUB_TOKEN: ${{ secrets.github_token }} ================================================ FILE: .gitignore ================================================ # Logs logs *.log npm-debug.log* yarn-debug.log* yarn-error.log* lerna-debug.log* # Diagnostic reports (https://nodejs.org/api/report.html) report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json # Runtime data pids *.pid *.seed *.pid.lock # Directory for instrumented libs generated by jscoverage/JSCover lib-cov # Coverage directory used by tools like istanbul coverage *.lcov # nyc test coverage .nyc_output # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) .grunt # Bower dependency directory (https://bower.io/) bower_components # node-waf configuration .lock-wscript # Compiled binary addons (https://nodejs.org/api/addons.html) build/Release # Dependency directories node_modules/ jspm_packages/ # TypeScript v1 declaration files typings/ # TypeScript cache *.tsbuildinfo # Optional npm cache directory .npm # Optional eslint cache .eslintcache # Microbundle cache .rpt2_cache/ .rts2_cache_cjs/ .rts2_cache_es/ .rts2_cache_umd/ # Optional REPL history .node_repl_history # Output of 'npm pack' *.tgz # Yarn Integrity file .yarn-integrity # dotenv environment variables file .env .env.test # parcel-bundler cache (https://parceljs.org/) .cache # Next.js build output .next # Nuxt.js build / generate output .nuxt dist # Gatsby files .cache/ # Comment in the public line in if your project uses Gatsby and *not* Next.js # https://nextjs.org/blog/next-9-1#public-directory-support # public # vuepress build output .vuepress/dist # Serverless directories .serverless/ # FuseBox cache .fusebox/ # DynamoDB Local files .dynamodb/ # TernJS port file .tern-port codecov .vscode docs/ ================================================ FILE: .npmignore ================================================ .cache .editorconfig .eslintrc.cjs .eslintignore .github .gitignore .npmignore .npmrc .stylelintrc.js .swcrc .travis.yml coverage docs esbuild.mjs jest.config.js node_modules playground pnpm-lock.yaml preview.png preview-cli.png rollup.*.ts src tsconfig.json tsconfig.*.json ================================================ FILE: .npmrc ================================================ use-lockfile-v6 = true ================================================ FILE: .stylelintrc.js ================================================ module.exports = { extends: 'stylelint-plugin-rexskz', }; ================================================ FILE: .swcrc ================================================ { "$schema": "https://json.schemastore.org/swcrc", "jsc": { "parser": { "syntax": "typescript" }, "target": "es2020", "loose": true, "keepClassNames": true }, "minify": false } ================================================ FILE: LICENSE ================================================ MIT License Copyright (c) 2022 Rex Zeng Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ # JSON Diff Kit [![NPM version][npm-image]][npm-url] [![Downloads][download-badge]][npm-url] [![Codecov](https://codecov.io/gh/RexSkz/json-diff-kit/branch/main/graph/badge.svg?token=8YRG3M4WTO)](https://codecov.io/gh/RexSkz/json-diff-kit) A better JSON differ & viewer library written in TypeScript. [Try it out in the playground!](https://json-diff-kit.js.org/) ## Install You can install `json-diff-kit` via various package managers. ```sh # using npm npm i json-diff-kit --save # using yarn yarn add json-diff-kit # using pnpm pnpm add json-diff-kit ``` ## Quick Start To generate the diff data: ```ts import { Differ } from 'json-diff-kit'; // or if you are using vue, you can import the differ only import Differ from 'json-diff-kit/dist/differ'; // the two JS objects const before = { a: 1, b: 2, d: [1, 5, 4], e: ['1', 2, { f: 3, g: null, h: [5], i: [] }, 9], m: [], q: 'JSON diff can\'t be possible', r: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.', s: 1024, }; const after = { b: 2, c: 3, d: [1, 3, 4, 6], e: ['1', 2, 3, { f: 4, g: false, i: [7, 8] }, 10], j: { k: 11, l: 12 }, m: [ { n: 1, o: 2 }, { p: 3 }, ], q: 'JSON diff is possible!', r: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed quasi architecto beatae incididunt ut labore et dolore magna aliqua.', s: '1024', }; // all configs are optional const differ = new Differ({ detectCircular: true, // default `true` maxDepth: Infinity, // default `Infinity` showModifications: true, // default `true` arrayDiffMethod: 'lcs', // default `"normal"`, but `"lcs"` may be more useful }); // you may want to use `useMemo` (for React) or `computed` (for Vue) // to avoid redundant computations const diff = differ.diff(before, after); console.log(diff); ``` You can use your own component to visualize the `diff` data, or use the built-in viewer: ```tsx import { Viewer } from 'json-diff-kit'; import type { DiffResult } from 'json-diff-kit'; import 'json-diff-kit/dist/viewer.css'; interface PageProps { diff: [DiffResult[], DiffResult[]]; } const Page: React.FC = props => { return ( ); }; ``` The result is here: ![The result (using LCS array diff method).](./preview.png) ## Other Version of Viewer Here is an experimental [Vue version](https://github.com/RexSkz/json-diff-kit-vue) of the `Viewer` component. ## More Complex Usages Please check the [playground page](https://json-diff-kit.js.org/), where you can adjust nearly all parameters and see the result. ## CLI Tool You can use the CLI tool to generate the diff data from two JSON files. Please install the package `terminal-kit` before using it. ```bash pnpm add terminal-kit # or make sure it's already installed in your project # Compare two JSON files, output the diff data to the terminal. # You can navigate it using keyboard like `less`. jsondiff run path/to/before.json path/to/after.json # Output the diff data to a file. # Notice there will be no side-by-side view since it's not a TTY. jsondiff run path/to/before.json path/to/after.json -o path/to/result.diff # Use a custom configuration file and output the diff data to a file. jsondiff run path/to/before.json path/to/after.json -c path/to/config.json -o path/to/result.diff # Print the help message. jsondiff --help jsondiff run --help ``` ![A screenshot when using CLI.](./preview-cli.png) ## Algorithm Details Please refer to the article [JSON Diff Kit: A Combination of Several Simple Algorithms](https://blog.rexskz.info/json-diff-kit-a-combination-of-several-simple-algorithms.html?cc_lang=en). ## Features & Roadmap - [x] Provide a `Differ` class and a `Viewer` component - [x] Merge "remove & add" at the same place as a modification - [x] Support inline diffing by word instead of by character - [x] Generate code directly in the demo page (covered by playground) - [x] Optimise `Viewer` performance by adding virtual scrolling - [x] Add CLI tool - [x] Provide a Vue version of `Viewer` - [ ] Improve unit tests ## License MIT [npm-url]: https://npmjs.org/package/json-diff-kit [npm-image]: https://img.shields.io/npm/v/json-diff-kit.svg [download-badge]: https://img.shields.io/npm/dm/json-diff-kit.svg ================================================ FILE: bin/examples/after.json ================================================ { "b": 2, "c": 3, "d": [ 1, 3, 4, 6 ], "e": [ "1", 2, 3, { "f": 4, "g": false, "i": [ 7, 8 ] }, 10 ], "j": { "k": 11, "l": 12 }, "m": [ { "n": 1, "o": 2 }, { "p": 3 } ], "q": "JSON diff is possible!", "r": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed quasi architecto beatae incididunt ut labore et dolore magna aliqua.", "s": "1024" } ================================================ FILE: bin/examples/before.json ================================================ { "a": 1, "b": 2, "d": [ 1, 5, 4 ], "e": [ "1", 2, { "f": 3, "g": null, "h": [ 5 ], "i": [] }, 9 ], "m": [], "q": "JSON diff can't be possible", "r": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", "s": 1024 } ================================================ FILE: bin/examples/output.diff ================================================ { - "a": 1, "b": 2, + "c": 3, "d": [ 1, - 5, + 3, 4 + 6 ], "e": [ "1", 2, + 3, { - "f": 3, - "g": null, - "h": [ - 5 - ], + "f": 4, + "g": false, "i": [ + 7, + 8 ] }, - 9 + 10 ], + "j": { + "k": 11, + "l": 12 + }, "m": [ + { + "n": 1, + "o": 2 + }, + { + "p": 3 + } ], - "q": "JSON diff can't be possible", - "r": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", - "s": 1024 + "q": "JSON diff is possible!", + "r": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed quasi architecto beatae incididunt ut labore et dolore magna aliqua.", + "s": "1024" } ================================================ FILE: bin/jsondiff.cjs ================================================ #!/usr/bin/env node require('../dist/cjs/cli/index.js') ================================================ FILE: jest.config.js ================================================ module.exports = { transform: { '^.+\\.(t|j)sx?$': [ '@swc/jest', ], }, }; ================================================ FILE: package.json ================================================ { "name": "json-diff-kit", "version": "1.0.35", "description": "A better JSON differ & viewer.", "main": "dist/cjs/index.js", "module": "dist/index.js", "typings": "typings", "bin": { "jsondiff": "bin/jsondiff.cjs" }, "sideEffects": [ "*.css" ], "exports": { ".": { "import": "./dist/index.js", "require": "./dist/cjs/index.js", "types": "./typings/index.d.ts" }, "./*": { "import": "./dist/*", "require": "./dist/cjs/*", "types": "./typings/*.d.ts" }, "./dist/*": { "import": "./dist/*", "require": "./dist/cjs/*", "types": "./typings/*.d.ts" } }, "scripts": { "start": "cross-env rollup -c rollup.config.pages.mjs -w", "dev": "cross-env pnpm start", "lint:eslint": "eslint ./{src,playground}/**/*.{ts,tsx} --quiet", "lint:stylelint": "stylelint '**/*.{css,less}' --fix", "test": "cross-env jest --coverage", "build": "cross-env pnpm build:ts && pnpm build:less && pnpm build:typings", "build:ts": "cross-env rollup -c && rollup -c rollup.config.cli.mjs", "build:typings": "cross-env tsc -p tsconfig.build.json", "build:less": "cross-env lessc src/viewer.less dist/viewer.css && lessc src/viewer-monokai.less dist/viewer-monokai.css", "build:pages": "cross-env NODE_ENV=production BASEDIR=docs rollup -c rollup.config.pages.mjs", "prepublish": "cross-env pnpm build" }, "repository": { "type": "git", "url": "git+https://github.com/RexSkz/json-diff-kit.git" }, "keywords": [ "json", "diff", "view", "kit" ], "author": "Rex Zeng ", "license": "MIT", "bugs": { "url": "https://github.com/RexSkz/json-diff-kit/issues" }, "homepage": "https://github.com/RexSkz/json-diff-kit#readme", "devDependencies": { "@rollup/plugin-commonjs": "^21.0.1", "@rollup/plugin-html": "^0.2.4", "@rollup/plugin-node-resolve": "^13.1.3", "@rollup/plugin-replace": "^5.0.2", "@rollup/plugin-swc": "^0.4.0", "@swc/cli": "^0.5.2", "@swc/core": "^1.10.1", "@swc/jest": "^0.2.37", "@types/jest": "^29.5.14", "@types/lodash": "^4.14.191", "@types/node": "^20.11.16", "@types/prismjs": "^1.26.0", "@types/react": "^17.0.38", "@types/react-dom": "^17.0.11", "@types/terminal-kit": "^2.5.6", "cross-env": "^7.0.3", "eslint": "^8", "eslint-plugin-rexskz": "1.0.0", "fork-me-on-github": "^1.0.6", "jest": "^29.7.0", "less": "^4.1.3", "prismjs": "^1.29.0", "react": "^17.0.2", "react-dom": "^17.0.2", "rollup": "^4.28.1", "rollup-plugin-less": "^1.1.3", "rollup-plugin-livereload": "^2.0.5", "rollup-plugin-serve": "^1.1.1", "rollup-plugin-styles": "^4.0.0", "stylelint": "^15", "stylelint-plugin-rexskz": "1.0.0-alpha.3", "typescript": "^4.5.5" }, "dependencies": { "commander": "^11.1.0", "fast-myers-diff": "^3.0.1", "lodash": "^4.17.21", "prompts": "^2.4.2" }, "optionalDependencies": { "terminal-kit": "^3.0.1" }, "packageManager": "pnpm@8.15.7+sha256.50783dd0fa303852de2dd1557cd4b9f07cb5b018154a6e76d0f40635d6cee019" } ================================================ FILE: playground/docs.less ================================================ .demo-root { position: relative; width: 100%; max-width: 1200px; box-sizing: border-box; padding: 1em 2em; margin: auto; background: #fff; box-shadow: 0 0 30px rgba(0, 0, 0, 0.01); .statistics { img { margin-right: 8px; } } .banner { display: inline-block; padding: 8px 16px; border-radius: 4px; background: #000; color: #fff; cursor: pointer; &:hover { background: #333; text-decoration: underline; } } blockquote { margin: 0 0 1em; line-height: 24px; } .diff-config, .view-config { form { overflow: hidden; & > label { display: flex; align-items: center; padding: 0 4px; border-radius: 4px; margin-right: 8px; background: #e5e6e9; font-weight: 700; user-select: none; span { margin-left: 1em; font-weight: 400; } input, select { margin-left: 8px; } input[type="number"] { min-width: 8em; } } } } .diff-result .json-diff-viewer { box-sizing: border-box; padding: 1em; border: 1px solid; border-radius: 4px; margin-top: 1em; } .demo-footer { padding: 2em 0; border-top: 1px dashed; margin: 4em 0 0; text-align: center; } } ================================================ FILE: playground/docs.tsx ================================================ /* eslint-disable max-len, react/no-unescaped-entities */ import React from 'react'; import _ForkMeOnGithub from 'fork-me-on-github'; import { Differ, Viewer } from '../src'; import type { DifferOptions } from '../src/differ'; import { InlineDiffOptions } from '../src/utils/get-inline-diff'; import type { ViewerProps } from '../src/viewer'; import './docs.less'; import { updateInitialValues } from './initial-values'; interface PropTypes { onSwitch: () => void; } const ForkMeOnGithub = _ForkMeOnGithub.default; const Docs: React.FC = props => { // differ props const [detectCircular] = React.useState(true); const [maxDepth, setMaxDepth] = React.useState(Infinity); const [showModifications, setShowModifications] = React.useState(true); const [arrayDiffMethod, setArrayDiffMethod] = React.useState('lcs'); const [ignoreCase, setIgnoreCase] = React.useState(false); const [recursiveEqual, setRecursiveEqual] = React.useState(true); const [preserveKeyOrder, setPreserveKeyOrder] = React.useState(undefined); const [compareKey, setCompareKey] = React.useState(''); // viewer props const [indent, setIndent] = React.useState(4); const [lineNumbers, setLineNumbers] = React.useState(true); const [highlightInlineDiff, setHighlightInlineDiff] = React.useState(true); const [inlineDiffMode, setInlineDiffMode] = React.useState('word'); const [inlineDiffSeparator, setInlineDiffSeparator] = React.useState(' '); const [hideUnchangedLines, setHideUnchangedLines] = React.useState(true); const [syntaxHighlight, setSyntaxHighlight] = React.useState(true); const [useVirtual, setUseVirtual] = React.useState(false); const differOptions = React.useMemo(() => ({ detectCircular, maxDepth, showModifications, arrayDiffMethod, ignoreCase, recursiveEqual, preserveKeyOrder, compareKey, }), [ detectCircular, maxDepth, showModifications, arrayDiffMethod, ignoreCase, recursiveEqual, preserveKeyOrder, compareKey, ]); const differ = React.useMemo(() => new Differ(differOptions), [differOptions]); const [before1] = React.useState({ a: 1, b: 2, d: [1, 5, 4], e: ['1', 2, { f: 3, g: null, h: [5], i: [] }, 9], m: [], q: 'JSON diff can\'t be possible', r: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.', s: 1024, }); const [after1] = React.useState({ b: 2, c: 3, d: [1, 3, 4, 6], e: ['1', 2, 3, { f: 4, g: false, i: [7, 8] }, 10], j: { k: 11, l: 12 }, m: [ { n: 1, o: 2 }, { p: 3 }, ], q: 'JSON diff is possible!', r: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed quasi architecto beatae incididunt ut labore et dolore magna aliqua.', s: '1024', }); const diff1 = React.useMemo(() => differ.diff(before1, after1), [differ, before1, after1]); const [before2] = React.useState([2, 4, 3]); const [after2] = React.useState([2, 5, 4, 3, 1]); const diff2 = React.useMemo(() => differ.diff(before2, after2), [differ, before2, after2]); const [before3] = React.useState({ a: 1, b: [2] }); const [after3] = React.useState(666); const diff3 = React.useMemo(() => differ.diff(before3, after3), [differ, before3, after3]); const [before4] = React.useState(233); const [after4] = React.useState(666); const diff4 = React.useMemo(() => differ.diff(before4, after4), [differ, before4, after4]); const [before5] = React.useState([0, 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]); const [after5] = React.useState([0, 1, 2, 3, 4, 5, 6, 7, 8, 99, 10, 11, 12, 13, 14, 15, 16, 17, 1818, 1919, 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]); const diff5 = React.useMemo(() => differ.diff(before5, after5), [differ, before5, after5]); const [before6] = React.useState([ { text: 'hello world' }, ]); const [after6] = React.useState([ { text: 'above' }, { text: 'hello world' }, { text: 'below' }, ]); const diff6 = React.useMemo(() => differ.diff(before6, after6), [differ, before6, after6]); const [before7] = React.useState({ a: undefined, b: 123n, c: { c1: Symbol('foo'), c2: Symbol('bar'), }, d: () => alert(1), e: Infinity, f: NaN, h: [undefined, 123n, Symbol('foo'), Symbol('bar'), () => alert(1), Infinity, NaN, -Infinity], }); const [after7] = React.useState({ a: undefined, b: 123n, c: { c1: Symbol('foo'), c3: Symbol('baz'), }, d: () => alert(2), e: Infinity, f: NaN, g: -Infinity, h: [undefined, 123n, Symbol('foo'), Symbol('baz'), () => alert(2), Infinity, NaN, -Infinity], }); const diff7 = React.useMemo(() => differ.diff(before7, after7), [differ, before7, after7]); const openInPlayground = (l: unknown, r: unknown) => { updateInitialValues(JSON.stringify(l, null, 2), JSON.stringify(r, null, 2)); props.onSwitch(); }; const viewerCommonProps: Partial = { indent, lineNumbers, highlightInlineDiff, inlineDiffOptions: { mode: inlineDiffMode, wordSeparator: inlineDiffSeparator || '', }, hideUnchangedLines, syntaxHighlight: syntaxHighlight ? { theme: 'monokai' } : false, virtual: useVirtual ? {} : false, }; return (

JSON Diff Kit