Skip to content
IzzyBlazor 0.1.0-alpha.20

Enter all results ↑ ↓ move Esc close

Diff

Since 0.1.0-alpha.20
The lines two texts differ by, unified or side by side.

Static server-side rendering: no circuit, no WebAssembly.

Usage

razor
<Diff OldText="@older.Xml" NewText="@newer.Xml" Language="xml" Title="v3 → v4" />

<Diff OldText="@before" NewText="@after" Language="csharp" Layout="DiffLayout.Split" />

The diff is computed and colored on the server, so it looks the same with JavaScript off. Lines removed and added carry a − or + and their old or new line number; the numbers and signs aren't copied when you select the lines.

Two versions

Use OldText and NewText for the two texts and Language to color them; unchanged lines away from the changes fold.

Preview

v3 → v4
<?xml version="1.0" encoding="utf-8"?>
<ruleset xmlns="urn:rulebook:ruleset" id="putaway" name="Putaway" schemaVersion="1">
<scope site="CLT1"/>
<constraints>
Removed: <!-- Released tasks only. -->
<rule id="released" reason="Only released tasks are put away.">
Removed: <condition field="task.hostStatus" op="eq" value="released"/>
Added: <condition field="task.hostStatus" op="in"><value>released</value><value>staged</value></condition>
</rule>
<rule id="no-hazmat-mezzanine" reason="Hazardous goods stay off the mezzanine.">
<condition field="item.hazmat" op="eq" value="true"/>
<condition field="location.zone" op="eq" value="MEZZ"/>
</rule>
<rule id="weight" reason="Heavy items go on the floor.">
Removed: <condition field="item.weightKg" op="gt" value="25"/>
Added: <condition field="item.weightKg" op="gt" value="20"/>
<condition field="location.level" op="gt" value="1"/>
Added: </rule>Added: <rule id="cold" reason="Chilled items stay in the cooler.">Added: <condition field="item.storage" op="eq" value="chilled"/>Added: <condition field="location.zone" op="ne" value="COOL"/>
</rule>
</constraints>
<bands>
9 unchanged lines
<band id="fast" reason="Fast movers near the dock.">
<condition field="item.velocity" op="eq" value="A"/>
</band>
<band id="slow" reason="Slow movers at the back.">
<condition field="item.velocity" op="in"><value>C</value><value>D</value></condition>
</band>
<otherwise id="normal" reason="Everything else."/>
</bands>
</ruleset>

Code

Versions.razor
<Diff OldText="@V3" NewText="@V4" Language="xml" Title="v3 → v4" />

Each text is colored whole before it's cut into lines, so a comment or value across several lines keeps its color. In a removed line beside an added one, the changed words are marked, unless less than half of the longer line is unchanged (MarkWords turns this off). Context sets how many unchanged lines stay beside each change (3); the rest fold into a row that opens them in place.

Side by side

Use Layout DiffLayout.Split to put the old text beside the new; below 45rem wide it shows as unified.

Preview

OrderTotals.cs
Removed: public static decimal Total(Order order)
Added: public static decimal Total(Order order, decimal freeShippingOver = 50)
{
Removed: decimal total = 0;Removed: foreach (var line in order.Lines)Removed: {Removed: total += line.Price * line.Quantity;Removed: }
Added: var total = order.Lines.Sum(line => line.Price * line.Quantity);

Removed: // Free shipping over $50.Removed: if (total < 50)
Added: // Free shipping over the threshold.Added: if (total < freeShippingOver)
{
total += 4.99m;
}
3 unchanged lines

return total;
}

Code

SideBySide.razor
<Diff OldText="@Before" NewText="@After" Language="csharp" Title="OrderTotals.cs" Layout="DiffLayout.Split" />

Each removed line sits beside the line it became, and long lines wrap rather than scroll. Unchanged lines are drawn on both sides, so a split diff sends them twice.

Every line

Use Fold="false" to show every unchanged line and LineNumbers="false" to leave the numbers out, for a short text.

Preview

{
Removed: "retries": 3,
Added: "retries": 5,
"timeoutSeconds": 30,
Removed: "region": "us-east"
Added: "region": "us-east",Added: "logLevel": "warning"
}

Code

EveryLine.razor
<Diff OldText="@Before" NewText="@After" Language="json" Fold="false" LineNumbers="false" />

A diff computed first

Use Lines for a diff you computed with TextDiff.Compare or elsewhere, such as to count the changes first.

Preview

Release notes

2 added 1 removed
## 2.4.0

- Faster search on large lists.
Removed: - Fixed the export button on Safari.
Added: - Exports keep the column order.Added: - Fixed the export button on Safari and Firefox.

Code

Computed.razor
@{
    // Null when the texts differ by more lines than Compare looks for.
    var lines = TextDiff.Compare(Before, After);
}
<Column Gap="3">
    <Row Gap="2" Align="Align.Center">
        <TextBlock Weight="FontWeight.Medium">Release notes</TextBlock>
        @if (lines is not null)
        {
            <Badge Status="Status.Success">@lines.Count(l => l.Kind == DiffKind.Added) added</Badge>
            <Badge Status="Status.Danger">@lines.Count(l => l.Kind == DiffKind.Removed) removed</Badge>
        }
    </Row>
    @if (lines is not null)
    {
        <Diff Lines="lines" />
    }
    else
    {
        <TextBlock>Too many changes to show.</TextBlock>
    }
</Column>

TextDiff.Compare(oldText, newText) returns every line of both texts as a DiffLine (its Kind, OldNumber, NewNumber and Text), or null when they differ by more lines than it looks for. Lines from elsewhere should be every line of both texts, in order, removed lines before the added lines that replace them.

No changes, or too many

Use SameText and TooManyText to change the notes shown when the texts are the same, or differ by more than MaxChanges lines.

Preview

settings.json

The two texts are the same.

settings.json

The texts differ by more than 2 lines, too many to show line by line.

Code

Notes.razor
<Column Gap="4">
    <Diff OldText="@Text" NewText="@Text" Title="settings.json" />
    <Diff OldText="@Text" NewText="@Other" MaxChanges="2" Title="settings.json" />
</Column>

Large texts

The lines both texts start and end with cost nothing; past them, the comparison's work grows with the length of the rest times the lines that differ, and MaxChanges (1,000 lines removed and added) bounds it. Folded lines are still in the page, ready to open, so a 5,000-line file with one change sends 5,000 lines; set MaxHeight to keep a long diff in a scrolling box.

Mode support

What works in each mode, Diff
FeatureStaticInteractive
Lines removed and added, with old and new numbersYesYes
Changed words marked, colored as Code colors themYesYes
Unchanged runs folded, opened in placeYesYes
Side by side, unified when narrowYesYes

Static: static server-side rendering, with no circuit and no WebAssembly. Interactive: Server, WebAssembly or Auto.

Accessibility

  • The lines are a tab stop, so they can be scrolled from the keyboard: a group named by Title, or "Changes" without one, described by the counts ("3 added, 1 removed").
  • Each removed or added line starts with "Removed:" or "Added:" for screen readers; the visible + and −, the line numbers and that text aren't copied with the lines.
  • Colors aren't the only mark: removed and added lines have their sign, also in forced colors.
  • A folded run is a summary, opened with Enter or Space, read as collapsed or expanded.
  • In Split, unchanged lines are read once (the old side's copy is hidden from screen readers).

Parameters

Diff parameters
PropTypeDefault
OldTextThe old text.string?
NewTextThe new text.string?
LinesA diff computed elsewhere, such as by Compare, in place of OldText and NewText: every line of both texts, in order.IReadOnlyList<DiffLine>?
LanguageThe language, such as "xml", "csharp" or "json": colors the lines as Code does, when the highlighter knows it (see Languages).string?
HighlightColors the lines by Language.booltrue
TitleA file name or caption, such as "rules.xml" or "v3 → v4", in a header row above the lines.string?
LayoutDiffLayout.Unified (the default): one column, removed lines before added.DiffLayoutDiffLayout.Unified
ContextThe unchanged lines kept on each side of a change when the rest are folded.int3
FoldFolds runs of unchanged lines away from the changes into a row that opens them.booltrue
MarkWordsMarks the changed words of a removed line and the added line paired with it.booltrue
LineNumbersShows the old and new line numbers.booltrue
MaxHeightThe tallest the lines get before they scroll, such as Length.Rem(30).Length?
MaxChangesThe most lines removed and added to look for.int1000
SameTextShown when the two texts are the same.string?
TooManyTextShown when the texts differ by more than MaxChanges lines.string?

See also

Connection lost

Rejoining the server…