jsondiffpatch

repository·master·Indexed 26 days ago

https://github.com/benjamine/jsondiffpatch

A library for computing and applying deltas between JavaScript objects. It features deep diffing, smart array diffing using LCS, and support for various output formats including JSON Patch, visual HTML diffs, and annotated JSON. The package also includes diff-mcp, an MCP server that allows comparing text and structured data (JSON, JSON5, YAML, TOML, XML, and HTML) with outputs in text, JSON, and JSONPatch.

Tokens
7.9K
Snippets
20
Records
47
Agent score
90%

What's inside jsondiffpatch

  1. Overview of diff-mcp

    master
    diff-mcp is an MCP (Model Context Protocol) server powered by jsondiffpatch. It allows users to compare text or structured data and receive a readable diff. It supports comparing text (using google-diff-match-patch) and various data formats including JSON, JSON5, YAML, TOML, XML, and HTML. Output formats include text, JSON, and JSONPatch.
  2. Implement custom filters using the Pipes & Filters pattern

    master

    The diff(), patch(), and reverse() functions are implemented using a pipes & filters pattern. You can customize or replace filters to handle special objects (DOM nodes, RegExp, etc.), ignore specific parts of the graph, or implement custom diff mechanisms like relative numeric deltas.

    To create a filter, define a function that accepts a context object. The context provides access to left and right values and allows you to control the flow using context.setResult(value).exit() or by returning early.

  3. Log colored diffs to the console

    master

    You can use the console formatter to output colored text to the console. This can be done by calling the formatter explicitly or using the shorthand jsondiffpatch.console.log(delta).

    const delta = jsondiffpatch.diff(left, right);
    const output = jsondiffpatch.formatters.console.format(delta);
    console.log(output);
    
    // or simply
    jsondiffpatch.console.log(delta);
  4. Render HTML diffs in the browser

    master

    To display a visual HTML diff, include build/formatters.js and src/formatters/html.css in your page. You can use jsondiffpatch.formatters.html.format(delta, left) to generate the HTML string. Providing the left object is optional; if provided, unchanged values will also be visible.

    You can also dynamically toggle the visibility of unchanged values using showUnchanged() and hideUnchanged(). These methods also adjust array move arrows (SVG) to maintain layout integrity.

    const delta = jsondiffpatch.diff(left, right);
    // left is optional, if specified unchanged values will be visible too
    document.getElementBy('the-diff').innerHTML =
      jsondiffpatch.formatters.html.format(delta, left);
    
    // Also you can dinamically show/hide unchanged values
    jsondiffpatch.formatters.html.showUnchanged();
    jsondiffpatch.formatters.html.hideUnchanged();
  5. Render Annotated JSON diffs

    master

    Annotated JSON renders the JSON delta in HTML with side annotations explaining the meaning of each part. To use this, include build/formatters.js and src/formatters/annotated.css in your page.

    const delta = jsondiffpatch.diff(left, right);
    document.getElementBy('the-diff').innerHTML =
      jsondiffpatch.formatters.annotated.format(delta);
  6. Implement a custom React component for jsondiffpatch

    master

    If you require more control or need to specify a specific version of jsondiffpatch, you can build your own React component. To render the diff visually, you must import the HTML formatter and its corresponding CSS file.

    Note: When implementing this, it is recommended to use useMemo to memoize the jsondiffpatch instance and the delta calculation, especially when working with immutable objects to prevent unnecessary re-renders.

    import { create, diff } from 'jsondiffpatch';
    import { format } from 'jsondiffpatch/formatters/html';
    import 'jsondiffpatch/formatters/styles/html.css';
    
    export const JsonDiffPatch = ({
      left,
      right,
      diffOptions,
      hideUnchangedValues,
    }: {
      left: unknown;
      right: unknown;
      diffOptions?: Parameters<typeof create>[0];
      hideUnchangedValues?: boolean;
    }) => {
      // note: you might to useMemo here (especially if these are immutable objects)
      const jsondiffpatch = create(diffOptions || {});
      const delta = jsondiffpatch.diff(left, right);
      const htmlDiff = format(delta, left);
      return (
        <div
          className={`json-diff-container ${
            hideUnchangedValues ? 'jsondiffpatch-unchanged-hidden' : ''
          }`}
        >
          <div
            dangerouslySetInnerHTML={() =>
              ({ __html: htmlDiff || '' }) as { __html: TrustedHTML }
            }
          ></div>
        </div>
      );
    };
  7. Configure jsondiffpatch instance options

    master

    Use jsondiffpatch.create(options) to customize diffing behavior, including array detection, text diffing, and property filtering.

    import * as jsondiffpatch from 'jsondiffpatch';
    import { diff_match_patch } from '@dmsnell/diff-match-patch';
    
    const jsondiffpatchInstance = jsondiffpatch.create({
      // used to match objects when diffing arrays
      objectHash: function (obj) {
        return obj._id || obj.id;
      },
      arrays: {
        // detect items moved inside the array (default: true)
        detectMove: true,
        // include the value of moved items in deltas (default: false)
        includeValueOnMove: false,
      },
      textDiff: {
        // required if using text diffs
        diffMatchPatch: diff_match_patch,
        // minimum string length to use text diff algorithm (default: 60)
        minLength: 60,
      },
      // ignore specific properties (e.g., volatile data)
      propertyFilter: function (name, context) {
        return name.slice(0, 1) !== '$';
      },
      // if true, values in the delta are cloned to prevent references to original objects
      cloneDiffValues: false,
      // if true, 'old' values are omitted from the delta to reduce size
      omitRemovedValues: false,
    });