@crashbytes/react-version-compare 1.0.1 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +43 -3
- package/dist/cjs/index.js +287 -4
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/index.js +287 -4
- package/dist/esm/index.js.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/styles.css +42 -0
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -18,6 +18,7 @@ The Storybook provides interactive examples for all comparison scenarios. You ca
|
|
|
18
18
|
- 🎯 **Precise Highlighting**: Only highlights the actual differences, not entire lines
|
|
19
19
|
- 📝 **String Comparison**: Word-level diff for text content
|
|
20
20
|
- 📋 **Array Comparison**: Item-level diff for arrays of strings
|
|
21
|
+
- 📄 **Contentful Rich Text**: Compare Contentful documents with text or structure modes
|
|
21
22
|
- 🎨 **Clean Visual Design**: Clear red/green highlighting for changes
|
|
22
23
|
- 📱 **Responsive**: Works on desktop and mobile devices
|
|
23
24
|
- ⚡ **TypeScript Support**: Full TypeScript definitions included
|
|
@@ -78,16 +79,52 @@ const modifiedArray = [
|
|
|
78
79
|
/>
|
|
79
80
|
```
|
|
80
81
|
|
|
82
|
+
### Contentful Rich Text Comparison
|
|
83
|
+
|
|
84
|
+
The component now supports comparing Contentful Rich Text documents with two different modes:
|
|
85
|
+
|
|
86
|
+
```tsx
|
|
87
|
+
import { Compare } from '@crashbytes/react-version-compare';
|
|
88
|
+
import { Document } from '@contentful/rich-text-types';
|
|
89
|
+
|
|
90
|
+
// Text mode - extracts plain text for comparison
|
|
91
|
+
<Compare
|
|
92
|
+
original={contentfulDoc1}
|
|
93
|
+
modified={contentfulDoc2}
|
|
94
|
+
compareMode="text"
|
|
95
|
+
viewMode="side-by-side"
|
|
96
|
+
/>
|
|
97
|
+
|
|
98
|
+
// Structure mode - compares document structure
|
|
99
|
+
<Compare
|
|
100
|
+
original={contentfulDoc1}
|
|
101
|
+
modified={contentfulDoc2}
|
|
102
|
+
compareMode="structure"
|
|
103
|
+
viewMode="side-by-side"
|
|
104
|
+
/>
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
**Structure Mode** preserves the semantic meaning of the document by comparing:
|
|
108
|
+
- Headings (with levels)
|
|
109
|
+
- Paragraphs
|
|
110
|
+
- Lists and list items
|
|
111
|
+
- Block quotes
|
|
112
|
+
- And other rich text elements
|
|
113
|
+
|
|
114
|
+
**Text Mode** extracts plain text content and performs word-level comparison, similar to string comparison.
|
|
115
|
+
|
|
81
116
|
## API Reference
|
|
82
117
|
|
|
83
118
|
### Props
|
|
84
119
|
|
|
85
120
|
| Prop | Type | Default | Description |
|
|
86
121
|
|------|------|---------|-------------|
|
|
87
|
-
| `original` | `string \| string[]` | **required** | The original content |
|
|
88
|
-
| `modified` | `string \| string[]` | **required** | The modified content |
|
|
122
|
+
| `original` | `string \| string[] \| Document` | **required** | The original content |
|
|
123
|
+
| `modified` | `string \| string[] \| Document` | **required** | The modified content |
|
|
89
124
|
| `viewMode` | `'side-by-side' \| 'inline'` | `'side-by-side'` | How to display the comparison |
|
|
90
125
|
| `className` | `string` | `''` | Custom CSS class name |
|
|
126
|
+
| `caseSensitive` | `boolean` | `true` | Whether comparison is case sensitive |
|
|
127
|
+
| `compareMode` | `'text' \| 'structure'` | `'text'` | Comparison mode for Contentful documents |
|
|
91
128
|
|
|
92
129
|
## Examples
|
|
93
130
|
|
|
@@ -149,13 +186,16 @@ The component uses CSS classes that you can customize:
|
|
|
149
186
|
- **Content management**: Show edits in articles or posts
|
|
150
187
|
- **Data comparison**: Compare lists or arrays of items
|
|
151
188
|
- **Translation work**: Compare original and translated text
|
|
189
|
+
- **Contentful CMS**: Compare rich text content versions and track editorial changes
|
|
190
|
+
- **Documentation**: Track changes in structured content with semantic meaning
|
|
152
191
|
|
|
153
192
|
## How It Works
|
|
154
193
|
|
|
155
194
|
- **String comparison**: Uses word-level diffing to identify precise changes
|
|
156
195
|
- **Array comparison**: Compares items by position and content
|
|
196
|
+
- **Contentful comparison**: Extracts plain text or compares structural elements
|
|
157
197
|
- **Smart highlighting**: Only highlights actual differences, not entire lines
|
|
158
|
-
- **Type safety**: Ensures both inputs are the same type (
|
|
198
|
+
- **Type safety**: Ensures both inputs are the same type (strings, arrays, or Contentful documents)
|
|
159
199
|
|
|
160
200
|
## License
|
|
161
201
|
|
package/dist/cjs/index.js
CHANGED
|
@@ -4,14 +4,114 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
4
4
|
|
|
5
5
|
var diff = require('diff');
|
|
6
6
|
require('react');
|
|
7
|
+
var richTextTypes = require('@contentful/rich-text-types');
|
|
7
8
|
var jsxRuntime = require('react/jsx-runtime');
|
|
8
9
|
|
|
10
|
+
const extractPlainText = document => {
|
|
11
|
+
const extractFromNode = node => {
|
|
12
|
+
if (node.nodeType === 'text') {
|
|
13
|
+
return node.value;
|
|
14
|
+
}
|
|
15
|
+
if ('content' in node && node.content) {
|
|
16
|
+
return node.content.map(child => extractFromNode(child)).join('');
|
|
17
|
+
}
|
|
18
|
+
return '';
|
|
19
|
+
};
|
|
20
|
+
return extractFromNode(document);
|
|
21
|
+
};
|
|
22
|
+
const extractStructuredContent = document => {
|
|
23
|
+
const result = [];
|
|
24
|
+
const extractFromNode = node => {
|
|
25
|
+
if (node.nodeType === 'text') {
|
|
26
|
+
// Skip standalone text nodes as they're usually part of a parent structure
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
if ('content' in node && node.content) {
|
|
30
|
+
const textContent = node.content.map(child => child.nodeType === 'text' ? child.value : '').join('');
|
|
31
|
+
|
|
32
|
+
// Map node types to user-friendly names and extract heading levels
|
|
33
|
+
let displayType = node.nodeType;
|
|
34
|
+
let headingLevel;
|
|
35
|
+
switch (node.nodeType) {
|
|
36
|
+
case richTextTypes.BLOCKS.HEADING_1:
|
|
37
|
+
displayType = 'Heading';
|
|
38
|
+
headingLevel = 1;
|
|
39
|
+
break;
|
|
40
|
+
case richTextTypes.BLOCKS.HEADING_2:
|
|
41
|
+
displayType = 'Heading';
|
|
42
|
+
headingLevel = 2;
|
|
43
|
+
break;
|
|
44
|
+
case richTextTypes.BLOCKS.HEADING_3:
|
|
45
|
+
displayType = 'Heading';
|
|
46
|
+
headingLevel = 3;
|
|
47
|
+
break;
|
|
48
|
+
case richTextTypes.BLOCKS.HEADING_4:
|
|
49
|
+
displayType = 'Heading';
|
|
50
|
+
headingLevel = 4;
|
|
51
|
+
break;
|
|
52
|
+
case richTextTypes.BLOCKS.HEADING_5:
|
|
53
|
+
displayType = 'Heading';
|
|
54
|
+
headingLevel = 5;
|
|
55
|
+
break;
|
|
56
|
+
case richTextTypes.BLOCKS.HEADING_6:
|
|
57
|
+
displayType = 'Heading';
|
|
58
|
+
headingLevel = 6;
|
|
59
|
+
break;
|
|
60
|
+
case richTextTypes.BLOCKS.PARAGRAPH:
|
|
61
|
+
displayType = 'Text';
|
|
62
|
+
break;
|
|
63
|
+
case richTextTypes.BLOCKS.UL_LIST:
|
|
64
|
+
displayType = 'List';
|
|
65
|
+
break;
|
|
66
|
+
case richTextTypes.BLOCKS.OL_LIST:
|
|
67
|
+
displayType = 'Numbered List';
|
|
68
|
+
break;
|
|
69
|
+
case richTextTypes.BLOCKS.LIST_ITEM:
|
|
70
|
+
displayType = 'List Item';
|
|
71
|
+
break;
|
|
72
|
+
case richTextTypes.BLOCKS.QUOTE:
|
|
73
|
+
displayType = 'Quote';
|
|
74
|
+
break;
|
|
75
|
+
case richTextTypes.BLOCKS.TABLE:
|
|
76
|
+
displayType = 'Table';
|
|
77
|
+
break;
|
|
78
|
+
default:
|
|
79
|
+
displayType = node.nodeType.charAt(0).toUpperCase() + node.nodeType.slice(1);
|
|
80
|
+
}
|
|
81
|
+
if (textContent.trim()) {
|
|
82
|
+
result.push({
|
|
83
|
+
type: displayType,
|
|
84
|
+
content: textContent.trim(),
|
|
85
|
+
level: headingLevel
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Recursively process child nodes for nested structures like list items
|
|
90
|
+
node.content.forEach(child => {
|
|
91
|
+
if (child.nodeType !== 'text') {
|
|
92
|
+
extractFromNode(child);
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
if (document.content) {
|
|
98
|
+
document.content.forEach(node => extractFromNode(node));
|
|
99
|
+
}
|
|
100
|
+
return result;
|
|
101
|
+
};
|
|
102
|
+
const isContentfulDocument = value => {
|
|
103
|
+
return value && typeof value === 'object' && value.nodeType === richTextTypes.BLOCKS.DOCUMENT && Array.isArray(value.content);
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
// Types
|
|
107
|
+
|
|
9
108
|
const Compare = ({
|
|
10
109
|
original,
|
|
11
110
|
modified,
|
|
12
111
|
className = '',
|
|
13
112
|
viewMode = 'side-by-side',
|
|
14
|
-
caseSensitive = true
|
|
113
|
+
caseSensitive = true,
|
|
114
|
+
compareMode = 'text' // Default to text comparison
|
|
15
115
|
}) => {
|
|
16
116
|
// Handle string comparison
|
|
17
117
|
const renderStringDiff = (orig, mod) => {
|
|
@@ -92,12 +192,186 @@ const Compare = ({
|
|
|
92
192
|
modifiedParts
|
|
93
193
|
};
|
|
94
194
|
};
|
|
195
|
+
|
|
196
|
+
// Handle Contentful document comparison
|
|
197
|
+
const renderContentfulDiff = (origDoc, modDoc) => {
|
|
198
|
+
if (compareMode === 'structure') {
|
|
199
|
+
// Compare structural elements
|
|
200
|
+
const origStructure = extractStructuredContent(origDoc);
|
|
201
|
+
const modStructure = extractStructuredContent(modDoc);
|
|
202
|
+
|
|
203
|
+
// Create a more sophisticated comparison that can handle changes within the same structure type
|
|
204
|
+
const maxLength = Math.max(origStructure.length, modStructure.length);
|
|
205
|
+
const originalParts = [];
|
|
206
|
+
const modifiedParts = [];
|
|
207
|
+
for (let i = 0; i < maxLength; i++) {
|
|
208
|
+
const origItem = origStructure[i];
|
|
209
|
+
const modItem = modStructure[i];
|
|
210
|
+
if (!origItem && modItem) {
|
|
211
|
+
// Added item
|
|
212
|
+
modifiedParts.push(/*#__PURE__*/jsxRuntime.jsxs("div", {
|
|
213
|
+
className: "diff-added-line",
|
|
214
|
+
children: [/*#__PURE__*/jsxRuntime.jsx("span", {
|
|
215
|
+
className: "diff-structure-type",
|
|
216
|
+
children: modItem.type
|
|
217
|
+
}), modItem.level && /*#__PURE__*/jsxRuntime.jsxs("span", {
|
|
218
|
+
className: "diff-structure-level",
|
|
219
|
+
children: [" H", modItem.level]
|
|
220
|
+
}), /*#__PURE__*/jsxRuntime.jsxs("span", {
|
|
221
|
+
className: "diff-structure-content",
|
|
222
|
+
children: [": ", modItem.content]
|
|
223
|
+
})]
|
|
224
|
+
}, `added-${i}`));
|
|
225
|
+
} else if (origItem && !modItem) {
|
|
226
|
+
// Removed item
|
|
227
|
+
originalParts.push(/*#__PURE__*/jsxRuntime.jsxs("div", {
|
|
228
|
+
className: "diff-removed-line",
|
|
229
|
+
children: [/*#__PURE__*/jsxRuntime.jsx("span", {
|
|
230
|
+
className: "diff-structure-type",
|
|
231
|
+
children: origItem.type
|
|
232
|
+
}), origItem.level && /*#__PURE__*/jsxRuntime.jsxs("span", {
|
|
233
|
+
className: "diff-structure-level",
|
|
234
|
+
children: [" H", origItem.level]
|
|
235
|
+
}), /*#__PURE__*/jsxRuntime.jsxs("span", {
|
|
236
|
+
className: "diff-structure-content",
|
|
237
|
+
children: [": ", origItem.content]
|
|
238
|
+
})]
|
|
239
|
+
}, `removed-${i}`));
|
|
240
|
+
} else if (origItem && modItem) {
|
|
241
|
+
// Compare items at the same position
|
|
242
|
+
const sameType = origItem.type === modItem.type && origItem.level === modItem.level;
|
|
243
|
+
if (sameType && origItem.content !== modItem.content) {
|
|
244
|
+
// Same structure type but different content - show word-level diff
|
|
245
|
+
const wordDiff = diff.diffWords(origItem.content, modItem.content, {
|
|
246
|
+
ignoreCase: !caseSensitive
|
|
247
|
+
});
|
|
248
|
+
const origContentParts = [];
|
|
249
|
+
const modContentParts = [];
|
|
250
|
+
for (const part of wordDiff) {
|
|
251
|
+
if (part.removed) {
|
|
252
|
+
origContentParts.push(/*#__PURE__*/jsxRuntime.jsx("span", {
|
|
253
|
+
className: "diff-removed",
|
|
254
|
+
children: part.value
|
|
255
|
+
}, origContentParts.length));
|
|
256
|
+
} else if (part.added) {
|
|
257
|
+
modContentParts.push(/*#__PURE__*/jsxRuntime.jsx("span", {
|
|
258
|
+
className: "diff-added",
|
|
259
|
+
children: part.value
|
|
260
|
+
}, modContentParts.length));
|
|
261
|
+
} else {
|
|
262
|
+
origContentParts.push(/*#__PURE__*/jsxRuntime.jsx("span", {
|
|
263
|
+
className: "diff-unchanged",
|
|
264
|
+
children: part.value
|
|
265
|
+
}, origContentParts.length));
|
|
266
|
+
modContentParts.push(/*#__PURE__*/jsxRuntime.jsx("span", {
|
|
267
|
+
className: "diff-unchanged",
|
|
268
|
+
children: part.value
|
|
269
|
+
}, modContentParts.length));
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
originalParts.push(/*#__PURE__*/jsxRuntime.jsxs("div", {
|
|
273
|
+
className: "diff-unchanged-line",
|
|
274
|
+
children: [/*#__PURE__*/jsxRuntime.jsx("span", {
|
|
275
|
+
className: "diff-structure-type",
|
|
276
|
+
children: origItem.type
|
|
277
|
+
}), origItem.level && /*#__PURE__*/jsxRuntime.jsxs("span", {
|
|
278
|
+
className: "diff-structure-level",
|
|
279
|
+
children: [" H", origItem.level]
|
|
280
|
+
}), /*#__PURE__*/jsxRuntime.jsxs("span", {
|
|
281
|
+
className: "diff-structure-content",
|
|
282
|
+
children: [": ", origContentParts]
|
|
283
|
+
})]
|
|
284
|
+
}, `orig-${i}`));
|
|
285
|
+
modifiedParts.push(/*#__PURE__*/jsxRuntime.jsxs("div", {
|
|
286
|
+
className: "diff-unchanged-line",
|
|
287
|
+
children: [/*#__PURE__*/jsxRuntime.jsx("span", {
|
|
288
|
+
className: "diff-structure-type",
|
|
289
|
+
children: modItem.type
|
|
290
|
+
}), modItem.level && /*#__PURE__*/jsxRuntime.jsxs("span", {
|
|
291
|
+
className: "diff-structure-level",
|
|
292
|
+
children: [" H", modItem.level]
|
|
293
|
+
}), /*#__PURE__*/jsxRuntime.jsxs("span", {
|
|
294
|
+
className: "diff-structure-content",
|
|
295
|
+
children: [": ", modContentParts]
|
|
296
|
+
})]
|
|
297
|
+
}, `mod-${i}`));
|
|
298
|
+
} else if (sameType && origItem.content === modItem.content) {
|
|
299
|
+
// Completely unchanged
|
|
300
|
+
originalParts.push(/*#__PURE__*/jsxRuntime.jsxs("div", {
|
|
301
|
+
className: "diff-unchanged-line",
|
|
302
|
+
children: [/*#__PURE__*/jsxRuntime.jsx("span", {
|
|
303
|
+
className: "diff-structure-type",
|
|
304
|
+
children: origItem.type
|
|
305
|
+
}), origItem.level && /*#__PURE__*/jsxRuntime.jsxs("span", {
|
|
306
|
+
className: "diff-structure-level",
|
|
307
|
+
children: [" H", origItem.level]
|
|
308
|
+
}), /*#__PURE__*/jsxRuntime.jsxs("span", {
|
|
309
|
+
className: "diff-structure-content",
|
|
310
|
+
children: [": ", origItem.content]
|
|
311
|
+
})]
|
|
312
|
+
}, `unchanged-orig-${i}`));
|
|
313
|
+
modifiedParts.push(/*#__PURE__*/jsxRuntime.jsxs("div", {
|
|
314
|
+
className: "diff-unchanged-line",
|
|
315
|
+
children: [/*#__PURE__*/jsxRuntime.jsx("span", {
|
|
316
|
+
className: "diff-structure-type",
|
|
317
|
+
children: modItem.type
|
|
318
|
+
}), modItem.level && /*#__PURE__*/jsxRuntime.jsxs("span", {
|
|
319
|
+
className: "diff-structure-level",
|
|
320
|
+
children: [" H", modItem.level]
|
|
321
|
+
}), /*#__PURE__*/jsxRuntime.jsxs("span", {
|
|
322
|
+
className: "diff-structure-content",
|
|
323
|
+
children: [": ", modItem.content]
|
|
324
|
+
})]
|
|
325
|
+
}, `unchanged-mod-${i}`));
|
|
326
|
+
} else {
|
|
327
|
+
// Different structure types - show as removed and added
|
|
328
|
+
originalParts.push(/*#__PURE__*/jsxRuntime.jsxs("div", {
|
|
329
|
+
className: "diff-removed-line",
|
|
330
|
+
children: [/*#__PURE__*/jsxRuntime.jsx("span", {
|
|
331
|
+
className: "diff-structure-type",
|
|
332
|
+
children: origItem.type
|
|
333
|
+
}), origItem.level && /*#__PURE__*/jsxRuntime.jsxs("span", {
|
|
334
|
+
className: "diff-structure-level",
|
|
335
|
+
children: [" H", origItem.level]
|
|
336
|
+
}), /*#__PURE__*/jsxRuntime.jsxs("span", {
|
|
337
|
+
className: "diff-structure-content",
|
|
338
|
+
children: [": ", origItem.content]
|
|
339
|
+
})]
|
|
340
|
+
}, `changed-orig-${i}`));
|
|
341
|
+
modifiedParts.push(/*#__PURE__*/jsxRuntime.jsxs("div", {
|
|
342
|
+
className: "diff-added-line",
|
|
343
|
+
children: [/*#__PURE__*/jsxRuntime.jsx("span", {
|
|
344
|
+
className: "diff-structure-type",
|
|
345
|
+
children: modItem.type
|
|
346
|
+
}), modItem.level && /*#__PURE__*/jsxRuntime.jsxs("span", {
|
|
347
|
+
className: "diff-structure-level",
|
|
348
|
+
children: [" H", modItem.level]
|
|
349
|
+
}), /*#__PURE__*/jsxRuntime.jsxs("span", {
|
|
350
|
+
className: "diff-structure-content",
|
|
351
|
+
children: [": ", modItem.content]
|
|
352
|
+
})]
|
|
353
|
+
}, `changed-mod-${i}`));
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
return {
|
|
358
|
+
originalParts,
|
|
359
|
+
modifiedParts
|
|
360
|
+
};
|
|
361
|
+
} else {
|
|
362
|
+
// Text-based comparison of Contentful documents
|
|
363
|
+
const origText = extractPlainText(origDoc);
|
|
364
|
+
const modText = extractPlainText(modDoc);
|
|
365
|
+
return renderStringDiff(origText, modText);
|
|
366
|
+
}
|
|
367
|
+
};
|
|
95
368
|
const isStringComparison = typeof original === 'string' && typeof modified === 'string';
|
|
96
369
|
const isArrayComparison = Array.isArray(original) && Array.isArray(modified);
|
|
97
|
-
|
|
370
|
+
const isContentfulComparison = isContentfulDocument(original) && isContentfulDocument(modified);
|
|
371
|
+
if (!isStringComparison && !isArrayComparison && !isContentfulComparison) {
|
|
98
372
|
return /*#__PURE__*/jsxRuntime.jsx("div", {
|
|
99
373
|
className: `compare-error ${className}`,
|
|
100
|
-
children: "Error: Both inputs must be either strings
|
|
374
|
+
children: "Error: Both inputs must be either strings, arrays of strings, or Contentful documents"
|
|
101
375
|
});
|
|
102
376
|
}
|
|
103
377
|
let originalParts, modifiedParts;
|
|
@@ -106,11 +380,20 @@ const Compare = ({
|
|
|
106
380
|
originalParts,
|
|
107
381
|
modifiedParts
|
|
108
382
|
} = renderStringDiff(original, modified));
|
|
109
|
-
} else {
|
|
383
|
+
} else if (isArrayComparison) {
|
|
110
384
|
({
|
|
111
385
|
originalParts,
|
|
112
386
|
modifiedParts
|
|
113
387
|
} = renderArrayDiff(original, modified));
|
|
388
|
+
} else if (isContentfulComparison) {
|
|
389
|
+
({
|
|
390
|
+
originalParts,
|
|
391
|
+
modifiedParts
|
|
392
|
+
} = renderContentfulDiff(original, modified));
|
|
393
|
+
} else {
|
|
394
|
+
// This should never happen due to the check above, but provide a fallback
|
|
395
|
+
originalParts = [];
|
|
396
|
+
modifiedParts = [];
|
|
114
397
|
}
|
|
115
398
|
if (viewMode === 'inline') {
|
|
116
399
|
return /*#__PURE__*/jsxRuntime.jsx("div", {
|
package/dist/cjs/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../src/components/Compare.tsx"],"sourcesContent":["import { diffWords, diffArrays } from 'diff';\nimport React from 'react';\n\n// Types\nexport interface CompareProps {\n original: string | string[];\n modified: string | string[];\n className?: string;\n viewMode?: 'side-by-side' | 'inline';\n caseSensitive?: boolean; // <-- Added\n}\n\nexport const Compare: React.FC<CompareProps> = ({\n original,\n modified,\n className = '',\n viewMode = 'side-by-side',\n caseSensitive = true, // <-- Default true\n}) => {\n // Handle string comparison\n const renderStringDiff = (orig: string, mod: string) => {\n const diff = diffWords(orig, mod, { ignoreCase: !caseSensitive });\n const originalParts: any[] = [];\n const modifiedParts: any[] = [];\n for (const part of diff) {\n if (part.removed) {\n originalParts.push(\n <span key={originalParts.length} className=\"diff-removed\">\n {part.value}\n </span>\n );\n } else if (part.added) {\n modifiedParts.push(\n <span key={modifiedParts.length} className=\"diff-added\">\n {part.value}\n </span>\n );\n } else {\n originalParts.push(\n <span key={originalParts.length} className=\"diff-unchanged\">\n {part.value}\n </span>\n );\n modifiedParts.push(\n <span key={modifiedParts.length} className=\"diff-unchanged\">\n {part.value}\n </span>\n );\n }\n }\n return { originalParts, modifiedParts };\n };\n\n // Handle array comparison\n const renderArrayDiff = (orig: string[], mod: string[]) => {\n let origArr = orig;\n let modArr = mod;\n if (!caseSensitive) {\n origArr = orig.map((s) => (typeof s === 'string' ? s.toLowerCase() : s));\n modArr = mod.map((s) => (typeof s === 'string' ? s.toLowerCase() : s));\n }\n const diff = diffArrays(origArr, modArr);\n const originalParts: any[] = [];\n const modifiedParts: any[] = [];\n for (const part of diff) {\n if (part.removed) {\n part.value.forEach((item: string, index: number) => {\n originalParts.push(\n <div key={`${originalParts.length}-${index}`} className=\"diff-removed-line\">\n {orig[origArr.indexOf(item, originalParts.length)] ?? item}\n </div>\n );\n });\n } else if (part.added) {\n part.value.forEach((item: string, index: number) => {\n modifiedParts.push(\n <div key={`${modifiedParts.length}-${index}`} className=\"diff-added-line\">\n {mod[modArr.indexOf(item, modifiedParts.length)] ?? item}\n </div>\n );\n });\n } else {\n part.value.forEach((item: string, index: number) => {\n originalParts.push(\n <div key={`${originalParts.length}-${index}`} className=\"diff-unchanged-line\">\n {orig[origArr.indexOf(item, originalParts.length)] ?? item}\n </div>\n );\n modifiedParts.push(\n <div key={`${modifiedParts.length}-${index}`} className=\"diff-unchanged-line\">\n {mod[modArr.indexOf(item, modifiedParts.length)] ?? item}\n </div>\n );\n });\n }\n }\n return { originalParts, modifiedParts };\n };\n\n const isStringComparison = typeof original === 'string' && typeof modified === 'string';\n const isArrayComparison = Array.isArray(original) && Array.isArray(modified);\n\n if (!isStringComparison && !isArrayComparison) {\n return (\n <div className={`compare-error ${className}`}>\n Error: Both inputs must be either strings or arrays of strings\n </div>\n );\n }\n\n let originalParts: any[], modifiedParts: any[];\n if (isStringComparison) {\n ({ originalParts, modifiedParts } = renderStringDiff(original as string, modified as string));\n } else {\n ({ originalParts, modifiedParts } = renderArrayDiff(original as string[], modified as string[]));\n }\n\n if (viewMode === 'inline') {\n return (\n <div className={`compare-inline ${className}`}>\n <div className=\"compare-content\">\n {originalParts}\n {modifiedParts}\n </div>\n </div>\n );\n }\n\n return (\n <div className={`compare-side-by-side ${className}`}>\n <div className=\"compare-panel\">\n <div className=\"compare-header original-header\">Original</div>\n <div className=\"compare-content original-content\">\n {originalParts}\n </div>\n </div>\n <div className=\"compare-panel\">\n <div className=\"compare-header modified-header\">Modified</div>\n <div className=\"compare-content modified-content\">\n {modifiedParts}\n </div>\n </div>\n </div>\n );\n};\n\nexport default Compare;"],"names":["Compare","original","modified","className","viewMode","caseSensitive","renderStringDiff","orig","mod","diff","diffWords","ignoreCase","originalParts","modifiedParts","part","removed","push","_jsx","children","value","length","added","renderArrayDiff","origArr","modArr","map","s","toLowerCase","diffArrays","forEach","item","index","indexOf","isStringComparison","isArrayComparison","Array","isArray","_jsxs"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../src/components/Compare.tsx"],"sourcesContent":["import { diffWords, diffArrays } from 'diff';\nimport React from 'react';\nimport { Document, Block, Inline, Text, BLOCKS } from '@contentful/rich-text-types';\n\n// Utility functions for Contentful Rich Text\nconst extractPlainText = (document: Document): string => {\n const extractFromNode = (node: Block | Inline | Text): string => {\n if (node.nodeType === 'text') {\n return (node as Text).value;\n }\n \n if ('content' in node && node.content) {\n return node.content.map(child => extractFromNode(child)).join('');\n }\n \n return '';\n };\n \n return extractFromNode(document);\n};\n\nconst extractStructuredContent = (document: Document): Array<{ type: string; content: string; level?: number }> => {\n const result: Array<{ type: string; content: string; level?: number }> = [];\n \n const extractFromNode = (node: Block | Inline | Text): void => {\n if (node.nodeType === 'text') {\n // Skip standalone text nodes as they're usually part of a parent structure\n return;\n }\n \n if ('content' in node && node.content) {\n const textContent = node.content.map(child => \n child.nodeType === 'text' ? (child as Text).value : ''\n ).join('');\n \n // Map node types to user-friendly names and extract heading levels\n let displayType: string = node.nodeType;\n let headingLevel: number | undefined;\n \n switch (node.nodeType) {\n case BLOCKS.HEADING_1:\n displayType = 'Heading';\n headingLevel = 1;\n break;\n case BLOCKS.HEADING_2:\n displayType = 'Heading';\n headingLevel = 2;\n break;\n case BLOCKS.HEADING_3:\n displayType = 'Heading';\n headingLevel = 3;\n break;\n case BLOCKS.HEADING_4:\n displayType = 'Heading';\n headingLevel = 4;\n break;\n case BLOCKS.HEADING_5:\n displayType = 'Heading';\n headingLevel = 5;\n break;\n case BLOCKS.HEADING_6:\n displayType = 'Heading';\n headingLevel = 6;\n break;\n case BLOCKS.PARAGRAPH:\n displayType = 'Text';\n break;\n case BLOCKS.UL_LIST:\n displayType = 'List';\n break;\n case BLOCKS.OL_LIST:\n displayType = 'Numbered List';\n break;\n case BLOCKS.LIST_ITEM:\n displayType = 'List Item';\n break;\n case BLOCKS.QUOTE:\n displayType = 'Quote';\n break;\n case BLOCKS.TABLE:\n displayType = 'Table';\n break;\n default:\n displayType = node.nodeType.charAt(0).toUpperCase() + node.nodeType.slice(1);\n }\n \n if (textContent.trim()) {\n result.push({\n type: displayType,\n content: textContent.trim(),\n level: headingLevel\n });\n }\n \n // Recursively process child nodes for nested structures like list items\n node.content.forEach(child => {\n if (child.nodeType !== 'text') {\n extractFromNode(child);\n }\n });\n }\n };\n \n if (document.content) {\n document.content.forEach(node => extractFromNode(node));\n }\n \n return result;\n};\n\nconst isContentfulDocument = (value: any): value is Document => {\n return value && typeof value === 'object' && value.nodeType === BLOCKS.DOCUMENT && Array.isArray(value.content);\n};\n\n// Types\nexport interface CompareProps {\n original: string | string[] | Document;\n modified: string | string[] | Document;\n className?: string;\n viewMode?: 'side-by-side' | 'inline';\n caseSensitive?: boolean;\n compareMode?: 'text' | 'structure'; // New prop for Contentful documents\n}\n\nexport const Compare: React.FC<CompareProps> = ({\n original,\n modified,\n className = '',\n viewMode = 'side-by-side',\n caseSensitive = true,\n compareMode = 'text', // Default to text comparison\n}) => {\n // Handle string comparison\n const renderStringDiff = (orig: string, mod: string) => {\n const diff = diffWords(orig, mod, { ignoreCase: !caseSensitive });\n const originalParts: any[] = [];\n const modifiedParts: any[] = [];\n for (const part of diff) {\n if (part.removed) {\n originalParts.push(\n <span key={originalParts.length} className=\"diff-removed\">\n {part.value}\n </span>\n );\n } else if (part.added) {\n modifiedParts.push(\n <span key={modifiedParts.length} className=\"diff-added\">\n {part.value}\n </span>\n );\n } else {\n originalParts.push(\n <span key={originalParts.length} className=\"diff-unchanged\">\n {part.value}\n </span>\n );\n modifiedParts.push(\n <span key={modifiedParts.length} className=\"diff-unchanged\">\n {part.value}\n </span>\n );\n }\n }\n return { originalParts, modifiedParts };\n };\n\n // Handle array comparison\n const renderArrayDiff = (orig: string[], mod: string[]) => {\n let origArr = orig;\n let modArr = mod;\n if (!caseSensitive) {\n origArr = orig.map((s) => (typeof s === 'string' ? s.toLowerCase() : s));\n modArr = mod.map((s) => (typeof s === 'string' ? s.toLowerCase() : s));\n }\n const diff = diffArrays(origArr, modArr);\n const originalParts: any[] = [];\n const modifiedParts: any[] = [];\n for (const part of diff) {\n if (part.removed) {\n part.value.forEach((item: string, index: number) => {\n originalParts.push(\n <div key={`${originalParts.length}-${index}`} className=\"diff-removed-line\">\n {orig[origArr.indexOf(item, originalParts.length)] ?? item}\n </div>\n );\n });\n } else if (part.added) {\n part.value.forEach((item: string, index: number) => {\n modifiedParts.push(\n <div key={`${modifiedParts.length}-${index}`} className=\"diff-added-line\">\n {mod[modArr.indexOf(item, modifiedParts.length)] ?? item}\n </div>\n );\n });\n } else {\n part.value.forEach((item: string, index: number) => {\n originalParts.push(\n <div key={`${originalParts.length}-${index}`} className=\"diff-unchanged-line\">\n {orig[origArr.indexOf(item, originalParts.length)] ?? item}\n </div>\n );\n modifiedParts.push(\n <div key={`${modifiedParts.length}-${index}`} className=\"diff-unchanged-line\">\n {mod[modArr.indexOf(item, modifiedParts.length)] ?? item}\n </div>\n );\n });\n }\n }\n return { originalParts, modifiedParts };\n };\n\n // Handle Contentful document comparison\n const renderContentfulDiff = (origDoc: Document, modDoc: Document) => {\n if (compareMode === 'structure') {\n // Compare structural elements\n const origStructure = extractStructuredContent(origDoc);\n const modStructure = extractStructuredContent(modDoc);\n \n // Create a more sophisticated comparison that can handle changes within the same structure type\n const maxLength = Math.max(origStructure.length, modStructure.length);\n const originalParts: any[] = [];\n const modifiedParts: any[] = [];\n \n for (let i = 0; i < maxLength; i++) {\n const origItem = origStructure[i];\n const modItem = modStructure[i];\n \n if (!origItem && modItem) {\n // Added item\n modifiedParts.push(\n <div key={`added-${i}`} className=\"diff-added-line\">\n <span className=\"diff-structure-type\">{modItem.type}</span>\n {modItem.level && <span className=\"diff-structure-level\"> H{modItem.level}</span>}\n <span className=\"diff-structure-content\">: {modItem.content}</span>\n </div>\n );\n } else if (origItem && !modItem) {\n // Removed item\n originalParts.push(\n <div key={`removed-${i}`} className=\"diff-removed-line\">\n <span className=\"diff-structure-type\">{origItem.type}</span>\n {origItem.level && <span className=\"diff-structure-level\"> H{origItem.level}</span>}\n <span className=\"diff-structure-content\">: {origItem.content}</span>\n </div>\n );\n } else if (origItem && modItem) {\n // Compare items at the same position\n const sameType = origItem.type === modItem.type && origItem.level === modItem.level;\n \n if (sameType && origItem.content !== modItem.content) {\n // Same structure type but different content - show word-level diff\n const wordDiff = diffWords(origItem.content, modItem.content, { ignoreCase: !caseSensitive });\n \n const origContentParts: any[] = [];\n const modContentParts: any[] = [];\n \n for (const part of wordDiff) {\n if (part.removed) {\n origContentParts.push(\n <span key={origContentParts.length} className=\"diff-removed\">\n {part.value}\n </span>\n );\n } else if (part.added) {\n modContentParts.push(\n <span key={modContentParts.length} className=\"diff-added\">\n {part.value}\n </span>\n );\n } else {\n origContentParts.push(\n <span key={origContentParts.length} className=\"diff-unchanged\">\n {part.value}\n </span>\n );\n modContentParts.push(\n <span key={modContentParts.length} className=\"diff-unchanged\">\n {part.value}\n </span>\n );\n }\n }\n \n originalParts.push(\n <div key={`orig-${i}`} className=\"diff-unchanged-line\">\n <span className=\"diff-structure-type\">{origItem.type}</span>\n {origItem.level && <span className=\"diff-structure-level\"> H{origItem.level}</span>}\n <span className=\"diff-structure-content\">: {origContentParts}</span>\n </div>\n );\n modifiedParts.push(\n <div key={`mod-${i}`} className=\"diff-unchanged-line\">\n <span className=\"diff-structure-type\">{modItem.type}</span>\n {modItem.level && <span className=\"diff-structure-level\"> H{modItem.level}</span>}\n <span className=\"diff-structure-content\">: {modContentParts}</span>\n </div>\n );\n } else if (sameType && origItem.content === modItem.content) {\n // Completely unchanged\n originalParts.push(\n <div key={`unchanged-orig-${i}`} className=\"diff-unchanged-line\">\n <span className=\"diff-structure-type\">{origItem.type}</span>\n {origItem.level && <span className=\"diff-structure-level\"> H{origItem.level}</span>}\n <span className=\"diff-structure-content\">: {origItem.content}</span>\n </div>\n );\n modifiedParts.push(\n <div key={`unchanged-mod-${i}`} className=\"diff-unchanged-line\">\n <span className=\"diff-structure-type\">{modItem.type}</span>\n {modItem.level && <span className=\"diff-structure-level\"> H{modItem.level}</span>}\n <span className=\"diff-structure-content\">: {modItem.content}</span>\n </div>\n );\n } else {\n // Different structure types - show as removed and added\n originalParts.push(\n <div key={`changed-orig-${i}`} className=\"diff-removed-line\">\n <span className=\"diff-structure-type\">{origItem.type}</span>\n {origItem.level && <span className=\"diff-structure-level\"> H{origItem.level}</span>}\n <span className=\"diff-structure-content\">: {origItem.content}</span>\n </div>\n );\n modifiedParts.push(\n <div key={`changed-mod-${i}`} className=\"diff-added-line\">\n <span className=\"diff-structure-type\">{modItem.type}</span>\n {modItem.level && <span className=\"diff-structure-level\"> H{modItem.level}</span>}\n <span className=\"diff-structure-content\">: {modItem.content}</span>\n </div>\n );\n }\n }\n }\n \n return { originalParts, modifiedParts };\n } else {\n // Text-based comparison of Contentful documents\n const origText = extractPlainText(origDoc);\n const modText = extractPlainText(modDoc);\n return renderStringDiff(origText, modText);\n }\n };\n\n const isStringComparison = typeof original === 'string' && typeof modified === 'string';\n const isArrayComparison = Array.isArray(original) && Array.isArray(modified);\n const isContentfulComparison = isContentfulDocument(original) && isContentfulDocument(modified);\n\n if (!isStringComparison && !isArrayComparison && !isContentfulComparison) {\n return (\n <div className={`compare-error ${className}`}>\n Error: Both inputs must be either strings, arrays of strings, or Contentful documents\n </div>\n );\n }\n\n let originalParts: any[], modifiedParts: any[];\n if (isStringComparison) {\n ({ originalParts, modifiedParts } = renderStringDiff(original as string, modified as string));\n } else if (isArrayComparison) {\n ({ originalParts, modifiedParts } = renderArrayDiff(original as string[], modified as string[]));\n } else if (isContentfulComparison) {\n ({ originalParts, modifiedParts } = renderContentfulDiff(original as Document, modified as Document));\n } else {\n // This should never happen due to the check above, but provide a fallback\n originalParts = [];\n modifiedParts = [];\n }\n\n if (viewMode === 'inline') {\n return (\n <div className={`compare-inline ${className}`}>\n <div className=\"compare-content\">\n {originalParts}\n {modifiedParts}\n </div>\n </div>\n );\n }\n\n return (\n <div className={`compare-side-by-side ${className}`}>\n <div className=\"compare-panel\">\n <div className=\"compare-header original-header\">Original</div>\n <div className=\"compare-content original-content\">\n {originalParts}\n </div>\n </div>\n <div className=\"compare-panel\">\n <div className=\"compare-header modified-header\">Modified</div>\n <div className=\"compare-content modified-content\">\n {modifiedParts}\n </div>\n </div>\n </div>\n );\n};\n\nexport default Compare;"],"names":["extractPlainText","document","extractFromNode","node","nodeType","value","content","map","child","join","extractStructuredContent","result","textContent","displayType","headingLevel","BLOCKS","HEADING_1","HEADING_2","HEADING_3","HEADING_4","HEADING_5","HEADING_6","PARAGRAPH","UL_LIST","OL_LIST","LIST_ITEM","QUOTE","TABLE","charAt","toUpperCase","slice","trim","push","type","level","forEach","isContentfulDocument","DOCUMENT","Array","isArray","Compare","original","modified","className","viewMode","caseSensitive","compareMode","renderStringDiff","orig","mod","diff","diffWords","ignoreCase","originalParts","modifiedParts","part","removed","_jsx","children","length","added","renderArrayDiff","origArr","modArr","s","toLowerCase","diffArrays","item","index","indexOf","renderContentfulDiff","origDoc","modDoc","origStructure","modStructure","maxLength","Math","max","i","origItem","modItem","_jsxs","sameType","wordDiff","origContentParts","modContentParts","origText","modText","isStringComparison","isArrayComparison","isContentfulComparison"],"mappings":"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"}
|
package/dist/esm/index.js
CHANGED
|
@@ -1,13 +1,113 @@
|
|
|
1
1
|
import { diffWords, diffArrays } from 'diff';
|
|
2
2
|
import 'react';
|
|
3
|
+
import { BLOCKS } from '@contentful/rich-text-types';
|
|
3
4
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
4
5
|
|
|
6
|
+
const extractPlainText = document => {
|
|
7
|
+
const extractFromNode = node => {
|
|
8
|
+
if (node.nodeType === 'text') {
|
|
9
|
+
return node.value;
|
|
10
|
+
}
|
|
11
|
+
if ('content' in node && node.content) {
|
|
12
|
+
return node.content.map(child => extractFromNode(child)).join('');
|
|
13
|
+
}
|
|
14
|
+
return '';
|
|
15
|
+
};
|
|
16
|
+
return extractFromNode(document);
|
|
17
|
+
};
|
|
18
|
+
const extractStructuredContent = document => {
|
|
19
|
+
const result = [];
|
|
20
|
+
const extractFromNode = node => {
|
|
21
|
+
if (node.nodeType === 'text') {
|
|
22
|
+
// Skip standalone text nodes as they're usually part of a parent structure
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
if ('content' in node && node.content) {
|
|
26
|
+
const textContent = node.content.map(child => child.nodeType === 'text' ? child.value : '').join('');
|
|
27
|
+
|
|
28
|
+
// Map node types to user-friendly names and extract heading levels
|
|
29
|
+
let displayType = node.nodeType;
|
|
30
|
+
let headingLevel;
|
|
31
|
+
switch (node.nodeType) {
|
|
32
|
+
case BLOCKS.HEADING_1:
|
|
33
|
+
displayType = 'Heading';
|
|
34
|
+
headingLevel = 1;
|
|
35
|
+
break;
|
|
36
|
+
case BLOCKS.HEADING_2:
|
|
37
|
+
displayType = 'Heading';
|
|
38
|
+
headingLevel = 2;
|
|
39
|
+
break;
|
|
40
|
+
case BLOCKS.HEADING_3:
|
|
41
|
+
displayType = 'Heading';
|
|
42
|
+
headingLevel = 3;
|
|
43
|
+
break;
|
|
44
|
+
case BLOCKS.HEADING_4:
|
|
45
|
+
displayType = 'Heading';
|
|
46
|
+
headingLevel = 4;
|
|
47
|
+
break;
|
|
48
|
+
case BLOCKS.HEADING_5:
|
|
49
|
+
displayType = 'Heading';
|
|
50
|
+
headingLevel = 5;
|
|
51
|
+
break;
|
|
52
|
+
case BLOCKS.HEADING_6:
|
|
53
|
+
displayType = 'Heading';
|
|
54
|
+
headingLevel = 6;
|
|
55
|
+
break;
|
|
56
|
+
case BLOCKS.PARAGRAPH:
|
|
57
|
+
displayType = 'Text';
|
|
58
|
+
break;
|
|
59
|
+
case BLOCKS.UL_LIST:
|
|
60
|
+
displayType = 'List';
|
|
61
|
+
break;
|
|
62
|
+
case BLOCKS.OL_LIST:
|
|
63
|
+
displayType = 'Numbered List';
|
|
64
|
+
break;
|
|
65
|
+
case BLOCKS.LIST_ITEM:
|
|
66
|
+
displayType = 'List Item';
|
|
67
|
+
break;
|
|
68
|
+
case BLOCKS.QUOTE:
|
|
69
|
+
displayType = 'Quote';
|
|
70
|
+
break;
|
|
71
|
+
case BLOCKS.TABLE:
|
|
72
|
+
displayType = 'Table';
|
|
73
|
+
break;
|
|
74
|
+
default:
|
|
75
|
+
displayType = node.nodeType.charAt(0).toUpperCase() + node.nodeType.slice(1);
|
|
76
|
+
}
|
|
77
|
+
if (textContent.trim()) {
|
|
78
|
+
result.push({
|
|
79
|
+
type: displayType,
|
|
80
|
+
content: textContent.trim(),
|
|
81
|
+
level: headingLevel
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Recursively process child nodes for nested structures like list items
|
|
86
|
+
node.content.forEach(child => {
|
|
87
|
+
if (child.nodeType !== 'text') {
|
|
88
|
+
extractFromNode(child);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
if (document.content) {
|
|
94
|
+
document.content.forEach(node => extractFromNode(node));
|
|
95
|
+
}
|
|
96
|
+
return result;
|
|
97
|
+
};
|
|
98
|
+
const isContentfulDocument = value => {
|
|
99
|
+
return value && typeof value === 'object' && value.nodeType === BLOCKS.DOCUMENT && Array.isArray(value.content);
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
// Types
|
|
103
|
+
|
|
5
104
|
const Compare = ({
|
|
6
105
|
original,
|
|
7
106
|
modified,
|
|
8
107
|
className = '',
|
|
9
108
|
viewMode = 'side-by-side',
|
|
10
|
-
caseSensitive = true
|
|
109
|
+
caseSensitive = true,
|
|
110
|
+
compareMode = 'text' // Default to text comparison
|
|
11
111
|
}) => {
|
|
12
112
|
// Handle string comparison
|
|
13
113
|
const renderStringDiff = (orig, mod) => {
|
|
@@ -88,12 +188,186 @@ const Compare = ({
|
|
|
88
188
|
modifiedParts
|
|
89
189
|
};
|
|
90
190
|
};
|
|
191
|
+
|
|
192
|
+
// Handle Contentful document comparison
|
|
193
|
+
const renderContentfulDiff = (origDoc, modDoc) => {
|
|
194
|
+
if (compareMode === 'structure') {
|
|
195
|
+
// Compare structural elements
|
|
196
|
+
const origStructure = extractStructuredContent(origDoc);
|
|
197
|
+
const modStructure = extractStructuredContent(modDoc);
|
|
198
|
+
|
|
199
|
+
// Create a more sophisticated comparison that can handle changes within the same structure type
|
|
200
|
+
const maxLength = Math.max(origStructure.length, modStructure.length);
|
|
201
|
+
const originalParts = [];
|
|
202
|
+
const modifiedParts = [];
|
|
203
|
+
for (let i = 0; i < maxLength; i++) {
|
|
204
|
+
const origItem = origStructure[i];
|
|
205
|
+
const modItem = modStructure[i];
|
|
206
|
+
if (!origItem && modItem) {
|
|
207
|
+
// Added item
|
|
208
|
+
modifiedParts.push(/*#__PURE__*/jsxs("div", {
|
|
209
|
+
className: "diff-added-line",
|
|
210
|
+
children: [/*#__PURE__*/jsx("span", {
|
|
211
|
+
className: "diff-structure-type",
|
|
212
|
+
children: modItem.type
|
|
213
|
+
}), modItem.level && /*#__PURE__*/jsxs("span", {
|
|
214
|
+
className: "diff-structure-level",
|
|
215
|
+
children: [" H", modItem.level]
|
|
216
|
+
}), /*#__PURE__*/jsxs("span", {
|
|
217
|
+
className: "diff-structure-content",
|
|
218
|
+
children: [": ", modItem.content]
|
|
219
|
+
})]
|
|
220
|
+
}, `added-${i}`));
|
|
221
|
+
} else if (origItem && !modItem) {
|
|
222
|
+
// Removed item
|
|
223
|
+
originalParts.push(/*#__PURE__*/jsxs("div", {
|
|
224
|
+
className: "diff-removed-line",
|
|
225
|
+
children: [/*#__PURE__*/jsx("span", {
|
|
226
|
+
className: "diff-structure-type",
|
|
227
|
+
children: origItem.type
|
|
228
|
+
}), origItem.level && /*#__PURE__*/jsxs("span", {
|
|
229
|
+
className: "diff-structure-level",
|
|
230
|
+
children: [" H", origItem.level]
|
|
231
|
+
}), /*#__PURE__*/jsxs("span", {
|
|
232
|
+
className: "diff-structure-content",
|
|
233
|
+
children: [": ", origItem.content]
|
|
234
|
+
})]
|
|
235
|
+
}, `removed-${i}`));
|
|
236
|
+
} else if (origItem && modItem) {
|
|
237
|
+
// Compare items at the same position
|
|
238
|
+
const sameType = origItem.type === modItem.type && origItem.level === modItem.level;
|
|
239
|
+
if (sameType && origItem.content !== modItem.content) {
|
|
240
|
+
// Same structure type but different content - show word-level diff
|
|
241
|
+
const wordDiff = diffWords(origItem.content, modItem.content, {
|
|
242
|
+
ignoreCase: !caseSensitive
|
|
243
|
+
});
|
|
244
|
+
const origContentParts = [];
|
|
245
|
+
const modContentParts = [];
|
|
246
|
+
for (const part of wordDiff) {
|
|
247
|
+
if (part.removed) {
|
|
248
|
+
origContentParts.push(/*#__PURE__*/jsx("span", {
|
|
249
|
+
className: "diff-removed",
|
|
250
|
+
children: part.value
|
|
251
|
+
}, origContentParts.length));
|
|
252
|
+
} else if (part.added) {
|
|
253
|
+
modContentParts.push(/*#__PURE__*/jsx("span", {
|
|
254
|
+
className: "diff-added",
|
|
255
|
+
children: part.value
|
|
256
|
+
}, modContentParts.length));
|
|
257
|
+
} else {
|
|
258
|
+
origContentParts.push(/*#__PURE__*/jsx("span", {
|
|
259
|
+
className: "diff-unchanged",
|
|
260
|
+
children: part.value
|
|
261
|
+
}, origContentParts.length));
|
|
262
|
+
modContentParts.push(/*#__PURE__*/jsx("span", {
|
|
263
|
+
className: "diff-unchanged",
|
|
264
|
+
children: part.value
|
|
265
|
+
}, modContentParts.length));
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
originalParts.push(/*#__PURE__*/jsxs("div", {
|
|
269
|
+
className: "diff-unchanged-line",
|
|
270
|
+
children: [/*#__PURE__*/jsx("span", {
|
|
271
|
+
className: "diff-structure-type",
|
|
272
|
+
children: origItem.type
|
|
273
|
+
}), origItem.level && /*#__PURE__*/jsxs("span", {
|
|
274
|
+
className: "diff-structure-level",
|
|
275
|
+
children: [" H", origItem.level]
|
|
276
|
+
}), /*#__PURE__*/jsxs("span", {
|
|
277
|
+
className: "diff-structure-content",
|
|
278
|
+
children: [": ", origContentParts]
|
|
279
|
+
})]
|
|
280
|
+
}, `orig-${i}`));
|
|
281
|
+
modifiedParts.push(/*#__PURE__*/jsxs("div", {
|
|
282
|
+
className: "diff-unchanged-line",
|
|
283
|
+
children: [/*#__PURE__*/jsx("span", {
|
|
284
|
+
className: "diff-structure-type",
|
|
285
|
+
children: modItem.type
|
|
286
|
+
}), modItem.level && /*#__PURE__*/jsxs("span", {
|
|
287
|
+
className: "diff-structure-level",
|
|
288
|
+
children: [" H", modItem.level]
|
|
289
|
+
}), /*#__PURE__*/jsxs("span", {
|
|
290
|
+
className: "diff-structure-content",
|
|
291
|
+
children: [": ", modContentParts]
|
|
292
|
+
})]
|
|
293
|
+
}, `mod-${i}`));
|
|
294
|
+
} else if (sameType && origItem.content === modItem.content) {
|
|
295
|
+
// Completely unchanged
|
|
296
|
+
originalParts.push(/*#__PURE__*/jsxs("div", {
|
|
297
|
+
className: "diff-unchanged-line",
|
|
298
|
+
children: [/*#__PURE__*/jsx("span", {
|
|
299
|
+
className: "diff-structure-type",
|
|
300
|
+
children: origItem.type
|
|
301
|
+
}), origItem.level && /*#__PURE__*/jsxs("span", {
|
|
302
|
+
className: "diff-structure-level",
|
|
303
|
+
children: [" H", origItem.level]
|
|
304
|
+
}), /*#__PURE__*/jsxs("span", {
|
|
305
|
+
className: "diff-structure-content",
|
|
306
|
+
children: [": ", origItem.content]
|
|
307
|
+
})]
|
|
308
|
+
}, `unchanged-orig-${i}`));
|
|
309
|
+
modifiedParts.push(/*#__PURE__*/jsxs("div", {
|
|
310
|
+
className: "diff-unchanged-line",
|
|
311
|
+
children: [/*#__PURE__*/jsx("span", {
|
|
312
|
+
className: "diff-structure-type",
|
|
313
|
+
children: modItem.type
|
|
314
|
+
}), modItem.level && /*#__PURE__*/jsxs("span", {
|
|
315
|
+
className: "diff-structure-level",
|
|
316
|
+
children: [" H", modItem.level]
|
|
317
|
+
}), /*#__PURE__*/jsxs("span", {
|
|
318
|
+
className: "diff-structure-content",
|
|
319
|
+
children: [": ", modItem.content]
|
|
320
|
+
})]
|
|
321
|
+
}, `unchanged-mod-${i}`));
|
|
322
|
+
} else {
|
|
323
|
+
// Different structure types - show as removed and added
|
|
324
|
+
originalParts.push(/*#__PURE__*/jsxs("div", {
|
|
325
|
+
className: "diff-removed-line",
|
|
326
|
+
children: [/*#__PURE__*/jsx("span", {
|
|
327
|
+
className: "diff-structure-type",
|
|
328
|
+
children: origItem.type
|
|
329
|
+
}), origItem.level && /*#__PURE__*/jsxs("span", {
|
|
330
|
+
className: "diff-structure-level",
|
|
331
|
+
children: [" H", origItem.level]
|
|
332
|
+
}), /*#__PURE__*/jsxs("span", {
|
|
333
|
+
className: "diff-structure-content",
|
|
334
|
+
children: [": ", origItem.content]
|
|
335
|
+
})]
|
|
336
|
+
}, `changed-orig-${i}`));
|
|
337
|
+
modifiedParts.push(/*#__PURE__*/jsxs("div", {
|
|
338
|
+
className: "diff-added-line",
|
|
339
|
+
children: [/*#__PURE__*/jsx("span", {
|
|
340
|
+
className: "diff-structure-type",
|
|
341
|
+
children: modItem.type
|
|
342
|
+
}), modItem.level && /*#__PURE__*/jsxs("span", {
|
|
343
|
+
className: "diff-structure-level",
|
|
344
|
+
children: [" H", modItem.level]
|
|
345
|
+
}), /*#__PURE__*/jsxs("span", {
|
|
346
|
+
className: "diff-structure-content",
|
|
347
|
+
children: [": ", modItem.content]
|
|
348
|
+
})]
|
|
349
|
+
}, `changed-mod-${i}`));
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
return {
|
|
354
|
+
originalParts,
|
|
355
|
+
modifiedParts
|
|
356
|
+
};
|
|
357
|
+
} else {
|
|
358
|
+
// Text-based comparison of Contentful documents
|
|
359
|
+
const origText = extractPlainText(origDoc);
|
|
360
|
+
const modText = extractPlainText(modDoc);
|
|
361
|
+
return renderStringDiff(origText, modText);
|
|
362
|
+
}
|
|
363
|
+
};
|
|
91
364
|
const isStringComparison = typeof original === 'string' && typeof modified === 'string';
|
|
92
365
|
const isArrayComparison = Array.isArray(original) && Array.isArray(modified);
|
|
93
|
-
|
|
366
|
+
const isContentfulComparison = isContentfulDocument(original) && isContentfulDocument(modified);
|
|
367
|
+
if (!isStringComparison && !isArrayComparison && !isContentfulComparison) {
|
|
94
368
|
return /*#__PURE__*/jsx("div", {
|
|
95
369
|
className: `compare-error ${className}`,
|
|
96
|
-
children: "Error: Both inputs must be either strings
|
|
370
|
+
children: "Error: Both inputs must be either strings, arrays of strings, or Contentful documents"
|
|
97
371
|
});
|
|
98
372
|
}
|
|
99
373
|
let originalParts, modifiedParts;
|
|
@@ -102,11 +376,20 @@ const Compare = ({
|
|
|
102
376
|
originalParts,
|
|
103
377
|
modifiedParts
|
|
104
378
|
} = renderStringDiff(original, modified));
|
|
105
|
-
} else {
|
|
379
|
+
} else if (isArrayComparison) {
|
|
106
380
|
({
|
|
107
381
|
originalParts,
|
|
108
382
|
modifiedParts
|
|
109
383
|
} = renderArrayDiff(original, modified));
|
|
384
|
+
} else if (isContentfulComparison) {
|
|
385
|
+
({
|
|
386
|
+
originalParts,
|
|
387
|
+
modifiedParts
|
|
388
|
+
} = renderContentfulDiff(original, modified));
|
|
389
|
+
} else {
|
|
390
|
+
// This should never happen due to the check above, but provide a fallback
|
|
391
|
+
originalParts = [];
|
|
392
|
+
modifiedParts = [];
|
|
110
393
|
}
|
|
111
394
|
if (viewMode === 'inline') {
|
|
112
395
|
return /*#__PURE__*/jsx("div", {
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../src/components/Compare.tsx"],"sourcesContent":["import { diffWords, diffArrays } from 'diff';\nimport React from 'react';\n\n// Types\nexport interface CompareProps {\n original: string | string[];\n modified: string | string[];\n className?: string;\n viewMode?: 'side-by-side' | 'inline';\n caseSensitive?: boolean; // <-- Added\n}\n\nexport const Compare: React.FC<CompareProps> = ({\n original,\n modified,\n className = '',\n viewMode = 'side-by-side',\n caseSensitive = true, // <-- Default true\n}) => {\n // Handle string comparison\n const renderStringDiff = (orig: string, mod: string) => {\n const diff = diffWords(orig, mod, { ignoreCase: !caseSensitive });\n const originalParts: any[] = [];\n const modifiedParts: any[] = [];\n for (const part of diff) {\n if (part.removed) {\n originalParts.push(\n <span key={originalParts.length} className=\"diff-removed\">\n {part.value}\n </span>\n );\n } else if (part.added) {\n modifiedParts.push(\n <span key={modifiedParts.length} className=\"diff-added\">\n {part.value}\n </span>\n );\n } else {\n originalParts.push(\n <span key={originalParts.length} className=\"diff-unchanged\">\n {part.value}\n </span>\n );\n modifiedParts.push(\n <span key={modifiedParts.length} className=\"diff-unchanged\">\n {part.value}\n </span>\n );\n }\n }\n return { originalParts, modifiedParts };\n };\n\n // Handle array comparison\n const renderArrayDiff = (orig: string[], mod: string[]) => {\n let origArr = orig;\n let modArr = mod;\n if (!caseSensitive) {\n origArr = orig.map((s) => (typeof s === 'string' ? s.toLowerCase() : s));\n modArr = mod.map((s) => (typeof s === 'string' ? s.toLowerCase() : s));\n }\n const diff = diffArrays(origArr, modArr);\n const originalParts: any[] = [];\n const modifiedParts: any[] = [];\n for (const part of diff) {\n if (part.removed) {\n part.value.forEach((item: string, index: number) => {\n originalParts.push(\n <div key={`${originalParts.length}-${index}`} className=\"diff-removed-line\">\n {orig[origArr.indexOf(item, originalParts.length)] ?? item}\n </div>\n );\n });\n } else if (part.added) {\n part.value.forEach((item: string, index: number) => {\n modifiedParts.push(\n <div key={`${modifiedParts.length}-${index}`} className=\"diff-added-line\">\n {mod[modArr.indexOf(item, modifiedParts.length)] ?? item}\n </div>\n );\n });\n } else {\n part.value.forEach((item: string, index: number) => {\n originalParts.push(\n <div key={`${originalParts.length}-${index}`} className=\"diff-unchanged-line\">\n {orig[origArr.indexOf(item, originalParts.length)] ?? item}\n </div>\n );\n modifiedParts.push(\n <div key={`${modifiedParts.length}-${index}`} className=\"diff-unchanged-line\">\n {mod[modArr.indexOf(item, modifiedParts.length)] ?? item}\n </div>\n );\n });\n }\n }\n return { originalParts, modifiedParts };\n };\n\n const isStringComparison = typeof original === 'string' && typeof modified === 'string';\n const isArrayComparison = Array.isArray(original) && Array.isArray(modified);\n\n if (!isStringComparison && !isArrayComparison) {\n return (\n <div className={`compare-error ${className}`}>\n Error: Both inputs must be either strings or arrays of strings\n </div>\n );\n }\n\n let originalParts: any[], modifiedParts: any[];\n if (isStringComparison) {\n ({ originalParts, modifiedParts } = renderStringDiff(original as string, modified as string));\n } else {\n ({ originalParts, modifiedParts } = renderArrayDiff(original as string[], modified as string[]));\n }\n\n if (viewMode === 'inline') {\n return (\n <div className={`compare-inline ${className}`}>\n <div className=\"compare-content\">\n {originalParts}\n {modifiedParts}\n </div>\n </div>\n );\n }\n\n return (\n <div className={`compare-side-by-side ${className}`}>\n <div className=\"compare-panel\">\n <div className=\"compare-header original-header\">Original</div>\n <div className=\"compare-content original-content\">\n {originalParts}\n </div>\n </div>\n <div className=\"compare-panel\">\n <div className=\"compare-header modified-header\">Modified</div>\n <div className=\"compare-content modified-content\">\n {modifiedParts}\n </div>\n </div>\n </div>\n );\n};\n\nexport default Compare;"],"names":["Compare","original","modified","className","viewMode","caseSensitive","renderStringDiff","orig","mod","diff","diffWords","ignoreCase","originalParts","modifiedParts","part","removed","push","_jsx","children","value","length","added","renderArrayDiff","origArr","modArr","map","s","toLowerCase","diffArrays","forEach","item","index","indexOf","isStringComparison","isArrayComparison","Array","isArray","_jsxs"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../src/components/Compare.tsx"],"sourcesContent":["import { diffWords, diffArrays } from 'diff';\nimport React from 'react';\nimport { Document, Block, Inline, Text, BLOCKS } from '@contentful/rich-text-types';\n\n// Utility functions for Contentful Rich Text\nconst extractPlainText = (document: Document): string => {\n const extractFromNode = (node: Block | Inline | Text): string => {\n if (node.nodeType === 'text') {\n return (node as Text).value;\n }\n \n if ('content' in node && node.content) {\n return node.content.map(child => extractFromNode(child)).join('');\n }\n \n return '';\n };\n \n return extractFromNode(document);\n};\n\nconst extractStructuredContent = (document: Document): Array<{ type: string; content: string; level?: number }> => {\n const result: Array<{ type: string; content: string; level?: number }> = [];\n \n const extractFromNode = (node: Block | Inline | Text): void => {\n if (node.nodeType === 'text') {\n // Skip standalone text nodes as they're usually part of a parent structure\n return;\n }\n \n if ('content' in node && node.content) {\n const textContent = node.content.map(child => \n child.nodeType === 'text' ? (child as Text).value : ''\n ).join('');\n \n // Map node types to user-friendly names and extract heading levels\n let displayType: string = node.nodeType;\n let headingLevel: number | undefined;\n \n switch (node.nodeType) {\n case BLOCKS.HEADING_1:\n displayType = 'Heading';\n headingLevel = 1;\n break;\n case BLOCKS.HEADING_2:\n displayType = 'Heading';\n headingLevel = 2;\n break;\n case BLOCKS.HEADING_3:\n displayType = 'Heading';\n headingLevel = 3;\n break;\n case BLOCKS.HEADING_4:\n displayType = 'Heading';\n headingLevel = 4;\n break;\n case BLOCKS.HEADING_5:\n displayType = 'Heading';\n headingLevel = 5;\n break;\n case BLOCKS.HEADING_6:\n displayType = 'Heading';\n headingLevel = 6;\n break;\n case BLOCKS.PARAGRAPH:\n displayType = 'Text';\n break;\n case BLOCKS.UL_LIST:\n displayType = 'List';\n break;\n case BLOCKS.OL_LIST:\n displayType = 'Numbered List';\n break;\n case BLOCKS.LIST_ITEM:\n displayType = 'List Item';\n break;\n case BLOCKS.QUOTE:\n displayType = 'Quote';\n break;\n case BLOCKS.TABLE:\n displayType = 'Table';\n break;\n default:\n displayType = node.nodeType.charAt(0).toUpperCase() + node.nodeType.slice(1);\n }\n \n if (textContent.trim()) {\n result.push({\n type: displayType,\n content: textContent.trim(),\n level: headingLevel\n });\n }\n \n // Recursively process child nodes for nested structures like list items\n node.content.forEach(child => {\n if (child.nodeType !== 'text') {\n extractFromNode(child);\n }\n });\n }\n };\n \n if (document.content) {\n document.content.forEach(node => extractFromNode(node));\n }\n \n return result;\n};\n\nconst isContentfulDocument = (value: any): value is Document => {\n return value && typeof value === 'object' && value.nodeType === BLOCKS.DOCUMENT && Array.isArray(value.content);\n};\n\n// Types\nexport interface CompareProps {\n original: string | string[] | Document;\n modified: string | string[] | Document;\n className?: string;\n viewMode?: 'side-by-side' | 'inline';\n caseSensitive?: boolean;\n compareMode?: 'text' | 'structure'; // New prop for Contentful documents\n}\n\nexport const Compare: React.FC<CompareProps> = ({\n original,\n modified,\n className = '',\n viewMode = 'side-by-side',\n caseSensitive = true,\n compareMode = 'text', // Default to text comparison\n}) => {\n // Handle string comparison\n const renderStringDiff = (orig: string, mod: string) => {\n const diff = diffWords(orig, mod, { ignoreCase: !caseSensitive });\n const originalParts: any[] = [];\n const modifiedParts: any[] = [];\n for (const part of diff) {\n if (part.removed) {\n originalParts.push(\n <span key={originalParts.length} className=\"diff-removed\">\n {part.value}\n </span>\n );\n } else if (part.added) {\n modifiedParts.push(\n <span key={modifiedParts.length} className=\"diff-added\">\n {part.value}\n </span>\n );\n } else {\n originalParts.push(\n <span key={originalParts.length} className=\"diff-unchanged\">\n {part.value}\n </span>\n );\n modifiedParts.push(\n <span key={modifiedParts.length} className=\"diff-unchanged\">\n {part.value}\n </span>\n );\n }\n }\n return { originalParts, modifiedParts };\n };\n\n // Handle array comparison\n const renderArrayDiff = (orig: string[], mod: string[]) => {\n let origArr = orig;\n let modArr = mod;\n if (!caseSensitive) {\n origArr = orig.map((s) => (typeof s === 'string' ? s.toLowerCase() : s));\n modArr = mod.map((s) => (typeof s === 'string' ? s.toLowerCase() : s));\n }\n const diff = diffArrays(origArr, modArr);\n const originalParts: any[] = [];\n const modifiedParts: any[] = [];\n for (const part of diff) {\n if (part.removed) {\n part.value.forEach((item: string, index: number) => {\n originalParts.push(\n <div key={`${originalParts.length}-${index}`} className=\"diff-removed-line\">\n {orig[origArr.indexOf(item, originalParts.length)] ?? item}\n </div>\n );\n });\n } else if (part.added) {\n part.value.forEach((item: string, index: number) => {\n modifiedParts.push(\n <div key={`${modifiedParts.length}-${index}`} className=\"diff-added-line\">\n {mod[modArr.indexOf(item, modifiedParts.length)] ?? item}\n </div>\n );\n });\n } else {\n part.value.forEach((item: string, index: number) => {\n originalParts.push(\n <div key={`${originalParts.length}-${index}`} className=\"diff-unchanged-line\">\n {orig[origArr.indexOf(item, originalParts.length)] ?? item}\n </div>\n );\n modifiedParts.push(\n <div key={`${modifiedParts.length}-${index}`} className=\"diff-unchanged-line\">\n {mod[modArr.indexOf(item, modifiedParts.length)] ?? item}\n </div>\n );\n });\n }\n }\n return { originalParts, modifiedParts };\n };\n\n // Handle Contentful document comparison\n const renderContentfulDiff = (origDoc: Document, modDoc: Document) => {\n if (compareMode === 'structure') {\n // Compare structural elements\n const origStructure = extractStructuredContent(origDoc);\n const modStructure = extractStructuredContent(modDoc);\n \n // Create a more sophisticated comparison that can handle changes within the same structure type\n const maxLength = Math.max(origStructure.length, modStructure.length);\n const originalParts: any[] = [];\n const modifiedParts: any[] = [];\n \n for (let i = 0; i < maxLength; i++) {\n const origItem = origStructure[i];\n const modItem = modStructure[i];\n \n if (!origItem && modItem) {\n // Added item\n modifiedParts.push(\n <div key={`added-${i}`} className=\"diff-added-line\">\n <span className=\"diff-structure-type\">{modItem.type}</span>\n {modItem.level && <span className=\"diff-structure-level\"> H{modItem.level}</span>}\n <span className=\"diff-structure-content\">: {modItem.content}</span>\n </div>\n );\n } else if (origItem && !modItem) {\n // Removed item\n originalParts.push(\n <div key={`removed-${i}`} className=\"diff-removed-line\">\n <span className=\"diff-structure-type\">{origItem.type}</span>\n {origItem.level && <span className=\"diff-structure-level\"> H{origItem.level}</span>}\n <span className=\"diff-structure-content\">: {origItem.content}</span>\n </div>\n );\n } else if (origItem && modItem) {\n // Compare items at the same position\n const sameType = origItem.type === modItem.type && origItem.level === modItem.level;\n \n if (sameType && origItem.content !== modItem.content) {\n // Same structure type but different content - show word-level diff\n const wordDiff = diffWords(origItem.content, modItem.content, { ignoreCase: !caseSensitive });\n \n const origContentParts: any[] = [];\n const modContentParts: any[] = [];\n \n for (const part of wordDiff) {\n if (part.removed) {\n origContentParts.push(\n <span key={origContentParts.length} className=\"diff-removed\">\n {part.value}\n </span>\n );\n } else if (part.added) {\n modContentParts.push(\n <span key={modContentParts.length} className=\"diff-added\">\n {part.value}\n </span>\n );\n } else {\n origContentParts.push(\n <span key={origContentParts.length} className=\"diff-unchanged\">\n {part.value}\n </span>\n );\n modContentParts.push(\n <span key={modContentParts.length} className=\"diff-unchanged\">\n {part.value}\n </span>\n );\n }\n }\n \n originalParts.push(\n <div key={`orig-${i}`} className=\"diff-unchanged-line\">\n <span className=\"diff-structure-type\">{origItem.type}</span>\n {origItem.level && <span className=\"diff-structure-level\"> H{origItem.level}</span>}\n <span className=\"diff-structure-content\">: {origContentParts}</span>\n </div>\n );\n modifiedParts.push(\n <div key={`mod-${i}`} className=\"diff-unchanged-line\">\n <span className=\"diff-structure-type\">{modItem.type}</span>\n {modItem.level && <span className=\"diff-structure-level\"> H{modItem.level}</span>}\n <span className=\"diff-structure-content\">: {modContentParts}</span>\n </div>\n );\n } else if (sameType && origItem.content === modItem.content) {\n // Completely unchanged\n originalParts.push(\n <div key={`unchanged-orig-${i}`} className=\"diff-unchanged-line\">\n <span className=\"diff-structure-type\">{origItem.type}</span>\n {origItem.level && <span className=\"diff-structure-level\"> H{origItem.level}</span>}\n <span className=\"diff-structure-content\">: {origItem.content}</span>\n </div>\n );\n modifiedParts.push(\n <div key={`unchanged-mod-${i}`} className=\"diff-unchanged-line\">\n <span className=\"diff-structure-type\">{modItem.type}</span>\n {modItem.level && <span className=\"diff-structure-level\"> H{modItem.level}</span>}\n <span className=\"diff-structure-content\">: {modItem.content}</span>\n </div>\n );\n } else {\n // Different structure types - show as removed and added\n originalParts.push(\n <div key={`changed-orig-${i}`} className=\"diff-removed-line\">\n <span className=\"diff-structure-type\">{origItem.type}</span>\n {origItem.level && <span className=\"diff-structure-level\"> H{origItem.level}</span>}\n <span className=\"diff-structure-content\">: {origItem.content}</span>\n </div>\n );\n modifiedParts.push(\n <div key={`changed-mod-${i}`} className=\"diff-added-line\">\n <span className=\"diff-structure-type\">{modItem.type}</span>\n {modItem.level && <span className=\"diff-structure-level\"> H{modItem.level}</span>}\n <span className=\"diff-structure-content\">: {modItem.content}</span>\n </div>\n );\n }\n }\n }\n \n return { originalParts, modifiedParts };\n } else {\n // Text-based comparison of Contentful documents\n const origText = extractPlainText(origDoc);\n const modText = extractPlainText(modDoc);\n return renderStringDiff(origText, modText);\n }\n };\n\n const isStringComparison = typeof original === 'string' && typeof modified === 'string';\n const isArrayComparison = Array.isArray(original) && Array.isArray(modified);\n const isContentfulComparison = isContentfulDocument(original) && isContentfulDocument(modified);\n\n if (!isStringComparison && !isArrayComparison && !isContentfulComparison) {\n return (\n <div className={`compare-error ${className}`}>\n Error: Both inputs must be either strings, arrays of strings, or Contentful documents\n </div>\n );\n }\n\n let originalParts: any[], modifiedParts: any[];\n if (isStringComparison) {\n ({ originalParts, modifiedParts } = renderStringDiff(original as string, modified as string));\n } else if (isArrayComparison) {\n ({ originalParts, modifiedParts } = renderArrayDiff(original as string[], modified as string[]));\n } else if (isContentfulComparison) {\n ({ originalParts, modifiedParts } = renderContentfulDiff(original as Document, modified as Document));\n } else {\n // This should never happen due to the check above, but provide a fallback\n originalParts = [];\n modifiedParts = [];\n }\n\n if (viewMode === 'inline') {\n return (\n <div className={`compare-inline ${className}`}>\n <div className=\"compare-content\">\n {originalParts}\n {modifiedParts}\n </div>\n </div>\n );\n }\n\n return (\n <div className={`compare-side-by-side ${className}`}>\n <div className=\"compare-panel\">\n <div className=\"compare-header original-header\">Original</div>\n <div className=\"compare-content original-content\">\n {originalParts}\n </div>\n </div>\n <div className=\"compare-panel\">\n <div className=\"compare-header modified-header\">Modified</div>\n <div className=\"compare-content modified-content\">\n {modifiedParts}\n </div>\n </div>\n </div>\n );\n};\n\nexport default Compare;"],"names":["extractPlainText","document","extractFromNode","node","nodeType","value","content","map","child","join","extractStructuredContent","result","textContent","displayType","headingLevel","BLOCKS","HEADING_1","HEADING_2","HEADING_3","HEADING_4","HEADING_5","HEADING_6","PARAGRAPH","UL_LIST","OL_LIST","LIST_ITEM","QUOTE","TABLE","charAt","toUpperCase","slice","trim","push","type","level","forEach","isContentfulDocument","DOCUMENT","Array","isArray","Compare","original","modified","className","viewMode","caseSensitive","compareMode","renderStringDiff","orig","mod","diff","diffWords","ignoreCase","originalParts","modifiedParts","part","removed","_jsx","children","length","added","renderArrayDiff","origArr","modArr","s","toLowerCase","diffArrays","item","index","indexOf","renderContentfulDiff","origDoc","modDoc","origStructure","modStructure","maxLength","Math","max","i","origItem","modItem","_jsxs","sameType","wordDiff","origContentParts","modContentParts","origText","modText","isStringComparison","isArrayComparison","isContentfulComparison"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
import { Document } from '@contentful/rich-text-types';
|
|
2
3
|
|
|
3
4
|
interface CompareProps {
|
|
4
|
-
original: string | string[];
|
|
5
|
-
modified: string | string[];
|
|
5
|
+
original: string | string[] | Document;
|
|
6
|
+
modified: string | string[] | Document;
|
|
6
7
|
className?: string;
|
|
7
8
|
viewMode?: 'side-by-side' | 'inline';
|
|
8
9
|
caseSensitive?: boolean;
|
|
10
|
+
compareMode?: 'text' | 'structure';
|
|
9
11
|
}
|
|
10
12
|
declare const Compare: React.FC<CompareProps>;
|
|
11
13
|
|
package/dist/styles.css
CHANGED
|
@@ -119,6 +119,48 @@
|
|
|
119
119
|
font-weight: 500;
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
+
/* Contentful document comparison styles */
|
|
123
|
+
.diff-structure-type {
|
|
124
|
+
font-weight: bold;
|
|
125
|
+
color: #4a5568;
|
|
126
|
+
font-size: 0.875rem;
|
|
127
|
+
text-transform: uppercase;
|
|
128
|
+
letter-spacing: 0.05em;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.diff-structure-level {
|
|
132
|
+
color: #718096;
|
|
133
|
+
font-size: 0.75rem;
|
|
134
|
+
margin-left: 0.25rem;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.diff-structure-content {
|
|
138
|
+
margin-left: 0.5rem;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.diff-removed-line .diff-structure-type {
|
|
142
|
+
color: #c53030;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.diff-added-line .diff-structure-type {
|
|
146
|
+
color: #38a169;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
.diff-unchanged-line .diff-structure-type {
|
|
150
|
+
color: #4a5568;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/* Enhanced styles for Contentful content */
|
|
154
|
+
.compare-content .diff-structure-type {
|
|
155
|
+
display: inline-block;
|
|
156
|
+
min-width: 80px;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
.compare-content .diff-structure-level {
|
|
160
|
+
display: inline-block;
|
|
161
|
+
min-width: 20px;
|
|
162
|
+
}
|
|
163
|
+
|
|
122
164
|
/* Responsive design */
|
|
123
165
|
@media (max-width: 768px) {
|
|
124
166
|
.compare-side-by-side {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crashbytes/react-version-compare",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "A React component for comparing strings and arrays with precise word-level and item-level highlighting of differences.",
|
|
5
5
|
"main": "dist/cjs/index.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|
|
@@ -55,6 +55,7 @@
|
|
|
55
55
|
"react-dom": ">=16.8.0"
|
|
56
56
|
},
|
|
57
57
|
"dependencies": {
|
|
58
|
+
"@contentful/rich-text-types": "^17.0.1",
|
|
58
59
|
"diff": "^8.0.1",
|
|
59
60
|
"tslib": "^2.8.1"
|
|
60
61
|
},
|