npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@ferrow/text-diff-patch

v1.0.0

Published

Zero-dependency line-based Myers diff (O(ND)) producing unified-diff hunks, with fuzzy patch application, reject reporting, and word-level intra-line diff highlighting.

Readme

text-diff-patch

CI

Zero-dependency line-based diff and patch for TypeScript/JavaScript: Myers O(ND) diff producing unified-diff-style hunks, fuzzy patch application with reject reporting, and a word-level intra-line diff highlighter.

Why

Most diff libraries either only diff or only apply, and few report why a hunk failed to apply against a shifted file. This package does both directions with zero runtime dependencies, strict TypeScript, and an explicit fuzz tolerance for applying patches against slightly-moved text — the case agents hit constantly when re-applying an edit to a file that changed underneath them.

Install

npm install text-diff-patch

Quickstart

import { createPatch, applyPatch, highlightWordDiff } from "text-diff-patch";

const patch = createPatch(oldText, newText, { oldFile: "a", newFile: "b" });
console.log(patch); // unified-diff-style string

const { result, applied, rejects } = applyPatch(oldText, patch, { fuzz: 3 });
// applied: number of hunks applied; rejects: hunks that couldn't be placed

highlightWordDiff("hello world", "hello there");
// "hello {-world-}{+there+}"

API

myersDiff(a: string[], b: string[]): DiffOp[]

Raw Myers O(ND) line-array diff. DiffOp = { type: "equal"|"delete"|"insert", value: string }.

toLines(text: string): string[]

Splits text into lines ("" → []).

buildHunks(ops: DiffOp[], context = 3): Hunk[]

Groups a DiffOp[] into unified-diff hunks with context lines of surrounding unchanged text; adjacent changes within 2 * context lines merge into one hunk.

createPatch(oldText: string, newText: string, options?: CreatePatchOptions): string

Full unified-diff text. CreatePatchOptions = { context?: number; oldFile?: string; newFile?: string }.

parsePatch(patchText: string): Hunk[]

Parses a unified-diff string back into Hunk[] ({ oldStart, oldLines, newStart, newLines, lines }).

applyPatch(text: string, patch: string | Hunk[], options?: ApplyOptions): ApplyResult

Applies hunks to text. ApplyOptions = { fuzz?: number } — with fuzz > 0, a hunk whose exact recorded line is off is retried at nearby offsets (±1..±fuzz) before being rejected. ApplyResult = { result: string; applied: number; rejects: RejectedHunk[] }, RejectedHunk = { hunk: Hunk; reason: string }.

tokenizeWords(line: string): string[]

Splits a line into word/whitespace tokens, exactly reconstructible via join("").

diffWords(a: string, b: string): DiffOp[]

Word-level Myers diff over tokenized lines.

highlightWordDiff(a: string, b: string, options?: HighlightOptions): string

Renders a word-diff as one string with insertions/deletions wrapped in markers. HighlightOptions = { insertOpen?, insertClose?, deleteOpen?, deleteClose? } (defaults: {+...+} / {-...-}).

Limits

  • Line-based only — myersDiff/createPatch operate on \n-split lines, not characters (use diffWords for intra-line detail).
  • applyPatch's fuzz search is a bounded ±N-line offset retry per hunk, not a general approximate-matching algorithm — very large shifts or heavily edited context will still reject.
  • No binary-file support; input is always treated as text.
  • parsePatch expects hunk bodies to use exactly one leading ' '/'+'/'-' per line (standard unified-diff shape) — it does not tolerate tab-indented or CRLF-mixed patches.

Part of the ferrow-toolkit collection · Sponsored by Ferrow