node-diff3
node-diff3 is a Javascript library to find differences between two buffers, generate and apply patches, and perform 3-way merging between an original and two changed buffers. It contains similar functionality to the GNU Diffutils tools.
The code originally came from project Synchrotron, created by Tony Garnock-Jones. For more detail please visit:
- https://leastfixedpoint.com/tonyg/kcbbs/projects/synchrotron.html
- https://github.com/tonyg/synchrotron
Usage
Use in Node
To install node-diff3 as a dependency in your project:
$ npm install --save node-diff3
node-diff3 is distributed in CJS and ESM module formats for maxmimum compatibility. (Read more about Javascript module formats)
const Diff3 = require('node-diff3'); // CommonJS import all
const diff3Merge = require('node-diff3').diff3Merge; // CommonJS import named
// or
import * as Diff3 from 'node-diff3'; // ESM import all
import { diff3Merge } from 'node-diff3'; // ESM import named
Use in Browsers
You can also use node-diff3 directly in a web browser. A good way to do this is to fetch the "iife" bundle from the jsDelivr CDN, which can even deliver minified versions.
When you load this file in a <script>
tag, you'll get a Diff3
global to use elsewhere in your scripts:
<head>
<script src="https://cdn.jsdelivr.net/npm/node-diff3@3.1/dist/index.iife.min.js"></script>
</head>
…
<script>
const o = ['AA', 'ZZ', '00', 'M', '99'];
const a = ['AA', 'a', 'b', 'c', 'ZZ', 'new', '00', 'a', 'a', 'M', '99'];
const b = ['AA', 'a', 'd', 'c', 'ZZ', '11', 'M', 'z', 'z', '99'];
const result = Diff3.diff3Merge(a, o, b);
</script>
API Reference
3-way diff and merging
# Diff3.diff3Merge(a, o, b, options)
Performs a 3-way diff on buffers o
(original), and a
and b
(changed).
The buffers may be arrays or strings. If strings, they will be split into arrays on whitespace /\s+/
by default.
The returned result alternates between "ok" and "conflict" blocks.
See examples: https://github.com/bhousel/node-diff3/blob/main/test/diff3Merge.test.js
const o = ['AA', 'ZZ', '00', 'M', '99'];
const a = ['AA', 'a', 'b', 'c', 'ZZ', 'new', '00', 'a', 'a', 'M', '99'];
const b = ['AA', 'a', 'd', 'c', 'ZZ', '11', 'M', 'z', 'z', '99'];
const result = Diff3.diff3Merge(a, o, b);
Options may passed as an object:
{
excludeFalseConflicts: true,
stringSeparator: /\s+/
}
-
excludeFalseConflicts
- If botha
andb
contain an identical change fromo
, this is considered a "false" conflict. -
stringSeparator
- If inputs buffers are strings, this controls how to split the strings into arrays. The separator value may be a string or a regular expression, as it is just passed to String.split().
# Diff3.merge(a, o, b, options)
Passes arguments to diff3Merge to generate a diff3-style merge result.
See examples: https://github.com/bhousel/node-diff3/blob/main/test/merge.test.js
const r = Diff3.merge(a, o, b);
const result = r.result;
// [
// 'AA',
// '<<<<<<<',
// 'a',
// 'b',
// 'c',
// '=======',
// 'a',
// 'd',
// 'c',
// '>>>>>>>',
// 'ZZ',
// '<<<<<<<',
// 'new',
// '00',
// 'a',
// 'a',
// '=======',
// '11',
// '>>>>>>>',
// 'M',
// 'z',
// 'z',
// '99'
// ]
# Diff3.mergeDiff3(a, o, b, options)
Passes arguments to diff3Merge to generate a diff3-style merge result with original (similar to git-diff3).
See examples: https://github.com/bhousel/node-diff3/blob/main/test/mergeDiff3.test.js
const r = Diff3.mergeDiff3(a, o, b, { label: { a: 'a', o: 'o', b: 'b' } });
const result = r.result;
// [
// 'AA',
// '<<<<<<< a',
// 'a',
// 'b',
// 'c',
// '||||||| o',
// '=======',
// 'a',
// 'd',
// 'c',
// '>>>>>>> b',
// 'ZZ',
// '<<<<<<< a',
// 'new',
// '00',
// 'a',
// 'a',
// '||||||| o',
// '00',
// '=======',
// '11',
// '>>>>>>> b',
// 'M',
// 'z',
// 'z',
// '99'
// ]
Extra options:
{
// labels for conflict marker lines
label: {
a: 'a',
o: 'o',
b: 'b'
},
}
# Diff3.mergeDigIn(a, o, b, options)
Passes arguments to diff3Merge to generate a digin-style merge result.
See examples: https://github.com/bhousel/node-diff3/blob/main/test/mergeDigIn.test.js
# Diff3.diff3MergeRegions(a, o, b)
Low-level function used by diff3Merge to determine the stable and unstable regions between a
, o
, b
.
See examples: https://github.com/bhousel/node-diff3/blob/main/test/diff3MergeRegions.test.js
2-way diff and patching
# Diff3.diffPatch(buffer1, buffer2)
Performs a diff between arrays buffer1
and buffer2
.
The returned patch
result contains the information about the differing regions and can be applied to buffer1
to yield buffer2
.
See examples: https://github.com/bhousel/node-diff3/blob/main/test/diffPatch.test.js
const buffer1 = ['AA', 'a', 'b', 'c', 'ZZ', 'new', '00', 'a', 'a', 'M', '99'];
const buffer2 = ['AA', 'a', 'd', 'c', 'ZZ', '11', 'M', 'z', 'z', '99'];
const patch = Diff3.diffPatch(buffer1, buffer2);
// `patch` contains the information needed to turn `buffer1` into `buffer2`
# Diff3.patch(buffer1, patch)
Applies a patch to a buffer, returning a new buffer without modifying the original.
See examples: https://github.com/bhousel/node-diff3/blob/main/test/diffPatch.test.js
const result = Diff3.patch(buffer1, patch);
// `result` contains a new arrray which is a copy of `buffer2`
# Diff3.stripPatch(patch)
Strips some extra information from the patch, returning a new patch without modifying the original.
The "stripped" patch can still patch buffer1
-> buffer2
, but can no longer be inverted.
See examples: https://github.com/bhousel/node-diff3/blob/main/test/diffPatch.test.js
const stripped = Diff3.stripPatch(patch);
// `stripped` contains a copy of a patch but with the extra information removed
# Diff3.invertPatch(patch)
Inverts the patch (for example to turn buffer2
back into buffer1
), returning a new patch without modifying the original.
See examples: https://github.com/bhousel/node-diff3/blob/main/test/diffPatch.test.js
const inverted = Diff3.invertPatch(patch);
// `inverted` contains a copy of a patch to turn `buffer2` back into `buffer1`
# Diff3.diffComm(buffer1, buffer2)
Returns a comm-style result of the differences between buffer1
and buffer2
.
See examples: https://github.com/bhousel/node-diff3/blob/main/test/diffComm.test.js
# Diff3.diffIndices(buffer1, buffer2)
Low-level function used by diff3MergeRegions to determine differing regions between buffer1
and buffer2
.
See examples: https://github.com/bhousel/node-diff3/blob/main/test/diffIndices.test.js
Longest Common Sequence (LCS)
# Diff3.LCS(buffer1, buffer2)
Low-level function used by other functions to find the LCS between buffer1
and buffer2
.
Returns a result linked list chain containing the common sequence path.
See also:
See examples: https://github.com/bhousel/node-diff3/blob/main/test/LCS.test.js
License
This project is available under the MIT License. See the LICENSE.md file for more details.