@harbour-enterprises/superdoc 1.4.0 → 1.4.1-next.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.
@@ -1,6 +1,6 @@
1
1
  import { B as Buffer$2 } from "./jszip-B1fkPkPJ.es.js";
2
2
  import { t as twipsToInches, i as inchesToTwips, p as ptToTwips, l as linesToTwips, a as twipsToLines, b as pixelsToTwips, h as halfPointToPoints, c as twipsToPixels$2, d as convertSizeToCSS, e as inchesToPixels } from "./helpers-C8e9wR5l.es.js";
3
- import { g as generateDocxRandomId, T as TextSelection$1, o as objectIncludes, w as wrapTextsInRuns, D as DOMParser$1, c as createDocFromMarkdown, a as createDocFromHTML, b as chainableEditorState, d as convertMarkdownToHTML, f as findParentNode, e as findParentNodeClosestToPos, h as generateRandom32BitHex, i as generateRandomSigned32BitIntStrId, P as PluginKey, j as Plugin, M as Mapping, N as NodeSelection, k as Selection, l as Slice, m as DOMSerializer, F as Fragment, n as Mark$1, p as dropPoint, A as AllSelection, q as Schema$1, s as canSplit, t as resolveRunProperties, u as encodeMarksFromRPr, v as liftTarget, x as canJoin, y as joinPoint, z as replaceStep$1, R as ReplaceAroundStep$1, B as htmlHandler, C as ReplaceStep, E as getResolvedParagraphProperties, G as changeListLevel, H as isList$1, I as updateNumberingProperties, L as ListHelpers, J as inputRulesPlugin, K as TrackDeleteMarkName$1, O as TrackInsertMarkName$1, Q as TrackFormatMarkName$1, U as AddMarkStep, V as RemoveMarkStep, W as CommandService, S as SuperConverter, X as EditorState, Y as unflattenListsInHtml, Z as SelectionRange, _ as Transform, $ as createOoxmlResolver, a0 as translator, a1 as translator$1, a2 as resolveDocxFontFamily, a3 as combineIndentProperties, a4 as _getReferencedTableStyles, a5 as decodeRPrFromMarks, a6 as calculateResolvedParagraphProperties, a7 as encodeCSSFromPPr, a8 as encodeCSSFromRPr, a9 as generateOrderedListIndex, aa as docxNumberingHelpers, ab as InputRule, ac as insertNewRelationship, ad as kebabCase$1, ae as getUnderlineCssString } from "./SuperConverter-DAO7c_d4.es.js";
3
+ import { g as generateDocxRandomId, T as TextSelection$1, o as objectIncludes, w as wrapTextsInRuns, D as DOMParser$1, c as createDocFromMarkdown, a as createDocFromHTML, b as chainableEditorState, d as convertMarkdownToHTML, f as findParentNode, e as findParentNodeClosestToPos, h as generateRandom32BitHex, i as generateRandomSigned32BitIntStrId, P as PluginKey, j as Plugin, M as Mapping, N as NodeSelection, k as Selection, l as Slice, m as DOMSerializer, F as Fragment, n as Mark$1, p as dropPoint, A as AllSelection, q as Schema$1, s as canSplit, t as resolveRunProperties, u as encodeMarksFromRPr, v as liftTarget, x as canJoin, y as joinPoint, z as replaceStep$1, R as ReplaceAroundStep$1, B as htmlHandler, C as ReplaceStep, E as getResolvedParagraphProperties, G as changeListLevel, H as isList$1, I as updateNumberingProperties, L as ListHelpers, J as inputRulesPlugin, K as TrackDeleteMarkName$1, O as TrackInsertMarkName$1, Q as TrackFormatMarkName$1, U as AddMarkStep, V as RemoveMarkStep, W as CommandService, S as SuperConverter, X as EditorState, Y as unflattenListsInHtml, Z as SelectionRange, _ as Transform, $ as createOoxmlResolver, a0 as translator, a1 as translator$1, a2 as resolveDocxFontFamily, a3 as combineIndentProperties, a4 as _getReferencedTableStyles, a5 as decodeRPrFromMarks, a6 as calculateResolvedParagraphProperties, a7 as encodeCSSFromPPr, a8 as encodeCSSFromRPr, a9 as generateOrderedListIndex, aa as docxNumberingHelpers, ab as InputRule, ac as insertNewRelationship, ad as kebabCase$1, ae as getUnderlineCssString } from "./SuperConverter-BJi_tRyc.es.js";
4
4
  import { p as process$1, r as ref, C as global$1, c as computed, E as createElementBlock, F as Fragment$1, S as renderList, O as withModifiers, G as openBlock, P as normalizeClass, M as createCommentVNode, H as toDisplayString, K as createBaseVNode, U as createApp, f as onMounted, X as onUnmounted, R as withDirectives, v as unref, Y as vModelText, y as nextTick, L as normalizeStyle, u as watch, Z as withKeys, _ as createTextVNode, I as createVNode, h, $ as readonly, s as getCurrentInstance, o as onBeforeUnmount, j as reactive, b as onBeforeMount, i as inject, a0 as onActivated, a1 as onDeactivated, a2 as Comment, d as defineComponent, a as provide, g as Teleport, t as toRef, a3 as renderSlot, a4 as isVNode, D as shallowRef, w as watchEffect, T as Transition, a5 as mergeProps, a6 as vShow, a7 as cloneVNode, a8 as Text$2, m as markRaw, N as createBlock, J as withCtx, a9 as useCssVars, V as resolveDynamicComponent, aa as normalizeProps, ab as guardReactiveProps } from "./vue-BnBKJwCW.es.js";
5
5
  import "./jszip.min-DCl8qkFO.es.js";
6
6
  import { E as EventEmitter$1 } from "./eventemitter3-CwrdEv8r.es.js";
@@ -12621,11 +12621,15 @@ const resolveCommentMeta = ({ converter, importedId }) => {
12621
12621
  const matchingImportedComment = comments.find((c2) => c2.importedId == importedId);
12622
12622
  const resolvedCommentId = matchingImportedComment?.commentId ?? (importedId ? String(importedId) : v4());
12623
12623
  const internal = matchingImportedComment?.internal ?? matchingImportedComment?.isInternal ?? false;
12624
+ const parentCommentId = matchingImportedComment?.parentCommentId;
12625
+ const trackedChangeIds = converter?.trackedChangeIdMap ? new Set(Array.from(converter.trackedChangeIdMap.values()).map((id) => String(id))) : null;
12626
+ const isTrackedChangeParent = parentCommentId && trackedChangeIds ? trackedChangeIds.has(String(parentCommentId)) : false;
12624
12627
  return {
12625
12628
  resolvedCommentId,
12626
12629
  importedId,
12627
12630
  internal,
12628
- matchingImportedComment
12631
+ matchingImportedComment,
12632
+ trackedChange: matchingImportedComment?.trackedChange === true || isTrackedChangeParent
12629
12633
  };
12630
12634
  };
12631
12635
  const ensureFallbackComment = ({ converter, matchingImportedComment, commentId, importedId }) => {
@@ -12643,6 +12647,7 @@ const ensureFallbackComment = ({ converter, matchingImportedComment, commentId,
12643
12647
  isDone: false
12644
12648
  });
12645
12649
  };
12650
+ const TRACK_CHANGE_MARKS$1 = [TrackInsertMarkName$1, TrackDeleteMarkName$1, TrackFormatMarkName$1];
12646
12651
  const removeCommentsById = ({ commentId, state, tr, dispatch }) => {
12647
12652
  const positions = getCommentPositionsById(commentId, state.doc);
12648
12653
  positions.forEach(({ from: from3, to }) => {
@@ -12786,6 +12791,35 @@ const prepareCommentsForExport = (doc2, tr, schema, comments = []) => {
12786
12791
  });
12787
12792
  });
12788
12793
  });
12794
+ const trackedChangeMark = node.marks?.find((mark) => TRACK_CHANGE_MARKS$1.includes(mark.type.name));
12795
+ if (trackedChangeMark) {
12796
+ const trackedChangeId = trackedChangeMark.attrs?.id;
12797
+ if (trackedChangeId) {
12798
+ const childComments = comments.filter((c2) => c2.parentCommentId === trackedChangeId && !c2.trackedChange).sort((a, b) => a.createdTime - b.createdTime);
12799
+ childComments.forEach((c2) => {
12800
+ if (seen.has(c2.commentId)) return;
12801
+ seen.add(c2.commentId);
12802
+ const childMark = getPreparedComment({
12803
+ commentId: c2.commentId,
12804
+ internal: c2.isInternal
12805
+ });
12806
+ const childStartNode = schema.nodes.commentRangeStart.create(childMark);
12807
+ startNodes.push({
12808
+ pos,
12809
+ node: childStartNode,
12810
+ commentId: c2.commentId,
12811
+ parentCommentId: c2.parentCommentId
12812
+ });
12813
+ const childEndNode = schema.nodes.commentRangeEnd.create(childMark);
12814
+ endNodes.push({
12815
+ pos: pos + node.nodeSize,
12816
+ node: childEndNode,
12817
+ commentId: c2.commentId,
12818
+ parentCommentId: c2.parentCommentId
12819
+ });
12820
+ });
12821
+ }
12822
+ }
12789
12823
  });
12790
12824
  startNodes.sort((a, b) => {
12791
12825
  if (a.pos !== b.pos) return a.pos - b.pos;
@@ -12840,17 +12874,18 @@ const prepareCommentsForImport = (doc2, tr, schema, converter) => {
12840
12874
  const { type } = node;
12841
12875
  const commentNodes = ["commentRangeStart", "commentRangeEnd", "commentReference"];
12842
12876
  if (!commentNodes.includes(type.name)) return;
12843
- const { resolvedCommentId, importedId, internal, matchingImportedComment } = resolveCommentMeta({
12877
+ const { resolvedCommentId, importedId, internal, matchingImportedComment, trackedChange } = resolveCommentMeta({
12844
12878
  converter,
12845
12879
  importedId: node.attrs["w:id"]
12846
12880
  });
12847
12881
  const isDone = !!matchingImportedComment?.isDone;
12848
12882
  if (type.name === "commentRangeStart") {
12849
- if (!isDone) {
12883
+ if (!matchingImportedComment || !matchingImportedComment.isDone) {
12850
12884
  toMark.push({
12851
12885
  commentId: resolvedCommentId,
12852
12886
  importedId,
12853
12887
  internal,
12888
+ trackedChange,
12854
12889
  start: pos
12855
12890
  });
12856
12891
  }
@@ -12889,7 +12924,8 @@ const prepareCommentsForImport = (doc2, tr, schema, converter) => {
12889
12924
  const markAttrs = {
12890
12925
  commentId: itemToMark.commentId,
12891
12926
  importedId,
12892
- internal: itemToMark.internal
12927
+ internal: itemToMark.internal,
12928
+ trackedChange: itemToMark.trackedChange
12893
12929
  };
12894
12930
  tr.addMark(start2, pos + 1, schema.marks[CommentMarkName$1].create(markAttrs));
12895
12931
  toDelete.push({ start: pos, end: pos + 1 });
@@ -13451,26 +13487,30 @@ const handleTrackedChangeTransaction = (trackedChangeMeta, trackedChanges, newEd
13451
13487
  if (emitParams) editor.emit("commentsUpdate", emitParams);
13452
13488
  return newTrackedChanges;
13453
13489
  };
13454
- const getTrackedChangeText = ({ nodes, mark, trackedChangeType, isDeletionInsertion }) => {
13490
+ const getTrackedChangeText = ({ nodes, mark, trackedChangeType, isDeletionInsertion, marks }) => {
13455
13491
  let trackedChangeText = "";
13456
13492
  let deletionText = "";
13457
- if (trackedChangeType === TrackInsertMarkName$1) {
13493
+ if (trackedChangeType === TrackDeleteMarkName$1 || isDeletionInsertion) {
13494
+ deletionText = nodes.reduce((acc, node) => {
13495
+ const hasDeleteMark = node.marks.find((nodeMark) => nodeMark.type.name === TrackDeleteMarkName$1);
13496
+ if (!hasDeleteMark) return acc;
13497
+ const nodeText = node?.text || node?.textContent || "";
13498
+ acc += nodeText;
13499
+ return acc;
13500
+ }, "");
13501
+ }
13502
+ if (trackedChangeType === TrackInsertMarkName$1 || isDeletionInsertion) {
13458
13503
  trackedChangeText = nodes.reduce((acc, node) => {
13459
- if (!node.marks.find((nodeMark) => nodeMark.type.name === mark.type.name)) return acc;
13460
- acc += node?.text || node?.textContent || "";
13504
+ const hasInsertMark = node.marks.find((nodeMark) => nodeMark.type.name === TrackInsertMarkName$1);
13505
+ if (!hasInsertMark) return acc;
13506
+ const nodeText = node?.text || node?.textContent || "";
13507
+ acc += nodeText;
13461
13508
  return acc;
13462
13509
  }, "");
13463
13510
  }
13464
13511
  if (trackedChangeType === TrackFormatMarkName$1) {
13465
13512
  trackedChangeText = translateFormatChangesToEnglish(mark.attrs);
13466
13513
  }
13467
- if (trackedChangeType === TrackDeleteMarkName$1 || isDeletionInsertion) {
13468
- deletionText = nodes.reduce((acc, node) => {
13469
- if (!node.marks.find((nodeMark) => nodeMark.type.name === TrackDeleteMarkName$1)) return acc;
13470
- acc += node?.text || node?.textContent || "";
13471
- return acc;
13472
- }, "");
13473
- }
13474
13514
  return {
13475
13515
  deletionText,
13476
13516
  trackedChangeText
@@ -13483,22 +13523,41 @@ const createOrUpdateTrackedChangeComment = ({ event, marks, deletionNodes, nodes
13483
13523
  const { author, authorEmail, authorImage, date, importedAuthor } = attrs;
13484
13524
  const id = attrs.id;
13485
13525
  const node = nodes[0];
13486
- const isDeletionInsertion = !!(marks.insertedMark && marks.deletionMark);
13526
+ const trackedChangesWithId = getTrackChanges(newEditorState, id);
13527
+ let isDeletionInsertion = !!(marks.insertedMark && marks.deletionMark);
13528
+ if (!isDeletionInsertion) {
13529
+ const hasInsertMark = trackedChangesWithId.some(({ mark }) => mark.type.name === TrackInsertMarkName$1);
13530
+ const hasDeleteMark = trackedChangesWithId.some(({ mark }) => mark.type.name === TrackDeleteMarkName$1);
13531
+ isDeletionInsertion = hasInsertMark && hasDeleteMark;
13532
+ }
13487
13533
  let nodesWithMark = [];
13488
- newEditorState.doc.descendants((node2) => {
13489
- const { marks: marks2 = [] } = node2;
13490
- const changeMarks = marks2.filter((mark) => TRACK_CHANGE_MARKS.includes(mark.type.name));
13491
- if (!changeMarks.length) return;
13492
- const hasMatchingId = changeMarks.find((mark) => mark.attrs.id === id);
13493
- if (hasMatchingId) nodesWithMark.push(node2);
13534
+ trackedChangesWithId.forEach(({ from: from3, to, mark }) => {
13535
+ newEditorState.doc.nodesBetween(from3, to, (node2, pos) => {
13536
+ if (node2.isText) {
13537
+ const hasMatchingMark = node2.marks?.some((m) => TRACK_CHANGE_MARKS.includes(m.type.name) && m.attrs.id === id);
13538
+ if (hasMatchingMark) {
13539
+ const alreadyAdded = nodesWithMark.some((n) => n === node2);
13540
+ if (!alreadyAdded) {
13541
+ nodesWithMark.push(node2);
13542
+ }
13543
+ }
13544
+ }
13545
+ });
13494
13546
  });
13495
- const nodesToProcess = nodesWithMark.length ? nodesWithMark : node ? [node] : [];
13496
- if (!nodesToProcess.length) {
13547
+ let nodesToUse;
13548
+ if (isDeletionInsertion) {
13549
+ const allNodes = [...nodesWithMark, ...nodes, ...deletionNodes || []];
13550
+ nodesToUse = Array.from(new Set(allNodes));
13551
+ } else {
13552
+ nodesToUse = nodesWithMark.length ? nodesWithMark : node ? [node] : [];
13553
+ }
13554
+ if (!nodesToUse.length) {
13497
13555
  return;
13498
13556
  }
13499
13557
  const { deletionText, trackedChangeText } = getTrackedChangeText({
13500
- nodes: nodesToProcess,
13558
+ nodes: nodesToUse,
13501
13559
  mark: trackedMark,
13560
+ marks,
13502
13561
  trackedChangeType,
13503
13562
  isDeletionInsertion
13504
13563
  });
@@ -15440,7 +15499,7 @@ const canUseDOM = () => {
15440
15499
  return false;
15441
15500
  }
15442
15501
  };
15443
- const summaryVersion = "1.4.0";
15502
+ const summaryVersion = "1.4.1-next.2";
15444
15503
  const nodeKeys = ["group", "content", "marks", "inline", "atom", "defining", "code", "tableRole", "summary"];
15445
15504
  const markKeys = ["group", "inclusive", "excludes", "spanning", "code"];
15446
15505
  function mapAttributes(attrs) {
@@ -18072,7 +18131,7 @@ class Editor extends EventEmitter {
18072
18131
  * Process collaboration migrations
18073
18132
  */
18074
18133
  processCollaborationMigrations() {
18075
- console.debug("[checkVersionMigrations] Current editor version", "1.4.0");
18134
+ console.debug("[checkVersionMigrations] Current editor version", "1.4.1-next.2");
18076
18135
  if (!this.options.ydoc) return;
18077
18136
  const metaMap = this.options.ydoc.getMap("meta");
18078
18137
  let docVersion = metaMap.get("version");
@@ -23255,7 +23314,6 @@ const SDT_CONTAINER_STYLES = `
23255
23314
  const FIELD_ANNOTATION_STYLES = `
23256
23315
  /* Field annotation draggable styles */
23257
23316
  .superdoc-layout .annotation[data-draggable="true"] {
23258
- cursor: grab;
23259
23317
  user-select: none;
23260
23318
  -webkit-user-select: none;
23261
23319
  }
@@ -27180,12 +27238,15 @@ class DomPainter {
27180
27238
  }
27181
27239
  }
27182
27240
  applyRunStyles(elem, run, isActiveLink);
27183
- const commentColor = getCommentHighlight(run);
27184
- if (commentColor && !run.highlight) {
27241
+ const textRun = run;
27242
+ const commentAnnotations = textRun.comments;
27243
+ const hasAnyComment = !!commentAnnotations?.length;
27244
+ const hasHighlightableComment = !!commentAnnotations?.some((c2) => !c2.trackedChange);
27245
+ const commentColor = getCommentHighlight(textRun);
27246
+ if (commentColor && !textRun.highlight && hasHighlightableComment) {
27185
27247
  elem.style.backgroundColor = commentColor;
27186
27248
  }
27187
- const commentAnnotations = run.comments;
27188
- if (commentAnnotations?.length) {
27249
+ if (hasAnyComment) {
27189
27250
  elem.dataset.commentIds = commentAnnotations.map((c2) => c2.commentId).join(",");
27190
27251
  if (commentAnnotations.some((c2) => c2.internal)) {
27191
27252
  elem.dataset.commentInternal = "true";
@@ -41165,6 +41226,7 @@ const pushCommentAnnotation = (run, attrs) => {
41165
41226
  const commentId = typeof attrs?.commentId === "string" ? attrs.commentId : void 0;
41166
41227
  const importedId = typeof attrs?.importedId === "string" ? attrs.importedId : void 0;
41167
41228
  const internal = attrs?.internal === true;
41229
+ const trackedChange = attrs?.trackedChange === true;
41168
41230
  if (!commentId && !importedId) return;
41169
41231
  const annotations = run.comments ? [...run.comments] : [];
41170
41232
  const key2 = `${commentId ?? ""}::${importedId ?? ""}`;
@@ -41173,7 +41235,8 @@ const pushCommentAnnotation = (run, attrs) => {
41173
41235
  annotations.push({
41174
41236
  commentId: commentId ?? importedId,
41175
41237
  importedId,
41176
- internal
41238
+ internal,
41239
+ trackedChange
41177
41240
  });
41178
41241
  }
41179
41242
  run.comments = annotations;
@@ -52452,6 +52515,40 @@ class PresentationEditor extends EventEmitter {
52452
52515
  this.#editor.view?.focus();
52453
52516
  }
52454
52517
  }
52518
+ #resolveFieldAnnotationSelectionFromElement(annotationEl) {
52519
+ const pmStartRaw = annotationEl.dataset?.pmStart;
52520
+ if (pmStartRaw == null) {
52521
+ return null;
52522
+ }
52523
+ const pmStart = Number(pmStartRaw);
52524
+ if (!Number.isFinite(pmStart)) {
52525
+ return null;
52526
+ }
52527
+ const doc2 = this.#editor.state?.doc;
52528
+ if (!doc2) {
52529
+ return null;
52530
+ }
52531
+ const layoutEpochRaw = annotationEl.dataset?.layoutEpoch;
52532
+ const layoutEpoch = layoutEpochRaw != null ? Number(layoutEpochRaw) : NaN;
52533
+ const effectiveEpoch = Number.isFinite(layoutEpoch) ? layoutEpoch : this.#epochMapper.getCurrentEpoch();
52534
+ const mapped = this.#epochMapper.mapPosFromLayoutToCurrentDetailed(pmStart, effectiveEpoch, 1);
52535
+ if (!mapped.ok) {
52536
+ const fallbackPos = Math.max(0, Math.min(pmStart, doc2.content.size));
52537
+ const fallbackNode = doc2.nodeAt(fallbackPos);
52538
+ if (fallbackNode?.type?.name === "fieldAnnotation") {
52539
+ return { node: fallbackNode, pos: fallbackPos };
52540
+ }
52541
+ this.#pendingDocChange = true;
52542
+ this.#scheduleRerender();
52543
+ return null;
52544
+ }
52545
+ const clampedPos = Math.max(0, Math.min(mapped.pos, doc2.content.size));
52546
+ const node = doc2.nodeAt(clampedPos);
52547
+ if (!node || node.type.name !== "fieldAnnotation") {
52548
+ return null;
52549
+ }
52550
+ return { node, pos: clampedPos };
52551
+ }
52455
52552
  #setupInputBridge() {
52456
52553
  this.#inputBridge?.destroy();
52457
52554
  const win = this.#visibleHost.ownerDocument?.defaultView ?? window;
@@ -52542,8 +52639,30 @@ class PresentationEditor extends EventEmitter {
52542
52639
  linkEl.dispatchEvent(linkClickEvent);
52543
52640
  return;
52544
52641
  }
52642
+ const annotationEl = target?.closest?.(".annotation[data-pm-start]");
52545
52643
  const isDraggableAnnotation = target?.closest?.('[data-draggable="true"]') != null;
52546
52644
  this.#suppressFocusInFromDraggable = isDraggableAnnotation;
52645
+ if (annotationEl) {
52646
+ if (!this.#editor.isEditable) {
52647
+ return;
52648
+ }
52649
+ const resolved = this.#resolveFieldAnnotationSelectionFromElement(annotationEl);
52650
+ if (resolved) {
52651
+ try {
52652
+ const tr = this.#editor.state.tr.setSelection(NodeSelection.create(this.#editor.state.doc, resolved.pos));
52653
+ this.#editor.view?.dispatch(tr);
52654
+ } catch {
52655
+ }
52656
+ this.#editor.emit("fieldAnnotationClicked", {
52657
+ editor: this.#editor,
52658
+ node: resolved.node,
52659
+ nodePos: resolved.pos,
52660
+ event,
52661
+ currentTarget: annotationEl
52662
+ });
52663
+ }
52664
+ return;
52665
+ }
52547
52666
  if (!this.#layoutState.layout) {
52548
52667
  if (!isDraggableAnnotation) {
52549
52668
  event.preventDefault();
@@ -60158,6 +60277,10 @@ const CommentsMark = Mark.create({
60158
60277
  internal: {
60159
60278
  default: true,
60160
60279
  rendered: false
60280
+ },
60281
+ trackedChange: {
60282
+ default: false,
60283
+ rendered: false
60161
60284
  }
60162
60285
  };
60163
60286
  },
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
- const index = require("./index-BKXWekME.cjs");
3
- require("./SuperConverter-C4XfNZf6.cjs");
2
+ const index = require("./index-DS7Ttafb.cjs");
3
+ require("./SuperConverter-Bukam51x.cjs");
4
4
  const blankDocx = require("./blank-docx-DfW3Eeh2.cjs");
5
5
  const eventemitter3 = require("./eventemitter3-BQuRcMPI.cjs");
6
6
  const provider = require("@hocuspocus/provider");
@@ -5130,11 +5130,14 @@ const groupChanges = (changes) => {
5130
5130
  trackFormat: "formatMark"
5131
5131
  };
5132
5132
  const grouped = [];
5133
+ const processed = /* @__PURE__ */ new Set();
5133
5134
  for (let i = 0; i < changes.length; i++) {
5135
+ if (processed.has(i)) continue;
5134
5136
  const c1 = changes[i];
5135
- const c2 = changes[i + 1];
5136
5137
  const c1Key = markMetaKeys[c1.mark.type.name];
5137
- if (c1 && c2 && c1.to === c2.from && c1.mark.attrs.id === c2.mark.attrs.id) {
5138
+ const c1Id = c1.mark.attrs.id;
5139
+ const c2 = changes[i + 1];
5140
+ if (c2 && c1.to === c2.from && c1Id === c2.mark.attrs.id) {
5138
5141
  const c2Key = markMetaKeys[c2.mark.type.name];
5139
5142
  grouped.push({
5140
5143
  from: c1.from,
@@ -5142,13 +5145,35 @@ const groupChanges = (changes) => {
5142
5145
  [c1Key]: c1,
5143
5146
  [c2Key]: c2
5144
5147
  });
5145
- i++;
5146
- } else {
5148
+ processed.add(i);
5149
+ processed.add(i + 1);
5150
+ continue;
5151
+ }
5152
+ let foundMatch = false;
5153
+ for (let j = i + 1; j < changes.length; j++) {
5154
+ if (processed.has(j)) continue;
5155
+ const c22 = changes[j];
5156
+ if (c1Id === c22.mark.attrs.id && c1.mark.type.name !== c22.mark.type.name) {
5157
+ const c2Key = markMetaKeys[c22.mark.type.name];
5158
+ grouped.push({
5159
+ from: Math.min(c1.from, c22.from),
5160
+ to: Math.max(c1.to, c22.to),
5161
+ [c1Key]: c1,
5162
+ [c2Key]: c22
5163
+ });
5164
+ processed.add(i);
5165
+ processed.add(j);
5166
+ foundMatch = true;
5167
+ break;
5168
+ }
5169
+ }
5170
+ if (!foundMatch) {
5147
5171
  grouped.push({
5148
5172
  from: c1.from,
5149
5173
  to: c1.to,
5150
5174
  [c1Key]: c1
5151
5175
  });
5176
+ processed.add(i);
5152
5177
  }
5153
5178
  }
5154
5179
  return grouped;
@@ -5450,7 +5475,12 @@ const useCommentsStore = /* @__PURE__ */ defineStore("comments", () => {
5450
5475
  trackedChange: comment.trackedChange || false,
5451
5476
  trackedChangeText: comment.trackedChangeText,
5452
5477
  trackedChangeType: comment.trackedChangeType,
5453
- deletedText: comment.trackedDeletedText
5478
+ deletedText: comment.trackedDeletedText,
5479
+ // Preserve origin metadata for export
5480
+ origin: comment.origin || "word",
5481
+ // Default to 'word' for backward compatibility
5482
+ threadingMethod: comment.threadingMethod,
5483
+ originalXmlStructure: comment.originalXmlStructure
5454
5484
  });
5455
5485
  addComment({ superdoc, comment: newComment });
5456
5486
  });
@@ -6230,7 +6260,11 @@ const _sfc_main$c = {
6230
6260
  const isThreadedComment = c.parentCommentId === parentComment.commentId;
6231
6261
  const isThisComment = c.commentId === props.comment.commentId;
6232
6262
  return isThreadedComment || isThisComment;
6233
- }).sort((a, b) => a.commentId === props.comment.commentId && a.createdTime - b.createdTime);
6263
+ }).sort((a, b) => {
6264
+ if (a.commentId === props.comment.commentId) return -1;
6265
+ if (b.commentId === props.comment.commentId) return 1;
6266
+ return a.createdTime - b.createdTime;
6267
+ });
6234
6268
  });
6235
6269
  const isInternalDropdownDisabled = vue.computed(() => {
6236
6270
  if (props.comment.resolvedTime) return true;
@@ -6489,7 +6523,7 @@ const _sfc_main$c = {
6489
6523
  };
6490
6524
  }
6491
6525
  };
6492
- const CommentDialog = /* @__PURE__ */ index._export_sfc(_sfc_main$c, [["__scopeId", "data-v-d50fd675"]]);
6526
+ const CommentDialog = /* @__PURE__ */ index._export_sfc(_sfc_main$c, [["__scopeId", "data-v-f9956635"]]);
6493
6527
  const _hoisted_1$a = { class: "comments-list" };
6494
6528
  const _hoisted_2$5 = { key: 0 };
6495
6529
  const _hoisted_3$3 = { class: "comment-item" };
@@ -7496,7 +7530,7 @@ const _sfc_main = {
7496
7530
  __name: "SuperDoc",
7497
7531
  emits: ["selection-update"],
7498
7532
  setup(__props, { emit: __emit }) {
7499
- const PdfViewer = vue.defineAsyncComponent(() => Promise.resolve().then(() => require("./PdfViewer-Dl9_ocZH.cjs")));
7533
+ const PdfViewer = vue.defineAsyncComponent(() => Promise.resolve().then(() => require("./PdfViewer-BynotIK6.cjs")));
7500
7534
  const superdocStore = useSuperdocStore();
7501
7535
  const commentsStore = useCommentsStore();
7502
7536
  const {
@@ -8450,7 +8484,7 @@ class SuperDoc extends eventemitter3.EventEmitter {
8450
8484
  this.config.colors = shuffleArray(this.config.colors);
8451
8485
  this.userColorMap = /* @__PURE__ */ new Map();
8452
8486
  this.colorIndex = 0;
8453
- this.version = "1.4.0";
8487
+ this.version = "1.4.1-next.2";
8454
8488
  this.#log("🦋 [superdoc] Using SuperDoc version:", this.version);
8455
8489
  this.superdocId = config.superdocId || uuid.v4();
8456
8490
  this.colors = this.config.colors;