DiffPlex 1.7.1

There is a newer version of this package available.
See the version list below for details.
dotnet add package DiffPlex --version 1.7.1
NuGet\Install-Package DiffPlex -Version 1.7.1
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="DiffPlex" Version="1.7.1" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add DiffPlex --version 1.7.1
#r "nuget: DiffPlex, 1.7.1"
#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.
// Install DiffPlex as a Cake Addin
#addin nuget:?package=DiffPlex&version=1.7.1

// Install DiffPlex as a Cake Tool
#tool nuget:?package=DiffPlex&version=1.7.1

DiffPlex .NET DiffPlex NuGet version

DiffPlex is C# library to generate textual diffs. It targets netstandard1.0+.

About the API

The DiffPlex library currently exposes two interfaces for generating diffs:

  • IDiffer (implemented by the Differ class) - This is the core diffing class. It exposes the low level functions to generate differences between texts.
  • ISidebySideDiffer (implemented by the SideBySideDiffer class) - This is a higher level interface. It consumes the IDiffer interface and generates a SideBySideDiffModel. This is a model which is suited for displaying the differences of two pieces of text in a side by side view.

Examples

For examples of how to use the API please see the the following projects contained in the DiffPlex solution.

For use of the IDiffer interface see:

  • SidebySideDiffer.cs contained in the DiffPlex Project.
  • UnidiffFormater.cs contained in the DiffPlex.ConsoleRunner project.

For use of the ISidebySideDiffer interface see:

  • DiffController.cs and associated MVC views in the WebDiffer project
  • TextBoxDiffRenderer.cs in the SilverlightDiffer project

Sample code

var diff = InlineDiffBuilder.Diff(before, after);

var savedColor = Console.ForegroundColor;
foreach (var line in diff.Lines)
{
    switch (line.Type)
    {
        case ChangeType.Inserted:
            Console.ForegroundColor = ConsoleColor.Green;
            Console.Write("+ ");
            break;
        case ChangeType.Deleted:
            Console.ForegroundColor = ConsoleColor.Red;
            Console.Write("- ");
            break;
        default:
            Console.ForegroundColor = ConsoleColor.Gray; // compromise for dark or light background
            Console.Write("  ");
            break;
    }

    Console.WriteLine(line.Text);
}
Console.ForegroundColor = savedColor;

IDiffer Interface

/// <summary>
/// Provides methods for generate differences between texts
/// </summary>
public interface IDiffer
{
    /// <summary>
    /// Create a diff by comparing text line by line
    /// </summary>
    /// <param name="oldText">The old text.</param>
    /// <param name="newText">The new text.</param>
    /// <param name="ignoreWhiteSpace">if set to <c>true</c> will ignore white space when determining if lines are the same.</param>
    /// <returns>A DiffResult object which details the differences</returns>
    DiffResult CreateLineDiffs(string oldText, string newText, bool ignoreWhiteSpace);

    /// <summary>
    /// Create a diff by comparing text character by character
    /// </summary>
    /// <param name="oldText">The old text.</param>
    /// <param name="newText">The new text.</param>
    /// <param name="ignoreWhitespace">if set to <c>true</c> will treat all whitespace characters are empty strings.</param>
    /// <returns>A DiffResult object which details the differences</returns>
    DiffResult CreateCharacterDiffs(string oldText, string newText, bool ignoreWhitespace);

    /// <summary>
    /// Create a diff by comparing text word by word
    /// </summary>
    /// <param name="oldText">The old text.</param>
    /// <param name="newText">The new text.</param>
    /// <param name="ignoreWhitespace">if set to <c>true</c> will ignore white space when determining if words are the same.</param>
    /// <param name="separators">The list of characters which define word separators.</param>
    /// <returns>A DiffResult object which details the differences</returns>
    DiffResult CreateWordDiffs(string oldText, string newText, bool ignoreWhitespace, char[] separators);

    /// <summary>
    /// Create a diff by comparing text in chunks determined by the supplied chunker function.
    /// </summary>
    /// <param name="oldText">The old text.</param>
    /// <param name="newText">The new text.</param>
    /// <param name="ignoreWhiteSpace">if set to <c>true</c> will ignore white space when determining if chunks are the same.</param>
    /// <param name="chunker">A function that will break the text into chunks.</param>
    /// <returns>A DiffResult object which details the differences</returns>
    DiffResult CreateCustomDiffs(string oldText, string newText, bool ignoreWhiteSpace, Func<string, string[]> chunker);

            /// <summary>
        /// Create a diff by comparing text line by line
        /// </summary>
        /// <param name="oldText">The old text.</param>
        /// <param name="newText">The new text.</param>
        /// <param name="ignoreWhiteSpace">if set to <c>true</c> will ignore white space when determining if lines are the same.</param>
        /// <param name="ignoreCase">Determine if the text comparision is case sensitive or not</param>
        /// <param name="chunker">Component responsible for tokenizing the compared texts</param>
        /// <returns>A DiffResult object which details the differences</returns>
        DiffResult CreateDiffs(string oldText, string newText, bool ignoreWhiteSpace, bool ignoreCase, IChunker chunker);
}

IChunker Interface

public interface IChunker
{
    /// <summary>
    /// Dive text into sub-parts
    /// </summary>
    string[] Chunk(string text);
}

Currently provided implementations:

  • CharacterChunker
  • CustomFunctionChunker
  • DelimiterChunker
  • LineChunker
  • LineEndingsPreservingChunker
  • WordChunker

ISideBySideDifferBuilder Interface

/// <summary>
/// Provides methods that generate differences between texts for displaying in a side by side view.
/// </summary>
public interface ISideBySideDiffBuilder
{
    /// <summary>
    /// Builds a diff model for  displaying diffs in a side by side view
    /// </summary>
    /// <param name="oldText">The old text.</param>
    /// <param name="newText">The new text.</param>
    /// <returns>The side by side diff model</returns>
    SideBySideDiffModel BuildDiffModel(string oldText, string newText);
}

Sample Website

DiffPlex also contains a sample website that shows how to create a basic side by side diff in an ASP MVC website.

Web page sample

WPF Controls

NuGet

DiffPlex WPF control library DiffPlex.Wpf is used to render textual diffs in your WPF application. It targets .NET 5, .NET Core 3.1, .NET Framework 4.8 and .NET Framework 4.6.

using DiffPlex.Wpf.Controls;

To import the controls into your window/page/control, please insert following attribute into the root node (such as <Window />) of your xaml files.

xmlns:diffplex="clr-namespace:DiffPlex.Wpf.Controls;assembly=DiffPlex.Wpf"

Then you can add one of following controls in UI.

  • DiffViewer Textual diffs viewer control with view mode switching by setting an old text and a new text to diff.
  • SideBySideDiffViewer Side-by-side (splitted) textual diffs viewer control by setting a diff model SideBySideDiffModel.
  • InlineDiffViewer Inline textual diffs viewer control by setting a diff model DiffPaneModel.

For example.

<diffplex:DiffViewer x:Name="DiffView" />
DiffView.OldText = oldText;
DiffView.NewText = newText;

WPF sample

You can also customize the style. Following are some of the properties you can get or set.

// The header of old text.
public string OldTextHeader { get; set; }

// The header of new text.
public string NewTextHeader { get; set; }

// The header of new text.
public string NewTextHeader { get; set; }

// true if it is in side-by-side (split) view;
// otherwise, false, in inline (unified) view.
public bool IsSideBySideViewMode { get; }

// true if collapse unchanged sections; otherwise, false.
public bool IgnoreUnchanged { get; set; }

// The font size.
public double FontSize { get; set; }

// The preferred font family.
public FontFamily FontFamily { get; set; }

// The font weight.
public FontWeight FontWeight { get; set; }

// The font style.
public FontStyle FontStyle { get; set; }

// The font-stretching characteristics.
public FontStretch FontStretch { get; set; }

// The default text color (foreground brush).
public Brush Foreground { get; set; }

// The background brush of the line inserted.
public Brush InsertedBackground { get; set; }

// The background brush of the line deleted.
public Brush DeletedBackground { get; set; }

// The text color (foreground brush) of the line number.
public Brush LineNumberForeground { get; set; }

// The width of the line number and change type symbol.
public int LineNumberWidth { get; set; }

// The background brush of the line imaginary.
public Brush ImaginaryBackground { get; set; }

// The text color (foreground brush) of the change type symbol.
public Brush ChangeTypeForeground { get; set; }

// The background brush of the header.
public Brush HeaderBackground { get; set; }

// The height of the header.
public double HeaderHeight { get; set; }

// The background brush of the grid splitter.
public Brush SplitterBackground { get; set; }

// The width of the grid splitter.
public Thickness SplitterWidth { get; set; }

// A value that represents the actual calculated width of the left side panel.
public double LeftSideActualWidth { get; }

// A value that represents the actual calculated width of the right side panel.
public double RightSideActualWidth { get; }

And you can listen following event handlers.


// Occurs when the grid splitter loses mouse capture.
public event DragCompletedEventHandler SplitterDragCompleted;

// Occurs one or more times as the mouse changes position when the grid splitter has logical focus and mouse capture.
public event DragDeltaEventHandler SplitterDragDelta;

// Occurs when the grid splitter receives logical focus and mouse capture.
public event DragStartedEventHandler SplitterDragStarted;

// Occurs when the view mode is changed.
public event EventHandler<ViewModeChangedEventArgs> ViewModeChanged;

WinForms Controls

NuGet

Windows Forms control of diff viewer is a WPF element host control. It is also included in DiffPlex.Wpf assembly. You can import it to use in your Windows Forms application. It targets .NET 5, .NET Core 3.1, .NET Framework 4.8 and .NET Framework 4.6.

using DiffPlex.WindowsForms.Controls;

Then you can add the following control in window or user control.

  • DiffViewer Textual diffs viewer control with view mode switching by setting an old text and a new text to diff.

For example.

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();

        var diffView = new DiffViewer
        {
            Margin = new Padding(0),
            Dock = DockStyle.Fill,
            OldText = oldText,
            NewText = newText
        };
        Controls.Add(diffView);
    }
}

Windows Forms sample

You can also customize the style. Following are some of the properties you can get or set.

// The header of old text.
public string OldTextHeader { get; set; }

// The header of new text.
public string NewTextHeader { get; set; }

// The header of new text.
public string NewTextHeader { get; set; }

// true if it is in side-by-side (split) view;
// otherwise, false, in inline (unified) view.
public bool IsSideBySideViewMode { get; }

// true if collapse unchanged sections; otherwise, false.
public bool IgnoreUnchanged { get; set; }

// The font size.
public double FontSize { get; set; }

// The preferred font family names in string.
public string FontFamilyNames { get; set; }

// The font weight.
public int FontWeight { get; set; }

// The font style.
public bool IsFontItalic { get; set; }

// The default text color (foreground brush).
public Color ForeColor { get; set; }

// The background brush of the line inserted.
public Color InsertedBackColor { get; set; }

// The background brush of the line deleted.
public Color DeletedBackColor { get; set; }

// The text color (foreground color) of the line number.
public Color LineNumberForeColor { get; set; }

// The width of the line number and change type symbol.
public int LineNumberWidth { get; set; }

// The background brush of the line imaginary.
public Color ImaginaryBackColor { get; set; }

// The text color (foreground color) of the change type symbol.
public Color ChangeTypeForeColor { get; set; }

// The background brush of the header.
public Color HeaderBackColor { get; set; }

// The height of the header.
public double HeaderHeight { get; set; }

// The background brush of the grid splitter.
public Color SplitterBackColor { get; set; }

// The width of the grid splitter.
public Padding SplitterWidth { get; set; }

// A value that represents the actual calculated width of the left side panel.
public double LeftSideActualWidth { get; }

// A value that represents the actual calculated width of the right side panel.
public double RightSideActualWidth { get; }
Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
.NET Core netcoreapp1.0 was computed.  netcoreapp1.1 was computed.  netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard1.0 is compatible.  netstandard1.1 was computed.  netstandard1.2 was computed.  netstandard1.3 was computed.  netstandard1.4 was computed.  netstandard1.5 was computed.  netstandard1.6 was computed.  netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net35 is compatible.  net40 is compatible.  net403 was computed.  net45 was computed.  net451 was computed.  net452 was computed.  net46 was computed.  net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen30 was computed.  tizen40 was computed.  tizen60 was computed. 
Universal Windows Platform uap was computed.  uap10.0 was computed. 
Windows Phone wp8 was computed.  wp81 was computed.  wpa81 was computed. 
Windows Store netcore was computed.  netcore45 was computed.  netcore451 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • .NETFramework 3.5

    • No dependencies.
  • .NETFramework 4.0

    • No dependencies.
  • .NETStandard 1.0

  • .NETStandard 2.0

    • No dependencies.
  • net6.0

    • No dependencies.

NuGet packages (39)

Showing the top 5 NuGet packages that depend on DiffPlex:

Package Downloads
Microsoft.CodeAnalysis.Analyzer.Testing The ID prefix of this package has been reserved for one of the owners of this package by NuGet.org.

Roslyn Analyzer Test Framework Common Types.

ppy.osu.Game

Package Description

Verify.DiffPlex The ID prefix of this package has been reserved for one of the owners of this package by NuGet.org.

Extends Verify (https://github.com/VerifyTests/Verify) to allow comparison of text via DiffPlex (https://github.com/mmanela/diffplex).

DiffPlex.Wpf

DiffPlex.Wpf is a WPF control library that allows you to programatically render visual text diffs in your application. It also provide a diff viewer control used in Windows Forms application.

Expecto.Diff The ID prefix of this package has been reserved for one of the owners of this package by NuGet.org.

Integration of Expecto with DiffPlex

GitHub repositories (39)

Showing the top 5 popular GitHub repositories that depend on DiffPlex:

Repository Stars
dotnet/roslyn
The Roslyn .NET compiler provides C# and Visual Basic languages with rich code analysis APIs.
ppy/osu
rhythm is just a *click* away!
0x7c13/Notepads
A modern, lightweight text editor with a minimalist design.
Humanizr/Humanizer
Humanizer meets all your .NET needs for manipulating and displaying strings, enums, dates, times, timespans, numbers and quantities
dotnet/reactive
The Reactive Extensions for .NET
Version Downloads Last updated
1.7.2 175,706 12/11/2023
1.7.1 2,361,550 3/5/2022
1.7.0 1,504,797 3/10/2021
1.6.3 1,851,672 5/30/2020
1.6.2 11,568 5/22/2020
1.6.1 335,163 4/1/2020
1.6.0 1,941 3/31/2020
1.5.0 2,131,993 11/26/2019
1.4.4 1,618,664 3/21/2019
1.4.3 45,221 1/24/2019
1.4.2 175,321 9/21/2018
1.4.1 542,784 3/31/2017
1.4.0 1,980 3/20/2017
1.3.0 4,904 3/14/2017
1.2.1 537,306 9/14/2014
1.2.0 50,737 5/23/2011
1.1.0 7,566 3/10/2011

Fixed diffing of sub-components (like words). Ensures ignoreWhitespace and ignoreCase are honoroed in that case and that the parent reflects modification state of the child.