docx-diff-editor 1.0.26 → 1.0.28

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/dist/index.mjs CHANGED
@@ -185,6 +185,18 @@ function getMarksAtPosition(spans, pos) {
185
185
  }
186
186
  return [];
187
187
  }
188
+ function hasDefinedAttributes(marks) {
189
+ if (!marks || marks.length === 0) return false;
190
+ for (const mark of marks) {
191
+ if (!mark.attrs) continue;
192
+ for (const value of Object.values(mark.attrs)) {
193
+ if (value !== void 0 && value !== null) {
194
+ return true;
195
+ }
196
+ }
197
+ }
198
+ return marks.some((m) => !m.attrs);
199
+ }
188
200
  function detectFormatChanges(spansA, spansB, segments) {
189
201
  const formatChanges = [];
190
202
  let posA = 0;
@@ -208,13 +220,17 @@ function detectFormatChanges(spansA, spansB, segments) {
208
220
  break;
209
221
  }
210
222
  }
211
- formatChanges.push({
212
- from: posA + startI,
213
- to: posA + i,
214
- text: segment.text.substring(startI, i),
215
- before: startMarksA,
216
- after: startMarksB
217
- });
223
+ if (hasDefinedAttributes(startMarksB) || hasDefinedAttributes(startMarksA)) {
224
+ if (hasDefinedAttributes(startMarksB)) {
225
+ formatChanges.push({
226
+ from: posA + startI,
227
+ to: posA + i,
228
+ text: segment.text.substring(startI, i),
229
+ before: startMarksA,
230
+ after: startMarksB
231
+ });
232
+ }
233
+ }
218
234
  } else {
219
235
  i++;
220
236
  }
@@ -272,11 +288,11 @@ function diffDocuments(docA, docB) {
272
288
  summary
273
289
  };
274
290
  }
275
- function createTrackInsertMark(author = DEFAULT_AUTHOR) {
291
+ function createTrackInsertMark(author = DEFAULT_AUTHOR, id) {
276
292
  return {
277
293
  type: "trackInsert",
278
294
  attrs: {
279
- id: v4(),
295
+ id: id ?? v4(),
280
296
  author: author.name,
281
297
  authorEmail: author.email,
282
298
  authorImage: "",
@@ -284,11 +300,11 @@ function createTrackInsertMark(author = DEFAULT_AUTHOR) {
284
300
  }
285
301
  };
286
302
  }
287
- function createTrackDeleteMark(author = DEFAULT_AUTHOR) {
303
+ function createTrackDeleteMark(author = DEFAULT_AUTHOR, id) {
288
304
  return {
289
305
  type: "trackDelete",
290
306
  attrs: {
291
- id: v4(),
307
+ id: id ?? v4(),
292
308
  author: author.name,
293
309
  authorEmail: author.email,
294
310
  authorImage: "",
@@ -329,17 +345,30 @@ function mergeDocuments(docA, docB, diffResult, author = DEFAULT_AUTHOR) {
329
345
  return null;
330
346
  }
331
347
  let docAOffset = 0;
332
- for (const segment of diffResult.segments) {
348
+ const segments = diffResult.segments;
349
+ for (let segIdx = 0; segIdx < segments.length; segIdx++) {
350
+ const segment = segments[segIdx];
333
351
  if (segment.type === "equal") {
334
352
  for (let i = 0; i < segment.text.length; i++) {
335
353
  charStates[docAOffset + i] = { type: "equal" };
336
354
  }
337
355
  docAOffset += segment.text.length;
338
356
  } else if (segment.type === "delete") {
357
+ const nextSegment = segments[segIdx + 1];
358
+ const isReplacement = nextSegment && nextSegment.type === "insert";
359
+ const replacementId = isReplacement ? v4() : void 0;
339
360
  for (let i = 0; i < segment.text.length; i++) {
340
- charStates[docAOffset + i] = { type: "delete" };
361
+ charStates[docAOffset + i] = { type: "delete", replacementId };
341
362
  }
342
363
  docAOffset += segment.text.length;
364
+ if (isReplacement && nextSegment) {
365
+ insertions.push({
366
+ afterOffset: docAOffset,
367
+ text: nextSegment.text,
368
+ replacementId
369
+ });
370
+ segIdx++;
371
+ }
343
372
  } else if (segment.type === "insert") {
344
373
  insertions.push({
345
374
  afterOffset: docAOffset,
@@ -360,7 +389,7 @@ function mergeDocuments(docA, docB, diffResult, author = DEFAULT_AUTHOR) {
360
389
  result.push({
361
390
  type: "text",
362
391
  text: ins.text,
363
- marks: [...node.marks || [], createTrackInsertMark(author)]
392
+ marks: [...node.marks || [], createTrackInsertMark(author, ins.replacementId)]
364
393
  });
365
394
  }
366
395
  const currentFormatChange = getFormatChangeAt(nodeOffset + i);
@@ -376,7 +405,7 @@ function mergeDocuments(docA, docB, diffResult, author = DEFAULT_AUTHOR) {
376
405
  const chunk = text.substring(i, j);
377
406
  let marks = [...node.marks || []];
378
407
  if (charState.type === "delete") {
379
- marks.push(createTrackDeleteMark(author));
408
+ marks.push(createTrackDeleteMark(author, charState.replacementId));
380
409
  } else if (charState.type === "equal") {
381
410
  if (currentFormatChange) {
382
411
  const trackFormatMark = createTrackFormatMark(
@@ -400,7 +429,7 @@ function mergeDocuments(docA, docB, diffResult, author = DEFAULT_AUTHOR) {
400
429
  result.push({
401
430
  type: "text",
402
431
  text: ins.text,
403
- marks: [...node.marks || [], createTrackInsertMark(author)]
432
+ marks: [...node.marks || [], createTrackInsertMark(author, ins.replacementId)]
404
433
  });
405
434
  }
406
435
  insertions = insertions.filter(
@@ -445,7 +474,7 @@ function mergeDocuments(docA, docB, diffResult, author = DEFAULT_AUTHOR) {
445
474
  {
446
475
  type: "text",
447
476
  text: ins.text,
448
- marks: [createTrackInsertMark(author)]
477
+ marks: [createTrackInsertMark(author, ins.replacementId)]
449
478
  }
450
479
  ]
451
480
  }