docx-diff-editor 1.0.47 → 1.0.50

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.d.mts CHANGED
@@ -513,6 +513,11 @@ declare function createTrackInsertMark(author?: TrackChangeAuthor, id?: string):
513
513
  declare function createTrackDeleteMark(author?: TrackChangeAuthor, id?: string): ProseMirrorMark;
514
514
  /**
515
515
  * Create a trackFormat mark.
516
+ *
517
+ * Note: SuperDoc's parseFormatList requires all marks in before/after arrays
518
+ * to have both `type` and `attrs` properties. Marks without `attrs` get filtered out,
519
+ * causing empty values in track change bubbles. We normalize marks here to ensure
520
+ * all have at least an empty `attrs` object.
516
521
  */
517
522
  declare function createTrackFormatMark(before: ProseMirrorMark[], after: ProseMirrorMark[], author?: TrackChangeAuthor): ProseMirrorMark;
518
523
 
package/dist/index.d.ts CHANGED
@@ -513,6 +513,11 @@ declare function createTrackInsertMark(author?: TrackChangeAuthor, id?: string):
513
513
  declare function createTrackDeleteMark(author?: TrackChangeAuthor, id?: string): ProseMirrorMark;
514
514
  /**
515
515
  * Create a trackFormat mark.
516
+ *
517
+ * Note: SuperDoc's parseFormatList requires all marks in before/after arrays
518
+ * to have both `type` and `attrs` properties. Marks without `attrs` get filtered out,
519
+ * causing empty values in track change bubbles. We normalize marks here to ensure
520
+ * all have at least an empty `attrs` object.
516
521
  */
517
522
  declare function createTrackFormatMark(before: ProseMirrorMark[], after: ProseMirrorMark[], author?: TrackChangeAuthor): ProseMirrorMark;
518
523
 
package/dist/index.js CHANGED
@@ -4,8 +4,8 @@ Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var react = require('react');
6
6
  var jsxRuntime = require('react/jsx-runtime');
7
- var DiffMatchPatch = require('diff-match-patch');
8
7
  var uuid = require('uuid');
8
+ var DiffMatchPatch = require('diff-match-patch');
9
9
 
10
10
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
11
11
 
@@ -452,14 +452,212 @@ var TIMEOUTS = {
452
452
  /** Cleanup delay (ms) */
453
453
  CLEANUP_DELAY: 100
454
454
  };
455
+ var CSS_NAMED_COLORS = {
456
+ // Basic colors
457
+ black: "#000000",
458
+ white: "#ffffff",
459
+ red: "#ff0000",
460
+ green: "#008000",
461
+ blue: "#0000ff",
462
+ yellow: "#ffff00",
463
+ cyan: "#00ffff",
464
+ magenta: "#ff00ff",
465
+ // Extended colors
466
+ orange: "#ffa500",
467
+ pink: "#ffc0cb",
468
+ purple: "#800080",
469
+ violet: "#ee82ee",
470
+ brown: "#a52a2a",
471
+ gray: "#808080",
472
+ grey: "#808080",
473
+ // Light variants
474
+ lightblue: "#add8e6",
475
+ lightgreen: "#90ee90",
476
+ lightgray: "#d3d3d3",
477
+ lightgrey: "#d3d3d3",
478
+ lightpink: "#ffb6c1",
479
+ lightyellow: "#ffffe0",
480
+ // Dark variants
481
+ darkblue: "#00008b",
482
+ darkgreen: "#006400",
483
+ darkgray: "#a9a9a9",
484
+ darkgrey: "#a9a9a9",
485
+ darkred: "#8b0000",
486
+ // Other common colors
487
+ navy: "#000080",
488
+ teal: "#008080",
489
+ maroon: "#800000",
490
+ olive: "#808000",
491
+ silver: "#c0c0c0",
492
+ aqua: "#00ffff",
493
+ fuchsia: "#ff00ff",
494
+ lime: "#00ff00",
495
+ coral: "#ff7f50",
496
+ salmon: "#fa8072",
497
+ gold: "#ffd700",
498
+ indigo: "#4b0082",
499
+ crimson: "#dc143c",
500
+ tomato: "#ff6347",
501
+ chocolate: "#d2691e",
502
+ tan: "#d2b48c",
503
+ beige: "#f5f5dc",
504
+ ivory: "#fffff0",
505
+ khaki: "#f0e68c",
506
+ lavender: "#e6e6fa",
507
+ plum: "#dda0dd",
508
+ orchid: "#da70d6",
509
+ turquoise: "#40e0d0",
510
+ skyblue: "#87ceeb",
511
+ steelblue: "#4682b4",
512
+ slategray: "#708090",
513
+ slategrey: "#708090"
514
+ };
515
+ function ensureValidCssColor(color) {
516
+ if (typeof color !== "string" || !color) {
517
+ return void 0;
518
+ }
519
+ const trimmed = color.trim();
520
+ const lowerColor = trimmed.toLowerCase();
521
+ if (CSS_NAMED_COLORS[lowerColor]) {
522
+ return CSS_NAMED_COLORS[lowerColor];
523
+ }
524
+ if (/^[0-9a-fA-F]{6}$/.test(trimmed)) {
525
+ return `#${trimmed}`;
526
+ }
527
+ if (/^[0-9a-fA-F]{3}$/.test(trimmed)) {
528
+ return `#${trimmed}`;
529
+ }
530
+ return trimmed;
531
+ }
532
+ function normalizeMark(mark) {
533
+ const attrs = { ...mark.attrs || {} };
534
+ if (attrs.color !== void 0) {
535
+ attrs.color = ensureValidCssColor(attrs.color);
536
+ }
537
+ return {
538
+ type: mark.type,
539
+ attrs
540
+ };
541
+ }
542
+ function normalizeMarks(marks) {
543
+ return marks.map(normalizeMark);
544
+ }
545
+ function normalizeMarksForRendering(marks) {
546
+ return normalizeMarks(marks);
547
+ }
548
+ function createTrackInsertMark(author = DEFAULT_AUTHOR, id) {
549
+ return {
550
+ type: "trackInsert",
551
+ attrs: {
552
+ id: id ?? uuid.v4(),
553
+ author: author.name,
554
+ authorEmail: author.email,
555
+ authorImage: "",
556
+ date: (/* @__PURE__ */ new Date()).toISOString()
557
+ }
558
+ };
559
+ }
560
+ function createTrackDeleteMark(author = DEFAULT_AUTHOR, id) {
561
+ return {
562
+ type: "trackDelete",
563
+ attrs: {
564
+ id: id ?? uuid.v4(),
565
+ author: author.name,
566
+ authorEmail: author.email,
567
+ authorImage: "",
568
+ date: (/* @__PURE__ */ new Date()).toISOString()
569
+ }
570
+ };
571
+ }
572
+ function createTrackFormatMark(before, after, author = DEFAULT_AUTHOR) {
573
+ const normalizedBefore = normalizeMarks(before);
574
+ const normalizedAfter = normalizeMarks(after);
575
+ return {
576
+ type: "trackFormat",
577
+ attrs: {
578
+ id: uuid.v4(),
579
+ author: author.name,
580
+ authorEmail: author.email,
581
+ authorImage: "",
582
+ date: (/* @__PURE__ */ new Date()).toISOString(),
583
+ before: normalizedBefore,
584
+ after: normalizedAfter
585
+ }
586
+ };
587
+ }
455
588
 
456
589
  // src/services/runPropertiesSync.ts
457
590
  var PT_TO_TWIPS = 20;
591
+ var CSS_NAMED_COLORS_HEX = {
592
+ // Basic colors
593
+ black: "000000",
594
+ white: "ffffff",
595
+ red: "ff0000",
596
+ green: "008000",
597
+ blue: "0000ff",
598
+ yellow: "ffff00",
599
+ cyan: "00ffff",
600
+ magenta: "ff00ff",
601
+ // Extended colors
602
+ orange: "ffa500",
603
+ pink: "ffc0cb",
604
+ purple: "800080",
605
+ violet: "ee82ee",
606
+ brown: "a52a2a",
607
+ gray: "808080",
608
+ grey: "808080",
609
+ // Light variants
610
+ lightblue: "add8e6",
611
+ lightgreen: "90ee90",
612
+ lightgray: "d3d3d3",
613
+ lightgrey: "d3d3d3",
614
+ lightpink: "ffb6c1",
615
+ lightyellow: "ffffe0",
616
+ // Dark variants
617
+ darkblue: "00008b",
618
+ darkgreen: "006400",
619
+ darkgray: "a9a9a9",
620
+ darkgrey: "a9a9a9",
621
+ darkred: "8b0000",
622
+ // Other common colors
623
+ navy: "000080",
624
+ teal: "008080",
625
+ maroon: "800000",
626
+ olive: "808000",
627
+ silver: "c0c0c0",
628
+ aqua: "00ffff",
629
+ fuchsia: "ff00ff",
630
+ lime: "00ff00",
631
+ coral: "ff7f50",
632
+ salmon: "fa8072",
633
+ gold: "ffd700",
634
+ indigo: "4b0082",
635
+ crimson: "dc143c",
636
+ tomato: "ff6347",
637
+ chocolate: "d2691e",
638
+ tan: "d2b48c",
639
+ beige: "f5f5dc",
640
+ ivory: "fffff0",
641
+ khaki: "f0e68c",
642
+ lavender: "e6e6fa",
643
+ plum: "dda0dd",
644
+ orchid: "da70d6",
645
+ turquoise: "40e0d0",
646
+ skyblue: "87ceeb",
647
+ steelblue: "4682b4",
648
+ slategray: "708090",
649
+ slategrey: "708090"
650
+ };
458
651
  function ptToTwips(ptValue) {
459
652
  return Math.round(ptValue * PT_TO_TWIPS);
460
653
  }
461
- function stripHashFromColor(color) {
462
- return color.replace(/^#/, "");
654
+ function colorToHexWithoutHash(color) {
655
+ const trimmed = color.trim();
656
+ const lowerColor = trimmed.toLowerCase();
657
+ if (CSS_NAMED_COLORS_HEX[lowerColor]) {
658
+ return CSS_NAMED_COLORS_HEX[lowerColor];
659
+ }
660
+ return trimmed.replace(/^#/, "");
463
661
  }
464
662
  function parseFontSizeToPoints(fontSize) {
465
663
  if (typeof fontSize === "number") {
@@ -503,7 +701,7 @@ function marksToRunProperties(marks) {
503
701
  underlineAttrs["w:val"] = "single";
504
702
  }
505
703
  if (attrs.underlineColor) {
506
- underlineAttrs["w:color"] = stripHashFromColor(String(attrs.underlineColor));
704
+ underlineAttrs["w:color"] = colorToHexWithoutHash(String(attrs.underlineColor));
507
705
  }
508
706
  if (Object.keys(underlineAttrs).length > 0) {
509
707
  runProperties.underline = underlineAttrs;
@@ -526,7 +724,7 @@ function marksToRunProperties(marks) {
526
724
  case "textStyle": {
527
725
  if (attrs.color != null) {
528
726
  runProperties.color = {
529
- val: stripHashFromColor(String(attrs.color))
727
+ val: colorToHexWithoutHash(String(attrs.color))
530
728
  };
531
729
  }
532
730
  if (attrs.fontSize != null) {
@@ -584,8 +782,17 @@ function collectMarksFromRunChildren(runNode) {
584
782
  return Array.from(marksByType.values());
585
783
  }
586
784
  function normalizeNode(node) {
785
+ if (node.type === "text" && node.marks && Array.isArray(node.marks)) {
786
+ const normalizedMarks = normalizeMarksForRendering(node.marks);
787
+ return {
788
+ ...node,
789
+ marks: normalizedMarks
790
+ };
791
+ }
587
792
  if (node.type === "run") {
588
- const marks = collectMarksFromRunChildren(node);
793
+ const normalizedContent = node.content?.map(normalizeNode);
794
+ const normalizedNode = { ...node, content: normalizedContent };
795
+ const marks = collectMarksFromRunChildren(normalizedNode);
589
796
  if (marks.length > 0) {
590
797
  const runPropsFromMarks = marksToRunProperties(marks);
591
798
  const existingRunProps = node.attrs?.runProperties || {};
@@ -594,15 +801,14 @@ function normalizeNode(node) {
594
801
  ...runPropsFromMarks
595
802
  };
596
803
  return {
597
- ...node,
804
+ ...normalizedNode,
598
805
  attrs: {
599
- ...node.attrs,
806
+ ...normalizedNode.attrs,
600
807
  runProperties: mergedRunProps
601
- },
602
- // Also recursively process children (though runs usually just have text)
603
- content: node.content?.map(normalizeNode)
808
+ }
604
809
  };
605
810
  }
811
+ return normalizedNode;
606
812
  }
607
813
  if (node.content && Array.isArray(node.content)) {
608
814
  return {
@@ -1303,44 +1509,6 @@ function groupReplacements(changes) {
1303
1509
  }
1304
1510
  return result;
1305
1511
  }
1306
- function createTrackInsertMark(author = DEFAULT_AUTHOR, id) {
1307
- return {
1308
- type: "trackInsert",
1309
- attrs: {
1310
- id: id ?? uuid.v4(),
1311
- author: author.name,
1312
- authorEmail: author.email,
1313
- authorImage: "",
1314
- date: (/* @__PURE__ */ new Date()).toISOString()
1315
- }
1316
- };
1317
- }
1318
- function createTrackDeleteMark(author = DEFAULT_AUTHOR, id) {
1319
- return {
1320
- type: "trackDelete",
1321
- attrs: {
1322
- id: id ?? uuid.v4(),
1323
- author: author.name,
1324
- authorEmail: author.email,
1325
- authorImage: "",
1326
- date: (/* @__PURE__ */ new Date()).toISOString()
1327
- }
1328
- };
1329
- }
1330
- function createTrackFormatMark(before, after, author = DEFAULT_AUTHOR) {
1331
- return {
1332
- type: "trackFormat",
1333
- attrs: {
1334
- id: uuid.v4(),
1335
- author: author.name,
1336
- authorEmail: author.email,
1337
- authorImage: "",
1338
- date: (/* @__PURE__ */ new Date()).toISOString(),
1339
- before,
1340
- after
1341
- }
1342
- };
1343
- }
1344
1512
 
1345
1513
  // src/services/nodeAligner.ts
1346
1514
  init_nodeFingerprint();
@@ -1569,7 +1737,8 @@ function createInsertedTextNodes(text, posB, spansB, author, replacementId) {
1569
1737
  }
1570
1738
  if (span.relEnd > span.relStart) {
1571
1739
  const spanText = text.substring(span.relStart, span.relEnd);
1572
- const marks = [...span.marks, trackMark];
1740
+ const normalizedSpanMarks = normalizeMarksForRendering(span.marks);
1741
+ const marks = [...normalizedSpanMarks, trackMark];
1573
1742
  result.push({
1574
1743
  type: "text",
1575
1744
  text: spanText,
@@ -1677,7 +1846,8 @@ function mergeDocuments(docA, docB, diffResult, author = DEFAULT_AUTHOR) {
1677
1846
  currentFormatChange.after,
1678
1847
  author
1679
1848
  );
1680
- marks = [...currentFormatChange.after, trackFormatMark];
1849
+ const normalizedAfterMarks = normalizeMarksForRendering(currentFormatChange.after);
1850
+ marks = [...normalizedAfterMarks, trackFormatMark];
1681
1851
  }
1682
1852
  }
1683
1853
  result.push({
@@ -2266,9 +2436,10 @@ function cloneNode2(node) {
2266
2436
  }
2267
2437
  function markAllTextAsInserted(node, sharedId, author) {
2268
2438
  if (node.type === "text") {
2439
+ const existingMarks = normalizeMarksForRendering(node.marks || []);
2269
2440
  return {
2270
2441
  ...node,
2271
- marks: [...node.marks || [], createTrackInsertMark(author, sharedId)]
2442
+ marks: [...existingMarks, createTrackInsertMark(author, sharedId)]
2272
2443
  };
2273
2444
  }
2274
2445
  if (node.content && Array.isArray(node.content)) {
@@ -2283,9 +2454,10 @@ function markAllTextAsInserted(node, sharedId, author) {
2283
2454
  }
2284
2455
  function markAllTextAsDeleted(node, sharedId, author) {
2285
2456
  if (node.type === "text") {
2457
+ const existingMarks = normalizeMarksForRendering(node.marks || []);
2286
2458
  return {
2287
2459
  ...node,
2288
- marks: [...node.marks || [], createTrackDeleteMark(author, sharedId)]
2460
+ marks: [...existingMarks, createTrackDeleteMark(author, sharedId)]
2289
2461
  };
2290
2462
  }
2291
2463
  if (node.content && Array.isArray(node.content)) {
@@ -3546,9 +3718,10 @@ var DocxDiffEditor_default = DocxDiffEditor;
3546
3718
  init_nodeFingerprint();
3547
3719
  function markAllTextAsInserted2(node, sharedId, author) {
3548
3720
  if (node.type === "text") {
3721
+ const existingMarks = normalizeMarksForRendering(node.marks || []);
3549
3722
  return {
3550
3723
  ...node,
3551
- marks: [...node.marks || [], createTrackInsertMark(author, sharedId)]
3724
+ marks: [...existingMarks, createTrackInsertMark(author, sharedId)]
3552
3725
  };
3553
3726
  }
3554
3727
  if (node.content && Array.isArray(node.content)) {
@@ -3563,9 +3736,10 @@ function markAllTextAsInserted2(node, sharedId, author) {
3563
3736
  }
3564
3737
  function markAllTextAsDeleted2(node, sharedId, author) {
3565
3738
  if (node.type === "text") {
3739
+ const existingMarks = normalizeMarksForRendering(node.marks || []);
3566
3740
  return {
3567
3741
  ...node,
3568
- marks: [...node.marks || [], createTrackDeleteMark(author, sharedId)]
3742
+ marks: [...existingMarks, createTrackDeleteMark(author, sharedId)]
3569
3743
  };
3570
3744
  }
3571
3745
  if (node.content && Array.isArray(node.content)) {