{"id":16386449,"url":"https://github.com/bhousel/node-diff3","last_synced_at":"2025-04-06T02:08:49.579Z","repository":{"id":26881765,"uuid":"108042532","full_name":"bhousel/node-diff3","owner":"bhousel","description":"A node.js library for text diffing and three-way-merge","archived":false,"fork":false,"pushed_at":"2024-09-10T17:26:07.000Z","size":105,"stargazers_count":91,"open_issues_count":6,"forks_count":13,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-10-12T04:17:21.170Z","etag":null,"topics":["diff","diff3","diffpatch","diffutils","javascript","merge","nodejs"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bhousel.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-10-23T21:37:53.000Z","updated_at":"2024-09-10T17:27:28.000Z","dependencies_parsed_at":"2024-06-18T15:18:18.166Z","dependency_job_id":"4d62e67a-cca8-4fae-952a-8245390a7c12","html_url":"https://github.com/bhousel/node-diff3","commit_stats":{"total_commits":126,"total_committers":11,"mean_commits":"11.454545454545455","dds":"0.47619047619047616","last_synced_commit":"e6df2ee76e74610ef9789404235f287a71a5e644"},"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bhousel%2Fnode-diff3","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bhousel%2Fnode-diff3/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bhousel%2Fnode-diff3/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bhousel%2Fnode-diff3/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bhousel","download_url":"https://codeload.github.com/bhousel/node-diff3/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247423515,"owners_count":20936626,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["diff","diff3","diffpatch","diffutils","javascript","merge","nodejs"],"created_at":"2024-10-11T04:17:19.940Z","updated_at":"2025-04-06T02:08:49.561Z","avatar_url":"https://github.com/bhousel.png","language":"JavaScript","readme":"[![build](https://github.com/bhousel/node-diff3/workflows/build/badge.svg)](https://github.com/bhousel/node-diff3/actions?query=workflow%3A%22build%22)\n[![npm version](https://badge.fury.io/js/node-diff3.svg)](https://badge.fury.io/js/node-diff3)\n\n# node-diff3\n\n**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](https://www.gnu.org/software/diffutils/manual/diffutils.html) tools.\n\nThe code originally came from project Synchrotron, created by Tony Garnock-Jones. For more detail please visit:\n\n* https://leastfixedpoint.com/tonyg/kcbbs/projects/synchrotron.html\n* https://github.com/tonyg/synchrotron\n\n\u0026nbsp;\n\n## Usage\n\n### Use in Node\n\nTo install node-diff3 as a dependency in your project:\n```bash\n$  npm install --save node-diff3\n```\n\n**node-diff3** is distributed in CJS and ESM module formats for maxmimum compatibility. ([Read more about Javascript module formats](https://dev.to/iggredible/what-the-heck-are-cjs-amd-umd-and-esm-ikm))\n\n\n```js\nconst Diff3 = require('node-diff3');                   // CommonJS import all\nconst diff3Merge = require('node-diff3').diff3Merge;   // CommonJS import named\n// or\nimport * as Diff3 from 'node-diff3';                   // ESM import all\nimport { diff3Merge } from 'node-diff3';               // ESM import named\n```\n\n### Use in Browsers\n\nYou can also use **node-diff3** directly in a web browser.  A good way to do this is to fetch the [\"iife\"](https://esbuild.github.io/api/#format-iife) bundle from the [jsDelivr CDN](https://www.jsdelivr.com/), which can even deliver minified versions.\n\nWhen you load this file in a `\u003cscript\u003e` tag, you'll get a `Diff3` global to use elsewhere in your scripts:\n```html\n\u003chead\u003e\n\u003cscript src=\"https://cdn.jsdelivr.net/npm/node-diff3@3.1/dist/index.iife.min.js\"\u003e\u003c/script\u003e\n\u003c/head\u003e\n…\n\u003cscript\u003e\n  const o = ['AA', 'ZZ', '00', 'M', '99'];\n  const a = ['AA', 'a', 'b', 'c', 'ZZ', 'new', '00', 'a', 'a', 'M', '99'];\n  const b = ['AA', 'a', 'd', 'c', 'ZZ', '11', 'M', 'z', 'z', '99'];\n  const result = Diff3.diff3Merge(a, o, b);\n\u003c/script\u003e\n```\n\n👉 This project uses modern JavaScript syntax for use in supported node versions and modern browsers.  If you need support for legacy environments like ES5 or Internet Explorer, you'll need to build your own bundle with something like [Babel](https://babeljs.io/docs/en/index.html).\n\n\u0026nbsp;\n\n## API Reference\n\n* [3-way diff and merging](#3-way-diff-and-merging)\n  * [diff3Merge](#diff3Merge)\n  * [merge](#merge)\n  * [mergeDiff3](#mergeDiff3)\n  * [mergeDigIn](#mergeDigIn)\n  * [diff3MergeRegions](#diff3MergeRegions)\n* [2-way diff and patching](#2-way-diff-and-patching)\n  * [diffPatch](#diffPatch)\n  * [patch](#patch)\n  * [stripPatch](#stripPatch)\n  * [invertPatch](#invertPatch)\n  * [diffComm](#diffComm)\n  * [diffIndices](#diffIndices)\n* [Longest Common Sequence (LCS)](#longest-common-sequence-lcs)\n  * [LCS](#LCS)\n\n\u0026nbsp;\n\n### 3-way diff and merging\n\n\u0026nbsp;\n\n\u003ca name=\"diff3Merge\" href=\"#diff3Merge\"\u003e#\u003c/a\u003e \u003ci\u003eDiff3\u003c/i\u003e.\u003cb\u003ediff3Merge\u003c/b\u003e(\u003ci\u003ea\u003c/i\u003e, \u003ci\u003eo\u003c/i\u003e, \u003ci\u003eb\u003c/i\u003e, \u003ci\u003eoptions\u003c/i\u003e)\n\nPerforms a 3-way diff on buffers `o` (original), and `a` and `b` (changed).\nThe buffers may be arrays or strings. If strings, they will be split into arrays on whitespace `/\\s+/` by default.\nThe returned result alternates between \"ok\" and \"conflict\" blocks.\n\nSee examples: https://github.com/bhousel/node-diff3/blob/main/test/diff3Merge.test.js\n\n```js\nconst o = ['AA', 'ZZ', '00', 'M', '99'];\nconst a = ['AA', 'a', 'b', 'c', 'ZZ', 'new', '00', 'a', 'a', 'M', '99'];\nconst b = ['AA', 'a', 'd', 'c', 'ZZ', '11', 'M', 'z', 'z', '99'];\nconst result = Diff3.diff3Merge(a, o, b);\n```\n\nOptions may passed as an object:\n```js\n{\n  excludeFalseConflicts: true,\n  stringSeparator: /\\s+/\n}\n```\n\n* `excludeFalseConflicts` - If both `a` and `b` contain an identical change from `o`, this is considered a \"false\" conflict.\n* `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()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/split).\n\n\u0026nbsp;\n\n\u003ca name=\"merge\" href=\"#merge\"\u003e#\u003c/a\u003e \u003ci\u003eDiff3\u003c/i\u003e.\u003cb\u003emerge\u003c/b\u003e(\u003ci\u003ea\u003c/i\u003e, \u003ci\u003eo\u003c/i\u003e, \u003ci\u003eb\u003c/i\u003e, \u003ci\u003eoptions\u003c/i\u003e)\n\nPasses arguments to [diff3Merge](#diff3Merge) to generate a diff3-style merge result.\n\nSee examples: https://github.com/bhousel/node-diff3/blob/main/test/merge.test.js\n\n```js\nconst r = Diff3.merge(a, o, b);\nconst result = r.result;\n// [\n//   'AA',\n//   '\u003c\u003c\u003c\u003c\u003c\u003c\u003c',\n//   'a',\n//   'b',\n//   'c',\n//   '=======',\n//   'a',\n//   'd',\n//   'c',\n//   '\u003e\u003e\u003e\u003e\u003e\u003e\u003e',\n//   'ZZ',\n//   '\u003c\u003c\u003c\u003c\u003c\u003c\u003c',\n//   'new',\n//   '00',\n//   'a',\n//   'a',\n//   '=======',\n//   '11',\n//   '\u003e\u003e\u003e\u003e\u003e\u003e\u003e',\n//   'M',\n//   'z',\n//   'z',\n//   '99'\n//  ]\n```\n\n\u0026nbsp;\n\n\u003ca name=\"mergeDiff3\" href=\"#mergeDiff3\"\u003e#\u003c/a\u003e \u003ci\u003eDiff3\u003c/i\u003e.\u003cb\u003emergeDiff3\u003c/b\u003e(\u003ci\u003ea\u003c/i\u003e, \u003ci\u003eo\u003c/i\u003e, \u003ci\u003eb\u003c/i\u003e, \u003ci\u003eoptions\u003c/i\u003e)\n\nPasses arguments to [diff3Merge](#diff3Merge) to generate a diff3-style merge result with original (similar to [git-diff3](https://git-scm.com/book/en/v2/Git-Tools-Advanced-Merging)).\n\nSee examples: https://github.com/bhousel/node-diff3/blob/main/test/mergeDiff3.test.js\n\n```js\nconst r = Diff3.mergeDiff3(a, o, b, { label: { a: 'a', o: 'o', b: 'b' } });\nconst result = r.result;\n// [\n//   'AA',\n//   '\u003c\u003c\u003c\u003c\u003c\u003c\u003c a',\n//   'a',\n//   'b',\n//   'c',\n//   '||||||| o',\n//   '=======',\n//   'a',\n//   'd',\n//   'c',\n//   '\u003e\u003e\u003e\u003e\u003e\u003e\u003e b',\n//   'ZZ',\n//   '\u003c\u003c\u003c\u003c\u003c\u003c\u003c a',\n//   'new',\n//   '00',\n//   'a',\n//   'a',\n//   '||||||| o',\n//   '00',\n//   '=======',\n//   '11',\n//   '\u003e\u003e\u003e\u003e\u003e\u003e\u003e b',\n//   'M',\n//   'z',\n//   'z',\n//   '99'\n//  ]\n```\n\nExtra options:\n```js\n{\n  // labels for conflict marker lines\n  label: {\n    a: 'a',\n    o: 'o',\n    b: 'b'\n  },\n}\n```\n\n\u0026nbsp;\n\n\u003ca name=\"mergeDigIn\" href=\"#mergeDigIn\"\u003e#\u003c/a\u003e \u003ci\u003eDiff3\u003c/i\u003e.\u003cb\u003emergeDigIn\u003c/b\u003e(\u003ci\u003ea\u003c/i\u003e, \u003ci\u003eo\u003c/i\u003e, \u003ci\u003eb\u003c/i\u003e, \u003ci\u003eoptions\u003c/i\u003e)\n\nPasses arguments to [diff3Merge](#diff3Merge) to generate a digin-style merge result.\n\nSee examples: https://github.com/bhousel/node-diff3/blob/main/test/mergeDigIn.test.js\n\n\u0026nbsp;\n\n\u003ca name=\"diff3MergeRegions\" href=\"#diff3MergeRegions\"\u003e#\u003c/a\u003e \u003ci\u003eDiff3\u003c/i\u003e.\u003cb\u003ediff3MergeRegions\u003c/b\u003e(\u003ci\u003ea\u003c/i\u003e, \u003ci\u003eo\u003c/i\u003e, \u003ci\u003eb\u003c/i\u003e)\n\nLow-level function used by [diff3Merge](#diff3Merge) to determine the stable and unstable regions between `a`, `o`, `b`.\n\nSee examples: https://github.com/bhousel/node-diff3/blob/main/test/diff3MergeRegions.test.js\n\n\n\u0026nbsp;\n\n### 2-way diff and patching\n\n\u0026nbsp;\n\n\u003ca name=\"diffPatch\" href=\"#diffPatch\"\u003e#\u003c/a\u003e \u003ci\u003eDiff3\u003c/i\u003e.\u003cb\u003ediffPatch\u003c/b\u003e(\u003ci\u003ebuffer1\u003c/i\u003e, \u003ci\u003ebuffer2\u003c/i\u003e)\n\nPerforms a diff between arrays `buffer1` and `buffer2`.\nThe returned `patch` result contains the information about the differing regions and can be applied to `buffer1` to yield `buffer2`.\n\nSee examples: https://github.com/bhousel/node-diff3/blob/main/test/diffPatch.test.js\n\n```js\nconst buffer1 = ['AA', 'a', 'b', 'c', 'ZZ', 'new', '00', 'a', 'a', 'M', '99'];\nconst buffer2 = ['AA', 'a', 'd', 'c', 'ZZ', '11', 'M', 'z', 'z', '99'];\nconst patch = Diff3.diffPatch(buffer1, buffer2);\n// `patch` contains the information needed to turn `buffer1` into `buffer2`\n```\n\n\u0026nbsp;\n\n\u003ca name=\"patch\" href=\"#patch\"\u003e#\u003c/a\u003e \u003ci\u003eDiff3\u003c/i\u003e.\u003cb\u003epatch\u003c/b\u003e(\u003ci\u003ebuffer1\u003c/i\u003e, \u003ci\u003epatch\u003c/i\u003e)\n\nApplies a patch to a buffer, returning a new buffer without modifying the original.\n\nSee examples: https://github.com/bhousel/node-diff3/blob/main/test/diffPatch.test.js\n\n```js\nconst result = Diff3.patch(buffer1, patch);\n// `result` contains a new arrray which is a copy of `buffer2`\n```\n\n\u0026nbsp;\n\n\u003ca name=\"stripPatch\" href=\"#stripPatch\"\u003e#\u003c/a\u003e \u003ci\u003eDiff3\u003c/i\u003e.\u003cb\u003estripPatch\u003c/b\u003e(\u003ci\u003epatch\u003c/i\u003e)\n\nStrips some extra information from the patch, returning a new patch without modifying the original.\nThe \"stripped\" patch can still patch `buffer1` -\u003e `buffer2`, but can no longer be inverted.\n\nSee examples: https://github.com/bhousel/node-diff3/blob/main/test/diffPatch.test.js\n\n```js\nconst stripped = Diff3.stripPatch(patch);\n// `stripped` contains a copy of a patch but with the extra information removed\n```\n\n\u0026nbsp;\n\n\u003ca name=\"invertPatch\" href=\"#invertPatch\"\u003e#\u003c/a\u003e \u003ci\u003eDiff3\u003c/i\u003e.\u003cb\u003einvertPatch\u003c/b\u003e(\u003ci\u003epatch\u003c/i\u003e)\n\nInverts the patch (for example to turn `buffer2` back into `buffer1`), returning a new patch without modifying the original.\n\nSee examples: https://github.com/bhousel/node-diff3/blob/main/test/diffPatch.test.js\n\n```js\nconst inverted = Diff3.invertPatch(patch);\n// `inverted` contains a copy of a patch to turn `buffer2` back into `buffer1`\n```\n\n\u0026nbsp;\n\n\u003ca name=\"diffComm\" href=\"#diffComm\"\u003e#\u003c/a\u003e \u003ci\u003eDiff3\u003c/i\u003e.\u003cb\u003ediffComm\u003c/b\u003e(\u003ci\u003ebuffer1\u003c/i\u003e, \u003ci\u003ebuffer2\u003c/i\u003e)\n\nReturns a comm-style result of the differences between `buffer1` and `buffer2`.\n\nSee examples: https://github.com/bhousel/node-diff3/blob/main/test/diffComm.test.js\n\n\u0026nbsp;\n\n\u003ca name=\"diffIndices\" href=\"#diffIndices\"\u003e#\u003c/a\u003e \u003ci\u003eDiff3\u003c/i\u003e.\u003cb\u003ediffIndices\u003c/b\u003e(\u003ci\u003ebuffer1\u003c/i\u003e, \u003ci\u003ebuffer2\u003c/i\u003e)\n\nLow-level function used by [diff3MergeRegions](#diff3MergeRegions) to determine differing regions between `buffer1` and `buffer2`.\n\nSee examples: https://github.com/bhousel/node-diff3/blob/main/test/diffIndices.test.js\n\n\n\u0026nbsp;\n\n### Longest Common Sequence (LCS)\n\n\u0026nbsp;\n\n\u003ca name=\"LCS\" href=\"#LCS\"\u003e#\u003c/a\u003e \u003ci\u003eDiff3\u003c/i\u003e.\u003cb\u003eLCS\u003c/b\u003e(\u003ci\u003ebuffer1\u003c/i\u003e, \u003ci\u003ebuffer2\u003c/i\u003e)\n\nLow-level function used by other functions to find the LCS between `buffer1` and `buffer2`.\nReturns a result linked list chain containing the common sequence path.\n\nSee also:\n* http://www.cs.dartmouth.edu/~doug/\n* https://en.wikipedia.org/wiki/Longest_common_subsequence_problem\n\nSee examples: https://github.com/bhousel/node-diff3/blob/main/test/LCS.test.js\n\n\n\u0026nbsp;\n\n## License\n\nThis project is available under the [MIT License](https://opensource.org/licenses/MIT).\nSee the [LICENSE.md](LICENSE.md) file for more details.\n","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbhousel%2Fnode-diff3","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbhousel%2Fnode-diff3","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbhousel%2Fnode-diff3/lists"}