0
# Diff Editor
1
2
The Diff Editor component provides specialized functionality for comparing two pieces of text with visual highlighting of differences. It's built on top of the Split Editor and uses diff-match-patch for intelligent difference detection and highlighting.
3
4
## Capabilities
5
6
### DiffComponent
7
8
Diff editor component that compares two text sources and highlights their differences with visual indicators.
9
10
```typescript { .api }
11
/**
12
* Diff editor component for comparing and highlighting differences between two text sources
13
* Automatically detects changes and provides visual indicators for additions, deletions, and modifications
14
*/
15
declare class DiffComponent extends React.Component<IDiffEditorProps, IDiffEditorState> {}
16
17
interface IDiffEditorProps {
18
/** Starting cursor position */
19
cursorStart?: number;
20
/** Additional editor properties */
21
editorProps?: object;
22
/** Enable basic autocompletion */
23
enableBasicAutocompletion?: boolean | string[];
24
/** Enable live autocompletion */
25
enableLiveAutocompletion?: boolean | string[];
26
/** Auto-focus the diff editor on mount */
27
focus?: boolean;
28
/** Font size for both editor panes */
29
fontSize?: number;
30
/** Total height of the diff editor */
31
height?: string;
32
/** Highlight active line in both panes */
33
highlightActiveLine?: boolean;
34
/** Maximum lines for both editor panes */
35
maxLines?: number;
36
/** Minimum lines for both editor panes */
37
minLines?: number;
38
/** Syntax highlighting mode for both panes */
39
mode?: string;
40
/** Unique identifier for the diff editor instance */
41
name?: string;
42
/** CSS class name for the diff editor container */
43
className?: string;
44
/** Called when diff editor is fully loaded */
45
onLoad?: (editor: IEditorProps) => void;
46
/** Called when content changes in either pane */
47
onChange?: (value: string[], event?: any) => void;
48
/** Called when text is pasted into either pane */
49
onPaste?: (value: string) => void;
50
/** Called when either pane is scrolled */
51
onScroll?: (editor: IEditorProps) => void;
52
/** Split orientation ("beside" or "below") */
53
orientation?: string;
54
/** Make both editor panes read-only */
55
readOnly?: boolean;
56
/** Scroll margin for both editor panes */
57
scrollMargin?: number[];
58
/** Ace editor configuration options */
59
setOptions?: object;
60
/** Show line numbers in both panes */
61
showGutter?: boolean;
62
/** Show print margin in both panes */
63
showPrintMargin?: boolean;
64
/** Number of splits (typically 2 for diff view) */
65
splits?: number;
66
/** CSS styles for the diff editor container */
67
style?: object;
68
/** Tab size for both editor panes */
69
tabSize?: number;
70
/** Editor theme for both panes */
71
theme?: string;
72
/** Content for comparison [original, modified] */
73
value?: string[];
74
/** Total width of the diff editor */
75
width?: string;
76
/** Enable line wrapping in both panes */
77
wrapEnabled?: boolean;
78
}
79
80
interface IDiffEditorState {
81
/** Current content values [original, modified] */
82
value: string[];
83
}
84
```
85
86
### Usage Examples
87
88
**Basic Diff Comparison:**
89
90
```typescript
91
import React, { useState } from "react";
92
import { diff } from "react-ace";
93
94
import "ace-builds/src-noconflict/mode-javascript";
95
import "ace-builds/src-noconflict/theme-github";
96
97
const DiffEditor = diff;
98
99
function CodeComparison() {
100
const [values, setValues] = useState([
101
// Original code
102
`function calculateTotal(items) {
103
let total = 0;
104
for (let i = 0; i < items.length; i++) {
105
total += items[i].price;
106
}
107
return total;
108
}`,
109
// Modified code
110
`function calculateTotal(items) {
111
return items.reduce((total, item) => total + item.price, 0);
112
}`
113
]);
114
115
return (
116
<DiffEditor
117
mode="javascript"
118
theme="github"
119
value={values}
120
onChange={setValues}
121
name="code-diff"
122
width="100%"
123
height="400px"
124
fontSize={14}
125
showGutter={true}
126
highlightActiveLine={true}
127
/>
128
);
129
}
130
```
131
132
**Document Comparison with Headers:**
133
134
```typescript
135
import React, { useState } from "react";
136
import { diff } from "react-ace";
137
138
import "ace-builds/src-noconflict/mode-markdown";
139
import "ace-builds/src-noconflict/theme-github";
140
141
const DiffEditor = diff;
142
143
function DocumentDiff() {
144
const [originalDoc, setOriginalDoc] = useState(`# Project Documentation
145
146
## Overview
147
This project provides basic functionality.
148
149
## Features
150
- Feature A
151
- Feature B
152
153
## Installation
154
Run npm install to get started.`);
155
156
const [modifiedDoc, setModifiedDoc] = useState(`# Project Documentation
157
158
## Overview
159
This project provides comprehensive functionality with advanced features.
160
161
## Features
162
- Feature A (Enhanced)
163
- Feature B
164
- Feature C (New)
165
166
## Installation
167
Run npm install to get started.
168
169
## Configuration
170
Set environment variables before running.`);
171
172
const handleChange = (values) => {
173
setOriginalDoc(values[0]);
174
setModifiedDoc(values[1]);
175
};
176
177
return (
178
<div>
179
<div style={{ display: 'flex', marginBottom: '10px' }}>
180
<div style={{ flex: 1, textAlign: 'center', fontWeight: 'bold' }}>
181
Original
182
</div>
183
<div style={{ flex: 1, textAlign: 'center', fontWeight: 'bold' }}>
184
Modified
185
</div>
186
</div>
187
<DiffEditor
188
mode="markdown"
189
theme="github"
190
value={[originalDoc, modifiedDoc]}
191
onChange={handleChange}
192
name="document-diff"
193
width="100%"
194
height="500px"
195
fontSize={14}
196
showGutter={true}
197
orientation="beside"
198
/>
199
</div>
200
);
201
}
202
```
203
204
**Read-Only Diff Viewer:**
205
206
```typescript
207
import React from "react";
208
import { diff } from "react-ace";
209
210
import "ace-builds/src-noconflict/mode-json";
211
import "ace-builds/src-noconflict/theme-monokai";
212
213
const DiffEditor = diff;
214
215
interface DiffViewerProps {
216
beforeData: object;
217
afterData: object;
218
}
219
220
function DiffViewer({ beforeData, afterData }: DiffViewerProps) {
221
const values = [
222
JSON.stringify(beforeData, null, 2),
223
JSON.stringify(afterData, null, 2)
224
];
225
226
return (
227
<DiffEditor
228
mode="json"
229
theme="monokai"
230
value={values}
231
name="json-diff-viewer"
232
readOnly={true}
233
width="100%"
234
height="600px"
235
fontSize={14}
236
showGutter={true}
237
highlightActiveLine={false}
238
setOptions={{
239
showLineNumbers: true,
240
showFoldWidgets: true
241
}}
242
/>
243
);
244
}
245
```
246
247
**Diff with Custom Styling:**
248
249
```typescript
250
import React, { useState } from "react";
251
import { diff } from "react-ace";
252
253
const DiffEditor = diff;
254
255
function StyledDiffEditor() {
256
const [values, setValues] = useState([
257
"Original text content",
258
"Modified text content with changes"
259
]);
260
261
const customStyle = {
262
border: '2px solid #ccc',
263
borderRadius: '8px',
264
overflow: 'hidden'
265
};
266
267
return (
268
<div>
269
<style>{`
270
.diff-editor .ace_gutter {
271
background: #f5f5f5;
272
}
273
.diff-editor .ace_gutter-active-line {
274
background: #e8f4f8;
275
}
276
.diff-added {
277
background-color: #d4edda;
278
}
279
.diff-removed {
280
background-color: #f8d7da;
281
}
282
`}</style>
283
284
<DiffEditor
285
mode="text"
286
theme="github"
287
value={values}
288
onChange={setValues}
289
name="styled-diff"
290
className="diff-editor"
291
style={customStyle}
292
width="100%"
293
height="400px"
294
fontSize={14}
295
/>
296
</div>
297
);
298
}
299
```
300
301
**Vertical Diff Layout:**
302
303
```typescript
304
import React, { useState } from "react";
305
import { diff } from "react-ace";
306
307
import "ace-builds/src-noconflict/mode-html";
308
import "ace-builds/src-noconflict/theme-github";
309
310
const DiffEditor = diff;
311
312
function VerticalDiff() {
313
const [values, setValues] = useState([
314
'<div class="old-version">Old HTML</div>',
315
'<div class="new-version">New HTML with improvements</div>'
316
]);
317
318
return (
319
<DiffEditor
320
mode="html"
321
theme="github"
322
value={values}
323
onChange={setValues}
324
name="vertical-diff"
325
orientation="below"
326
width="100%"
327
height="600px"
328
fontSize={14}
329
showGutter={true}
330
splits={2}
331
/>
332
);
333
}
334
```
335
336
### Diff Features
337
338
**Automatic Difference Detection:**
339
340
The Diff Editor automatically detects and highlights:
341
- **Added lines**: New content in the modified version
342
- **Removed lines**: Content present in original but not modified
343
- **Changed lines**: Lines with modifications
344
- **Unchanged lines**: Content that remains the same
345
346
**Visual Indicators:**
347
348
- Different background colors for added/removed/changed content
349
- Line-by-line comparison with clear visual separation
350
- Gutter indicators showing change types
351
- Synchronized scrolling between panes
352
353
### Configuration Options
354
355
**Layout Configuration:**
356
357
```typescript { .api }
358
interface DiffLayoutConfig {
359
/** Split orientation */
360
orientation?: "beside" | "below";
361
/** Number of comparison panes */
362
splits?: number;
363
/** Synchronized scrolling */
364
syncScroll?: boolean;
365
}
366
```
367
368
**Diff-Specific Options:**
369
370
The Diff Editor inherits all standard Ace Editor options and adds diff-specific behavior:
371
372
- Automatic line-by-line comparison
373
- Visual difference highlighting
374
- Synchronized cursor movement (optional)
375
- Read-only mode for pure viewing
376
- Custom styling for different change types
377
378
### Event Handling
379
380
**Change Detection:**
381
382
```typescript { .api }
383
/** Called when content changes in either pane */
384
onChange?: (values: string[], event?: {
385
paneIndex: number;
386
changeType: 'addition' | 'deletion' | 'modification';
387
affectedLines: number[];
388
}) => void;
389
```
390
391
**Load Event:**
392
393
```typescript { .api }
394
/** Called when diff editor is fully loaded */
395
onLoad?: (editor: {
396
leftPane: Ace.Editor;
397
rightPane: Ace.Editor;
398
getDiffs: () => DiffResult[];
399
}) => void;
400
```
401
402
### Integration with diff-match-patch
403
404
The Diff Editor uses the diff-match-patch library internally for:
405
406
- Intelligent text comparison algorithms
407
- Efficient difference calculation
408
- Line-level and character-level diff detection
409
- Optimal highlighting placement
410
411
### Performance Considerations
412
413
- **Large Files**: Consider pagination or virtualization for very large files
414
- **Real-time Updates**: Use debouncing for frequently changing content
415
- **Memory Usage**: Diff calculations can be memory-intensive for large texts
416
- **Rendering**: Complex diffs may impact rendering performance
417
418
### Accessibility
419
420
The Diff Editor includes accessibility features:
421
422
- Keyboard navigation between panes
423
- Screen reader support for change descriptions
424
- High contrast mode compatibility
425
- Focus management for diff navigation