TextDiffLibrary 1.0.2

dotnet add package TextDiffLibrary --version 1.0.2
                    
NuGet\Install-Package TextDiffLibrary -Version 1.0.2
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="TextDiffLibrary" Version="1.0.2" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="TextDiffLibrary" Version="1.0.2" />
                    
Directory.Packages.props
<PackageReference Include="TextDiffLibrary" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add TextDiffLibrary --version 1.0.2
                    
#r "nuget: TextDiffLibrary, 1.0.2"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package TextDiffLibrary@1.0.2
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=TextDiffLibrary&version=1.0.2
                    
Install as a Cake Addin
#tool nuget:?package=TextDiffLibrary&version=1.0.2
                    
Install as a Cake Tool

TextDiffLibrary

NuGet License: MIT

TextDiffLibrary is a high-performance text comparison library for .NET 9.0, implementing the Myers diff algorithm with support for both line-level and character-level differences. Ideal for comparing SQL stored procedures, configuration files, or any text content.

โœจ Features

  • ๐Ÿš€ Myers Diff Algorithm - Industry-standard, efficient O(ND) complexity
  • ๐Ÿ“Š Line & Character Level Diffs - Detailed change tracking
  • ๐ŸŽจ Multiple Output Formats:
    • Excel DTO - Side-by-side comparison for spreadsheet export
    • JSON - Structured data for API integration
    • Unified Diff - Git-compatible patch format
    • HTML - Rich visual comparison with syntax highlighting
  • โš™๏ธ Configurable Options:
    • Ignore whitespace/case/empty lines
    • Character-level diff toggle
    • Custom context lines for unified diff
  • ๐Ÿ’‰ Dependency Injection Ready - Built-in DI support with AddTextDiffLibrary()
  • ๐Ÿ”ง Async Support - Non-blocking diff computation
  • ๐Ÿ“ Strongly Typed - Full C# nullable reference types support

๐Ÿ“ฆ Installation

NuGet Package Manager

Install-Package TextDiffLibrary

.NET CLI

dotnet add package TextDiffLibrary

Package Reference

<PackageReference Include="TextDiffLibrary" Version="1.0.0" />

๐Ÿš€ Quick Start

1. Setup Dependency Injection

using Microsoft.Extensions.DependencyInjection;
using TextDiffLibrary.Core.Extensions;

var services = new ServiceCollection();
services.AddTextDiffLibrary();
var serviceProvider = services.BuildServiceProvider();

2. Basic Text Comparison

using TextDiffLibrary.Contracts.Interfaces;
using TextDiffLibrary.Contracts.Models;

// Get the differ service
var differ = serviceProvider.GetRequiredService<ITextDiffer>();

// Source and target texts
string sourceText = """
    SELECT * FROM Users
    WHERE Age > 18
    ORDER BY Name
    """;

string targetText = """
    SELECT Name, Email FROM Users
    WHERE Age > 21
    ORDER BY Email
    """;

// Configure comparison options
var options = DiffOptions.CreateDefault(); // or customize

// Create comparison context
var context = ComparisonContext.Create(sourceText, targetText, options);

// Perform comparison
var result = differ.Compare(context);

// Access results
Console.WriteLine($"Total Changes: {result.Statistics.TotalChanges}");
Console.WriteLine($"Added: {result.Statistics.AddedLines}");
Console.WriteLine($"Deleted: {result.Statistics.DeletedLines}");
Console.WriteLine($"Modified: {result.Statistics.ModifiedLines}");

3. Iterate Over Changes

foreach (var line in result.Lines)
{
    Console.WriteLine($"[{line.ChangeType}] Line {line.SourceLineNumber ?? line.TargetLineNumber}");
    
    if (line.ChangeType == ChangeType.Modified && line.CharacterChanges != null)
    {
        foreach (var charChange in line.CharacterChanges)
        {
            Console.WriteLine($"  Char change at pos {charChange.Position}: {charChange.OldValue} โ†’ {charChange.NewValue}");
        }
    }
}

๐ŸŽจ Output Formats

JSON Output

using TextDiffLibrary.Contracts.Interfaces;

var formatterFactory = serviceProvider.GetRequiredService<IFormatterFactory>();

// Use type-safe enum
var jsonFormatter = formatterFactory.GetFormatter<string>(FormatterType.Json);
var json = jsonFormatter.Format(result);

File.WriteAllText("diff-result.json", json);

Unified Diff (Git-compatible)

var unifiedFormatter = formatterFactory.GetFormatter<string>(FormatterType.Unified);
var patch = unifiedFormatter.Format(result);

File.WriteAllText("changes.patch", patch);
// Apply with: git apply changes.patch

HTML Report

var htmlFormatter = formatterFactory.GetFormatter<string>(FormatterType.Html);
var html = htmlFormatter.Format(result);

File.WriteAllText("diff-report.html", html);
Process.Start(new ProcessStartInfo("diff-report.html") { UseShellExecute = true });

Excel DTO (for spreadsheet export)

using TextDiffLibrary.Contracts.DTOs;

var excelFormatter = formatterFactory.GetFormatter<ExcelDiffDto>(FormatterType.Excel);
var excelDto = excelFormatter.Format(result);

foreach (var row in excelDto.Rows)
{
    Console.WriteLine($"{row.Status}: {row.SourceContent} โ†’ {row.TargetContent}");
}

โš™๏ธ Configuration Options

DiffOptions

var options = new DiffOptions
{
    IgnoreWhitespace = true,           // Normalize whitespace differences
    IgnoreCase = true,                 // Case-insensitive comparison
    IgnoreEmptyLines = true,           // Skip empty lines
    EnableCharacterLevelDiff = true    // Compute character-level changes for Modified lines
};

Configure via appsettings.json

{
  "TextDiffLibrary": {
    "DefaultIgnoreWhitespace": true,
    "DefaultIgnoreCase": true,
    "DefaultIgnoreEmptyLines": true,
    "DefaultEnableCharacterDiff": true,
    "UnifiedDiffContextLines": 3,
    "EnablePerformanceLogging": false
  }
}
// Program.cs (ASP.NET Core / Web API)
builder.Services.AddTextDiffLibrary(options =>
{
    builder.Configuration.GetSection("TextDiffLibrary").Bind(options);
    options.Validate();
});

๐Ÿ—๏ธ Architecture

TextDiffLibrary
โ”œโ”€โ”€ TextDiffLibrary.Contracts     - Interfaces, Models, DTOs
โ”œโ”€โ”€ TextDiffLibrary.Core          - Myers Algorithm, Services
โ””โ”€โ”€ TextDiffLibrary.Formatters    - Output Formatters (JSON, HTML, etc.)

Key Interfaces

  • ITextDiffer - Main diff computation service
  • ITextNormalizer - Text preprocessing (whitespace, case)
  • IMyersDiffEngine - Core Myers diff algorithm
  • ICharacterDiffer - Character-level diff for modified lines
  • IOutputFormatter<TOutput> - Generic formatter interface
  • IFormatterFactory - Formatter resolution (by string or enum)

๐Ÿ“š Advanced Usage

Async Comparison

var result = await differ.CompareAsync(context, cancellationToken);

Custom JSON Serialization Options

builder.Services.AddTextDiffLibrary(options =>
{
    options.JsonSerializerOptions = new JsonSerializerOptions
    {
        WriteIndented = false,
        PropertyNamingPolicy = JsonNamingPolicy.CamelCase
    };
});

E2E Workflow with DiffService

using TextDiffLibrary.Core.Services;

var diffService = serviceProvider.GetRequiredService<DiffService>();

// Compute diff and format in one call (uses configured options if null)
var json = diffService.ComputeAndFormat<string>(sourceText, targetText, null, FormatterType.Json);
var html = diffService.ComputeAndFormat<string>(sourceText, targetText, null, FormatterType.Html);

๐Ÿ”ง Customization

Create Custom Formatter

public class MarkdownFormatter : IOutputFormatter<string>
{
    public string Format(DiffResult result)
    {
        var sb = new StringBuilder();
        sb.AppendLine("# Diff Report");
        
        foreach (var line in result.Lines)
        {
            sb.AppendLine($"- **{line.ChangeType}**: {line.SourceContent ?? line.TargetContent}");
        }
        
        return sb.ToString();
    }
}

// Register in DI
services.AddSingleton<MarkdownFormatter>();

๐Ÿ“Š Performance

  • Algorithm: Myers diff - O(ND) time complexity (N = input size, D = edit distance)
  • Memory: O(N) with trace optimization
  • Optimizations:
    • String hashing for fast equality checks
    • Early termination for identical files
    • Efficient line pairing with similarity threshold (80%)

Benchmarks (example)

Input Size Time (ms) Memory (MB)
100 lines 5 ms 2 MB
1,000 lines 50 ms 15 MB
5,000 lines 250 ms 70 MB

๐Ÿงช Testing

The library includes comprehensive test coverage:

  • 118+ unit tests covering all components
  • Integration tests for E2E workflows
  • Edge case handling (empty files, identical files, all changes)
dotnet test
# Test summary: total: 118; failed: 0; succeeded: 118; skipped: 0

๐Ÿ“„ License

This project is licensed under the MIT License. See LICENSE for details.


๐Ÿค Contributing

Contributions are welcome! Please follow these steps:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/AmazingFeature)
  3. Commit your changes (git commit -m 'Add AmazingFeature')
  4. Push to the branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

๐Ÿ“ Changelog

v1.0.0 (2026-01-27)

  • โœจ Initial release
  • ๐Ÿš€ Myers diff algorithm implementation
  • ๐Ÿ“Š Line and character-level diff support
  • ๐ŸŽจ Four output formatters (Excel DTO, JSON, Unified Diff, HTML)
  • โš™๏ธ Configurable comparison options
  • ๐Ÿ’‰ Dependency injection integration
  • ๐Ÿ”ง Async support


๐Ÿ’ก Use Cases

  • ๐Ÿ“œ SQL Stored Procedure Comparison - Track changes in database schema
  • ๐Ÿ”ง Configuration File Diffs - Monitor application config changes
  • ๐Ÿ“ Document Versioning - Compare text document revisions
  • ๐ŸŒ API Response Validation - Diff JSON/XML responses
  • ๐Ÿงช Test Result Comparison - Validate test output changes

๐Ÿ‘ฅ Authors

Maintained by the TextDiffLibrary contributors.


Happy Diffing! ๐ŸŽ‰

Product Compatible and additional computed target framework versions.
.NET net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.2 31 2/24/2026

v1.0.2 - Added word-level diff support with DetailLevel enum (None/Character/Word). Tokenizes words, whitespace, and punctuation separately. Replaced EnableCharacterLevelDiff with DetailLevel property for better extensibility. HTML formatter now highlights character and word changes with darker colors. Fully backward compatible via DI.