English

Text & everyday tools · Text Toolkit

Line-based text diff explained: why one changed word flags the whole line

· How it works

text-diff document-comparison editing

Two clause lists aligned by line, with one removed line and one added line highlighted
Original ToolAcre vector illustration

Explains what a line-based diff compares, why it reports a one-word edit as a replaced line, and how to prepare two texts so the comparison highlights what actually changed.

The diff that says everything changed — how a reflowed paragraph turns one edit into dozens of flagged lines

A contracts administrator can change one obligation in a clause, paste two document versions into a comparison, and see a large block reported around that edit. The usual cause is not that every sentence changed. It is that copying from a word processor reflowed the paragraph, moving later words onto different physical lines.

A line comparison can only align the units it receives. If version A wraps a paragraph after “supplier” and version B wraps it after “supplier must,” the remaining rows no longer match exactly even when most wording is identical. Restore deliberate line boundaries before deciding that the document contains dozens of substantive revisions.

What a line diff compares — whole lines as units, matched by equality, with insertions and deletions in between

ToolAcre splits each input into lines and compares those complete strings for equality. It builds a longest-common-subsequence table, which identifies the largest ordered set of identical lines shared by both sides. Material between those anchors is then emitted as rows removed from the left or added to the right.

Order matters as much as text. An unchanged clause can anchor the alignment only where it appears in sequence; moving it elsewhere is not represented by a special move operation. The result is a minimal line-oriented edit script, not an interpretation of legal meaning or an attempt to pair similar sentences by topic.

Why one word flags a whole line — the unit of comparison is the line, so any difference replaces it

Changing “may” to “must” makes the complete line unequal. In this implementation, that line is emitted as removed from the old side and added to the new side; the core function does not emit a changed row for the one-word substitution. The two rows describe replacement at line granularity rather than deletion of the whole idea.

Read those adjacent rows together. Their shared wording helps a person locate the edited term, but the algorithm shown in the source does not highlight characters inside them. This distinction explains why the result can be accurate while appearing broad: its smallest reportable comparison unit is one line, regardless of how tiny the edit was.

Why one word produces a removed line and an added line in this implementation

A word-level diff tokenizes prose more finely and can isolate “may” versus “must.” A character-level diff can narrow the display further, which is useful for punctuation or spelling. Those approaches also create more fragments and require rules about token boundaries, so their apparent precision can produce a busier review.

Line comparison suits lists, configuration blocks, logs, and clauses when every row already represents a meaningful item. It gives reviewers stable context and preserves order without pretending to understand sentences. Choose a finer tool when the review must identify edits inside long paragraphs; do not expect this route to manufacture that detail.

Preparing texts to diff well — one sentence or item per line, trimmed whitespace and consistent line endings

Prepare both versions so one sentence, numbered clause, or list item occupies each line. Remove accidental blank rows and trim leading or trailing spaces when those differences carry no meaning. Keep intentional indentation when it matters, because the comparison function itself tests exact line strings and does not normalize whitespace before equality checks.

The outline calls for consistent line endings, but `toLines` already accepts CRLF, LF, and a lone CR as separators. The more important consistency is semantic: equivalent items should start and end at equivalent places. Avoid manual wrapping at a page width, because a changed margin can then masquerade as changed content.

Prepare stable line units; mixed CRLF, LF and lone CR are already accepted

Suppose the old list has three separate rows: “1. Deliver by Friday.”, “2. Buyer may inspect records.”, and “3. Payment is due in 30 days.” The revision changes only the middle row to “2. Buyer must inspect records.” Keep all three clauses on their own lines before running the comparison.

The first and third rows remain equal anchors. The old middle clause appears as removed and the revised middle clause appears as added, leaving the administrator with one focused pair to review. If the same clauses were pasted as reflowed prose, a wrapping difference could break those anchors and enlarge the apparent change set.

What this does not cover — three-way merges, moved-block detection and diffs of formatted documents

This comparison does not perform a three-way merge, so it cannot reconcile two edited descendants against a shared base version. It also has no moved-block classification: relocating a clause can appear as a removal at its old position and an addition at its new position, even when its text is untouched.

Formatted documents introduce another boundary. Fonts, tracked changes, tables, comments, and layout are not represented in plain strings passed to `diffLines`. Extract and structure the relevant text first, while retaining the originals for formal review. A useful text diff supplements document controls; it does not replace them.

The takeaway — the Text Toolkit's diff is line-based by design; prepare the input and it shows exactly which items changed

A line diff is most informative when each line carries one reviewable decision. ToolAcre aligns exact rows, preserves their order, and reports unmatched material as additions or removals. That design is predictable: a one-word edit affects its whole row, while identical rows around it provide the anchors that keep the result compact.

Before comparing clause lists, make boundaries deliberate, trim irrelevant edge spaces, and remove empty lines that add no structure. Then open Text diff and inspect adjacent removed and added rows as one replacement. Good preparation does not change the contract; it makes the algorithm’s line-based report match the units a reviewer actually cares about.