@harbour-enterprises/superdoc 1.4.0-next.3 → 1.4.1-next.1

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,8 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const vue = require("./vue-De9wkgLl.cjs");
4
- const superdoc = require("./index-D3X3kMWD.cjs");
5
- const index = require("./index-C0kuhYCD.cjs");
4
+ const superdoc = require("./index-lAO6pLM-.cjs");
5
+ const index = require("./index-Bpm2bUws.cjs");
6
6
  function self(vars) {
7
7
  const {
8
8
  opacityDisabled,
@@ -1,6 +1,6 @@
1
1
  import { d as defineComponent, h, T as Transition, p as process$1, w as watchEffect, c as computed, r as ref, f as onMounted, X as onUnmounted, E as createElementBlock, G as openBlock, K as createBaseVNode, M as createCommentVNode, I as createVNode, v as unref } from "./vue-BnBKJwCW.es.js";
2
- import { N as NBaseLoading, u as useSuperdocStore, s as storeToRefs, a as useSelection } from "./index-DF3OVaQj.es.js";
3
- import { C as derived, r as c, q as cB, aF as fadeInTransition, y as cM, I as warnOnce, J as useConfig, N as useTheme, aG as pxfy, P as createKey, Q as useThemeClass, aH as useCompitable, ai as _export_sfc } from "./index-B-20lDKU.es.js";
2
+ import { N as NBaseLoading, u as useSuperdocStore, s as storeToRefs, a as useSelection } from "./index-BGllXGwn.es.js";
3
+ import { C as derived, r as c, q as cB, aF as fadeInTransition, y as cM, I as warnOnce, J as useConfig, N as useTheme, aG as pxfy, P as createKey, Q as useThemeClass, aH as useCompitable, ai as _export_sfc } from "./index-DwUAu2hL.es.js";
4
4
  function self(vars) {
5
5
  const {
6
6
  opacityDisabled,
@@ -7256,8 +7256,11 @@ const validXmlAttributes$e = [
7256
7256
  createAttributeHandler("w:authorEmail", "authorEmail")
7257
7257
  ];
7258
7258
  const encode$K = (params, encodedAttrs = {}) => {
7259
- const { nodeListHandler, extraParams = {} } = params;
7259
+ const { nodeListHandler, extraParams = {}, converter } = params;
7260
7260
  const { node } = extraParams;
7261
+ if (encodedAttrs.id && converter?.trackedChangeIdMap?.has(encodedAttrs.id)) {
7262
+ encodedAttrs.id = converter.trackedChangeIdMap.get(encodedAttrs.id);
7263
+ }
7261
7264
  const subs = nodeListHandler.handler({
7262
7265
  ...params,
7263
7266
  insideTrackChange: true,
@@ -7265,6 +7268,9 @@ const encode$K = (params, encodedAttrs = {}) => {
7265
7268
  path: [...params.path || [], node]
7266
7269
  });
7267
7270
  encodedAttrs.importedAuthor = `${encodedAttrs.author} (imported)`;
7271
+ if (converter?.documentOrigin) {
7272
+ encodedAttrs.origin = converter.documentOrigin;
7273
+ }
7268
7274
  subs.forEach((subElement) => {
7269
7275
  subElement.marks = [];
7270
7276
  if (subElement?.content?.[0]) {
@@ -27324,8 +27330,11 @@ const validXmlAttributes$2 = [
27324
27330
  createAttributeHandler("w:authorEmail", "authorEmail")
27325
27331
  ];
27326
27332
  const encode$2 = (params, encodedAttrs = {}) => {
27327
- const { nodeListHandler, extraParams = {} } = params;
27333
+ const { nodeListHandler, extraParams = {}, converter } = params;
27328
27334
  const { node } = extraParams;
27335
+ if (encodedAttrs.id && converter?.trackedChangeIdMap?.has(encodedAttrs.id)) {
27336
+ encodedAttrs.id = converter.trackedChangeIdMap.get(encodedAttrs.id);
27337
+ }
27329
27338
  const subs = nodeListHandler.handler({
27330
27339
  ...params,
27331
27340
  insideTrackChange: true,
@@ -27333,6 +27342,9 @@ const encode$2 = (params, encodedAttrs = {}) => {
27333
27342
  path: [...params.path || [], node]
27334
27343
  });
27335
27344
  encodedAttrs.importedAuthor = `${encodedAttrs.author} (imported)`;
27345
+ if (converter?.documentOrigin) {
27346
+ encodedAttrs.origin = converter.documentOrigin;
27347
+ }
27336
27348
  subs.forEach((subElement) => {
27337
27349
  subElement.marks = [];
27338
27350
  if (subElement?.content?.[0]) {
@@ -28052,6 +28064,8 @@ function importCommentData({ docx, editor, converter }) {
28052
28064
  });
28053
28065
  const lastElement = parsedElements[parsedElements.length - 1];
28054
28066
  const paraId = lastElement?.attrs?.["w14:paraId"];
28067
+ const commentsExtended = docx["word/commentsExtended.xml"];
28068
+ const threadingMethod = commentsExtended ? "commentsExtended" : "range-based";
28055
28069
  return {
28056
28070
  commentId: internalId || v4(),
28057
28071
  importedId,
@@ -28066,19 +28080,31 @@ function importCommentData({ docx, editor, converter }) {
28066
28080
  trackedChangeText,
28067
28081
  trackedChangeType,
28068
28082
  trackedDeletedText,
28069
- isDone: false
28083
+ isDone: false,
28084
+ origin: converter?.documentOrigin || "word",
28085
+ threadingMethod,
28086
+ originalXmlStructure: {
28087
+ hasCommentsExtended: !!commentsExtended,
28088
+ hasCommentsExtensible: !!docx["word/commentsExtensible.xml"],
28089
+ hasCommentsIds: !!docx["word/commentsIds.xml"]
28090
+ }
28070
28091
  };
28071
28092
  });
28072
- const extendedComments = generateCommentsWithExtendedData({ docx, comments: extractedComments });
28093
+ const extendedComments = generateCommentsWithExtendedData({ docx, comments: extractedComments, converter });
28073
28094
  return extendedComments;
28074
28095
  }
28075
- const generateCommentsWithExtendedData = ({ docx, comments }) => {
28096
+ const generateCommentsWithExtendedData = ({ docx, comments, converter }) => {
28076
28097
  if (!comments?.length) return [];
28098
+ const rangeData = extractCommentRangesFromDocument(docx, converter);
28099
+ const { commentsInTrackedChanges } = rangeData;
28100
+ const trackedChangeParentMap = detectThreadingFromTrackedChanges(comments, commentsInTrackedChanges);
28077
28101
  const commentsExtended = docx["word/commentsExtended.xml"];
28078
28102
  if (!commentsExtended) {
28079
- const commentRanges = extractCommentRangesFromDocument(docx);
28080
- const commentsWithThreading = detectThreadingFromRanges(comments, commentRanges);
28081
- return commentsWithThreading.map((comment) => ({ ...comment, isDone: comment.isDone ?? false }));
28103
+ const commentsWithThreading = detectThreadingFromRanges(comments, rangeData);
28104
+ return commentsWithThreading.map((comment) => ({
28105
+ ...comment,
28106
+ isDone: comment.isDone ?? false
28107
+ }));
28082
28108
  }
28083
28109
  const { elements: initialElements = [] } = commentsExtended;
28084
28110
  if (!initialElements?.length) return comments.map((comment) => ({ ...comment, isDone: comment.isDone ?? false }));
@@ -28086,25 +28112,30 @@ const generateCommentsWithExtendedData = ({ docx, comments }) => {
28086
28112
  const commentEx = elements.filter((el) => el.name === "w15:commentEx");
28087
28113
  return comments.map((comment) => {
28088
28114
  const extendedDef = commentEx.find((ce2) => {
28089
- const isIncludedInCommentElements = comment.elements?.some(
28090
- (el) => el.attrs?.["w14:paraId"] === ce2.attributes["w15:paraId"]
28091
- );
28092
- return isIncludedInCommentElements;
28115
+ return comment.elements?.some((el) => el.attrs?.["w14:paraId"] === ce2.attributes["w15:paraId"]);
28093
28116
  });
28094
- if (!extendedDef) return { ...comment, isDone: comment.isDone ?? false };
28095
- const { isDone, paraIdParent } = getExtendedDetails(extendedDef);
28096
- let parentComment;
28097
- if (paraIdParent) {
28098
- parentComment = comments.find(
28099
- (c) => c.paraId === paraIdParent || c.elements?.some((el) => el.attrs?.["w14:paraId"] === paraIdParent)
28100
- );
28117
+ let isDone = comment.isDone ?? false;
28118
+ let parentCommentId = void 0;
28119
+ const trackedChangeParent = trackedChangeParentMap.get(comment.importedId);
28120
+ const isInsideTrackedChange = trackedChangeParent?.isTrackedChangeParent;
28121
+ if (extendedDef) {
28122
+ const details = getExtendedDetails(extendedDef);
28123
+ isDone = details.isDone ?? false;
28124
+ if (!isInsideTrackedChange && details.paraIdParent) {
28125
+ const parentComment = comments.find(
28126
+ (c) => c.paraId === details.paraIdParent || c.elements?.some((el) => el.attrs?.["w14:paraId"] === details.paraIdParent)
28127
+ );
28128
+ parentCommentId = parentComment?.commentId;
28129
+ }
28130
+ }
28131
+ if (isInsideTrackedChange) {
28132
+ parentCommentId = trackedChangeParent.trackedChangeId;
28101
28133
  }
28102
- const newComment = {
28134
+ return {
28103
28135
  ...comment,
28104
- isDone: isDone ?? false,
28105
- parentCommentId: parentComment?.commentId
28136
+ isDone,
28137
+ parentCommentId
28106
28138
  };
28107
- return newComment;
28108
28139
  });
28109
28140
  };
28110
28141
  const getExtendedDetails = (commentEx) => {
@@ -28114,34 +28145,117 @@ const getExtendedDetails = (commentEx) => {
28114
28145
  const paraIdParent = attributes["w15:paraIdParent"];
28115
28146
  return { paraId, isDone, paraIdParent };
28116
28147
  };
28117
- const extractCommentRangesFromDocument = (docx) => {
28148
+ const extractCommentRangesFromDocument = (docx, converter) => {
28118
28149
  const documentXml = docx["word/document.xml"];
28119
28150
  if (!documentXml) {
28120
- return [];
28121
- }
28122
- const pendingComments = [];
28123
- const walkElements = (elements) => {
28151
+ return { rangeEvents: [], rangePositions: /* @__PURE__ */ new Map(), commentsInTrackedChanges: /* @__PURE__ */ new Map() };
28152
+ }
28153
+ const rangeEvents = [];
28154
+ const rangePositions = /* @__PURE__ */ new Map();
28155
+ const commentsInTrackedChanges = /* @__PURE__ */ new Map();
28156
+ let positionIndex = 0;
28157
+ let lastElementWasCommentMarker = false;
28158
+ const recentlyClosedComments = /* @__PURE__ */ new Set();
28159
+ let lastTrackedChange = null;
28160
+ const walkElements = (elements, currentTrackedChangeId = null) => {
28124
28161
  if (!elements || !Array.isArray(elements)) return;
28125
28162
  elements.forEach((element) => {
28126
- if (element.name === "w:commentRangeStart") {
28163
+ const isCommentStart = element.name === "w:commentRangeStart";
28164
+ const isCommentEnd = element.name === "w:commentRangeEnd";
28165
+ const isTrackedChange = element.name === "w:ins" || element.name === "w:del";
28166
+ if (isCommentStart) {
28127
28167
  const commentId = element.attributes?.["w:id"];
28128
28168
  if (commentId !== void 0) {
28129
- pendingComments.push({
28169
+ const id = String(commentId);
28170
+ rangeEvents.push({
28130
28171
  type: "start",
28131
- commentId: String(commentId)
28172
+ commentId: id
28132
28173
  });
28174
+ if (!rangePositions.has(id)) {
28175
+ rangePositions.set(id, { startIndex: positionIndex, endIndex: -1 });
28176
+ } else {
28177
+ rangePositions.get(id).startIndex = positionIndex;
28178
+ }
28179
+ if (currentTrackedChangeId !== null) {
28180
+ commentsInTrackedChanges.set(id, currentTrackedChangeId);
28181
+ }
28133
28182
  }
28134
- } else if (element.name === "w:commentRangeEnd") {
28183
+ lastElementWasCommentMarker = true;
28184
+ recentlyClosedComments.clear();
28185
+ } else if (isCommentEnd) {
28135
28186
  const commentId = element.attributes?.["w:id"];
28136
28187
  if (commentId !== void 0) {
28137
- pendingComments.push({
28188
+ const id = String(commentId);
28189
+ rangeEvents.push({
28138
28190
  type: "end",
28139
- commentId: String(commentId)
28191
+ commentId: id
28140
28192
  });
28193
+ if (!rangePositions.has(id)) {
28194
+ rangePositions.set(id, { startIndex: -1, endIndex: positionIndex });
28195
+ } else {
28196
+ rangePositions.get(id).endIndex = positionIndex;
28197
+ }
28198
+ recentlyClosedComments.add(id);
28199
+ }
28200
+ lastElementWasCommentMarker = true;
28201
+ } else if (isTrackedChange) {
28202
+ const trackedChangeId = element.attributes?.["w:id"];
28203
+ const author = element.attributes?.["w:author"];
28204
+ const date = element.attributes?.["w:date"];
28205
+ const elementType = element.name;
28206
+ let mappedId = trackedChangeId;
28207
+ let isReplacement = false;
28208
+ if (trackedChangeId !== void 0 && converter) {
28209
+ if (!converter.trackedChangeIdMap) {
28210
+ converter.trackedChangeIdMap = /* @__PURE__ */ new Map();
28211
+ }
28212
+ if (lastTrackedChange && lastTrackedChange.type !== elementType && lastTrackedChange.author === author && lastTrackedChange.date === date) {
28213
+ mappedId = lastTrackedChange.mappedId;
28214
+ converter.trackedChangeIdMap.set(String(trackedChangeId), mappedId);
28215
+ isReplacement = true;
28216
+ } else {
28217
+ if (!converter.trackedChangeIdMap.has(String(trackedChangeId))) {
28218
+ converter.trackedChangeIdMap.set(String(trackedChangeId), v4());
28219
+ }
28220
+ mappedId = converter.trackedChangeIdMap.get(String(trackedChangeId));
28221
+ }
28222
+ }
28223
+ if (currentTrackedChangeId === null) {
28224
+ if (isReplacement) {
28225
+ lastTrackedChange = null;
28226
+ } else {
28227
+ lastTrackedChange = {
28228
+ type: elementType,
28229
+ author,
28230
+ date,
28231
+ mappedId,
28232
+ wordId: String(trackedChangeId)
28233
+ };
28234
+ }
28235
+ }
28236
+ if (mappedId && recentlyClosedComments.size > 0) {
28237
+ recentlyClosedComments.forEach((commentId) => {
28238
+ if (!commentsInTrackedChanges.has(commentId)) {
28239
+ commentsInTrackedChanges.set(commentId, String(mappedId));
28240
+ }
28241
+ });
28242
+ }
28243
+ recentlyClosedComments.clear();
28244
+ if (element.elements && Array.isArray(element.elements)) {
28245
+ walkElements(element.elements, mappedId !== void 0 ? String(mappedId) : currentTrackedChangeId);
28246
+ }
28247
+ } else {
28248
+ if (lastElementWasCommentMarker) {
28249
+ positionIndex++;
28250
+ lastElementWasCommentMarker = false;
28251
+ }
28252
+ if (element.name === "w:p") {
28253
+ recentlyClosedComments.clear();
28254
+ lastTrackedChange = null;
28255
+ }
28256
+ if (element.elements && Array.isArray(element.elements)) {
28257
+ walkElements(element.elements, currentTrackedChangeId);
28141
28258
  }
28142
- }
28143
- if (element.elements && Array.isArray(element.elements)) {
28144
- walkElements(element.elements);
28145
28259
  }
28146
28260
  });
28147
28261
  };
@@ -28151,19 +28265,20 @@ const extractCommentRangesFromDocument = (docx) => {
28151
28265
  walkElements(body.elements);
28152
28266
  }
28153
28267
  }
28154
- return pendingComments;
28268
+ return { rangeEvents, rangePositions, commentsInTrackedChanges };
28155
28269
  };
28156
- const detectThreadingFromRanges = (comments, rangeEvents) => {
28157
- if (!rangeEvents || rangeEvents.length === 0) {
28158
- return comments;
28159
- }
28270
+ const detectThreadingFromNestedRanges = (comments, rangeEvents, skipComments = /* @__PURE__ */ new Set()) => {
28160
28271
  const openRanges = [];
28161
28272
  const parentMap = /* @__PURE__ */ new Map();
28162
28273
  rangeEvents.forEach((event) => {
28163
28274
  if (event.type === "start") {
28164
- if (openRanges.length > 0) {
28165
- const parentCommentId = openRanges[openRanges.length - 1];
28166
- parentMap.set(event.commentId, parentCommentId);
28275
+ if (!skipComments.has(event.commentId) && openRanges.length > 0) {
28276
+ for (let i = openRanges.length - 1; i >= 0; i--) {
28277
+ if (!skipComments.has(openRanges[i])) {
28278
+ parentMap.set(event.commentId, openRanges[i]);
28279
+ break;
28280
+ }
28281
+ }
28167
28282
  }
28168
28283
  openRanges.push(event.commentId);
28169
28284
  } else if (event.type === "end") {
@@ -28173,10 +28288,113 @@ const detectThreadingFromRanges = (comments, rangeEvents) => {
28173
28288
  }
28174
28289
  }
28175
28290
  });
28291
+ return parentMap;
28292
+ };
28293
+ const detectThreadingFromSharedPosition = (comments, rangePositions) => {
28294
+ const parentMap = /* @__PURE__ */ new Map();
28295
+ const commentsByStartPosition = /* @__PURE__ */ new Map();
28296
+ comments.forEach((comment) => {
28297
+ const position = rangePositions.get(comment.importedId);
28298
+ if (position && position.startIndex >= 0) {
28299
+ const startKey = position.startIndex;
28300
+ if (!commentsByStartPosition.has(startKey)) {
28301
+ commentsByStartPosition.set(startKey, []);
28302
+ }
28303
+ commentsByStartPosition.get(startKey).push(comment);
28304
+ }
28305
+ });
28306
+ commentsByStartPosition.forEach((commentsAtPosition) => {
28307
+ if (commentsAtPosition.length <= 1) return;
28308
+ const sorted = [...commentsAtPosition].sort((a, b2) => a.createdTime - b2.createdTime);
28309
+ const parentComment = sorted[0];
28310
+ for (let i = 1; i < sorted.length; i++) {
28311
+ parentMap.set(sorted[i].importedId, parentComment.importedId);
28312
+ }
28313
+ });
28314
+ return parentMap;
28315
+ };
28316
+ const detectThreadingFromMissingRanges = (comments, rangePositions) => {
28317
+ const parentMap = /* @__PURE__ */ new Map();
28318
+ const commentsWithRanges = [];
28319
+ const commentsWithoutRanges = [];
28320
+ comments.forEach((comment) => {
28321
+ const position = rangePositions.get(comment.importedId);
28322
+ if (position && position.startIndex >= 0) {
28323
+ commentsWithRanges.push(comment);
28324
+ } else {
28325
+ commentsWithoutRanges.push(comment);
28326
+ }
28327
+ });
28328
+ commentsWithoutRanges.forEach((comment) => {
28329
+ const potentialParents = commentsWithRanges.filter((c) => c.createdTime < comment.createdTime).sort((a, b2) => b2.createdTime - a.createdTime);
28330
+ if (potentialParents.length > 0) {
28331
+ parentMap.set(comment.importedId, potentialParents[0].importedId);
28332
+ }
28333
+ });
28334
+ return parentMap;
28335
+ };
28336
+ const detectThreadingFromTrackedChanges = (comments, commentsInTrackedChanges) => {
28337
+ const parentMap = /* @__PURE__ */ new Map();
28338
+ if (!commentsInTrackedChanges || commentsInTrackedChanges.size === 0) {
28339
+ return parentMap;
28340
+ }
28341
+ comments.forEach((comment) => {
28342
+ const trackedChangeId = commentsInTrackedChanges.get(comment.importedId);
28343
+ if (trackedChangeId !== void 0) {
28344
+ parentMap.set(comment.importedId, { trackedChangeId, isTrackedChangeParent: true });
28345
+ }
28346
+ });
28347
+ return parentMap;
28348
+ };
28349
+ const detectThreadingFromRanges = (comments, rangeData) => {
28350
+ const { rangeEvents, rangePositions, commentsInTrackedChanges } = Array.isArray(rangeData) ? { rangeEvents: rangeData, rangePositions: /* @__PURE__ */ new Map(), commentsInTrackedChanges: /* @__PURE__ */ new Map() } : rangeData;
28351
+ if (!rangeEvents || rangeEvents.length === 0) {
28352
+ if (comments.length > 1) {
28353
+ const parentMap = detectThreadingFromMissingRanges(comments, rangePositions);
28354
+ return applyParentRelationships(comments, parentMap);
28355
+ }
28356
+ return comments;
28357
+ }
28358
+ const commentsWithSharedPosition = findCommentsWithSharedStartPosition(comments, rangePositions);
28359
+ const nestedParentMap = detectThreadingFromNestedRanges(comments, rangeEvents, commentsWithSharedPosition);
28360
+ const sharedPositionParentMap = detectThreadingFromSharedPosition(comments, rangePositions);
28361
+ const missingRangeParentMap = detectThreadingFromMissingRanges(comments, rangePositions);
28362
+ const trackedChangeParentMap = detectThreadingFromTrackedChanges(comments, commentsInTrackedChanges);
28363
+ const mergedParentMap = new Map([...missingRangeParentMap, ...nestedParentMap, ...sharedPositionParentMap]);
28364
+ return applyParentRelationships(comments, mergedParentMap, trackedChangeParentMap);
28365
+ };
28366
+ const findCommentsWithSharedStartPosition = (comments, rangePositions) => {
28367
+ const sharedPositionComments = /* @__PURE__ */ new Set();
28368
+ const commentsByStartPosition = /* @__PURE__ */ new Map();
28369
+ comments.forEach((comment) => {
28370
+ const position = rangePositions.get(comment.importedId);
28371
+ if (position && position.startIndex >= 0) {
28372
+ const startKey = position.startIndex;
28373
+ if (!commentsByStartPosition.has(startKey)) {
28374
+ commentsByStartPosition.set(startKey, []);
28375
+ }
28376
+ commentsByStartPosition.get(startKey).push(comment.importedId);
28377
+ }
28378
+ });
28379
+ commentsByStartPosition.forEach((commentIds) => {
28380
+ if (commentIds.length > 1) {
28381
+ commentIds.forEach((id) => sharedPositionComments.add(id));
28382
+ }
28383
+ });
28384
+ return sharedPositionComments;
28385
+ };
28386
+ const applyParentRelationships = (comments, parentMap, trackedChangeParentMap = /* @__PURE__ */ new Map()) => {
28176
28387
  return comments.map((comment) => {
28177
- const parentCommentId = parentMap.get(comment.importedId);
28178
- if (parentCommentId) {
28179
- const parentComment = comments.find((c) => c.importedId === parentCommentId);
28388
+ const trackedChangeParent = trackedChangeParentMap.get(comment.importedId);
28389
+ if (trackedChangeParent && trackedChangeParent.isTrackedChangeParent) {
28390
+ return {
28391
+ ...comment,
28392
+ parentCommentId: trackedChangeParent.trackedChangeId
28393
+ };
28394
+ }
28395
+ const parentImportedId = parentMap.get(comment.importedId);
28396
+ if (parentImportedId) {
28397
+ const parentComment = comments.find((c) => c.importedId === parentImportedId);
28180
28398
  if (parentComment) {
28181
28399
  return {
28182
28400
  ...comment,
@@ -29052,9 +29270,30 @@ const commentRangeEndHandlerEntity = generateV2HandlerEntity(
29052
29270
  );
29053
29271
  const permStartHandlerEntity = generateV2HandlerEntity("permStartHandler", translator$8);
29054
29272
  const permEndHandlerEntity = generateV2HandlerEntity("permEndHandler", translator$7);
29273
+ const detectDocumentOrigin = (docx) => {
29274
+ const commentsExtended = docx["word/commentsExtended.xml"];
29275
+ if (commentsExtended) {
29276
+ const { elements: initialElements = [] } = commentsExtended;
29277
+ if (initialElements?.length > 0) {
29278
+ const { elements = [] } = initialElements[0] ?? {};
29279
+ const commentEx = elements.filter((el) => el.name === "w15:commentEx");
29280
+ if (commentEx.length > 0) {
29281
+ return "word";
29282
+ }
29283
+ }
29284
+ }
29285
+ const comments = docx["word/comments.xml"];
29286
+ if (comments && !commentsExtended) {
29287
+ return "google-docs";
29288
+ }
29289
+ return "unknown";
29290
+ };
29055
29291
  const createDocumentJson = (docx, converter, editor) => {
29056
29292
  const json = carbonCopy(getInitialJSON(docx));
29057
29293
  if (!json) return null;
29294
+ if (converter) {
29295
+ converter.documentOrigin = detectDocumentOrigin(docx);
29296
+ }
29058
29297
  if (converter?.telemetry) {
29059
29298
  const files = Object.keys(docx).map((filePath) => {
29060
29299
  const parts = filePath.split("/");
@@ -30626,7 +30865,9 @@ const getCommentDefinition = (comment, commentId, allComments, editor) => {
30626
30865
  };
30627
30866
  if (comment?.parentCommentId) {
30628
30867
  const parentComment = allComments.find((c) => c.commentId === comment.parentCommentId);
30629
- attributes["w15:paraIdParent"] = parentComment.commentParaId;
30868
+ if (parentComment && !parentComment.trackedChange) {
30869
+ attributes["w15:paraIdParent"] = parentComment.commentParaId;
30870
+ }
30630
30871
  }
30631
30872
  return {
30632
30873
  type: "element",
@@ -30671,7 +30912,22 @@ const updateCommentsXml = (commentDefs = [], commentsXml) => {
30671
30912
  newCommentsXml.elements[0].elements = commentDefs;
30672
30913
  return newCommentsXml;
30673
30914
  };
30674
- const updateCommentsExtendedXml = (comments = [], commentsExtendedXml) => {
30915
+ const determineExportStrategy = (comments) => {
30916
+ if (!comments || comments.length === 0) {
30917
+ return "word";
30918
+ }
30919
+ const origins = new Set(comments.map((c) => c.origin || "word"));
30920
+ if (origins.size === 1) {
30921
+ const origin = origins.values().next().value;
30922
+ return origin === "google-docs" ? "google-docs" : "word";
30923
+ }
30924
+ return "word";
30925
+ };
30926
+ const updateCommentsExtendedXml = (comments = [], commentsExtendedXml, exportStrategy = "word") => {
30927
+ const shouldGenerateCommentsExtended = exportStrategy === "word" || comments.some((c) => c.originalXmlStructure?.hasCommentsExtended);
30928
+ if (!shouldGenerateCommentsExtended && exportStrategy === "google-docs") {
30929
+ return null;
30930
+ }
30675
30931
  const xmlCopy = carbonCopy(commentsExtendedXml);
30676
30932
  const commentsEx = comments.map((comment) => {
30677
30933
  const isResolved = comment.resolvedTime || comment.isDone;
@@ -30680,9 +30936,11 @@ const updateCommentsExtendedXml = (comments = [], commentsExtendedXml) => {
30680
30936
  "w15:done": isResolved ? "1" : "0"
30681
30937
  };
30682
30938
  const parentId = comment.parentCommentId;
30683
- if (parentId) {
30939
+ if (parentId && (exportStrategy === "word" || comment.originalXmlStructure?.hasCommentsExtended)) {
30684
30940
  const parentComment = comments.find((c) => c.commentId === parentId);
30685
- attributes["w15:paraIdParent"] = parentComment.commentParaId;
30941
+ if (parentComment && !parentComment.trackedChange) {
30942
+ attributes["w15:paraIdParent"] = parentComment.commentParaId;
30943
+ }
30686
30944
  }
30687
30945
  return {
30688
30946
  type: "element",
@@ -30752,14 +31010,21 @@ const prepareCommentsXmlFilesForExport = ({ convertedXml, defs, commentsWithPara
30752
31010
  const documentXml = removeCommentsFilesFromConvertedXml(convertedXml);
30753
31011
  return { documentXml, relationships };
30754
31012
  }
31013
+ const exportStrategy = determineExportStrategy(commentsWithParaIds);
30755
31014
  const updatedXml = generateConvertedXmlWithCommentFiles(convertedXml);
30756
31015
  updatedXml["word/comments.xml"] = updateCommentsXml(defs, updatedXml["word/comments.xml"]);
30757
31016
  relationships.push(generateRelationship("comments.xml"));
30758
- updatedXml["word/commentsExtended.xml"] = updateCommentsExtendedXml(
31017
+ const commentsExtendedXml = updateCommentsExtendedXml(
30759
31018
  commentsWithParaIds,
30760
- updatedXml["word/commentsExtended.xml"]
31019
+ updatedXml["word/commentsExtended.xml"],
31020
+ exportStrategy
30761
31021
  );
30762
- relationships.push(generateRelationship("commentsExtended.xml"));
31022
+ if (commentsExtendedXml !== null) {
31023
+ updatedXml["word/commentsExtended.xml"] = commentsExtendedXml;
31024
+ relationships.push(generateRelationship("commentsExtended.xml"));
31025
+ } else {
31026
+ delete updatedXml["word/commentsExtended.xml"];
31027
+ }
30763
31028
  const { documentIdsUpdated, extensibleUpdated } = updateCommentsIdsAndExtensible(
30764
31029
  commentsWithParaIds,
30765
31030
  updatedXml["word/commentsIds.xml"],
@@ -31268,7 +31533,7 @@ class SuperConverter {
31268
31533
  static getStoredSuperdocVersion(docx) {
31269
31534
  return SuperConverter.getStoredCustomProperty(docx, "SuperdocVersion");
31270
31535
  }
31271
- static setStoredSuperdocVersion(docx = this.convertedXml, version = "1.4.0-next.3") {
31536
+ static setStoredSuperdocVersion(docx = this.convertedXml, version = "1.4.1-next.1") {
31272
31537
  return SuperConverter.setStoredCustomProperty(docx, "SuperdocVersion", version, false);
31273
31538
  }
31274
31539
  /**