Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

History

335 Commits

Repository files navigation

DiffPlex BuildDiffPlex NuGet version

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

About the API

The DiffPlex library currently exposes several interfaces and classes 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.
  • IThreeWayDiffer (implemented by the ThreeWayDiffer class) - This interface provides three-way diff and merge functionality, enabling intelligent merging by comparing a base text with two modified versions to detect changes and conflicts.
  • UnidiffRenderer - A renderer class that generates unified diff (unidiff) format output compatible with Git, patch utilities, and other standard diff tools.

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

For use of the UnidiffRenderer class see:

  • Program.cs in the DiffPlex.ConsoleRunner project

Sample code

vardiff=InlineDiffBuilder.Diff(before,after);varsavedColor=Console.ForegroundColor;foreach(varlineindiff.Lines){switch(line.Type){caseChangeType.Inserted:Console.ForegroundColor=ConsoleColor.Green;Console.Write("+ ");break;caseChangeType.Deleted:Console.ForegroundColor=ConsoleColor.Red;Console.Write("- ");break;default:Console.ForegroundColor=ConsoleColor.Gray;// compromise for dark or light backgroundConsole.Write(" ");break;}Console.WriteLine(line.Text);}Console.ForegroundColor=savedColor;

IDiffer Interface

/// <summary>/// Provides methods for generate differences between texts/// </summary>publicinterfaceIDiffer{/// <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>DiffResultCreateLineDiffs(stringoldText,stringnewText,boolignoreWhiteSpace);/// <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>DiffResultCreateCharacterDiffs(stringoldText,stringnewText,boolignoreWhitespace);/// <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>DiffResultCreateWordDiffs(stringoldText,stringnewText,boolignoreWhitespace,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>DiffResultCreateCustomDiffs(stringoldText,stringnewText,boolignoreWhiteSpace,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>DiffResultCreateDiffs(stringoldText,stringnewText,boolignoreWhiteSpace,boolignoreCase,IChunkerchunker);}

IChunker Interface

publicinterfaceIChunker{/// <summary>/// Dive text into sub-parts/// </summary>string[]Chunk(stringtext);}

Currently provided implementations:

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

UnidiffRenderer Class

The UnidiffRenderer class provides functionality to generate unified diff (unidiff) format output, which is the standard format used by Git, patch utilities, and other diff tools.

// Static method for simple usagestringunidiff=UnidiffRenderer.GenerateUnidiff(oldText:"old content",newText:"new content",oldFileName:"file1.txt",newFileName:"file2.txt");// Instance usage with custom settingsvarrenderer=newUnidiffRenderer(contextLines:5);stringunidiff=renderer.Generate(oldText,newText,"before.txt","after.txt");

Key features:

  • Generates standard unified diff format compatible with Git and patch tools
  • Configurable number of context lines around changes
  • Support for custom file names in diff headers
  • Options to ignore whitespace and case differences

Example output:

--- before.txt
+++ after.txt
@@ -1,4 +1,4 @@
Line 1
-Old line 2
+New line 2 Line 3
Line 4

IThreeWayDiffer Interface

The IThreeWayDiffer interface provides functionality for three-way diffing and merging, which is essential for merge operations in version control systems or when comparing three versions of text.

/// <summary>/// Responsible for generating three-way differences and merges between texts/// </summary>publicinterfaceIThreeWayDiffer{/// <summary>/// Creates a three-way diff by comparing base, old, and new text line by line./// </summary>ThreeWayDiffResultCreateDiffs(stringbaseText,stringoldText,stringnewText,boolignoreWhiteSpace,boolignoreCase,IChunkerchunker);/// <summary>/// Creates a three-way merge by comparing base, old, and new text line by line./// </summary>ThreeWayMergeResultCreateMerge(stringbaseText,stringoldText,stringnewText,boolignoreWhiteSpace,boolignoreCase,IChunkerchunker);}

Three-way diffing compares three versions of text:

  • Base text: The common ancestor or original version
  • Old text: One modified version (e.g., your changes)
  • New text: Another modified version (e.g., incoming changes)

This enables intelligent merging by identifying:

  • Changes unique to the old version
  • Changes unique to the new version
  • Changes made to both versions (conflicts)
  • Unchanged sections
varthreeWayDiffer=newThreeWayDiffer();// Three-way diffvardiffResult=threeWayDiffer.CreateDiffs(baseText,oldText,newText,ignoreWhiteSpace:false,ignoreCase:false,newLineChunker());// Three-way merge with automatic conflict detectionvarmergeResult=threeWayDiffer.CreateMerge(baseText,oldText,newText,ignoreWhiteSpace:false,ignoreCase:false,newLineChunker());// Check for conflictsif(mergeResult.HasConflicts){Console.WriteLine($"Found {mergeResult.ConflictBlocks.Count} conflicts");}else{Console.WriteLine("Merge completed successfully");Console.WriteLine(mergeResult.MergedText);}

ISideBySideDifferBuilder Interface

/// <summary>/// Provides methods that generate differences between texts for displaying in a side by side view./// </summary>publicinterfaceISideBySideDiffBuilder{/// <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>SideBySideDiffModelBuildDiffModel(stringoldText,stringnewText);}

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

Sample Blazor App

DiffPlex includes a Blazor sample application demonstrating how to render textual diffs in modern Blazor applications. The sample showcases both server-side and client-side rendering capabilities with interactive diff visualization.

image

The Blazor components provide:

  • Interactive side-by-side diff rendering
  • Inline diff view mode
  • Unififf rendering
  • Three-way merge

image

image

To run the sample Blazor application:

cd DiffPlex.Blazor
dotnet run

Windows app

There are 2 libraries for Windows app development. One is for Windows App SDK, another is for WPF and WinForms.

WinUI 3 Elements

NuGet

DiffPlex WinUI library DiffPlex.Windows is used to render textual diffs in your app which targets to Windows App SDK.

usingDiffPlex.UI;

And insert following code into the root node of your xaml file, e.g. user control, page or window.

xmlns:diffplex="using:DiffPlex.UI"
  • DiffTextView Textual diffs view element.

For example.

<diffplex:DiffTextViewx:Name="DiffView" />
DiffView.SetText(OldText,NewText);

WinUI sample

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

// true if it is in split view; otherwise, false, in unified view.publicboolIsSplitView{get;set;}// true if it is in unified view; otherwise, false, in split view.publicboolIsUnifiedView{get;set;}// The selection mode of list view. Default is None.publicListViewSelectionModeSelectionMode{get;set;}// true if ignore white spaces; otherwise, false. Default is true.publicboolIgnoreWhiteSpace{get;set;}// true if the text is case sensitive; otherwise, false. Default is false.publicboolIsCaseSensitive{get;set;}// The default text color (foreground brush).publicBrushForeground{get;set;}// The background.publicBrushBackground{get;set;}// The width of the line number. Default is 50.publicGridLengthLineNumberWidth{get;set;}// The style of the line number.publicStyleLineNumberStyle{get;set;}// The width of the change type symbol. Default is 20.publicGridLengthChangeTypeWidth{get;set;}// The style of the change type symbol.publicStyleChangeTypeStyle{get;set;}// The style of the text.publicStyleTextStyle{get;set;}// true if the text is selection enabled; otherwise, false. Default is true.publicboolIsTextSelectionEnabled{get;set;}// true if collapse unchanged sections; otherwise, false. Default is false.publicboolIsUnchangedSectionCollapsed{get;set;}// The lines for context. Default is 2.publicintLineCountForContext{get;set;}// true if the file selector menu button is enabled; otherwise, false. Default is true.publicboolIsFileMenuEnabled{get;set;}// The height of command bar. Default is 50.publicGridLengthCommandBarHeight{get;set;}// The default label position of command bar. Default is Right.publicCommandBarDefaultLabelPositionCommandLabelPosition{get;set;}// The collection of secondary command elements for the command bar.publicIObservableVector<ICommandBarElement>SecondaryCommands{get;}

WPF Controls

NuGet

DiffPlex WPF control library DiffPlex.Wpf is used to render textual diffs in your WPF application. It targets .NET 9, .NET 8, .NET 6, .NET Framework 4.8 and .NET Framework 4.6.

usingDiffPlex.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"
  • 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:DiffViewerx: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.publicstringOldTextHeader{get;set;}// The header of new text.publicstringNewTextHeader{get;set;}// true if it is in side-by-side (split) view;// otherwise, false, in inline (unified) view.publicboolIsSideBySideViewMode{get;}// true if collapse unchanged sections; otherwise, false.publicboolIgnoreUnchanged{get;set;}// Hides the line numbers.publicboolHideLineNumbers{get;set;}// The font size.publicdoubleFontSize{get;set;}// The preferred font family.publicFontFamilyFontFamily{get;set;}// The font weight.publicFontWeightFontWeight{get;set;}// The font style.publicFontStyleFontStyle{get;set;}// The font-stretching characteristics.publicFontStretchFontStretch{get;set;}// The default text color (foreground brush).publicBrushForeground{get;set;}// The background brush of the line inserted.publicBrushInsertedBackground{get;set;}// The background brush of the line deleted.publicBrushDeletedBackground{get;set;}// The text color (foreground brush) of the line number.publicBrushLineNumberForeground{get;set;}// The width of the line number and change type symbol.publicintLineNumberWidth{get;set;}// The background brush of the line imaginary.publicBrushImaginaryBackground{get;set;}// The text color (foreground brush) of the change type symbol.publicBrushChangeTypeForeground{get;set;}// The background brush of the header.publicBrushHeaderBackground{get;set;}// The height of the header.publicdoubleHeaderHeight{get;set;}// The background brush of the grid splitter.publicBrushSplitterBackground{get;set;}// The width of the grid splitter.publicThicknessSplitterWidth{get;set;}// A value that represents the actual calculated width of the left side panel.publicdoubleLeftSideActualWidth{get;}// A value that represents the actual calculated width of the right side panel.publicdoubleRightSideActualWidth{get;}

And you can listen following event handlers.

// Occurs when the grid splitter loses mouse capture.publiceventDragCompletedEventHandler SplitterDragCompleted;// Occurs one or more times as the mouse changes position when the grid splitter has logical focus and mouse capture.publiceventDragDeltaEventHandler SplitterDragDelta;// Occurs when the grid splitter receives logical focus and mouse capture.publiceventDragStartedEventHandler SplitterDragStarted;// Occurs when the view mode is changed.publiceventEventHandler<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 8, .NET 6, .NET Framework 4.8 and .NET Framework 4.6.

usingDiffPlex.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.

publicpartialclassForm1:Form{publicForm1(){InitializeComponent();vardiffView=newDiffViewer{Margin=newPadding(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.publicstringOldTextHeader{get;set;}// The header of new text.publicstringNewTextHeader{get;set;}// true if it is in side-by-side (split) view;// otherwise, false, in inline (unified) view.publicboolIsSideBySideViewMode{get;}// true if collapse unchanged sections; otherwise, false.publicboolIgnoreUnchanged{get;set;}// The font size.publicdoubleFontSize{get;set;}// The preferred font family names in string.publicstringFontFamilyNames{get;set;}// The font weight.publicintFontWeight{get;set;}// The font style.publicboolIsFontItalic{get;set;}// The default text color (foreground brush).publicColorForeColor{get;set;}// The background brush of the line inserted.publicColorInsertedBackColor{get;set;}// The background brush of the line deleted.publicColorDeletedBackColor{get;set;}// The text color (foreground color) of the line number.publicColorLineNumberForeColor{get;set;}// The width of the line number and change type symbol.publicintLineNumberWidth{get;set;}// The background brush of the line imaginary.publicColorImaginaryBackColor{get;set;}// The text color (foreground color) of the change type symbol.publicColorChangeTypeForeColor{get;set;}// The background brush of the header.publicColorHeaderBackColor{get;set;}// The height of the header.publicdoubleHeaderHeight{get;set;}// The background brush of the grid splitter.publicColorSplitterBackColor{get;set;}// The width of the grid splitter.publicPaddingSplitterWidth{get;set;}// A value that represents the actual calculated width of the left side panel.publicdoubleLeftSideActualWidth{get;}// A value that represents the actual calculated width of the right side panel.publicdoubleRightSideActualWidth{get;}

About

DiffPlex is Netstandard 2.0+ C# library to generate textual diffs.

Resources

Stars

1.3k stars

Watchers

45 watching

Forks

Releases

Sponsor this project

Packages

Used by

Contributors

Languages