json-diff-react
Version:
A React.js component based on the json-diff package
136 lines (135 loc) • 5.91 kB
JavaScript
import { jsx as _jsx } from "react/jsx-runtime";
// Copied from 'json-diff' with minor modifications.
//
// The 'colorize' function was adapted from console rendering to browser
// rendering - it now returns a JSX.Element.
import { extendedTypeOf, elisionMarker } from './utils';
import React from 'react';
const subcolorizeToCallback = function (options, key, diff, output, color, indent) {
var _a;
let subvalue;
const prefix = key ? `${key}: ` : '';
const subindent = indent + ' ';
const maxElisions = options.maxElisions === undefined ? Infinity : options.maxElisions;
const renderElision = (_a = options.renderElision) !== null && _a !== void 0 ? _a : ((n, max) => (n < max ? [...Array(n)].map(() => '...') : `... (${n} entries)`));
const outputElisions = (n) => {
const elisions = renderElision(n, maxElisions);
if (typeof elisions === 'string') {
output(' ', subindent + elisions);
}
else {
elisions.forEach((x) => {
output(' ', subindent + x);
});
}
};
switch (extendedTypeOf(diff)) {
case 'object':
if ('__old' in diff && '__new' in diff && Object.keys(diff).length === 2) {
subcolorizeToCallback(options, key, diff.__old, output, '-', indent);
return subcolorizeToCallback(options, key, diff.__new, output, '+', indent);
}
else {
output(color, `${indent}${prefix}{`);
// Elisions are added in “json-diff” module depending on the option.
let elisionCount = 0;
for (const subkey of Object.keys(diff)) {
let m;
subvalue = diff[subkey];
// Handle elisions
if (subvalue === elisionMarker) {
elisionCount++;
continue;
}
else if (elisionCount > 0) {
outputElisions(elisionCount);
elisionCount = 0;
}
if ((m = subkey.match(/^(.*)__deleted$/))) {
subcolorizeToCallback(options, m[1], subvalue, output, '-', subindent);
}
else if ((m = subkey.match(/^(.*)__added$/))) {
subcolorizeToCallback(options, m[1], subvalue, output, '+', subindent);
}
else {
subcolorizeToCallback(options, subkey, subvalue, output, color, subindent);
}
}
// Handle elisions
if (elisionCount > 0)
outputElisions(elisionCount);
return output(color, `${indent}}`);
}
case 'array': {
output(color, `${indent}${prefix}[`);
let looksLikeDiff = true;
for (const item of diff) {
if (extendedTypeOf(item) !== 'array' ||
!(item.length === 2 || (item.length === 1 && item[0] === ' ')) ||
!(typeof item[0] === 'string') ||
item[0].length !== 1 ||
![' ', '-', '+', '~'].includes(item[0])) {
looksLikeDiff = false;
}
}
if (looksLikeDiff) {
let op;
let elisionCount = 0;
for ([op, subvalue] of diff) {
if (op === ' ' && subvalue == null) {
elisionCount++;
}
else {
if (elisionCount > 0) {
outputElisions(elisionCount);
}
elisionCount = 0;
if (![' ', '~', '+', '-'].includes(op)) {
throw new Error(`Unexpected op '${op}' in ${JSON.stringify(diff, null, 2)}`);
}
if (op === '~') {
op = ' ';
}
subcolorizeToCallback(options, '', subvalue, output, op, subindent);
}
}
if (elisionCount > 0) {
outputElisions(elisionCount);
}
}
else {
for (subvalue of diff) {
subcolorizeToCallback(options, '', subvalue, output, color, subindent);
}
}
return output(color, `${indent}]`);
}
default:
if (diff === 0 || diff === null || diff === false || diff === '' || diff) {
return output(color, indent + prefix + JSON.stringify(diff));
}
}
};
const colorizeToCallback = (diff, options, output) => subcolorizeToCallback(options, '', diff, output, ' ', '');
export const colorize = function (diff, options = {}, customization) {
const output = [];
colorizeToCallback(diff, options, function (color, line) {
let className;
let style;
if (color === ' ') {
className = customization.unchangedClassName;
style = customization.unchangedLineStyle;
}
else if (color === '+') {
className = customization.additionClassName;
style = customization.additionLineStyle;
}
else {
className = customization.deletionClassName;
style = customization.deletionLineStyle;
}
let renderedLine = (_jsx("div", Object.assign({ className: className, style: style }, { children: line }), output.length));
return output.push(renderedLine);
});
return (_jsx("div", Object.assign({ className: customization.frameClassName, style: customization.frameStyle }, { children: output })));
};