PHPackages                             alto/code-diff - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Templating &amp; Views](/categories/templating)
4. /
5. alto/code-diff

ActiveLibrary[Templating &amp; Views](/categories/templating)

alto/code-diff
==============

Generate, render and apply code diffs. Myers algorithm, versatile rendering (HTML, JSON, ANSI), and full patching support.

v1.0.0(4mo ago)34MITPHPPHP ^8.3CI passing

Since Jan 4Pushed 4mo agoCompare

[ Source](https://github.com/PhpAlto/code-diff)[ Packagist](https://packagist.org/packages/alto/code-diff)[ Docs](https://github.com/phpalto/code-diff)[ GitHub Sponsors](https://github.com/sponsors/smnandre)[ RSS](/packages/alto-code-diff/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (1)Dependencies (3)Versions (2)Used By (0)

Alto Code Diff
==============

[](#alto-code-diff)

A modern PHP library to generate, render and apply diffs, featuring advanced algorithms, versatile rendering, and full patching support.

---

 [![PHP Version](https://camo.githubusercontent.com/0f663643ca39e7277b6b9296c9a8fc49a2f02d9a27ca5da60a4d155e8b2603ec/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048502d382e332b2d3165343061663f6c6f676f436f6c6f723d7768697465266c6162656c436f6c6f723d303030)](https://github.com/PhpAlto/code-diff) [![CI](https://camo.githubusercontent.com/03185167e70c8d393e01684db3c645d2995d349e92d4f1cbb083341bf221bda5/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f506870416c746f2f636f64652d646966662f43492e796d6c3f6272616e63683d6d61696e266c6162656c3d5465737473266c6f676f436f6c6f723d7768697465266c6f676f53697a653d6175746f266c6162656c436f6c6f723d30303026636f6c6f723d323536336562)](https://github.com/PhpAlto/code-diff/actions) [![Packagist Version](https://camo.githubusercontent.com/3bcf16c784888e30f3703654f3faade5c08e5c93adf65d9e55e38e1f25cfc10f/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f616c746f2f636f64652d646966663f6c6162656c3d537461626c65266c6f676f436f6c6f723d7768697465266c6f676f53697a653d6175746f266c6162656c436f6c6f723d30303026636f6c6f723d346261336637)](https://packagist.org/packages/alto/code-diff) [![GitHub Sponsors](https://camo.githubusercontent.com/ebfca758c0647a86a30597ec46270b8e4c284296c6f6285b34f7a4d518b2c82d/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f73706f6e736f72732f736d6e616e6472653f6c6f676f3d6769746875622d73706f6e736f7273266c6f676f436f6c6f723d346261336637266c6f676f53697a653d6175746f266c6162656c3d25323053706f6e736f72266c6162656c436f6c6f723d30303026636f6c6f723d323937396666)](https://github.com/sponsors/smnandre) [![License](https://camo.githubusercontent.com/c51dc7fd638786f3c5d99385aaa7be59f9b63b7faeff77caec71c3d166730955/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f506870416c746f2f636f64652d646966663f6c6162656c3d4c6963656e7365266c6f676f436f6c6f723d7768697465266c6f676f53697a653d6175746f266c6162656c436f6c6f723d30303026636f6c6f723d316534306166)](./LICENSE)

Features
--------

[](#features)

### Advanced Diff Algorithms

[](#advanced-diff-algorithms)

- **Myers Diff Algorithm (default)**: Fast and accurate line-by-line and word-by-word diffing (O(ND)).
- **LCS Diff Algorithm**: Opt-in Longest Common Subsequence engine (O(MN) time and memory) for deterministic academic use cases.
- **Binary Detection**: Automatic detection and rejection of binary content.

### Versatile Rendering

[](#versatile-rendering)

Visualize and format diffs for any output medium:

#### HTML Output

[](#html-output)

[![HTML Preview](docs/assets/html-preview.svg)](docs/assets/html-preview.svg)

#### ANSI Side-by-Side

[](#ansi-side-by-side)

[![ANSI Preview](docs/assets/side-by-side-preview.svg)](docs/assets/side-by-side-preview.svg)

### Full Patching Support

[](#full-patching-support)

- **Unified Diff Parsing**: Parse standard unified diff patches into objects.
- **Patch Application**: Apply patches to files with "fuzz" factor support.
- **Multi-file Bundles**: Handle complex patches affecting multiple files.

Requirements
------------

[](#requirements)

- PHP 8.3 or higher

Installation
------------

[](#installation)

```
composer require alto/code-diff
```

Quick Start
-----------

[](#quick-start)

### Basic Diff

[](#basic-diff)

```
use Alto\Code\Diff\Diff;
use Alto\Code\Diff\Renderer\UnifiedRenderer;

$old = "line1\nline2\nline3\n";
$new = "line1\nline2 modified\nline3\n";

$result = Diff::build()->compare($old, $new);

$renderer = new UnifiedRenderer('old.txt', 'new.txt');
echo $renderer->render($result);
```

Output:

```
--- old.txt
+++ new.txt
@@ -1,3 +1,3 @@
 line1
-line2
+line2 modified
 line3
```

### Word-Level Diff

[](#word-level-diff)

```
$result = Diff::build()
    ->withWordDiff()
    ->compare($old, $new);
```

### HTML Output

[](#html-output-1)

```
use Alto\Code\Diff\Renderer\HtmlRenderer;

$renderer = new HtmlRenderer(
    showLineNumbers: true,
    wrapLines: false,
    classPrefix: 'diff-'
);

echo $renderer->render($result);
```

### JSON Output

[](#json-output)

```
use Alto\Code\Diff\Renderer\JsonRenderer;

$renderer = new JsonRenderer(prettyPrint: true);
echo $renderer->render($result);
```

### ANSI Side-by-Side Output

[](#ansi-side-by-side-output)

```
use Alto\Code\Diff\Renderer\AnsiSideBySideRenderer;

$renderer = new AnsiSideBySideRenderer(
    showLineNumbers: true,
    width: 120
);

echo $renderer->render($result);
```

Configuration Options
---------------------

[](#configuration-options)

### Context Lines

[](#context-lines)

Control how many unchanged lines to show around changes:

```
$result = Diff::build()
    ->contextLines(5)  // Default is 3
    ->compare($old, $new);
```

### Ignore Whitespace

[](#ignore-whitespace)

Ignore whitespace differences:

```
$result = Diff::build()
    ->ignoreWhitespace()
    ->compare($old, $new);
```

### Size Limits

[](#size-limits)

Set maximum input size (default 5MB):

```
$result = Diff::build()
    ->maxBytes(10_000_000)  // 10MB
    ->compare($old, $new);
```

Parsing and Applying Patches
----------------------------

[](#parsing-and-applying-patches)

### Parse a Unified Diff

[](#parse-a-unified-diff)

```
use Alto\Code\Diff\Patch\UnifiedParser;

$patch = result->hunks()) . "\n";
}
```

### Apply a Patch

[](#apply-a-patch)

```
use Alto\Code\Diff\Patch\PatchApplier;

$original = "line1\nline2\nline3\n";

$applier = new PatchApplier();
$patched = $applier->apply($original, $patch);

echo $patched;
// Output: line1\nline2 modified\nline3\n
```

> **Note:** `PatchApplier::apply()` accepts a single-file patch. For multi-file diffs, parse the patch and call `applyBundle()` instead.

### Apply Patch with Fuzz Factor

[](#apply-patch-with-fuzz-factor)

```
$applier = new PatchApplier(fuzz: 2);
$patched = $applier->apply($original, $patch);
```

### Apply Patch to Multiple Files

[](#apply-patch-to-multiple-files)

```
use Alto\Code\Diff\Model\DiffBundle;

$files = [
    'file1.txt' => "content1\n",
    'file2.txt' => "content2\n",
];

$applier = new PatchApplier();
$patchedFiles = $applier->applyBundle($files, $bundle);
```

Emitting Unified Diffs
----------------------

[](#emitting-unified-diffs)

### From DiffResult

[](#from-diffresult)

```
use Alto\Code\Diff\Patch\UnifiedEmitter;

$result = Diff::build()->compare($old, $new);

$emitter = new UnifiedEmitter();
$patch = $emitter->emit($result);
```

### From DiffBundle

[](#from-diffbundle)

```
use Alto\Code\Diff\Model\DiffBundle;
use Alto\Code\Diff\Model\DiffFile;

$files = [
    new DiffFile('file1.txt', 'file1.txt', $result1),
    new DiffFile('file2.txt', 'file2.txt', $result2),
];

$bundle = new DiffBundle($files);
$emitter = new UnifiedEmitter();
$patch = $emitter->emit($bundle);
```

Renderer Options
----------------

[](#renderer-options)

### UnifiedRenderer

[](#unifiedrenderer)

```
new UnifiedRenderer(
    oldLabel: 'a/file.txt',  // Label for old version
    newLabel: 'b/file.txt'   // Label for new version
);
```

### HtmlRenderer

[](#htmlrenderer)

```
new HtmlRenderer(
    showLineNumbers: true,      // Show line numbers
    wrapLines: false,           // Wrap long lines
    classPrefix: 'diff-'        // CSS class prefix
);
```

### JsonRenderer

[](#jsonrenderer)

```
new JsonRenderer(
    prettyPrint: true  // Format with indentation
);
```

### AnsiSideBySideRenderer

[](#ansisidebysiderenderer)

```
new AnsiSideBySideRenderer(
    showLineNumbers: true,  // Show line numbers
    width: 120              // Terminal width
);
```

Advanced Usage
--------------

[](#advanced-usage)

### Custom Diff Engine

[](#custom-diff-engine)

You can choose between the built-in engines or implement your own.

**MyersDiffEngine** (Default): Uses the O(ND) Myers algorithm. Best for most use cases, especially when differences are small.

**LcsDiffEngine**: Uses the standard O(MN) LCS algorithm. Enable it explicitly with `->withEngine(new LcsDiffEngine())` only for small inputs, because its quadratic memory footprint is intended for controlled, academic scenarios.

```
use Alto\Code\Diff\Engine\LcsDiffEngine;

$result = Diff::build()
    ->withEngine(new LcsDiffEngine())
    ->compare($old, $new);
```

### Implementing a Custom Engine

[](#implementing-a-custom-engine)

```
use Alto\Code\Diff\Engine\DiffEngineInterface;

class MyCustomEngine implements DiffEngineInterface
{
    public function diff(string $old, string $new, Options $opts): DiffResult
    {
        // Custom implementation
    }
}

$result = Diff::build()
    ->withEngine(new MyCustomEngine())
    ->compare($old, $new);
```

### Working with Git Patches

[](#working-with-git-patches)

The library supports parsing git-style unified diffs with headers:

```
$patch = headers['diff'];   // 'diff --git a/file.txt b/file.txt'
$file->headers['index'];  // 'index abcdef..123456 100644'
```

Documentation
-------------

[](#documentation)

For more detailed information, please refer to the documentation in the `docs/` directory:

- [API Reference](docs/api-reference.md)
- [Architecture](docs/architecture.md)
- [Basic Text Comparison](docs/basic-text-comparison.md)
- [File Comparison](docs/file-comparison.md)
- [Git Integration](docs/git-integration.md)
- [Patch Operations](docs/patch-operations.md)
- [Rendering Options](docs/rendering-options.md)
- [Advanced Scenarios](docs/advanced-scenarios.md)
- [Examples](docs/examples.md)

Testing
-------

[](#testing)

Run the test suite:

```
vendor/bin/phpunit
```

Run tests with coverage:

```
vendor/bin/phpunit --coverage-text
```

License
-------

[](#license)

This project is licensed under the [MIT License](./LICENSE).

###  Health Score

36

—

LowBetter than 82% of packages

Maintenance75

Regular maintenance activity

Popularity7

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity49

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

134d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/a8951d49b371d210280a58ce48969a07d1f49924810f8a1fab3a9343eb46fdc9?d=identicon)[simonandre](/maintainers/simonandre)

---

Top Contributors

[![smnandre](https://avatars.githubusercontent.com/u/1359581?v=4)](https://github.com/smnandre "smnandre (3 commits)")

---

Tags

code-diffdiffdiff-viewergitlcspatchpatch-diffphp-diffphp-patchjsondiffhtmlformattingansipatchRenderinglcsvisualizationunifiedmyers

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP CS Fixer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/alto-code-diff/health.svg)

```
[![Health](https://phpackages.com/badges/alto-code-diff/health.svg)](https://phpackages.com/packages/alto-code-diff)
```

###  Alternatives

[fitztrev/laravel-html-minify

Minifies the HTML output of Laravel 4 applications

414211.4k](/packages/fitztrev-laravel-html-minify)[entomb/slim-json-api

Slim extension to implement fast JSON API's

268156.4k4](/packages/entomb-slim-json-api)[view-components/view-components

Flexible Framework-Agnostic UI for Enterprise Web Applications

2498.7k7](/packages/view-components-view-components)[helhum/typoscript-rendering

Can render a TypoScript path by URL, especially useful for Ajax dispatching

68653.7k12](/packages/helhum-typoscript-rendering)[phug/phug

Pug (ex-Jade) facade engine for PHP, HTML template engine structured by indentation

67292.2k13](/packages/phug-phug)[interaction-design-foundation/nova-unlayer-field

A Laravel Nova field for Unlayer to compose emails and landing pages.

35256.8k](/packages/interaction-design-foundation-nova-unlayer-field)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
