@crashbytes/react-version-compare 1.0.1 → 1.0.3

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 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 (both strings or both arrays)
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
@@ -2,142 +2,367 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var diff = require('diff');
6
- require('react');
7
5
  var jsxRuntime = require('react/jsx-runtime');
6
+ var react = require('react');
7
+ var richTextTypes = require('@contentful/rich-text-types');
8
+ var Diff = require('diff');
8
9
 
9
- const Compare = ({
10
- original,
11
- modified,
12
- className = '',
13
- viewMode = 'side-by-side',
14
- caseSensitive = true // <-- Default true
15
- }) => {
16
- // Handle string comparison
17
- const renderStringDiff = (orig, mod) => {
18
- const diff$1 = diff.diffWords(orig, mod, {
19
- ignoreCase: !caseSensitive
20
- });
21
- const originalParts = [];
22
- const modifiedParts = [];
23
- for (const part of diff$1) {
24
- if (part.removed) {
25
- originalParts.push(/*#__PURE__*/jsxRuntime.jsx("span", {
26
- className: "diff-removed",
27
- children: part.value
28
- }, originalParts.length));
29
- } else if (part.added) {
30
- modifiedParts.push(/*#__PURE__*/jsxRuntime.jsx("span", {
31
- className: "diff-added",
32
- children: part.value
33
- }, modifiedParts.length));
34
- } else {
35
- originalParts.push(/*#__PURE__*/jsxRuntime.jsx("span", {
36
- className: "diff-unchanged",
37
- children: part.value
38
- }, originalParts.length));
39
- modifiedParts.push(/*#__PURE__*/jsxRuntime.jsx("span", {
40
- className: "diff-unchanged",
41
- children: part.value
42
- }, modifiedParts.length));
43
- }
10
+ function _interopNamespaceDefault(e) {
11
+ var n = Object.create(null);
12
+ if (e) {
13
+ Object.keys(e).forEach(function (k) {
14
+ if (k !== 'default') {
15
+ var d = Object.getOwnPropertyDescriptor(e, k);
16
+ Object.defineProperty(n, k, d.get ? d : {
17
+ enumerable: true,
18
+ get: function () { return e[k]; }
19
+ });
20
+ }
21
+ });
44
22
  }
45
- return {
46
- originalParts,
47
- modifiedParts
48
- };
49
- };
23
+ n.default = e;
24
+ return Object.freeze(n);
25
+ }
26
+
27
+ var Diff__namespace = /*#__PURE__*/_interopNamespaceDefault(Diff);
50
28
 
51
- // Handle array comparison
52
- const renderArrayDiff = (orig, mod) => {
53
- let origArr = orig;
54
- let modArr = mod;
55
- if (!caseSensitive) {
56
- origArr = orig.map(s => typeof s === 'string' ? s.toLowerCase() : s);
57
- modArr = mod.map(s => typeof s === 'string' ? s.toLowerCase() : s);
29
+ // Exported type guard for Contentful documents
30
+ function isContentfulDocument(value) {
31
+ return value && typeof value === 'object' && value.nodeType === richTextTypes.BLOCKS.DOCUMENT && Array.isArray(value.content);
32
+ }
33
+ // Extract plain text from Contentful document
34
+ function extractPlainText(document) {
35
+ const extractFromNode = node => {
36
+ if (node.nodeType === 'text') {
37
+ return node.value;
38
+ }
39
+ if ('content' in node && node.content) {
40
+ return node.content.map(child => extractFromNode(child)).join('');
41
+ }
42
+ return '';
43
+ };
44
+ return extractFromNode(document);
45
+ }
46
+ // Extract structured content for structure diff
47
+ function extractStructuredContent(document) {
48
+ const result = [];
49
+ const extractFromNode = node => {
50
+ if (node.nodeType === 'text') return;
51
+ if ('content' in node && node.content) {
52
+ const textContent = node.content.map(child => child.nodeType === 'text' ? child.value : '').join('');
53
+ let displayType = node.nodeType;
54
+ let headingLevel;
55
+ switch (node.nodeType) {
56
+ case richTextTypes.BLOCKS.HEADING_1:
57
+ displayType = 'Heading';
58
+ headingLevel = 1;
59
+ break;
60
+ case richTextTypes.BLOCKS.HEADING_2:
61
+ displayType = 'Heading';
62
+ headingLevel = 2;
63
+ break;
64
+ case richTextTypes.BLOCKS.HEADING_3:
65
+ displayType = 'Heading';
66
+ headingLevel = 3;
67
+ break;
68
+ case richTextTypes.BLOCKS.HEADING_4:
69
+ displayType = 'Heading';
70
+ headingLevel = 4;
71
+ break;
72
+ case richTextTypes.BLOCKS.HEADING_5:
73
+ displayType = 'Heading';
74
+ headingLevel = 5;
75
+ break;
76
+ case richTextTypes.BLOCKS.HEADING_6:
77
+ displayType = 'Heading';
78
+ headingLevel = 6;
79
+ break;
80
+ case richTextTypes.BLOCKS.PARAGRAPH:
81
+ displayType = 'Text';
82
+ break;
83
+ case richTextTypes.BLOCKS.UL_LIST:
84
+ displayType = 'List';
85
+ break;
86
+ case richTextTypes.BLOCKS.OL_LIST:
87
+ displayType = 'Numbered List';
88
+ break;
89
+ case richTextTypes.BLOCKS.LIST_ITEM:
90
+ displayType = 'List Item';
91
+ break;
92
+ case richTextTypes.BLOCKS.QUOTE:
93
+ displayType = 'Quote';
94
+ break;
95
+ case richTextTypes.BLOCKS.TABLE:
96
+ displayType = 'Table';
97
+ break;
98
+ default:
99
+ displayType = node.nodeType.charAt(0).toUpperCase() + node.nodeType.slice(1);
100
+ }
101
+ if (textContent.trim()) {
102
+ result.push({
103
+ type: displayType,
104
+ content: textContent.trim(),
105
+ level: headingLevel
106
+ });
107
+ }
108
+ node.content.forEach(child => {
109
+ if (child.nodeType !== 'text') extractFromNode(child);
110
+ });
58
111
  }
59
- const diff$1 = diff.diffArrays(origArr, modArr);
112
+ };
113
+ if (document.content) document.content.forEach(node => extractFromNode(node));
114
+ return result;
115
+ }
116
+ // Main Contentful diff renderer
117
+ async function renderContentfulDiff(origDoc, modDoc, compareMode, caseSensitive, renderStringDiff) {
118
+ // Dynamically import diff for Vite/ESM compatibility
119
+ const DiffModule = await import('diff');
120
+ const Diff = DiffModule.default ?? DiffModule;
121
+ const {
122
+ diffWords,
123
+ diffArrays
124
+ } = Diff;
125
+ if (compareMode === 'structure') {
126
+ const origStructure = extractStructuredContent(origDoc);
127
+ const modStructure = extractStructuredContent(modDoc);
128
+ const diff = diffArrays(origStructure, modStructure, {
129
+ comparator: (a, b) => a.type === b.type && a.content === b.content && a.level === b.level
130
+ });
60
131
  const originalParts = [];
61
132
  const modifiedParts = [];
62
- for (const part of diff$1) {
63
- if (part.removed) {
64
- part.value.forEach((item, index) => {
65
- originalParts.push(/*#__PURE__*/jsxRuntime.jsx("div", {
66
- className: "diff-removed-line",
67
- children: orig[origArr.indexOf(item, originalParts.length)] ?? item
68
- }, `${originalParts.length}-${index}`));
69
- });
70
- } else if (part.added) {
71
- part.value.forEach((item, index) => {
72
- modifiedParts.push(/*#__PURE__*/jsxRuntime.jsx("div", {
133
+ let origIdx = 0;
134
+ let modIdx = 0;
135
+ diff.forEach(part => {
136
+ if (part.added) {
137
+ part.value.forEach((modItem, i) => {
138
+ originalParts.push(jsxRuntime.jsx("div", {
139
+ className: "diff-blank-line"
140
+ }, `blank-orig-${modIdx + i}`));
141
+ modifiedParts.push(jsxRuntime.jsxs("div", {
73
142
  className: "diff-added-line",
74
- children: mod[modArr.indexOf(item, modifiedParts.length)] ?? item
75
- }, `${modifiedParts.length}-${index}`));
143
+ children: [jsxRuntime.jsx("span", {
144
+ className: "diff-structure-type",
145
+ children: modItem.type
146
+ }), modItem.level && jsxRuntime.jsxs("span", {
147
+ className: "diff-structure-level",
148
+ children: [" H", modItem.level]
149
+ }), jsxRuntime.jsxs("span", {
150
+ className: "diff-structure-content",
151
+ children: [": ", modItem.content]
152
+ })]
153
+ }, `added-mod-${modIdx + i}`));
76
154
  });
155
+ modIdx += part.count || 0;
156
+ } else if (part.removed) {
157
+ part.value.forEach((origItem, i) => {
158
+ originalParts.push(jsxRuntime.jsxs("div", {
159
+ className: "diff-removed-line",
160
+ children: [jsxRuntime.jsx("span", {
161
+ className: "diff-structure-type",
162
+ children: origItem.type
163
+ }), origItem.level && jsxRuntime.jsxs("span", {
164
+ className: "diff-structure-level",
165
+ children: [" H", origItem.level]
166
+ }), jsxRuntime.jsxs("span", {
167
+ className: "diff-structure-content",
168
+ children: [": ", origItem.content]
169
+ })]
170
+ }, `removed-orig-${origIdx + i}`));
171
+ modifiedParts.push(jsxRuntime.jsx("div", {
172
+ className: "diff-blank-line"
173
+ }, `blank-mod-${origIdx + i}`));
174
+ });
175
+ origIdx += part.count || 0;
77
176
  } else {
78
- part.value.forEach((item, index) => {
79
- originalParts.push(/*#__PURE__*/jsxRuntime.jsx("div", {
177
+ part.value.forEach((item, i) => {
178
+ originalParts.push(jsxRuntime.jsxs("div", {
80
179
  className: "diff-unchanged-line",
81
- children: orig[origArr.indexOf(item, originalParts.length)] ?? item
82
- }, `${originalParts.length}-${index}`));
83
- modifiedParts.push(/*#__PURE__*/jsxRuntime.jsx("div", {
180
+ children: [jsxRuntime.jsx("span", {
181
+ className: "diff-structure-type",
182
+ children: item.type
183
+ }), item.level && jsxRuntime.jsxs("span", {
184
+ className: "diff-structure-level",
185
+ children: [" H", item.level]
186
+ }), jsxRuntime.jsxs("span", {
187
+ className: "diff-structure-content",
188
+ children: [": ", item.content]
189
+ })]
190
+ }, `unchanged-orig-${origIdx + i}`));
191
+ modifiedParts.push(jsxRuntime.jsxs("div", {
84
192
  className: "diff-unchanged-line",
85
- children: mod[modArr.indexOf(item, modifiedParts.length)] ?? item
86
- }, `${modifiedParts.length}-${index}`));
193
+ children: [jsxRuntime.jsx("span", {
194
+ className: "diff-structure-type",
195
+ children: item.type
196
+ }), item.level && jsxRuntime.jsxs("span", {
197
+ className: "diff-structure-level",
198
+ children: [" H", item.level]
199
+ }), jsxRuntime.jsxs("span", {
200
+ className: "diff-structure-content",
201
+ children: [": ", item.content]
202
+ })]
203
+ }, `unchanged-mod-${modIdx + i}`));
87
204
  });
205
+ origIdx += part.count || 0;
206
+ modIdx += part.count || 0;
88
207
  }
89
- }
208
+ });
90
209
  return {
91
210
  originalParts,
92
211
  modifiedParts
93
212
  };
213
+ } else {
214
+ // Text-based comparison of Contentful documents
215
+ const origText = extractPlainText(origDoc);
216
+ const modText = extractPlainText(modDoc);
217
+ return renderStringDiff(origText, modText);
218
+ }
219
+ }
220
+
221
+ function renderStringDiff(orig, mod) {
222
+ const difference = Diff__namespace.diffWords(orig, mod);
223
+ const originalParts = [];
224
+ const modifiedParts = [];
225
+ for (const part of difference) {
226
+ if (part.removed) {
227
+ originalParts.push(jsxRuntime.jsx("span", {
228
+ className: "diff-removed",
229
+ children: part.value
230
+ }, originalParts.length));
231
+ } else if (part.added) {
232
+ modifiedParts.push(jsxRuntime.jsx("span", {
233
+ className: "diff-added",
234
+ children: part.value
235
+ }, modifiedParts.length));
236
+ } else {
237
+ originalParts.push(jsxRuntime.jsx("span", {
238
+ className: "diff-unchanged",
239
+ children: part.value
240
+ }, originalParts.length));
241
+ modifiedParts.push(jsxRuntime.jsx("span", {
242
+ className: "diff-unchanged",
243
+ children: part.value
244
+ }, modifiedParts.length));
245
+ }
246
+ }
247
+ return {
248
+ originalParts,
249
+ modifiedParts
94
250
  };
251
+ }
252
+ function renderArrayDiff(original, modified) {
253
+ const maxLength = Math.max(original.length, modified.length);
254
+ const originalParts = [];
255
+ const modifiedParts = [];
256
+ for (let i = 0; i < maxLength; i++) {
257
+ const orig = original[i] ?? '';
258
+ const mod = modified[i] ?? '';
259
+ if (orig === mod) {
260
+ originalParts.push(jsxRuntime.jsx("div", {
261
+ className: "diff-unchanged-line",
262
+ children: orig
263
+ }, `orig-${i}`));
264
+ modifiedParts.push(jsxRuntime.jsx("div", {
265
+ className: "diff-unchanged-line",
266
+ children: mod
267
+ }, `mod-${i}`));
268
+ } else {
269
+ originalParts.push(jsxRuntime.jsx("div", {
270
+ className: orig ? "diff-removed-line" : "diff-blank-line",
271
+ children: orig
272
+ }, `orig-${i}`));
273
+ modifiedParts.push(jsxRuntime.jsx("div", {
274
+ className: mod ? "diff-added-line" : "diff-blank-line",
275
+ children: mod
276
+ }, `mod-${i}`));
277
+ }
278
+ }
279
+ return {
280
+ originalParts,
281
+ modifiedParts
282
+ };
283
+ }
284
+ const Compare = ({
285
+ original,
286
+ modified,
287
+ className = '',
288
+ viewMode = 'side-by-side',
289
+ caseSensitive = true,
290
+ compareMode = 'text'
291
+ }) => {
95
292
  const isStringComparison = typeof original === 'string' && typeof modified === 'string';
96
293
  const isArrayComparison = Array.isArray(original) && Array.isArray(modified);
97
- if (!isStringComparison && !isArrayComparison) {
98
- return /*#__PURE__*/jsxRuntime.jsx("div", {
99
- className: `compare-error ${className}`,
100
- children: "Error: Both inputs must be either strings or arrays of strings"
101
- });
102
- }
103
- let originalParts, modifiedParts;
294
+ const isContentfulComparison = isContentfulDocument(original) && isContentfulDocument(modified);
295
+ const [contentfulParts, setContentfulParts] = react.useState(null);
296
+ react.useEffect(() => {
297
+ let cancelled = false;
298
+ if (isContentfulComparison) {
299
+ setContentfulParts(null); // reset while loading
300
+ renderContentfulDiff(original, modified, compareMode, caseSensitive, renderStringDiff).then(result => {
301
+ if (!cancelled) setContentfulParts(result);
302
+ });
303
+ }
304
+ return () => {
305
+ cancelled = true;
306
+ };
307
+ // eslint-disable-next-line react-hooks/exhaustive-deps
308
+ }, [original, modified, compareMode, caseSensitive, isContentfulComparison]);
309
+ let originalParts = [],
310
+ modifiedParts = [];
104
311
  if (isStringComparison) {
105
312
  ({
106
313
  originalParts,
107
314
  modifiedParts
108
315
  } = renderStringDiff(original, modified));
109
- } else {
316
+ } else if (isArrayComparison) {
110
317
  ({
111
318
  originalParts,
112
319
  modifiedParts
113
320
  } = renderArrayDiff(original, modified));
321
+ } else if (isContentfulComparison) {
322
+ if (contentfulParts) {
323
+ originalParts = contentfulParts.originalParts;
324
+ modifiedParts = contentfulParts.modifiedParts;
325
+ } else {
326
+ originalParts = [jsxRuntime.jsx("div", {
327
+ children: "Loading..."
328
+ }, "loading")];
329
+ modifiedParts = [jsxRuntime.jsx("div", {
330
+ children: "Loading..."
331
+ }, "loading")];
332
+ }
333
+ }
334
+ if (!isStringComparison && !isArrayComparison && !isContentfulComparison) {
335
+ return jsxRuntime.jsx("div", {
336
+ className: `compare-error ${className}`,
337
+ children: "Error: Invalid input for comparison."
338
+ });
114
339
  }
115
340
  if (viewMode === 'inline') {
116
- return /*#__PURE__*/jsxRuntime.jsx("div", {
341
+ return jsxRuntime.jsx("div", {
117
342
  className: `compare-inline ${className}`,
118
- children: /*#__PURE__*/jsxRuntime.jsxs("div", {
343
+ children: jsxRuntime.jsxs("div", {
119
344
  className: "compare-content",
120
345
  children: [originalParts, modifiedParts]
121
346
  })
122
347
  });
123
348
  }
124
- return /*#__PURE__*/jsxRuntime.jsxs("div", {
349
+ return jsxRuntime.jsxs("div", {
125
350
  className: `compare-side-by-side ${className}`,
126
- children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
351
+ children: [jsxRuntime.jsxs("div", {
127
352
  className: "compare-panel",
128
- children: [/*#__PURE__*/jsxRuntime.jsx("div", {
353
+ children: [jsxRuntime.jsx("div", {
129
354
  className: "compare-header original-header",
130
355
  children: "Original"
131
- }), /*#__PURE__*/jsxRuntime.jsx("div", {
356
+ }), jsxRuntime.jsx("div", {
132
357
  className: "compare-content original-content",
133
358
  children: originalParts
134
359
  })]
135
- }), /*#__PURE__*/jsxRuntime.jsxs("div", {
360
+ }), jsxRuntime.jsxs("div", {
136
361
  className: "compare-panel",
137
- children: [/*#__PURE__*/jsxRuntime.jsx("div", {
362
+ children: [jsxRuntime.jsx("div", {
138
363
  className: "compare-header modified-header",
139
364
  children: "Modified"
140
- }), /*#__PURE__*/jsxRuntime.jsx("div", {
365
+ }), jsxRuntime.jsx("div", {
141
366
  className: "compare-content modified-content",
142
367
  children: modifiedParts
143
368
  })]
@@ -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/contentfulDiff.tsx","../../src/components/Compare.tsx"],"sourcesContent":["import React from 'react';\nimport { BLOCKS, Document, Block, Inline, Text } from '@contentful/rich-text-types';\n\n// Exported type guard for Contentful documents\nexport function isContentfulDocument(value: any): value is Document {\n return (\n value &&\n typeof value === 'object' &&\n value.nodeType === BLOCKS.DOCUMENT &&\n Array.isArray(value.content)\n );\n}\n\n// Extract plain text from Contentful document\nexport function 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 if ('content' in node && node.content) {\n return node.content.map(child => extractFromNode(child)).join('');\n }\n return '';\n };\n return extractFromNode(document);\n}\n\n// Extract structured content for structure diff\nexport function extractStructuredContent(document: Document): Array<{ type: string; content: string; level?: number }> {\n const result: Array<{ type: string; content: string; level?: number }> = [];\n const extractFromNode = (node: Block | Inline | Text): void => {\n if (node.nodeType === 'text') return;\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 let displayType: string = node.nodeType;\n let headingLevel: number | undefined;\n switch (node.nodeType) {\n case BLOCKS.HEADING_1: displayType = 'Heading'; headingLevel = 1; break;\n case BLOCKS.HEADING_2: displayType = 'Heading'; headingLevel = 2; break;\n case BLOCKS.HEADING_3: displayType = 'Heading'; headingLevel = 3; break;\n case BLOCKS.HEADING_4: displayType = 'Heading'; headingLevel = 4; break;\n case BLOCKS.HEADING_5: displayType = 'Heading'; headingLevel = 5; break;\n case BLOCKS.HEADING_6: displayType = 'Heading'; headingLevel = 6; break;\n case BLOCKS.PARAGRAPH: displayType = 'Text'; break;\n case BLOCKS.UL_LIST: displayType = 'List'; break;\n case BLOCKS.OL_LIST: displayType = 'Numbered List'; break;\n case BLOCKS.LIST_ITEM: displayType = 'List Item'; break;\n case BLOCKS.QUOTE: displayType = 'Quote'; break;\n case BLOCKS.TABLE: displayType = 'Table'; break;\n default: displayType = node.nodeType.charAt(0).toUpperCase() + node.nodeType.slice(1);\n }\n if (textContent.trim()) {\n result.push({ type: displayType, content: textContent.trim(), level: headingLevel });\n }\n node.content.forEach(child => {\n if (child.nodeType !== 'text') extractFromNode(child);\n });\n }\n };\n if (document.content) document.content.forEach(node => extractFromNode(node));\n return result;\n}\n\n// Main Contentful diff renderer\nexport async function renderContentfulDiff(\n origDoc: Document,\n modDoc: Document,\n compareMode: 'text' | 'structure',\n caseSensitive: boolean,\n renderStringDiff: (a: string, b: string) => { originalParts: any[]; modifiedParts: any[] }\n) {\n // Dynamically import diff for Vite/ESM compatibility\n const DiffModule = await import('diff');\n const Diff = DiffModule.default ?? DiffModule;\n const { diffWords, diffArrays } = Diff;\n\n if (compareMode === 'structure') {\n const origStructure = extractStructuredContent(origDoc);\n const modStructure = extractStructuredContent(modDoc);\n\n const diff = diffArrays(\n origStructure,\n modStructure,\n {\n comparator: (a: any, b: any) =>\n a.type === b.type &&\n a.content === b.content &&\n a.level === b.level\n }\n );\n\n const originalParts: any[] = [];\n const modifiedParts: any[] = [];\n\n let origIdx = 0;\n let modIdx = 0;\n\n diff.forEach((part: any) => {\n if (part.added) {\n part.value.forEach((modItem: any, i: number) => {\n originalParts.push(\n <div key={`blank-orig-${modIdx + i}`} className=\"diff-blank-line\" />\n );\n modifiedParts.push(\n <div key={`added-mod-${modIdx + 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 modIdx += part.count || 0;\n } else if (part.removed) {\n part.value.forEach((origItem: any, i: number) => {\n originalParts.push(\n <div key={`removed-orig-${origIdx + 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={`blank-mod-${origIdx + i}`} className=\"diff-blank-line\" />\n );\n });\n origIdx += part.count || 0;\n } else {\n part.value.forEach((item: any, i: number) => {\n originalParts.push(\n <div key={`unchanged-orig-${origIdx + i}`} className=\"diff-unchanged-line\">\n <span className=\"diff-structure-type\">{item.type}</span>\n {item.level && <span className=\"diff-structure-level\"> H{item.level}</span>}\n <span className=\"diff-structure-content\">: {item.content}</span>\n </div>\n );\n modifiedParts.push(\n <div key={`unchanged-mod-${modIdx + i}`} className=\"diff-unchanged-line\">\n <span className=\"diff-structure-type\">{item.type}</span>\n {item.level && <span className=\"diff-structure-level\"> H{item.level}</span>}\n <span className=\"diff-structure-content\">: {item.content}</span>\n </div>\n );\n });\n origIdx += part.count || 0;\n modIdx += part.count || 0;\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}","import React, { useEffect, useState } from 'react';\nimport { Document } from '@contentful/rich-text-types';\nimport {\n isContentfulDocument,\n renderContentfulDiff\n} from './contentfulDiff';\nimport * as Diff from 'diff';\n\nfunction renderStringDiff(orig: string, mod: string) {\n const difference = Diff.diffWords(orig, mod);\n const originalParts: any[] = [];\n const modifiedParts: any[] = [];\n for (const part of difference) {\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\nfunction renderArrayDiff(original: string[], modified: string[]) {\n const maxLength = Math.max(original.length, modified.length);\n const originalParts: any[] = [];\n const modifiedParts: any[] = [];\n for (let i = 0; i < maxLength; i++) {\n const orig = original[i] ?? '';\n const mod = modified[i] ?? '';\n if (orig === mod) {\n originalParts.push(\n <div key={`orig-${i}`} className=\"diff-unchanged-line\">{orig}</div>\n );\n modifiedParts.push(\n <div key={`mod-${i}`} className=\"diff-unchanged-line\">{mod}</div>\n );\n } else {\n originalParts.push(\n <div key={`orig-${i}`} className={orig ? \"diff-removed-line\" : \"diff-blank-line\"}>{orig}</div>\n );\n modifiedParts.push(\n <div key={`mod-${i}`} className={mod ? \"diff-added-line\" : \"diff-blank-line\"}>{mod}</div>\n );\n }\n }\n return { originalParts, modifiedParts };\n}\n\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';\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',\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 const [contentfulParts, setContentfulParts] = useState<{ originalParts: any[]; modifiedParts: any[] } | null>(null);\n\n useEffect(() => {\n let cancelled = false;\n if (isContentfulComparison) {\n setContentfulParts(null); // reset while loading\n renderContentfulDiff(\n original as Document,\n modified as Document,\n compareMode,\n caseSensitive,\n renderStringDiff\n ).then(result => {\n if (!cancelled) setContentfulParts(result);\n });\n }\n return () => { cancelled = true; };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [original, modified, compareMode, caseSensitive, isContentfulComparison]);\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 if (contentfulParts) {\n originalParts = contentfulParts.originalParts;\n modifiedParts = contentfulParts.modifiedParts;\n } else {\n originalParts = [<div key=\"loading\">Loading...</div>];\n modifiedParts = [<div key=\"loading\">Loading...</div>];\n }\n }\n\n if (\n !isStringComparison &&\n !isArrayComparison &&\n !isContentfulComparison\n ) {\n return (\n <div className={`compare-error ${className}`}>\n Error: Invalid input for comparison.\n </div>\n );\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\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":["isContentfulDocument","value","nodeType","BLOCKS","DOCUMENT","Array","isArray","content","extractPlainText","document","extractFromNode","node","map","child","join","extractStructuredContent","result","textContent","displayType","headingLevel","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","renderContentfulDiff","origDoc","modDoc","compareMode","caseSensitive","renderStringDiff","DiffModule","Diff","default","diffWords","diffArrays","origStructure","modStructure","diff","comparator","a","b","originalParts","modifiedParts","origIdx","modIdx","part","added","modItem","i","_jsx","className","_jsxs","children","count","removed","origItem","item","origText","modText","orig","mod","difference","length","renderArrayDiff","original","modified","maxLength","Math","max","Compare","viewMode","isStringComparison","isArrayComparison","isContentfulComparison","contentfulParts","setContentfulParts","useState","useEffect","cancelled","then"],"mappings":"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"}
package/dist/esm/index.js CHANGED
@@ -1,139 +1,345 @@
1
- import { diffWords, diffArrays } from 'diff';
2
- import 'react';
3
1
  import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import { useState, useEffect } from 'react';
3
+ import { BLOCKS } from '@contentful/rich-text-types';
4
+ import * as Diff from 'diff';
4
5
 
5
- const Compare = ({
6
- original,
7
- modified,
8
- className = '',
9
- viewMode = 'side-by-side',
10
- caseSensitive = true // <-- Default true
11
- }) => {
12
- // Handle string comparison
13
- const renderStringDiff = (orig, mod) => {
14
- const diff = diffWords(orig, mod, {
15
- ignoreCase: !caseSensitive
16
- });
17
- const originalParts = [];
18
- const modifiedParts = [];
19
- for (const part of diff) {
20
- if (part.removed) {
21
- originalParts.push(/*#__PURE__*/jsx("span", {
22
- className: "diff-removed",
23
- children: part.value
24
- }, originalParts.length));
25
- } else if (part.added) {
26
- modifiedParts.push(/*#__PURE__*/jsx("span", {
27
- className: "diff-added",
28
- children: part.value
29
- }, modifiedParts.length));
30
- } else {
31
- originalParts.push(/*#__PURE__*/jsx("span", {
32
- className: "diff-unchanged",
33
- children: part.value
34
- }, originalParts.length));
35
- modifiedParts.push(/*#__PURE__*/jsx("span", {
36
- className: "diff-unchanged",
37
- children: part.value
38
- }, modifiedParts.length));
39
- }
6
+ // Exported type guard for Contentful documents
7
+ function isContentfulDocument(value) {
8
+ return value && typeof value === 'object' && value.nodeType === BLOCKS.DOCUMENT && Array.isArray(value.content);
9
+ }
10
+ // Extract plain text from Contentful document
11
+ function extractPlainText(document) {
12
+ const extractFromNode = node => {
13
+ if (node.nodeType === 'text') {
14
+ return node.value;
40
15
  }
41
- return {
42
- originalParts,
43
- modifiedParts
44
- };
16
+ if ('content' in node && node.content) {
17
+ return node.content.map(child => extractFromNode(child)).join('');
18
+ }
19
+ return '';
45
20
  };
46
-
47
- // Handle array comparison
48
- const renderArrayDiff = (orig, mod) => {
49
- let origArr = orig;
50
- let modArr = mod;
51
- if (!caseSensitive) {
52
- origArr = orig.map(s => typeof s === 'string' ? s.toLowerCase() : s);
53
- modArr = mod.map(s => typeof s === 'string' ? s.toLowerCase() : s);
21
+ return extractFromNode(document);
22
+ }
23
+ // Extract structured content for structure diff
24
+ function extractStructuredContent(document) {
25
+ const result = [];
26
+ const extractFromNode = node => {
27
+ if (node.nodeType === 'text') return;
28
+ if ('content' in node && node.content) {
29
+ const textContent = node.content.map(child => child.nodeType === 'text' ? child.value : '').join('');
30
+ let displayType = node.nodeType;
31
+ let headingLevel;
32
+ switch (node.nodeType) {
33
+ case BLOCKS.HEADING_1:
34
+ displayType = 'Heading';
35
+ headingLevel = 1;
36
+ break;
37
+ case BLOCKS.HEADING_2:
38
+ displayType = 'Heading';
39
+ headingLevel = 2;
40
+ break;
41
+ case BLOCKS.HEADING_3:
42
+ displayType = 'Heading';
43
+ headingLevel = 3;
44
+ break;
45
+ case BLOCKS.HEADING_4:
46
+ displayType = 'Heading';
47
+ headingLevel = 4;
48
+ break;
49
+ case BLOCKS.HEADING_5:
50
+ displayType = 'Heading';
51
+ headingLevel = 5;
52
+ break;
53
+ case BLOCKS.HEADING_6:
54
+ displayType = 'Heading';
55
+ headingLevel = 6;
56
+ break;
57
+ case BLOCKS.PARAGRAPH:
58
+ displayType = 'Text';
59
+ break;
60
+ case BLOCKS.UL_LIST:
61
+ displayType = 'List';
62
+ break;
63
+ case BLOCKS.OL_LIST:
64
+ displayType = 'Numbered List';
65
+ break;
66
+ case BLOCKS.LIST_ITEM:
67
+ displayType = 'List Item';
68
+ break;
69
+ case BLOCKS.QUOTE:
70
+ displayType = 'Quote';
71
+ break;
72
+ case BLOCKS.TABLE:
73
+ displayType = 'Table';
74
+ break;
75
+ default:
76
+ displayType = node.nodeType.charAt(0).toUpperCase() + node.nodeType.slice(1);
77
+ }
78
+ if (textContent.trim()) {
79
+ result.push({
80
+ type: displayType,
81
+ content: textContent.trim(),
82
+ level: headingLevel
83
+ });
84
+ }
85
+ node.content.forEach(child => {
86
+ if (child.nodeType !== 'text') extractFromNode(child);
87
+ });
54
88
  }
55
- const diff = diffArrays(origArr, modArr);
89
+ };
90
+ if (document.content) document.content.forEach(node => extractFromNode(node));
91
+ return result;
92
+ }
93
+ // Main Contentful diff renderer
94
+ async function renderContentfulDiff(origDoc, modDoc, compareMode, caseSensitive, renderStringDiff) {
95
+ // Dynamically import diff for Vite/ESM compatibility
96
+ const DiffModule = await import('diff');
97
+ const Diff = DiffModule.default ?? DiffModule;
98
+ const {
99
+ diffWords,
100
+ diffArrays
101
+ } = Diff;
102
+ if (compareMode === 'structure') {
103
+ const origStructure = extractStructuredContent(origDoc);
104
+ const modStructure = extractStructuredContent(modDoc);
105
+ const diff = diffArrays(origStructure, modStructure, {
106
+ comparator: (a, b) => a.type === b.type && a.content === b.content && a.level === b.level
107
+ });
56
108
  const originalParts = [];
57
109
  const modifiedParts = [];
58
- for (const part of diff) {
59
- if (part.removed) {
60
- part.value.forEach((item, index) => {
61
- originalParts.push(/*#__PURE__*/jsx("div", {
62
- className: "diff-removed-line",
63
- children: orig[origArr.indexOf(item, originalParts.length)] ?? item
64
- }, `${originalParts.length}-${index}`));
65
- });
66
- } else if (part.added) {
67
- part.value.forEach((item, index) => {
68
- modifiedParts.push(/*#__PURE__*/jsx("div", {
110
+ let origIdx = 0;
111
+ let modIdx = 0;
112
+ diff.forEach(part => {
113
+ if (part.added) {
114
+ part.value.forEach((modItem, i) => {
115
+ originalParts.push(jsx("div", {
116
+ className: "diff-blank-line"
117
+ }, `blank-orig-${modIdx + i}`));
118
+ modifiedParts.push(jsxs("div", {
69
119
  className: "diff-added-line",
70
- children: mod[modArr.indexOf(item, modifiedParts.length)] ?? item
71
- }, `${modifiedParts.length}-${index}`));
120
+ children: [jsx("span", {
121
+ className: "diff-structure-type",
122
+ children: modItem.type
123
+ }), modItem.level && jsxs("span", {
124
+ className: "diff-structure-level",
125
+ children: [" H", modItem.level]
126
+ }), jsxs("span", {
127
+ className: "diff-structure-content",
128
+ children: [": ", modItem.content]
129
+ })]
130
+ }, `added-mod-${modIdx + i}`));
131
+ });
132
+ modIdx += part.count || 0;
133
+ } else if (part.removed) {
134
+ part.value.forEach((origItem, i) => {
135
+ originalParts.push(jsxs("div", {
136
+ className: "diff-removed-line",
137
+ children: [jsx("span", {
138
+ className: "diff-structure-type",
139
+ children: origItem.type
140
+ }), origItem.level && jsxs("span", {
141
+ className: "diff-structure-level",
142
+ children: [" H", origItem.level]
143
+ }), jsxs("span", {
144
+ className: "diff-structure-content",
145
+ children: [": ", origItem.content]
146
+ })]
147
+ }, `removed-orig-${origIdx + i}`));
148
+ modifiedParts.push(jsx("div", {
149
+ className: "diff-blank-line"
150
+ }, `blank-mod-${origIdx + i}`));
72
151
  });
152
+ origIdx += part.count || 0;
73
153
  } else {
74
- part.value.forEach((item, index) => {
75
- originalParts.push(/*#__PURE__*/jsx("div", {
154
+ part.value.forEach((item, i) => {
155
+ originalParts.push(jsxs("div", {
76
156
  className: "diff-unchanged-line",
77
- children: orig[origArr.indexOf(item, originalParts.length)] ?? item
78
- }, `${originalParts.length}-${index}`));
79
- modifiedParts.push(/*#__PURE__*/jsx("div", {
157
+ children: [jsx("span", {
158
+ className: "diff-structure-type",
159
+ children: item.type
160
+ }), item.level && jsxs("span", {
161
+ className: "diff-structure-level",
162
+ children: [" H", item.level]
163
+ }), jsxs("span", {
164
+ className: "diff-structure-content",
165
+ children: [": ", item.content]
166
+ })]
167
+ }, `unchanged-orig-${origIdx + i}`));
168
+ modifiedParts.push(jsxs("div", {
80
169
  className: "diff-unchanged-line",
81
- children: mod[modArr.indexOf(item, modifiedParts.length)] ?? item
82
- }, `${modifiedParts.length}-${index}`));
170
+ children: [jsx("span", {
171
+ className: "diff-structure-type",
172
+ children: item.type
173
+ }), item.level && jsxs("span", {
174
+ className: "diff-structure-level",
175
+ children: [" H", item.level]
176
+ }), jsxs("span", {
177
+ className: "diff-structure-content",
178
+ children: [": ", item.content]
179
+ })]
180
+ }, `unchanged-mod-${modIdx + i}`));
83
181
  });
182
+ origIdx += part.count || 0;
183
+ modIdx += part.count || 0;
84
184
  }
85
- }
185
+ });
86
186
  return {
87
187
  originalParts,
88
188
  modifiedParts
89
189
  };
190
+ } else {
191
+ // Text-based comparison of Contentful documents
192
+ const origText = extractPlainText(origDoc);
193
+ const modText = extractPlainText(modDoc);
194
+ return renderStringDiff(origText, modText);
195
+ }
196
+ }
197
+
198
+ function renderStringDiff(orig, mod) {
199
+ const difference = Diff.diffWords(orig, mod);
200
+ const originalParts = [];
201
+ const modifiedParts = [];
202
+ for (const part of difference) {
203
+ if (part.removed) {
204
+ originalParts.push(jsx("span", {
205
+ className: "diff-removed",
206
+ children: part.value
207
+ }, originalParts.length));
208
+ } else if (part.added) {
209
+ modifiedParts.push(jsx("span", {
210
+ className: "diff-added",
211
+ children: part.value
212
+ }, modifiedParts.length));
213
+ } else {
214
+ originalParts.push(jsx("span", {
215
+ className: "diff-unchanged",
216
+ children: part.value
217
+ }, originalParts.length));
218
+ modifiedParts.push(jsx("span", {
219
+ className: "diff-unchanged",
220
+ children: part.value
221
+ }, modifiedParts.length));
222
+ }
223
+ }
224
+ return {
225
+ originalParts,
226
+ modifiedParts
90
227
  };
228
+ }
229
+ function renderArrayDiff(original, modified) {
230
+ const maxLength = Math.max(original.length, modified.length);
231
+ const originalParts = [];
232
+ const modifiedParts = [];
233
+ for (let i = 0; i < maxLength; i++) {
234
+ const orig = original[i] ?? '';
235
+ const mod = modified[i] ?? '';
236
+ if (orig === mod) {
237
+ originalParts.push(jsx("div", {
238
+ className: "diff-unchanged-line",
239
+ children: orig
240
+ }, `orig-${i}`));
241
+ modifiedParts.push(jsx("div", {
242
+ className: "diff-unchanged-line",
243
+ children: mod
244
+ }, `mod-${i}`));
245
+ } else {
246
+ originalParts.push(jsx("div", {
247
+ className: orig ? "diff-removed-line" : "diff-blank-line",
248
+ children: orig
249
+ }, `orig-${i}`));
250
+ modifiedParts.push(jsx("div", {
251
+ className: mod ? "diff-added-line" : "diff-blank-line",
252
+ children: mod
253
+ }, `mod-${i}`));
254
+ }
255
+ }
256
+ return {
257
+ originalParts,
258
+ modifiedParts
259
+ };
260
+ }
261
+ const Compare = ({
262
+ original,
263
+ modified,
264
+ className = '',
265
+ viewMode = 'side-by-side',
266
+ caseSensitive = true,
267
+ compareMode = 'text'
268
+ }) => {
91
269
  const isStringComparison = typeof original === 'string' && typeof modified === 'string';
92
270
  const isArrayComparison = Array.isArray(original) && Array.isArray(modified);
93
- if (!isStringComparison && !isArrayComparison) {
94
- return /*#__PURE__*/jsx("div", {
95
- className: `compare-error ${className}`,
96
- children: "Error: Both inputs must be either strings or arrays of strings"
97
- });
98
- }
99
- let originalParts, modifiedParts;
271
+ const isContentfulComparison = isContentfulDocument(original) && isContentfulDocument(modified);
272
+ const [contentfulParts, setContentfulParts] = useState(null);
273
+ useEffect(() => {
274
+ let cancelled = false;
275
+ if (isContentfulComparison) {
276
+ setContentfulParts(null); // reset while loading
277
+ renderContentfulDiff(original, modified, compareMode, caseSensitive, renderStringDiff).then(result => {
278
+ if (!cancelled) setContentfulParts(result);
279
+ });
280
+ }
281
+ return () => {
282
+ cancelled = true;
283
+ };
284
+ // eslint-disable-next-line react-hooks/exhaustive-deps
285
+ }, [original, modified, compareMode, caseSensitive, isContentfulComparison]);
286
+ let originalParts = [],
287
+ modifiedParts = [];
100
288
  if (isStringComparison) {
101
289
  ({
102
290
  originalParts,
103
291
  modifiedParts
104
292
  } = renderStringDiff(original, modified));
105
- } else {
293
+ } else if (isArrayComparison) {
106
294
  ({
107
295
  originalParts,
108
296
  modifiedParts
109
297
  } = renderArrayDiff(original, modified));
298
+ } else if (isContentfulComparison) {
299
+ if (contentfulParts) {
300
+ originalParts = contentfulParts.originalParts;
301
+ modifiedParts = contentfulParts.modifiedParts;
302
+ } else {
303
+ originalParts = [jsx("div", {
304
+ children: "Loading..."
305
+ }, "loading")];
306
+ modifiedParts = [jsx("div", {
307
+ children: "Loading..."
308
+ }, "loading")];
309
+ }
310
+ }
311
+ if (!isStringComparison && !isArrayComparison && !isContentfulComparison) {
312
+ return jsx("div", {
313
+ className: `compare-error ${className}`,
314
+ children: "Error: Invalid input for comparison."
315
+ });
110
316
  }
111
317
  if (viewMode === 'inline') {
112
- return /*#__PURE__*/jsx("div", {
318
+ return jsx("div", {
113
319
  className: `compare-inline ${className}`,
114
- children: /*#__PURE__*/jsxs("div", {
320
+ children: jsxs("div", {
115
321
  className: "compare-content",
116
322
  children: [originalParts, modifiedParts]
117
323
  })
118
324
  });
119
325
  }
120
- return /*#__PURE__*/jsxs("div", {
326
+ return jsxs("div", {
121
327
  className: `compare-side-by-side ${className}`,
122
- children: [/*#__PURE__*/jsxs("div", {
328
+ children: [jsxs("div", {
123
329
  className: "compare-panel",
124
- children: [/*#__PURE__*/jsx("div", {
330
+ children: [jsx("div", {
125
331
  className: "compare-header original-header",
126
332
  children: "Original"
127
- }), /*#__PURE__*/jsx("div", {
333
+ }), jsx("div", {
128
334
  className: "compare-content original-content",
129
335
  children: originalParts
130
336
  })]
131
- }), /*#__PURE__*/jsxs("div", {
337
+ }), jsxs("div", {
132
338
  className: "compare-panel",
133
- children: [/*#__PURE__*/jsx("div", {
339
+ children: [jsx("div", {
134
340
  className: "compare-header modified-header",
135
341
  children: "Modified"
136
- }), /*#__PURE__*/jsx("div", {
342
+ }), jsx("div", {
137
343
  className: "compare-content modified-content",
138
344
  children: modifiedParts
139
345
  })]
@@ -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/contentfulDiff.tsx","../../src/components/Compare.tsx"],"sourcesContent":["import React from 'react';\nimport { BLOCKS, Document, Block, Inline, Text } from '@contentful/rich-text-types';\n\n// Exported type guard for Contentful documents\nexport function isContentfulDocument(value: any): value is Document {\n return (\n value &&\n typeof value === 'object' &&\n value.nodeType === BLOCKS.DOCUMENT &&\n Array.isArray(value.content)\n );\n}\n\n// Extract plain text from Contentful document\nexport function 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 if ('content' in node && node.content) {\n return node.content.map(child => extractFromNode(child)).join('');\n }\n return '';\n };\n return extractFromNode(document);\n}\n\n// Extract structured content for structure diff\nexport function extractStructuredContent(document: Document): Array<{ type: string; content: string; level?: number }> {\n const result: Array<{ type: string; content: string; level?: number }> = [];\n const extractFromNode = (node: Block | Inline | Text): void => {\n if (node.nodeType === 'text') return;\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 let displayType: string = node.nodeType;\n let headingLevel: number | undefined;\n switch (node.nodeType) {\n case BLOCKS.HEADING_1: displayType = 'Heading'; headingLevel = 1; break;\n case BLOCKS.HEADING_2: displayType = 'Heading'; headingLevel = 2; break;\n case BLOCKS.HEADING_3: displayType = 'Heading'; headingLevel = 3; break;\n case BLOCKS.HEADING_4: displayType = 'Heading'; headingLevel = 4; break;\n case BLOCKS.HEADING_5: displayType = 'Heading'; headingLevel = 5; break;\n case BLOCKS.HEADING_6: displayType = 'Heading'; headingLevel = 6; break;\n case BLOCKS.PARAGRAPH: displayType = 'Text'; break;\n case BLOCKS.UL_LIST: displayType = 'List'; break;\n case BLOCKS.OL_LIST: displayType = 'Numbered List'; break;\n case BLOCKS.LIST_ITEM: displayType = 'List Item'; break;\n case BLOCKS.QUOTE: displayType = 'Quote'; break;\n case BLOCKS.TABLE: displayType = 'Table'; break;\n default: displayType = node.nodeType.charAt(0).toUpperCase() + node.nodeType.slice(1);\n }\n if (textContent.trim()) {\n result.push({ type: displayType, content: textContent.trim(), level: headingLevel });\n }\n node.content.forEach(child => {\n if (child.nodeType !== 'text') extractFromNode(child);\n });\n }\n };\n if (document.content) document.content.forEach(node => extractFromNode(node));\n return result;\n}\n\n// Main Contentful diff renderer\nexport async function renderContentfulDiff(\n origDoc: Document,\n modDoc: Document,\n compareMode: 'text' | 'structure',\n caseSensitive: boolean,\n renderStringDiff: (a: string, b: string) => { originalParts: any[]; modifiedParts: any[] }\n) {\n // Dynamically import diff for Vite/ESM compatibility\n const DiffModule = await import('diff');\n const Diff = DiffModule.default ?? DiffModule;\n const { diffWords, diffArrays } = Diff;\n\n if (compareMode === 'structure') {\n const origStructure = extractStructuredContent(origDoc);\n const modStructure = extractStructuredContent(modDoc);\n\n const diff = diffArrays(\n origStructure,\n modStructure,\n {\n comparator: (a: any, b: any) =>\n a.type === b.type &&\n a.content === b.content &&\n a.level === b.level\n }\n );\n\n const originalParts: any[] = [];\n const modifiedParts: any[] = [];\n\n let origIdx = 0;\n let modIdx = 0;\n\n diff.forEach((part: any) => {\n if (part.added) {\n part.value.forEach((modItem: any, i: number) => {\n originalParts.push(\n <div key={`blank-orig-${modIdx + i}`} className=\"diff-blank-line\" />\n );\n modifiedParts.push(\n <div key={`added-mod-${modIdx + 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 modIdx += part.count || 0;\n } else if (part.removed) {\n part.value.forEach((origItem: any, i: number) => {\n originalParts.push(\n <div key={`removed-orig-${origIdx + 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={`blank-mod-${origIdx + i}`} className=\"diff-blank-line\" />\n );\n });\n origIdx += part.count || 0;\n } else {\n part.value.forEach((item: any, i: number) => {\n originalParts.push(\n <div key={`unchanged-orig-${origIdx + i}`} className=\"diff-unchanged-line\">\n <span className=\"diff-structure-type\">{item.type}</span>\n {item.level && <span className=\"diff-structure-level\"> H{item.level}</span>}\n <span className=\"diff-structure-content\">: {item.content}</span>\n </div>\n );\n modifiedParts.push(\n <div key={`unchanged-mod-${modIdx + i}`} className=\"diff-unchanged-line\">\n <span className=\"diff-structure-type\">{item.type}</span>\n {item.level && <span className=\"diff-structure-level\"> H{item.level}</span>}\n <span className=\"diff-structure-content\">: {item.content}</span>\n </div>\n );\n });\n origIdx += part.count || 0;\n modIdx += part.count || 0;\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}","import React, { useEffect, useState } from 'react';\nimport { Document } from '@contentful/rich-text-types';\nimport {\n isContentfulDocument,\n renderContentfulDiff\n} from './contentfulDiff';\nimport * as Diff from 'diff';\n\nfunction renderStringDiff(orig: string, mod: string) {\n const difference = Diff.diffWords(orig, mod);\n const originalParts: any[] = [];\n const modifiedParts: any[] = [];\n for (const part of difference) {\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\nfunction renderArrayDiff(original: string[], modified: string[]) {\n const maxLength = Math.max(original.length, modified.length);\n const originalParts: any[] = [];\n const modifiedParts: any[] = [];\n for (let i = 0; i < maxLength; i++) {\n const orig = original[i] ?? '';\n const mod = modified[i] ?? '';\n if (orig === mod) {\n originalParts.push(\n <div key={`orig-${i}`} className=\"diff-unchanged-line\">{orig}</div>\n );\n modifiedParts.push(\n <div key={`mod-${i}`} className=\"diff-unchanged-line\">{mod}</div>\n );\n } else {\n originalParts.push(\n <div key={`orig-${i}`} className={orig ? \"diff-removed-line\" : \"diff-blank-line\"}>{orig}</div>\n );\n modifiedParts.push(\n <div key={`mod-${i}`} className={mod ? \"diff-added-line\" : \"diff-blank-line\"}>{mod}</div>\n );\n }\n }\n return { originalParts, modifiedParts };\n}\n\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';\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',\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 const [contentfulParts, setContentfulParts] = useState<{ originalParts: any[]; modifiedParts: any[] } | null>(null);\n\n useEffect(() => {\n let cancelled = false;\n if (isContentfulComparison) {\n setContentfulParts(null); // reset while loading\n renderContentfulDiff(\n original as Document,\n modified as Document,\n compareMode,\n caseSensitive,\n renderStringDiff\n ).then(result => {\n if (!cancelled) setContentfulParts(result);\n });\n }\n return () => { cancelled = true; };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [original, modified, compareMode, caseSensitive, isContentfulComparison]);\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 if (contentfulParts) {\n originalParts = contentfulParts.originalParts;\n modifiedParts = contentfulParts.modifiedParts;\n } else {\n originalParts = [<div key=\"loading\">Loading...</div>];\n modifiedParts = [<div key=\"loading\">Loading...</div>];\n }\n }\n\n if (\n !isStringComparison &&\n !isArrayComparison &&\n !isContentfulComparison\n ) {\n return (\n <div className={`compare-error ${className}`}>\n Error: Invalid input for comparison.\n </div>\n );\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\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":["isContentfulDocument","value","nodeType","BLOCKS","DOCUMENT","Array","isArray","content","extractPlainText","document","extractFromNode","node","map","child","join","extractStructuredContent","result","textContent","displayType","headingLevel","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","renderContentfulDiff","origDoc","modDoc","compareMode","caseSensitive","renderStringDiff","DiffModule","Diff","default","diffWords","diffArrays","origStructure","modStructure","diff","comparator","a","b","originalParts","modifiedParts","origIdx","modIdx","part","added","modItem","i","_jsx","className","_jsxs","children","count","removed","origItem","item","origText","modText","orig","mod","difference","length","renderArrayDiff","original","modified","maxLength","Math","max","Compare","viewMode","isStringComparison","isArrayComparison","isContentfulComparison","contentfulParts","setContentfulParts","useState","useEffect","cancelled","then"],"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.1",
3
+ "version": "1.0.3",
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",
@@ -15,7 +15,8 @@
15
15
  "scripts": {
16
16
  "build": "rollup -c && cp src/styles/Compare.css dist/styles.css",
17
17
  "dev": "rollup -c -w",
18
- "test": "jest",
18
+ "test": "jest --no-coverage",
19
+ "test:coverage": "jest --coverage",
19
20
  "test:watch": "jest --watch",
20
21
  "clean": "rm -rf dist",
21
22
  "prepublishOnly": "npm run clean && npm run build",
@@ -55,6 +56,7 @@
55
56
  "react-dom": ">=16.8.0"
56
57
  },
57
58
  "dependencies": {
59
+ "@contentful/rich-text-types": "^17.0.1",
58
60
  "diff": "^8.0.1",
59
61
  "tslib": "^2.8.1"
60
62
  },