Skip to content

Commit 3c67632

Browse files
migrate tp data-diff-status attribute
1 parent e2f0ec0 commit 3c67632

13 files changed

Lines changed: 115 additions & 117 deletions

File tree

docs/components/interactive-showcase.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ export default function InteractiveShowcase() {
9696

9797
// Add event listeners to modified elements
9898
const updatedElements = ref.current.querySelectorAll(
99-
".diff-modified[data-diff-key]",
99+
'[data-diff-status="modified"][data-diff-key]',
100100
);
101101

102102
const handleMouseEnter = (e: Event) => {
@@ -160,13 +160,13 @@ export default function InteractiveShowcase() {
160160
font-weight: 500;
161161
color: #1f2937;
162162
}
163-
.diff-modified {
163+
[data-diff-status="modified"] {
164164
color: #f59e0b;
165165
cursor: pointer;
166166
transition: all 0.2s ease;
167167
position: relative;
168168
}
169-
.diff-modified:hover {
169+
[data-diff-status="modified"]:hover {
170170
background-color: rgba(245, 158, 11, 0.1);
171171
transform: scale(1.02);
172172
}

docs/examples/rich-text-document/styles.css

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1802,23 +1802,23 @@ button:hover {
18021802
}
18031803

18041804
/* Diff highlighting styles */
1805-
.diff-added {
1805+
[data-diff-status="added"] {
18061806
color: green;
18071807
text-decoration: none;
18081808
outline: none;
18091809
}
1810-
.diff-modified {
1810+
[data-diff-status="modified"] {
18111811
color: orange;
18121812
text-decoration: none;
18131813
outline: none;
18141814
}
1815-
.diff-removed {
1815+
[data-diff-status="removed"] {
18161816
color: red;
18171817
text-decoration: none;
18181818
outline: none;
18191819
}
18201820

18211821
/* Strikethrough only for word-level diffing */
1822-
[data-diff-mode="words"] .diff-removed {
1822+
[data-diff-mode="words"] [data-diff-status="removed"] {
18231823
text-decoration: line-through;
18241824
}

docs/examples/table-diff/index.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Table Diff
22

3-
This example demonstrates how `data-diff-key` preserves table structure while highlighting changes. Notice how only CSS classes are added to cells - no new elements are inserted that would break the table layout.
3+
This example demonstrates how `data-diff-key` preserves table structure while highlighting changes. Notice how only `data-diff-status` attributes are added to cellsno new elements are inserted that would break the table layout.
44

55
import Showcase from "../../components/showcase";
66
import beforeHtml from "./before.html?raw";

docs/examples/table-diff/styles.css

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,17 @@
1515
}
1616

1717
/* Diff styling */
18-
.diff-added {
18+
[data-diff-status="added"] {
1919
background-color: #d4edda;
2020
color: #155724;
2121
}
2222

23-
.diff-modified {
23+
[data-diff-status="modified"] {
2424
background-color: #fff3cd;
2525
color: #856404;
2626
}
2727

28-
.diff-removed {
28+
[data-diff-status="removed"] {
2929
background-color: #f8d7da;
3030
color: #721c24;
3131
}

docs/guide/attributes.mdx

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ The `data-diff-key` attribute provides a unique identifier that allows the diff
3232
<Showcase
3333
before="<div><p data-diff-key='ixn4'>First paragraph</p></div>"
3434
after="<div><p data-diff-key='ixn4'>First paragraph</p><p data-diff-key='zm7q'>Second paragraph</p></div>"
35-
css=".diff-added { color: green; } .diff-modified { color: orange; } .diff-removed { color: red; }"
35+
css="[data-diff-status='added'] { color: green; } [data-diff-status='modified'] { color: orange; } [data-diff-status='removed'] { color: red; }"
3636
/>
3737

3838
### Example: Removing an element
@@ -53,18 +53,18 @@ The `data-diff-key` attribute provides a unique identifier that allows the diff
5353
<Showcase
5454
before="<div><p data-diff-key='bw5c'>Keep this</p><p data-diff-key='ft9x'>Remove this</p></div>"
5555
after="<div><p data-diff-key='bw5c'>Keep this</p></div>"
56-
css=".diff-added { color: green; } .diff-modified { color: orange; } .diff-removed { color: red; }"
56+
css="[data-diff-status='added'] { color: green; } [data-diff-status='modified'] { color: orange; } [data-diff-status='removed'] { color: red; }"
5757
/>
5858

5959
## data-diff-mode
6060

6161
**Optional attribute to control diffing behavior.**
6262

63-
By default, when text content changes, elements with `data-diff-key` are marked as `diff-modified`. The `data-diff-mode` attribute allows you to specify different diffing behaviors for more control.
63+
By default, when text content changes, elements with `data-diff-key` are marked with `data-diff-status="modified"`. The `data-diff-mode` attribute allows you to specify different diffing behaviors for more control.
6464

6565
### element
6666

67-
Use `data-diff-mode="element"` to explicitly mark the element for atomic element diffing. When content changes, the old element is shown as `diff-removed` and the new element is shown as `diff-added`.
67+
Use `data-diff-mode="element"` to explicitly mark the element for atomic element diffing. When content changes, the old element is shown with `data-diff-status="removed"` and the new element is shown with `data-diff-status="added"`.
6868

6969
```html
7070
<!-- Before -->
@@ -83,7 +83,7 @@ Use `data-diff-mode="element"` to explicitly mark the element for atomic element
8383
<Showcase
8484
before="<div class='card' data-diff-key='my-card' data-diff-mode='element'><h3>Old Title</h3><p>Old content</p></div>"
8585
after="<div class='card' data-diff-key='my-card' data-diff-mode='element'><h3>New Title</h3><p>New content</p></div>"
86-
css=".diff-added { color: green; } .diff-modified { color: orange; } .diff-removed { color: red; } .card { border: 1px solid #ccc; padding: 10px; margin: 5px 0; }"
86+
css="[data-diff-status='added'] { color: green; } [data-diff-status='modified'] { color: orange; } [data-diff-status='removed'] { color: red; } .card { border: 1px solid #ccc; padding: 10px; margin: 5px 0; }"
8787
/>
8888

8989
#### When to use element mode
@@ -118,7 +118,7 @@ Use `data-diff-mode="words"` to enable granular word-level diffing within the el
118118
<Showcase
119119
before="<p data-diff-key='qr8n'>Hello there</p>"
120120
after="<p data-diff-key='qr8n'>Hello world</p>"
121-
css=".diff-added { color: green; } .diff-modified { color: orange; } .diff-removed { color: red; }"
121+
css="[data-diff-status='added'] { color: green; } [data-diff-status='modified'] { color: orange; } [data-diff-status='removed'] { color: red; }"
122122
/>
123123

124124
#### With data-diff-mode="words" (granular word diffing)
@@ -134,7 +134,7 @@ Use `data-diff-mode="words"` to enable granular word-level diffing within the el
134134
<Showcase
135135
before="<p data-diff-key='kv3m' data-diff-mode='words'>Hello there</p>"
136136
after="<p data-diff-key='kv3m' data-diff-mode='words'>Hello world</p>"
137-
css=".diff-added { color: green; } .diff-modified { color: orange; } .diff-removed { color: red; }"
137+
css="[data-diff-status='added'] { color: green; } [data-diff-status='modified'] { color: orange; } [data-diff-status='removed'] { color: red; }"
138138
/>
139139

140140
#### When to use data-diff-mode="words"
@@ -172,7 +172,7 @@ This example shows how using `data-diff-mode="words"` on complex components brea
172172
<Showcase
173173
before="<div class='card' data-diff-key='jx9w' data-diff-mode='words'><h3>Old Title</h3><p>Some content here</p></div>"
174174
after="<div class='card' data-diff-key='jx9w' data-diff-mode='words'><h3>New Title</h3><p>Different content here</p></div>"
175-
css=".diff-added { color: green; } .diff-modified { color: orange; } .diff-removed { color: red; } .card { border: 1px solid #ccc; padding: 10px; }"
175+
css="[data-diff-status='added'] { color: green; } [data-diff-status='modified'] { color: orange; } [data-diff-status='removed'] { color: red; } .card { border: 1px solid #ccc; padding: 10px; }"
176176
/>
177177

178178
Notice how the word-level diffing breaks the HTML structure by inserting `<span>` elements, making the result invalid HTML. The correct approach is to use `data-diff-mode="element"` or no mode at all for complex components.
@@ -181,7 +181,7 @@ Notice how the word-level diffing breaks the HTML structure by inserting `<span>
181181

182182
**Optional attribute to show removed elements in the diff result.**
183183

184-
By default, when elements are removed, they are not inserted into the diff result - only existing elements get CSS classes. The `data-diff-show-when-removed` attribute tells the diff engine that this element should be displayed with strikethrough styling when removed.
184+
By default, when elements are removed, they are not inserted into the diff resultonly existing elements receive diff attributes. The `data-diff-show-when-removed` attribute tells the diff engine that this element should be displayed with strikethrough styling when removed.
185185

186186
### When to use data-diff-show-when-removed
187187

@@ -234,7 +234,7 @@ By default, when elements are removed, they are not inserted into the diff resul
234234
<Showcase
235235
before="<table><tbody data-diff-key='table-body'><tr data-diff-key='row1' data-diff-show-when-removed><td>Product A</td><td>$10</td></tr><tr data-diff-key='row2' data-diff-show-when-removed><td>Product B</td><td>$20</td></tr><tr data-diff-key='row3' data-diff-show-when-removed><td>Product C</td><td>$30</td></tr></tbody></table>"
236236
after="<table><tbody data-diff-key='table-body'><tr data-diff-key='row1' data-diff-show-when-removed><td>Product A</td><td>$10</td></tr><tr data-diff-key='row3' data-diff-show-when-removed><td>Product C</td><td>$30</td></tr></tbody></table>"
237-
css="table { border-collapse: collapse; } td { border: 1px solid #ccc; padding: 8px; } .diff-added { color: green; } .diff-modified { color: orange; } .diff-removed { color: red; text-decoration: line-through; }"
237+
css="table { border-collapse: collapse; } td { border: 1px solid #ccc; padding: 8px; } [data-diff-status='added'] { color: green; } [data-diff-status='modified'] { color: orange; } [data-diff-status='removed'] { color: red; text-decoration: line-through; }"
238238
/>
239239

240240
Notice how the removed row (Product B) is inserted and shown with strikethrough styling.
@@ -261,7 +261,7 @@ Without the `data-diff-show-when-removed` attribute, removed elements are not in
261261
<Showcase
262262
before="<table><tbody data-diff-key='table-body'><tr data-diff-key='row1'><td>Product A</td><td>$10</td></tr><tr data-diff-key='row2'><td>Product B</td><td>$20</td></tr><tr data-diff-key='row3'><td>Product C</td><td>$30</td></tr></tbody></table>"
263263
after="<table><tbody data-diff-key='table-body'><tr data-diff-key='row1'><td>Product A</td><td>$10</td></tr><tr data-diff-key='row3'><td>Product C</td><td>$30</td></tr></tbody></table>"
264-
css="table { border-collapse: collapse; } td { border: 1px solid #ccc; padding: 8px; } .diff-added { color: green; } .diff-modified { color: orange; } .diff-removed { color: red; }"
264+
css="table { border-collapse: collapse; } td { border: 1px solid #ccc; padding: 8px; } [data-diff-status='added'] { color: green; } [data-diff-status='modified'] { color: orange; } [data-diff-status='removed'] { color: red; }"
265265
/>
266266

267267
Only the existing rows are shown - the removed row is not inserted.

docs/guide/how-it-works.mdx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,18 +43,18 @@ graph TD
4343

4444
The diagram above shows two approaches to building diff views. The **Custom Diff** approach (🟧) requires building and maintaining specialized diff logic and custom renderers for each document type. This means more development effort and one-off solutions that don't generalize.
4545

46-
In contrast, the **HTML Diff** approach (🟩) leverages the fact that most applications ultimately render to HTML. Rather than building custom diff logic, it works directly with the rendered HTML output. This requires no adjustments from developers in terms of creating diffed data structures or modifying renderers - it simply takes your existing HTML and adds CSS classes to highlight changes. This approach generalizes across any application UI that renders to HTML, making it a reusable solution.
46+
In contrast, the **HTML Diff** approach (🟩) leverages the fact that most applications ultimately render to HTML. Rather than building custom diff logic, it works directly with the rendered HTML output. This requires no adjustments from developers in terms of creating diffed data structures or modifying renderersit simply takes your existing HTML and adds `data-diff-status` attributes to highlight changes. This approach generalizes across any application UI that renders to HTML, making it a reusable solution.
4747

4848
## How Elements Are Tracked
4949

5050
HTML diff uses `data-diff-key` attributes to track elements across before/after states. Here's what happens:
5151

5252
### Structure Preservation
5353

54-
Adding `data-diff-key` to elements **only adds CSS classes** - it doesn't modify the HTML structure:
54+
Adding `data-diff-key` to elements **only adds diff attributes**it doesn't modify the HTML structure:
5555

5656
-**No structural changes**: Elements keep their original structure, attributes, and content
57-
-**Only CSS classes added**: Elements get `diff-added`, `diff-modified`, or `diff-removed` classes
57+
-**Only `data-diff-status` added**: Elements get `data-diff-status="added"`, `"modified"`, or `"removed"`
5858
-**Preserves layout**: No new elements inserted, so CSS layouts (tables, flexbox, grid) remain intact
5959

6060
<Showcase
@@ -78,7 +78,7 @@ Adding `data-diff-key` to elements **only adds CSS classes** - it doesn't modify
7878
border: 1px solid #ccc;
7979
padding: 8px;
8080
}
81-
.diff-modified {
81+
[data-diff-status="modified"] {
8282
background-color: #fff3cd;
8383
color: #856404;
8484
}
@@ -88,15 +88,15 @@ Adding `data-diff-key` to elements **only adds CSS classes** - it doesn't modify
8888
Notice how in the diff result:
8989

9090
- Table structure remains intact (no broken layout)
91-
- Only CSS classes are added to the `<td>` elements
91+
- Only the `data-diff-status` attribute is added to the `<td>` elements
9292
- No wrapper elements or structural modifications
9393

9494
### Diffing Modes
9595

9696
The progression of diffing granularity:
9797

9898
1. **No attributes**: No diffing, HTML unchanged
99-
2. **`data-diff-key` only**: CSS classes added to changed elements
99+
2. **`data-diff-key` only**: `data-diff-status` attributes added to changed elements
100100
3. **`data-diff-key` + `data-diff-mode="element"`**: Explicit atomic element diffing (entire element marked as updated)
101101
4. **`data-diff-key` + `data-diff-mode="words"`**: Granular word-level diffing with spans
102102

docs/guide/index.mdx

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -83,17 +83,17 @@ padding: 8px;
8383
font-weight: bold;
8484
}
8585
86-
.diff-added {
86+
[data-diff-status='added'] {
8787
background-color: #d4edda;
8888
color: #155724;
8989
}
9090
91-
.diff-modified {
91+
[data-diff-status='modified'] {
9292
background-color: #fff3cd;
9393
color: #856404;
9494
}
9595
96-
.diff-removed {
96+
[data-diff-status='removed'] {
9797
background-color: #f8d7da;
9898
color: #721c24;
9999
}`}
@@ -169,13 +169,13 @@ const afterHtml = `
169169
const diff = renderHtmlDiff({ beforeHtml, afterHtml });
170170

171171
// The diff now contains:
172-
// - "The fast red fox" with class="diff-modified"
173-
// - "The lazy dog sleeps" with class="diff-added"
172+
// - "The fast red fox" with data-diff-status="modified"
173+
// - "The lazy dog sleeps" with data-diff-status="added"
174174
```
175175

176176
### Step 3: Render the diff
177177

178-
The diff HTML preserves your original elements and styling - only CSS classes are added. Your app's existing CSS continues to work:
178+
The diff HTML preserves your original elements and styling—only `data-diff-status` attributes are added. Your app's existing CSS continues to work:
179179

180180
```typescript
181181
// Vanilla JS
@@ -197,14 +197,14 @@ function DiffViewer({ diff }: { diff: string }) {
197197
line-height: 1.4;
198198
}
199199

200-
/* Only these 3 classes needed for diff highlighting */
201-
.diff-added {
200+
/* Only these selectors needed for diff highlighting */
201+
[data-diff-status='added'] {
202202
color: #22c55e;
203203
}
204-
.diff-modified {
204+
[data-diff-status='modified'] {
205205
color: #f59e0b;
206206
}
207-
.diff-removed {
207+
[data-diff-status='removed'] {
208208
color: #ef4444;
209209
}
210210
```
@@ -224,14 +224,13 @@ function DiffViewer({ diff }: { diff: string }) {
224224
line-height: 1.4;
225225
}
226226
227-
/_ Only these 3 classes needed for diff highlighting _/
228-
229-
.diff-added { color: #22c55e }
230-
.diff-modified { color: #f59e0b }
231-
.diff-removed { color: #ef4444 }`}
227+
/* Only these selectors needed for diff highlighting */
228+
[data-diff-status='added'] { color: #22c55e }
229+
[data-diff-status='modified'] { color: #f59e0b }
230+
[data-diff-status='removed'] { color: #ef4444 }`}
232231
/>
233232

234-
Notice how your existing `.my-text` styles (large, bold typography) are preserved. Only the diff highlighting is added on top based on your CSS diff classes.
233+
Notice how your existing `.my-text` styles (large, bold typography) are preserved. Only the diff highlighting is added on top based on your CSS targeting `data-diff-status`.
235234

236235
### Step 4: Make diffs more granular (optional)
237236

@@ -252,9 +251,9 @@ For word-level highlighting within text elements, add the `data-diff-mode="words
252251
line-height: 1.4;
253252
}
254253
255-
.diff-added { color: #22c55e; }
256-
.diff-modified { color: #f59e0b; }
257-
.diff-removed { color: #ef4444; text-decoration: line-through; }`}
254+
[data-diff-status='added'] { color: #22c55e; }
255+
[data-diff-status='modified'] { color: #f59e0b; }
256+
[data-diff-status='removed'] { color: #ef4444; text-decoration: line-through; }`}
258257
/>
259258

260259
Notice how `data-diff-mode="words"` enables word-level highlighting instead of highlighting the entire element. Learn more in the [attributes guide](/guide/attributes).

docs/guide/interactivity.mdx

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Adding Interactivity
22

3-
The HTML diff engine provides the foundation for building interactive diff experiences. By combining the `data-diff-key` attributes with CSS classes applied by the diff engine, you can create rich interactive features like hover cards, blame views, and detailed change histories.
3+
The HTML diff engine provides the foundation for building interactive diff experiences. By combining the `data-diff-key` attributes with the `data-diff-status` markers applied by the diff engine, you can create rich interactive features like hover cards, blame views, and detailed change histories.
44

55
## Live Example
66

@@ -12,21 +12,21 @@ import InteractiveShowcase from "../components/interactive-showcase";
1212

1313
## Understanding the Data Structure
1414

15-
When the diff engine processes your HTML, it adds CSS classes to elements and preserves the `data-diff-key` attributes. This gives you everything needed to build interactive features:
15+
When the diff engine processes your HTML, it adds `data-diff-status` attributes to elements and preserves the `data-diff-key` attributes. This gives you everything needed to build interactive features:
1616

1717
```html
1818
<!-- After diff processing -->
19-
<p data-diff-key="intro" data-diff-mode="words" class="diff-modified">
20-
Welcome to our <span class="diff-removed">comprehensive</span>
21-
<span class="diff-added">updated</span> guide for new
22-
<span class="diff-removed">users</span
23-
><span class="diff-added">developers</span>.
19+
<p data-diff-key="intro" data-diff-mode="words" data-diff-status="modified">
20+
Welcome to our <span data-diff-status="removed">comprehensive</span>
21+
<span data-diff-status="added">updated</span> guide for new
22+
<span data-diff-status="removed">users</span
23+
><span data-diff-status="added">developers</span>.
2424
</p>
2525
```
2626

2727
## Building Interactive Features
2828

29-
The key insight is that after calling `renderHtmlDiff()`, you can query the result for elements with diff classes and their `data-diff-key` attributes to add any interactivity you want:
29+
The key insight is that after calling `renderHtmlDiff()`, you can query the result for elements with diff status attributes and their `data-diff-key` attributes to add any interactivity you want:
3030

3131
```javascript
3232
// 1. Generate the diff
@@ -39,11 +39,13 @@ container.innerHTML = diffResult;
3939

4040
// 3. Query for interactive elements
4141
const modifiedElements = container.querySelectorAll(
42-
".diff-modified[data-diff-key]",
42+
'[data-diff-status="modified"][data-diff-key]',
43+
);
44+
const addedElements = container.querySelectorAll(
45+
'[data-diff-status="added"][data-diff-key]',
4346
);
44-
const addedElements = container.querySelectorAll(".diff-added[data-diff-key]");
4547
const removedElements = container.querySelectorAll(
46-
".diff-removed[data-diff-key]",
48+
'[data-diff-status="removed"][data-diff-key]',
4749
);
4850

4951
// 4. Add any interactivity you want
@@ -138,7 +140,7 @@ export function InteractiveHtmlDiff() {
138140

139141
// Add event listeners to modified elements
140142
const modifiedElements = ref.current.querySelectorAll(
141-
".diff-modified[data-diff-key]",
143+
'[data-diff-status="modified"][data-diff-key]',
142144
);
143145

144146
const handleMouseEnter = (e) => {
@@ -189,12 +191,12 @@ export function InteractiveHtmlDiff() {
189191
border: 1px solid #e5e7eb;
190192
padding: 12px 16px;
191193
}
192-
.diff-modified {
194+
[data-diff-status="modified"] {
193195
color: #f59e0b;
194196
cursor: pointer;
195197
transition: all 0.2s ease;
196198
}
197-
.diff-modified:hover {
199+
[data-diff-status="modified"]:hover {
198200
background-color: rgba(245, 158, 11, 0.1);
199201
transform: scale(1.02);
200202
}

0 commit comments

Comments
 (0)