fast-diff

A fast, dependency-free JavaScript library for computing diffs between two strings using Myers' O(ND) algorithm.

Library
npm
v1.3.0
715stars
Apache License 2.0

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
32/100Needs Attention
Development Activity0
Maintenance0
Community48
Maturity60
Momentum20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
64/100Good
Architecture72
Code Quality58
Innovation75
Learning Curve50

fast-diff is a stripped-down import of Neil Fraser’s diff-match-patch library into the Node.js/browser environment, keeping only the diffing logic and removing the match and patch functionality along with several advanced options. What remains is a small, fast function for computing the difference between two strings as a sequence of insert, delete, and equal operations.

The core algorithm implements Myers’ “An O(ND) Difference Algorithm and its Variations” (1986) with a recursive divide-and-conquer strategy: common prefixes and suffixes are trimmed up front as a speedup, half-matches are located to split large problems into smaller independent diffs, and a bisecting middle-snake search handles the remaining cases. An optional cursor-position hint lets callers bias the result toward edits that make sense at a specific caret location, which is what makes the library popular as the diffing engine inside collaborative rich-text editors.

What You Get

  • A single diff(text1, text2, cursorPos, cleanup) function with no runtime dependencies
  • Tuple-based diff output ([-1, "text"], [0, "text"], [1, "text"]) that’s trivial to render or replay
  • Cursor-aware diffing that favors edits matching a known caret position, added in v1.1
  • Optional semantic cleanup pass to merge and simplify adjacent diff operations
  • Shipped TypeScript type declarations (diff.d.ts) alongside the CommonJS module
  • Convenience constants diff.INSERT, diff.EQUAL, diff.DELETE for readable comparisons

Common Use Cases

  • Computing the minimal edit sequence between two versions of user-entered text
  • Powering operational-transform/CRDT-style diffing inside rich-text editors (its best-known consumer is Quill)
  • Generating inline insert/delete highlighting for text-comparison UIs
  • Reconciling incremental updates to a string-based document model without diffing the whole document from scratch

Under The Hood

Architecture The library is a single procedural module (diff.js) ported almost verbatim from Google’s diff-match-patch, with match and patch functionality stripped out so only the diff pipeline remains. The public diff_main entry point short-circuits equal strings, applies a cursor-position override via find_cursor_edit_diff when a cursor hint is supplied, trims common prefixes/suffixes as a speedup, and hands the remaining middle block to diff_compute_. That function tries cheap wins first (pure insert, pure delete, substring containment) before checking diff_halfMatch_ to split the problem into two independent recursive diff_main calls, falling back to diff_bisect_ — a direct implementation of Myers’ middle-snake bisection — for the general case. Results are merged and optionally simplified through diff_cleanupMerge and diff_cleanupSemantic. There are no classes or DI: it’s a flat set of cooperating functions exported as one CommonJS entry point, so the only thing that would break from a core-abstraction change is the tuple shape itself.

Tech Stack Plain JavaScript (CommonJS, module.exports), zero runtime dependencies, distributed as a single diff.js file plus a hand-authored diff.d.ts for TypeScript consumers (declared via the types field in package.json). Dev-only dependencies are lodash and seedrandom (used to build reproducible fuzz-test input) and nyc for coverage during npm test. There is no bundler or build step — the package is consumed directly as-is by Node or bundler toolchains, and CI (GitHub Actions, .github/workflows/test.yml) simply runs npm install && npm test on push/PR to master.

Code Quality There is no conventional assertion-based test framework (no Mocha/Jest/Vitest); instead test.js runs a fixed set of regression cases plus 10,000 seeded fuzz iterations (with and without cursor hints), verifying correctness by reconstructing text1/text2 from the emitted diff tuples and asserting they match exactly — a correctness-by-reconstruction strategy well suited to a pure algorithmic library. Coverage is measured via nyc. Naming and structure closely mirror the original diff-match-patch source (trailing-underscore “private” functions, non-camelCase names like diff_bisect_), which favors fidelity to the upstream algorithm over house style; there’s no linter or formatter configured in the repo. Error handling is minimal, which is reasonable for pure, side-effect-free string-processing code.

API Design The public surface is deliberately tiny: one function, one options-order (text1, text2, cursorPos?, cleanup?), and three self-explanatory constants (diff.INSERT/DELETE/EQUAL) for reading tuple types back out. Getting started requires nothing more than require('fast-diff') and a single call — no configuration object, no class instantiation, no async ceremony. The README documents the exact return shape with a runnable example, and shipped TypeScript types give consumers autocomplete and tuple-literal typing ([-1 | 0 | 1, string]) without an extra @types package.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search