superdoc 2.28.0-next.11 → 2.28.0-next.13

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.
@@ -258,7 +258,7 @@ var v_click_outside_default = {
258
258
  var DEFAULT_ENDPOINT = "https://ingest.superdoc.dev/v1/collect";
259
259
  function getSuperdocVersion() {
260
260
  try {
261
- return "2.28.0-next.11";
261
+ return "2.28.0-next.13";
262
262
  } catch {
263
263
  return "unknown";
264
264
  }
@@ -5527,13 +5527,22 @@ function resolveLiveblocksFamily(candidate, authEndpointBaseUrl) {
5527
5527
  reason: "mixed-auth",
5528
5528
  message: "SuperDoc v2 Liveblocks collaboration accepts exactly one auth mode; pass either publicApiKey or authEndpoint, not both."
5529
5529
  };
5530
+ const baseUrlRaw = candidate.baseUrl;
5531
+ const baseUrl = baseUrlRaw === void 0 ? void 0 : normalizeHttpUrl(baseUrlRaw);
5532
+ if (baseUrl === null) return {
5533
+ ok: false,
5534
+ reason: "invalid-base-url",
5535
+ message: "SuperDoc v2 Liveblocks collaboration requires baseUrl to be an absolute http(s) URL."
5536
+ };
5537
+ const baseUrlOption = baseUrl ? { baseUrl } : {};
5530
5538
  if (publicApiKey) return {
5531
5539
  ok: true,
5532
5540
  target: {
5533
5541
  providerFamily: "liveblocks",
5534
5542
  documentId,
5535
5543
  roomMode,
5536
- publicApiKey
5544
+ publicApiKey,
5545
+ ...baseUrlOption
5537
5546
  }
5538
5547
  };
5539
5548
  const authEndpoint = normalizeHttpUrl(authEndpointRaw, authEndpointBaseUrl);
@@ -5548,7 +5557,8 @@ function resolveLiveblocksFamily(candidate, authEndpointBaseUrl) {
5548
5557
  providerFamily: "liveblocks",
5549
5558
  documentId,
5550
5559
  roomMode,
5551
- authEndpoint
5560
+ authEndpoint,
5561
+ ...baseUrlOption
5552
5562
  }
5553
5563
  };
5554
5564
  }
@@ -6831,87 +6841,6 @@ var useSuperdocStore = defineStore("superdoc", () => {
6831
6841
  };
6832
6842
  });
6833
6843
  //#endregion
6834
- //#region src/helpers/group-changes.js
6835
- /**
6836
- * Track changes helper
6837
- * Combines replace transactions which are represented by insertion + deletion
6838
- *
6839
- * @param {Array} changes - Array of tracked changes from the editor
6840
- * @returns {Array} Grouped track changes array with combined replacements
6841
- */
6842
- var groupChanges = (changes) => {
6843
- const markMetaKeys = {
6844
- trackInsert: "insertedMark",
6845
- trackDelete: "deletionMark",
6846
- trackFormat: "formatMark"
6847
- };
6848
- const byId = /* @__PURE__ */ new Map();
6849
- for (const change of changes) {
6850
- const id = change.mark.attrs.id;
6851
- if (!byId.has(id)) byId.set(id, []);
6852
- byId.get(id).push(change);
6853
- }
6854
- const grouped = [];
6855
- for (const [, group] of byId) {
6856
- if (group.length === 1) {
6857
- const c = group[0];
6858
- const key = markMetaKeys[c.mark.type.name];
6859
- grouped.push({
6860
- from: c.from,
6861
- to: c.to,
6862
- [key]: c
6863
- });
6864
- continue;
6865
- }
6866
- const processed = /* @__PURE__ */ new Set();
6867
- for (let i = 0; i < group.length; i++) {
6868
- if (processed.has(i)) continue;
6869
- const c1 = group[i];
6870
- const c1Key = markMetaKeys[c1.mark.type.name];
6871
- const c2 = group[i + 1];
6872
- if (c2 && !processed.has(i + 1) && c1.to === c2.from && c1.mark.type.name !== c2.mark.type.name) {
6873
- const c2Key = markMetaKeys[c2.mark.type.name];
6874
- grouped.push({
6875
- from: c1.from,
6876
- to: c2.to,
6877
- [c1Key]: c1,
6878
- [c2Key]: c2
6879
- });
6880
- processed.add(i);
6881
- processed.add(i + 1);
6882
- continue;
6883
- }
6884
- let foundMatch = false;
6885
- for (let j = i + 1; j < group.length; j++) {
6886
- if (processed.has(j)) continue;
6887
- const cj = group[j];
6888
- if (c1.mark.type.name !== cj.mark.type.name) {
6889
- const cjKey = markMetaKeys[cj.mark.type.name];
6890
- grouped.push({
6891
- from: Math.min(c1.from, cj.from),
6892
- to: Math.max(c1.to, cj.to),
6893
- [c1Key]: c1,
6894
- [cjKey]: cj
6895
- });
6896
- processed.add(i);
6897
- processed.add(j);
6898
- foundMatch = true;
6899
- break;
6900
- }
6901
- }
6902
- if (!foundMatch) {
6903
- grouped.push({
6904
- from: c1.from,
6905
- to: c1.to,
6906
- [c1Key]: c1
6907
- });
6908
- processed.add(i);
6909
- }
6910
- }
6911
- }
6912
- return grouped;
6913
- };
6914
- //#endregion
6915
6844
  //#region src/stores/helpers/floating-comment-instances.js
6916
6845
  var HEADER_FOOTER_TRACKED_CHANGE_STORY_TYPE = "headerFooterPart";
6917
6846
  var toFinitePageIndex = (value) => {
@@ -7472,20 +7401,11 @@ var buildTrackedChangeDecisionLinkIndex = (allComments, previous = /* @__PURE__
7472
7401
  };
7473
7402
  //#endregion
7474
7403
  //#region src/stores/comments-store.js
7475
- var Editor = class {
7476
- constructor() {
7477
- throw new Error("SuperDoc v2 beta: v1 editor-backed comment import paths are not available.");
7478
- }
7479
- };
7480
7404
  var trackChangesHelpers = {
7481
7405
  getTrackChanges: () => [],
7482
7406
  enumerateStructuralRowChanges: () => []
7483
7407
  };
7484
- var CommentsPluginKey = Symbol("comments-plugin-disabled");
7485
- var getRichTextExtensions = () => [];
7486
- var createOrUpdateTrackedChangeComment = () => null;
7487
7408
  var getTrackedChangeIndex = () => null;
7488
- var resolveTrackedChangeInStory = () => null;
7489
7409
  var makeTrackedChangeAnchorKey = ({ storyKey, rawId }) => `tc::${storyKey}::${rawId}`;
7490
7410
  var COMMENT_DRAFT_BR_TAG = /<br(?:\s[^>]*)?\s*\/?>/gi;
7491
7411
  var COMMENT_DRAFT_BLOCK_BOUNDARY = /(?:<\/(?:p|div|li|blockquote|pre|h[1-6])\s*>\s*)+(?:<(?:p|div|li|blockquote|pre|h[1-6])(?:\s[^>]*)?\s*\/?>)+/gi;
@@ -7630,25 +7550,6 @@ var useCommentsStore = defineStore("comments", () => {
7630
7550
  rawId: String(rawId)
7631
7551
  });
7632
7552
  };
7633
- /**
7634
- * Compute the stable public id for a structural (whole-table) tracked change.
7635
- *
7636
- * This MUST match the public id the document-api projects for the same change
7637
- * (`tracked-change-resolver.groupTrackedChanges`), otherwise the right-rail
7638
- * accept/reject would route `trackChanges.decide` to a change that does not
7639
- * exist. The doc-api derives the public id as `word:structural:<sourceId>`
7640
- * for imported Word revisions, falling back to the per-import logical id.
7641
- * Reuse the exact rule here so the bubble id is the decide id.
7642
- *
7643
- * @param {{ sourceId?: string, id?: string }} structural
7644
- * @returns {string | null}
7645
- */
7646
- const buildStructuralTrackedChangeId = (structural) => {
7647
- if (!structural) return null;
7648
- const sourceId = structural.sourceId ? String(structural.sourceId) : "";
7649
- if (sourceId) return `word:structural:${sourceId}`;
7650
- return structural.id ? String(structural.id) : null;
7651
- };
7652
7553
  const superdocStore = useSuperdocStore();
7653
7554
  const commentsConfig = reactive({
7654
7555
  name: "comments",
@@ -7680,8 +7581,6 @@ var useCommentsStore = defineStore("comments", () => {
7680
7581
  const isDebugging = false;
7681
7582
  const debounceTimers = {};
7682
7583
  const trackedChangeResolutionSnapshots = /* @__PURE__ */ new WeakMap();
7683
- const importedTrackedChangeBootstrapTasks = /* @__PURE__ */ new Map();
7684
- let importedTrackedChangeBootstrapGeneration = 0;
7685
7584
  const isBenchmarkCommentsDebugEnabled = () => {
7686
7585
  if (typeof window === "undefined") return false;
7687
7586
  return "__labsSuperDocV2BenchmarkDebug" in window;
@@ -8543,38 +8442,6 @@ var useCommentsStore = defineStore("comments", () => {
8543
8442
  endInteractionSpan(span);
8544
8443
  }
8545
8444
  };
8546
- const collectTrackedChangeMarksByType = (trackedChanges = []) => ({
8547
- insertedMark: trackedChanges.find(({ mark }) => mark?.type?.name === "trackInsert")?.mark ?? null,
8548
- deletionMark: trackedChanges.find(({ mark }) => mark?.type?.name === "trackDelete")?.mark ?? null,
8549
- formatMark: trackedChanges.find(({ mark }) => mark?.type?.name === "trackFormat")?.mark ?? null
8550
- });
8551
- const refreshTrackedChangeCommentsByIds = ({ superdoc, editor, changeIds, broadcastChanges = true }) => {
8552
- if (!superdoc || !editor?.state || !Array.isArray(changeIds) || !changeIds.length) return;
8553
- const documentId = editor?.options?.documentId != null ? String(editor.options.documentId) : null;
8554
- if (!documentId) return;
8555
- for (const changeId of new Set(changeIds.map((id) => id != null ? String(id) : null).filter(Boolean))) {
8556
- const trackedChangesForId = trackChangesHelpers.getTrackChanges(editor.state, changeId);
8557
- if (!trackedChangesForId.length) continue;
8558
- const params = createOrUpdateTrackedChangeComment({
8559
- event: "update",
8560
- marks: collectTrackedChangeMarksByType(trackedChangesForId),
8561
- nodes: [],
8562
- newEditorState: editor.state,
8563
- documentId,
8564
- trackedChangesForId
8565
- });
8566
- if (!params) continue;
8567
- params.trackedChangeStory = BODY_TRACKED_CHANGE_STORY;
8568
- params.trackedChangeStoryKind = "body";
8569
- params.trackedChangeStoryLabel = "";
8570
- params.trackedChangeAnchorKey = buildBodyTrackedChangeAnchorKey(params.changeId ?? changeId);
8571
- handleTrackedChangeUpdate({
8572
- superdoc,
8573
- params,
8574
- broadcastChanges
8575
- });
8576
- }
8577
- };
8578
8445
  const requestInstantSidebarAlignment = (targetY = null, threadId = null, instanceId = null) => {
8579
8446
  const hasTargetY = Number.isFinite(targetY);
8580
8447
  instantSidebarAlignmentTargetY.value = hasTargetY ? targetY : null;
@@ -10184,178 +10051,6 @@ var useCommentsStore = defineStore("comments", () => {
10184
10051
  removePendingComment(superdoc);
10185
10052
  };
10186
10053
  /**
10187
- * Imported DOCX comments can omit the normalized author string.
10188
- * Strip the exporter suffix when present and tolerate missing metadata.
10189
- *
10190
- * @param {string | null | undefined} creatorName
10191
- * @returns {string | null}
10192
- */
10193
- const normalizeImportedCreatorName = (creatorName) => {
10194
- if (typeof creatorName !== "string") return null;
10195
- return creatorName.replace(/\s*\(imported\)\s*$/u, "").trim() || null;
10196
- };
10197
- /**
10198
- * Read the mounted editor view and state without touching `editor.state`.
10199
- * The editor convenience getter delegates to `view.state` and throws after
10200
- * teardown, which is precisely when a deferred import callback can run.
10201
- *
10202
- * @param {Object | null | undefined} editor
10203
- * @returns {{ view: Object, state: Object } | null}
10204
- */
10205
- const readMountedEditorSnapshot = (editor) => {
10206
- if (!editor) return null;
10207
- try {
10208
- if (editor.isDestroyed === true) return null;
10209
- const view = editor.view;
10210
- if (!view || view.isDestroyed === true || view.destroyed === true) return null;
10211
- const state = view.state;
10212
- if (!state) return null;
10213
- return {
10214
- view,
10215
- state
10216
- };
10217
- } catch {
10218
- return null;
10219
- }
10220
- };
10221
- const normalizeBootstrapDocumentId = (documentId) => documentId !== void 0 && documentId !== null && String(documentId).length > 0 ? String(documentId) : null;
10222
- /**
10223
- * Cancel deferred imported tracked-change comment work. Passing a document
10224
- * id cancels only that document; omitting it cancels every pending task.
10225
- *
10226
- * @param {string | null | undefined} documentId
10227
- * @returns {number} number of invalidated tasks
10228
- */
10229
- const cancelImportedTrackedChangeBootstrap = (documentId) => {
10230
- const normalizedDocumentId = normalizeBootstrapDocumentId(documentId);
10231
- const entries = normalizedDocumentId ? [[normalizedDocumentId, importedTrackedChangeBootstrapTasks.get(normalizedDocumentId)]] : Array.from(importedTrackedChangeBootstrapTasks.entries());
10232
- let canceled = 0;
10233
- for (const [taskDocumentId, task] of entries) {
10234
- if (!task) continue;
10235
- importedTrackedChangeBootstrapTasks.delete(taskDocumentId);
10236
- if (task.timeoutHandle !== null && task.timeoutHandle !== void 0) clearTimeout(task.timeoutHandle);
10237
- canceled += 1;
10238
- }
10239
- return canceled;
10240
- };
10241
- const captureImportedTrackedChangeBootstrapSnapshot = (editor) => {
10242
- const mountedEditor = readMountedEditorSnapshot(editor);
10243
- if (!mountedEditor) return null;
10244
- let trackedChanges = [];
10245
- try {
10246
- trackedChanges = trackChangesHelpers.getTrackChanges(mountedEditor.state) ?? [];
10247
- } catch {
10248
- return null;
10249
- }
10250
- const enumerateStructuralChanges = trackChangesHelpers?.enumerateStructuralRowChanges;
10251
- let structuralChanges = [];
10252
- if (typeof enumerateStructuralChanges === "function") try {
10253
- structuralChanges = enumerateStructuralChanges(mountedEditor.state) ?? [];
10254
- } catch {
10255
- structuralChanges = [];
10256
- }
10257
- let storySnapshots = [];
10258
- if (typeof getTrackedChangeIndex === "function") try {
10259
- storySnapshots = getTrackedChangeIndex(editor)?.getAll?.() ?? [];
10260
- } catch {
10261
- storySnapshots = [];
10262
- }
10263
- return {
10264
- ...mountedEditor,
10265
- trackedChanges,
10266
- structuralChanges,
10267
- storySnapshots
10268
- };
10269
- };
10270
- /**
10271
- * Bootstrap tracked-change comment threads after a DOCX import finishes.
10272
- *
10273
- * Initial import historically rebuilt only body tracked-change threads so
10274
- * resolved imported body comments stayed resolved. Header/footer and note
10275
- * tracked changes live outside the body PM state, so they need an additional
10276
- * story-aware bootstrap pass here.
10277
- *
10278
- * We intentionally keep the existing body-only rebuild instead of switching
10279
- * to the broader syncTrackedChangeComments() path so imported resolved body
10280
- * tracked-change threads preserve their initial resolved state.
10281
- *
10282
- * @param {Object | null | undefined} editor
10283
- * @param {Object | null | undefined} superdoc
10284
- * @param {Object | null | undefined} snapshot
10285
- * @returns {boolean}
10286
- */
10287
- const bootstrapImportedTrackedChangeComments = (editor, superdoc, snapshot = null) => {
10288
- if (!editor || !superdoc) return false;
10289
- const captured = snapshot ?? captureImportedTrackedChangeBootstrapSnapshot(editor);
10290
- if (!captured) return false;
10291
- createCommentForTrackChanges(editor, superdoc, captured.trackedChanges, {
10292
- editorState: captured.state,
10293
- editorView: captured.view
10294
- });
10295
- syncStoryTrackedChangeComments({
10296
- superdoc,
10297
- editor,
10298
- snapshots: captured.storySnapshots,
10299
- documentState: captured.state,
10300
- resolveFromEditor: false
10301
- });
10302
- syncStructuralTrackedChangeComments({
10303
- superdoc,
10304
- editor,
10305
- structuralChanges: captured.structuralChanges
10306
- });
10307
- return true;
10308
- };
10309
- const isCurrentImportedTrackedChangeBootstrap = (task) => {
10310
- if (!task) return false;
10311
- if (importedTrackedChangeBootstrapTasks.get(task.documentId) !== task) return false;
10312
- try {
10313
- const editorDocumentId = task.editor?.options?.documentId;
10314
- if (editorDocumentId != null && String(editorDocumentId) !== task.documentId) return false;
10315
- const mountedDocument = superdocStore.getDocument(task.documentId);
10316
- if (!mountedDocument) return false;
10317
- if (mountedDocument.getEditor?.() !== task.editor) return false;
10318
- } catch {
10319
- return false;
10320
- }
10321
- return true;
10322
- };
10323
- const runImportedTrackedChangeBootstrap = (task) => {
10324
- if (!isCurrentImportedTrackedChangeBootstrap(task)) {
10325
- if (importedTrackedChangeBootstrapTasks.get(task?.documentId) === task) importedTrackedChangeBootstrapTasks.delete(task.documentId);
10326
- return false;
10327
- }
10328
- const snapshot = captureImportedTrackedChangeBootstrapSnapshot(task.editor);
10329
- if (!snapshot || !isCurrentImportedTrackedChangeBootstrap(task)) {
10330
- if (importedTrackedChangeBootstrapTasks.get(task.documentId) === task) importedTrackedChangeBootstrapTasks.delete(task.documentId);
10331
- return false;
10332
- }
10333
- try {
10334
- return bootstrapImportedTrackedChangeComments(task.editor, task.superdoc, snapshot);
10335
- } finally {
10336
- if (importedTrackedChangeBootstrapTasks.get(task.documentId) === task) importedTrackedChangeBootstrapTasks.delete(task.documentId);
10337
- }
10338
- };
10339
- const scheduleImportedTrackedChangeBootstrap = ({ editor, superdoc, documentId, defer = true }) => {
10340
- const normalizedDocumentId = normalizeBootstrapDocumentId(documentId);
10341
- if (!normalizedDocumentId || !editor || !superdoc) return false;
10342
- cancelImportedTrackedChangeBootstrap(normalizedDocumentId);
10343
- const task = {
10344
- documentId: normalizedDocumentId,
10345
- editor,
10346
- superdoc,
10347
- generation: ++importedTrackedChangeBootstrapGeneration,
10348
- timeoutHandle: null
10349
- };
10350
- importedTrackedChangeBootstrapTasks.set(normalizedDocumentId, task);
10351
- if (!defer) return runImportedTrackedChangeBootstrap(task);
10352
- task.timeoutHandle = setTimeout(() => {
10353
- task.timeoutHandle = null;
10354
- runImportedTrackedChangeBootstrap(task);
10355
- }, 0);
10356
- return true;
10357
- };
10358
- /**
10359
10054
  * Drop imported threads and cached positions for one document id.
10360
10055
  *
10361
10056
  * Replace-file swaps call this before hydrating the replacement so stale
@@ -10372,7 +10067,6 @@ var useCommentsStore = defineStore("comments", () => {
10372
10067
  delete next[activeDocumentId];
10373
10068
  committedReviewPresentations.value = next;
10374
10069
  }
10375
- cancelImportedTrackedChangeBootstrap(activeDocumentId);
10376
10070
  const removedComments = commentsList.value.filter((comment) => belongsToDocument(comment, activeDocumentId, { allowSingleDocumentMismatch: true }));
10377
10071
  if (!removedComments.length) return;
10378
10072
  const removedAliasIds = /* @__PURE__ */ new Set();
@@ -10390,170 +10084,6 @@ var useCommentsStore = defineStore("comments", () => {
10390
10084
  const activeCommentId = activeComment.value != null ? String(activeComment.value) : null;
10391
10085
  if (activeCommentId && removedAliasIds.has(activeCommentId)) clearActiveCommentSelection();
10392
10086
  }
10393
- function resetCommentsForReplacedDocument(documentId) {
10394
- removeCommentsForDocument(documentId);
10395
- }
10396
- /**
10397
- * Initialize loaded comments into SuperDoc by mapping the imported
10398
- * comment data to SuperDoc useComment objects.
10399
- *
10400
- * Updates the commentsList ref with the new comments.
10401
- *
10402
- * @param {Object} param0
10403
- * @param {Array} param0.comments The comments to be loaded
10404
- * @param {String} param0.documentId The document ID
10405
- * @param {boolean} [param0.replacedFile] Whether this load replaces an existing document in place
10406
- * @returns {void}
10407
- */
10408
- const processLoadedDocxComments = async ({ superdoc, editor, comments, documentId, replacedFile = false }) => {
10409
- const document = superdocStore.getDocument(documentId);
10410
- if (document?.commentThreadingProfile) document.commentThreadingProfile.value = editor?.converter?.commentThreadingProfile || null;
10411
- if (replacedFile) resetCommentsForReplacedDocument(documentId);
10412
- comments.forEach((comment) => {
10413
- const textElements = Array.isArray(comment.elements) ? comment.elements : [];
10414
- const htmlContent = getHtmlFromComment(textElements);
10415
- if (!htmlContent && !comment.trackedChange) return;
10416
- const creatorName = normalizeImportedCreatorName(comment.creatorName);
10417
- const importedName = creatorName ? `${creatorName} (imported)` : null;
10418
- const newComment = useComment({
10419
- fileId: documentId,
10420
- fileType: document.type,
10421
- docxCommentJSON: textElements.length ? textElements : null,
10422
- commentId: comment.commentId,
10423
- isInternal: false,
10424
- parentCommentId: comment.parentCommentId,
10425
- trackedChangeParentId: comment.trackedChangeParentId,
10426
- trackedChangeThreadParentId: comment.trackedChangeThreadParentId,
10427
- creatorId: null,
10428
- creatorName,
10429
- createdTime: comment.createdTime,
10430
- creatorEmail: comment.creatorEmail,
10431
- importedAuthor: {
10432
- ...importedName ? { name: importedName } : {},
10433
- email: comment.creatorEmail
10434
- },
10435
- commentText: htmlContent,
10436
- resolvedTime: comment.isDone ? Date.now() : null,
10437
- resolvedById: null,
10438
- resolvedByEmail: comment.isDone ? comment.creatorEmail : null,
10439
- resolvedByName: comment.isDone ? importedName || "(Imported)" : null,
10440
- trackedChange: comment.trackedChange || false,
10441
- trackedChangeText: comment.trackedChangeText,
10442
- trackedChangeType: comment.trackedChangeType,
10443
- trackedChangeDisplayType: comment.trackedChangeDisplayType,
10444
- deletedText: comment.trackedDeletedText,
10445
- origin: comment.origin || "word",
10446
- threadingMethod: comment.threadingMethod,
10447
- threadingStyleOverride: comment.threadingStyleOverride,
10448
- threadingParentCommentId: comment.threadingParentCommentId,
10449
- originalXmlStructure: comment.originalXmlStructure
10450
- });
10451
- addHydratedComment({
10452
- superdoc,
10453
- comment: newComment
10454
- });
10455
- });
10456
- if (replacedFile) {
10457
- scheduleImportedTrackedChangeBootstrap({
10458
- editor,
10459
- superdoc,
10460
- documentId,
10461
- defer: false
10462
- });
10463
- return;
10464
- }
10465
- scheduleImportedTrackedChangeBootstrap({
10466
- editor,
10467
- superdoc,
10468
- documentId
10469
- });
10470
- };
10471
- const createCommentForTrackChanges = (editor, superdoc, trackedChangesOverride = null, options = {}) => {
10472
- const { reopenResolved = false, refreshExisting = false, broadcastChanges = true, editorState: editorStateOverride = null, editorView: editorViewOverride = null } = options;
10473
- const mountedEditor = editorStateOverride ? {
10474
- state: editorStateOverride,
10475
- view: editorViewOverride
10476
- } : readMountedEditorSnapshot(editor);
10477
- if (!mountedEditor?.state) return;
10478
- const editorState = mountedEditor.state;
10479
- const trackedChanges = trackedChangesOverride ?? trackChangesHelpers.getTrackChanges(editorState);
10480
- const groupedChanges = groupChanges(trackedChanges);
10481
- const activeDocumentId = editor?.options?.documentId != null ? String(editor.options.documentId) : null;
10482
- if (!activeDocumentId) return;
10483
- const skipIds = /* @__PURE__ */ new Set();
10484
- const existingTrackedChangeById = /* @__PURE__ */ new Map();
10485
- commentsList.value.forEach((comment) => {
10486
- if (!comment?.trackedChange) return;
10487
- if (!belongsToTrackedChangeSyncDocument(comment, activeDocumentId)) return;
10488
- if (!isBodyTrackedChangeComment(comment)) return;
10489
- const commentIds = [comment.commentId, comment.importedId].map((id) => id != null ? String(id) : null).filter(Boolean);
10490
- if (comment.resolvedTime) {
10491
- if (!reopenResolved) commentIds.forEach((id) => skipIds.add(id));
10492
- return;
10493
- }
10494
- commentIds.forEach((id) => {
10495
- existingTrackedChangeById.set(id, comment);
10496
- if (!refreshExisting) skipIds.add(id);
10497
- });
10498
- });
10499
- const changesByIdMap = /* @__PURE__ */ new Map();
10500
- for (const change of trackedChanges) {
10501
- const id = change.mark.attrs.id;
10502
- if (!changesByIdMap.has(id)) changesByIdMap.set(id, []);
10503
- changesByIdMap.get(id).push(change);
10504
- }
10505
- const documentId = activeDocumentId;
10506
- const processedIds = /* @__PURE__ */ new Set();
10507
- groupedChanges.forEach(({ insertedMark, deletionMark, formatMark }) => {
10508
- const id = insertedMark?.mark.attrs.id || deletionMark?.mark.attrs.id || formatMark?.mark.attrs.id;
10509
- if (id == null) return;
10510
- const normalizedId = String(id);
10511
- if (processedIds.has(normalizedId)) return;
10512
- processedIds.add(normalizedId);
10513
- if (!refreshExisting && skipIds.has(normalizedId)) return;
10514
- const existingTrackedChange = existingTrackedChangeById.get(normalizedId);
10515
- const marks = {
10516
- ...insertedMark && { insertedMark: insertedMark.mark },
10517
- ...deletionMark && { deletionMark: deletionMark.mark },
10518
- ...formatMark && { formatMark: formatMark.mark }
10519
- };
10520
- const params = createOrUpdateTrackedChangeComment({
10521
- event: existingTrackedChange ? "update" : "add",
10522
- marks,
10523
- nodes: [],
10524
- newEditorState: editorState,
10525
- documentId,
10526
- trackedChangesForId: changesByIdMap.get(id) || []
10527
- });
10528
- if (params) {
10529
- const anchorKey = buildBodyTrackedChangeAnchorKey(params.changeId ?? id);
10530
- params.trackedChangeStory = BODY_TRACKED_CHANGE_STORY;
10531
- params.trackedChangeStoryKind = "body";
10532
- params.trackedChangeStoryLabel = "";
10533
- params.trackedChangeAnchorKey = anchorKey;
10534
- handleTrackedChangeUpdate({
10535
- superdoc,
10536
- params,
10537
- broadcastChanges,
10538
- documentState: editorState
10539
- });
10540
- if (!existingTrackedChange) {
10541
- skipIds.add(normalizedId);
10542
- if (params.changeId != null) skipIds.add(String(params.changeId));
10543
- if (params.importedId != null) skipIds.add(String(params.importedId));
10544
- }
10545
- }
10546
- });
10547
- const editorView = mountedEditor.view;
10548
- try {
10549
- if (!editorView || editor.view !== editorView || editorView.isDestroyed === true || editorView.destroyed === true) return;
10550
- } catch {
10551
- return;
10552
- }
10553
- const { tr } = editorState;
10554
- tr.setMeta(CommentsPluginKey, { type: "force" });
10555
- editorView.dispatch(tr);
10556
- };
10557
10087
  /**
10558
10088
  * Remove inline tracked-change comments whose change id is subsumed by a
10559
10089
  * tracked whole-table change. Mirrors the deletion-event emission of
@@ -11456,286 +10986,6 @@ var useCommentsStore = defineStore("comments", () => {
11456
10986
  return rowDocumentId != null && String(rowDocumentId) === normalizedDocumentId;
11457
10987
  }).length;
11458
10988
  };
11459
- const syncTrackedChangeComments = ({ superdoc, editor, broadcastChanges = true }) => {
11460
- if (!superdoc || !editor) return;
11461
- const activeDocumentId = editor?.options?.documentId != null ? String(editor.options.documentId) : null;
11462
- if (!activeDocumentId) return;
11463
- const captured = captureImportedTrackedChangeBootstrapSnapshot(editor);
11464
- if (!captured) return;
11465
- const trackedChanges = captured.trackedChanges;
11466
- const liveTrackedChangeIds = /* @__PURE__ */ new Set();
11467
- trackedChanges.forEach((change) => {
11468
- const id = change?.mark?.attrs?.id;
11469
- if (id == null) return;
11470
- liveTrackedChangeIds.add(String(id));
11471
- });
11472
- const storySnapshots = captured.storySnapshots;
11473
- const liveTrackedChangeAnchorKeys = new Set(storySnapshots.map((snapshot) => snapshot?.anchorKey).filter((anchorKey) => typeof anchorKey === "string" && anchorKey.length > 0));
11474
- pruneStaleTrackedChangeComments(liveTrackedChangeIds, liveTrackedChangeAnchorKeys, activeDocumentId, superdoc, { broadcastChanges });
11475
- createCommentForTrackChanges(editor, superdoc, trackedChanges, {
11476
- reopenResolved: true,
11477
- refreshExisting: true,
11478
- broadcastChanges,
11479
- editorState: captured.state,
11480
- editorView: captured.view
11481
- });
11482
- syncStoryTrackedChangeComments({
11483
- superdoc,
11484
- editor,
11485
- broadcastChanges,
11486
- snapshots: storySnapshots,
11487
- documentState: captured.state
11488
- });
11489
- syncStructuralTrackedChangeComments({
11490
- superdoc,
11491
- editor,
11492
- broadcastChanges,
11493
- structuralChanges: captured.structuralChanges
11494
- });
11495
- };
11496
- /**
11497
- * Surface decidable whole-table structural tracked changes (table insert /
11498
- * table delete) as right-rail bubbles, mirroring the inline tracked-change
11499
- * path. Structural row revisions live on node attrs (not inline marks), so
11500
- * the inline `getTrackChanges` enumerator never sees them — they are
11501
- * enumerated separately here.
11502
- *
11503
- * Only `decidable` whole-table changes are surfaced; partial/mixed shapes are
11504
- * not actionable (the decision engine fails them closed) so they get no
11505
- * bubble. The bubble id is the document-api public id so accept/reject in the
11506
- * sidebar routes `trackChanges.decide` to the same change.
11507
- *
11508
- * Positioning: the bubble carries a body-story anchorKey (matching the
11509
- * tracked-change index snapshot) and a body PM range (table start/end). The
11510
- * DocumentRendererRuntime position pass emits a body-story position entry for that
11511
- * anchorKey, whose bounds resolve through the same `getRangeRects` path inline
11512
- * body comments/TC use — so it lines up with the table in layout-engine
11513
- * viewing mode.
11514
- */
11515
- const syncStructuralTrackedChangeComments = ({ superdoc, editor, broadcastChanges = true, structuralChanges: structuralChangesOverride = null }) => {
11516
- const activeDocumentId = editor?.options?.documentId != null ? String(editor.options.documentId) : null;
11517
- if (!activeDocumentId) return;
11518
- const enumerate = trackChangesHelpers?.enumerateStructuralRowChanges;
11519
- if (typeof enumerate !== "function") return;
11520
- let structuralChanges = structuralChangesOverride;
11521
- if (!Array.isArray(structuralChanges)) {
11522
- const mountedEditor = readMountedEditorSnapshot(editor);
11523
- if (!mountedEditor) return;
11524
- try {
11525
- structuralChanges = enumerate(mountedEditor.state) ?? [];
11526
- } catch {
11527
- structuralChanges = [];
11528
- }
11529
- }
11530
- for (const structural of structuralChanges) {
11531
- if (!structural?.decidable || !structural?.wholeTable) continue;
11532
- const publicId = buildStructuralTrackedChangeId(structural);
11533
- if (!publicId) continue;
11534
- const anchorKey = buildBodyTrackedChangeAnchorKey(publicId);
11535
- const displayType = structural.subtype === "table-insert" ? "tableInsert" : "tableDelete";
11536
- const trackedChangeType = structural.side === "insertion" ? "trackInsert" : "trackDelete";
11537
- const normalizedPublicId = String(publicId);
11538
- const normalizedAnchorKey = anchorKey != null ? String(anchorKey) : null;
11539
- const params = {
11540
- event: commentsList.value.find((comment) => {
11541
- if (!comment?.trackedChange) return false;
11542
- if (!belongsToTrackedChangeSyncDocument(comment, activeDocumentId)) return false;
11543
- const commentAnchorKey = comment.trackedChangeAnchorKey != null ? String(comment.trackedChangeAnchorKey) : null;
11544
- if (normalizedAnchorKey && commentAnchorKey) return commentAnchorKey === normalizedAnchorKey;
11545
- const commentId = comment.commentId != null ? String(comment.commentId) : null;
11546
- const importedId = comment.importedId != null ? String(comment.importedId) : null;
11547
- return commentId === normalizedPublicId || importedId === normalizedPublicId;
11548
- }) ? "update" : "add",
11549
- changeId: publicId,
11550
- trackedChangeText: "",
11551
- trackedChangeType,
11552
- trackedChangeDisplayType: displayType,
11553
- deletedText: null,
11554
- authorId: null,
11555
- authorEmail: structural.authorEmail || null,
11556
- authorImage: structural.authorImage || null,
11557
- date: structural.date || null,
11558
- author: structural.author || null,
11559
- importedAuthor: structural.importedAuthor ? { name: structural.importedAuthor } : null,
11560
- semanticColorKey: structural.semanticColorKey ?? null,
11561
- semanticColor: structural.semanticColor ?? null,
11562
- documentId: activeDocumentId,
11563
- coords: null,
11564
- trackedChangeStory: BODY_TRACKED_CHANGE_STORY,
11565
- trackedChangeStoryKind: "body",
11566
- trackedChangeStoryLabel: "",
11567
- trackedChangeAnchorKey: anchorKey
11568
- };
11569
- handleTrackedChangeUpdate({
11570
- superdoc,
11571
- params,
11572
- broadcastChanges
11573
- });
11574
- }
11575
- };
11576
- const syncStoryTrackedChangeComments = ({ superdoc, editor, broadcastChanges = true, snapshots = null, documentState = void 0, resolveFromEditor = true }) => {
11577
- const activeDocumentId = editor?.options?.documentId != null ? String(editor.options.documentId) : null;
11578
- if (!activeDocumentId) return;
11579
- let resolvedSnapshots = snapshots;
11580
- if (!Array.isArray(resolvedSnapshots)) {
11581
- if (typeof getTrackedChangeIndex !== "function") return;
11582
- if (!readMountedEditorSnapshot(editor)) return;
11583
- let index = null;
11584
- try {
11585
- index = getTrackedChangeIndex(editor);
11586
- } catch {
11587
- return;
11588
- }
11589
- if (!index) return;
11590
- try {
11591
- resolvedSnapshots = index.getAll();
11592
- } catch {
11593
- return;
11594
- }
11595
- }
11596
- for (const snapshot of resolvedSnapshots) {
11597
- if (snapshot.storyKind === "body") continue;
11598
- upsertStoryTrackedChangeComment({
11599
- superdoc,
11600
- editor,
11601
- snapshot,
11602
- documentId: activeDocumentId,
11603
- broadcastChanges,
11604
- documentState,
11605
- resolveFromEditor
11606
- });
11607
- }
11608
- };
11609
- const getStoryTrackedChangeDisplayType = (snapshot) => {
11610
- if (snapshot?.type !== "structural") return snapshot?.type ?? null;
11611
- return snapshot?.subtype === "table-delete" ? "tableDelete" : "tableInsert";
11612
- };
11613
- const getStoryTrackedChangeType = (snapshot) => {
11614
- if (snapshot?.type !== "structural") return snapshot?.type ?? null;
11615
- return snapshot?.subtype === "table-delete" ? "trackDelete" : "trackInsert";
11616
- };
11617
- const isStoryTrackedChangeDeletion = (snapshot) => {
11618
- if (!snapshot) return false;
11619
- if (snapshot.type === "delete") return true;
11620
- return snapshot.type === "structural" && snapshot.subtype === "table-delete";
11621
- };
11622
- const buildStoryTrackedChangeParams = ({ editor, snapshot, documentId, event, resolveFromEditor = true }) => {
11623
- const trackedChangeType = getStoryTrackedChangeType(snapshot);
11624
- const trackedChangeDisplayType = getStoryTrackedChangeDisplayType(snapshot);
11625
- const fallbackParams = {
11626
- event,
11627
- changeId: snapshot.runtimeRef.rawId,
11628
- trackedChangeText: isStoryTrackedChangeDeletion(snapshot) ? "" : snapshot.excerpt ?? "",
11629
- trackedChangeType,
11630
- trackedChangeDisplayType,
11631
- semanticColorKey: snapshot.semanticColorKey ?? null,
11632
- semanticColor: snapshot.semanticColor ?? null,
11633
- deletedText: isStoryTrackedChangeDeletion(snapshot) ? snapshot.excerpt ?? "" : null,
11634
- authorId: snapshot.authorId,
11635
- authorEmail: snapshot.authorEmail,
11636
- authorImage: snapshot.authorImage,
11637
- date: snapshot.date,
11638
- author: snapshot.author,
11639
- documentId,
11640
- coords: null,
11641
- trackedChangeStory: snapshot.story,
11642
- trackedChangeStoryKind: snapshot.storyKind,
11643
- trackedChangeStoryLabel: snapshot.storyLabel,
11644
- trackedChangeAnchorKey: snapshot.anchorKey
11645
- };
11646
- if (!resolveFromEditor || typeof resolveTrackedChangeInStory !== "function") return fallbackParams;
11647
- let resolvedChange = null;
11648
- try {
11649
- resolvedChange = resolveTrackedChangeInStory(editor, {
11650
- kind: "entity",
11651
- entityType: "trackedChange",
11652
- entityId: snapshot.runtimeRef.rawId,
11653
- story: snapshot.story
11654
- });
11655
- } catch {
11656
- resolvedChange = null;
11657
- }
11658
- const storyEditorState = resolvedChange?.editor?.state ?? null;
11659
- if (!storyEditorState) return fallbackParams;
11660
- let trackedChangesForId = [];
11661
- try {
11662
- trackedChangesForId = trackChangesHelpers.getTrackChanges(storyEditorState, resolvedChange.change.rawId) ?? [];
11663
- } catch {
11664
- trackedChangesForId = [];
11665
- }
11666
- const resolvedParams = createOrUpdateTrackedChangeComment({
11667
- event,
11668
- marks: collectTrackedChangeMarksByType(trackedChangesForId),
11669
- nodes: [],
11670
- newEditorState: storyEditorState,
11671
- documentId,
11672
- trackedChangesForId
11673
- });
11674
- if (!resolvedParams) return fallbackParams;
11675
- if (resolvedParams.semanticColorKey == null && snapshot.semanticColorKey != null) resolvedParams.semanticColorKey = snapshot.semanticColorKey;
11676
- if (resolvedParams.semanticColor == null && snapshot.semanticColor != null) resolvedParams.semanticColor = snapshot.semanticColor;
11677
- resolvedParams.trackedChangeStory = snapshot.story;
11678
- resolvedParams.trackedChangeStoryKind = snapshot.storyKind;
11679
- resolvedParams.trackedChangeStoryLabel = snapshot.storyLabel;
11680
- resolvedParams.trackedChangeAnchorKey = snapshot.anchorKey;
11681
- return resolvedParams;
11682
- };
11683
- const upsertStoryTrackedChangeComment = ({ superdoc, editor, snapshot, documentId, broadcastChanges, documentState, resolveFromEditor }) => {
11684
- if (!snapshot?.runtimeRef?.rawId) return;
11685
- const existingComment = commentsList.value.find((comment) => {
11686
- if (!comment?.trackedChange) return false;
11687
- const commentAnchorKey = comment.trackedChangeAnchorKey != null ? String(comment.trackedChangeAnchorKey) : null;
11688
- if (commentAnchorKey && snapshot.anchorKey) return commentAnchorKey === snapshot.anchorKey;
11689
- if (commentAnchorKey || snapshot.anchorKey) return false;
11690
- return comment.commentId === snapshot.runtimeRef.rawId || comment.importedId === snapshot.runtimeRef.rawId;
11691
- });
11692
- const params = buildStoryTrackedChangeParams({
11693
- editor,
11694
- snapshot,
11695
- documentId,
11696
- event: existingComment ? "update" : "add",
11697
- resolveFromEditor
11698
- });
11699
- handleTrackedChangeUpdate({
11700
- superdoc,
11701
- params,
11702
- broadcastChanges,
11703
- documentState
11704
- });
11705
- if (existingComment) {
11706
- existingComment.trackedChangeStory = snapshot.story;
11707
- existingComment.trackedChangeStoryKind = snapshot.storyKind;
11708
- existingComment.trackedChangeStoryLabel = snapshot.storyLabel;
11709
- existingComment.trackedChangeAnchorKey = snapshot.anchorKey;
11710
- }
11711
- };
11712
- const normalizeDocxSchemaForExport = (value) => {
11713
- if (!value) return [];
11714
- return (Array.isArray(value) ? value : [value]).filter(Boolean);
11715
- };
11716
- const translateCommentsForExport = () => {
11717
- const processedComments = [];
11718
- commentsList.value.forEach((comment) => {
11719
- const values = comment.getValues();
11720
- const richText = values.commentText;
11721
- const docxSchema = normalizeDocxSchemaForExport(values.docxCommentJSON);
11722
- const schema = docxSchema.length ? docxSchema : convertHtmlToSchema(richText);
11723
- processedComments.push({
11724
- ...values,
11725
- commentJSON: schema
11726
- });
11727
- });
11728
- return processedComments;
11729
- };
11730
- const convertHtmlToSchema = (commentHTML) => {
11731
- const json = new Editor({
11732
- mode: "text",
11733
- isHeadless: true,
11734
- content: commentHTML,
11735
- extensions: getRichTextExtensions()
11736
- }).getJSON();
11737
- return Array.isArray(json?.content) ? json.content.filter(Boolean) : [];
11738
- };
11739
10989
  /**
11740
10990
  * Triggered when the editor locations are updated
11741
10991
  * Updates floating comment locations from the editor
@@ -11986,75 +11236,6 @@ var useCommentsStore = defineStore("comments", () => {
11986
11236
  if (typeof commentsVisible === "boolean") viewingVisibility.commentsVisible = commentsVisible;
11987
11237
  if (typeof trackChangesVisible === "boolean") viewingVisibility.trackChangesVisible = trackChangesVisible;
11988
11238
  };
11989
- /**
11990
- * Get HTML content from the comment text JSON (which uses DOCX schema)
11991
- *
11992
- * @param {Object} commentTextJson The comment text JSON
11993
- * @returns {string} The HTML content
11994
- */
11995
- const normalizeCommentForEditor = (node) => {
11996
- if (Array.isArray(node)) return node.map((child) => normalizeCommentForEditor(child)).flat().filter(Boolean);
11997
- if (!node || typeof node !== "object") return node;
11998
- const stripTextStyleAttrs = (attrs) => {
11999
- if (!attrs) return attrs;
12000
- const rest = { ...attrs };
12001
- delete rest.fontSize;
12002
- delete rest.fontFamily;
12003
- delete rest.eastAsiaFontFamily;
12004
- return Object.keys(rest).length ? rest : void 0;
12005
- };
12006
- const normalizeMark = (mark) => {
12007
- if (!mark) return mark;
12008
- const typeName = typeof mark.type === "string" ? mark.type : mark.type?.name;
12009
- const attrs = mark?.attrs ? { ...mark.attrs } : void 0;
12010
- if (typeName === "textStyle" && attrs) return {
12011
- ...mark,
12012
- attrs: stripTextStyleAttrs(attrs)
12013
- };
12014
- return {
12015
- ...mark,
12016
- attrs
12017
- };
12018
- };
12019
- const cloneMarks = (marks) => Array.isArray(marks) ? marks.filter(Boolean).map((mark) => normalizeMark(mark)) : void 0;
12020
- const cloneAttrs = (attrs) => attrs && typeof attrs === "object" ? { ...attrs } : void 0;
12021
- if (!Array.isArray(node.content)) return {
12022
- type: node.type,
12023
- ...node.text !== void 0 ? { text: node.text } : {},
12024
- ...node.attrs ? { attrs: cloneAttrs(node.attrs) } : {},
12025
- ...node.marks ? { marks: cloneMarks(node.marks) } : {}
12026
- };
12027
- const normalizedChildren = node.content.map((child) => normalizeCommentForEditor(child)).flat().filter(Boolean);
12028
- if (node.type === "run") return normalizedChildren;
12029
- return {
12030
- type: node.type,
12031
- ...node.attrs ? { attrs: cloneAttrs(node.attrs) } : {},
12032
- ...node.marks ? { marks: cloneMarks(node.marks) } : {},
12033
- content: normalizedChildren
12034
- };
12035
- };
12036
- const getHtmlFromComment = (commentTextElements) => {
12037
- const elementsArray = Array.isArray(commentTextElements) ? commentTextElements : commentTextElements ? [commentTextElements] : [];
12038
- if (!elementsArray.some((element) => element?.content?.length)) return;
12039
- try {
12040
- const normalizedContent = normalizeCommentForEditor(elementsArray);
12041
- const contentArray = Array.isArray(normalizedContent) ? normalizedContent : normalizedContent ? [normalizedContent] : [];
12042
- if (!contentArray.length) return null;
12043
- return new Editor({
12044
- mode: "text",
12045
- isHeadless: true,
12046
- content: {
12047
- type: "doc",
12048
- content: contentArray
12049
- },
12050
- loadFromSchema: true,
12051
- extensions: getRichTextExtensions()
12052
- }).getHTML();
12053
- } catch (error) {
12054
- console.warn("Failed to convert comment", error);
12055
- return;
12056
- }
12057
- };
12058
11239
  return {
12059
11240
  COMMENT_EVENTS,
12060
11241
  isDebugging,
@@ -12123,23 +11304,18 @@ var useCommentsStore = defineStore("comments", () => {
12123
11304
  cancelComment,
12124
11305
  deleteComment,
12125
11306
  removePendingComment,
12126
- cancelImportedTrackedChangeBootstrap,
12127
11307
  removeCommentsForDocument,
12128
11308
  setReviewDirectoryFromV2,
12129
11309
  clearReviewDirectory,
12130
- processLoadedDocxComments,
12131
- translateCommentsForExport,
12132
11310
  handleEditorLocationsUpdate,
12133
11311
  clearEditorCommentPositions,
12134
11312
  handleTrackedChangeUpdate,
12135
- refreshTrackedChangeCommentsByIds,
12136
11313
  syncResolvedCommentsWithDocument,
12137
11314
  syncTrackedChangePositionsWithDocument,
12138
11315
  setActiveFloatingCommentInstance,
12139
11316
  requestInstantSidebarAlignment,
12140
11317
  peekInstantSidebarAlignment,
12141
11318
  clearInstantSidebarAlignment,
12142
- syncTrackedChangeComments,
12143
11319
  decideTrackedChangeFromSidebar,
12144
11320
  v2CommentsAdapter,
12145
11321
  setV2CommentsAdapter,
@@ -21229,8 +20405,11 @@ function translateRenderReadinessDiagnostic(diag, ctx = {}) {
21229
20405
  else if (severity === "error") diagnosticCode = "RENDER_ERROR";
21230
20406
  else return null;
21231
20407
  const message = reason || code;
20408
+ const error = new Error(typeof diag.error?.message === "string" ? diag.error.message : message);
20409
+ if (typeof diag.error?.name === "string") error.name = diag.error.name;
20410
+ if (typeof diag.error?.stack === "string") error.stack = diag.error.stack;
21232
20411
  return {
21233
- error: new Error(message),
20412
+ error,
21234
20413
  diagnosticCode,
21235
20414
  diagnosticStage: unusableFurniture ? "parse" : "render",
21236
20415
  severity,
@@ -22115,7 +21294,7 @@ var SuperDoc_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
22115
21294
  }
22116
21295
  });
22117
21296
  const { getConfig, documentsWithConverations, commentsList, pendingComment, activeComment, skipSelectionUpdate, commentsByDocument, isCommentsListVisible, isFloatingCommentsReady, generalCommentIds, hasSyncedCollaborationComments, editorCommentPositions, hasInitializedLocations, isCommentHighlighted, hasOpenTrackedChanges } = storeToRefs(commentsStore);
22118
- const { showAddComment, handleEditorLocationsUpdate, handleTrackedChangeUpdate, refreshTrackedChangeCommentsByIds, syncTrackedChangePositionsWithDocument, syncTrackedChangeComments, addComment, addHydratedComment, getComment, resolveCommentPositionEntry, belongsToDocument, COMMENT_EVENTS, requestInstantSidebarAlignment, peekInstantSidebarAlignment, clearInstantSidebarAlignment } = commentsStore;
21297
+ const { showAddComment, handleEditorLocationsUpdate, handleTrackedChangeUpdate, syncTrackedChangePositionsWithDocument, addComment, addHydratedComment, getComment, resolveCommentPositionEntry, belongsToDocument, COMMENT_EVENTS, requestInstantSidebarAlignment, peekInstantSidebarAlignment, clearInstantSidebarAlignment } = commentsStore;
22119
21298
  const { proxy } = getCurrentInstance();
22120
21299
  commentsStore.proxy = proxy;
22121
21300
  const documentOpenTelemetry = createDocumentOpenTelemetry(proxy.$superdoc.config);
@@ -22167,7 +21346,6 @@ var SuperDoc_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
22167
21346
  const layers = ref(null);
22168
21347
  const rightSidebarRef = ref(null);
22169
21348
  const pdfViewerRef = ref(null);
22170
- const pendingReplayTrackedChangeSync = ref(false);
22171
21349
  const toolsMenuPosition = reactive({
22172
21350
  top: null,
22173
21351
  right: "-25px",
@@ -22230,20 +21408,6 @@ var SuperDoc_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
22230
21408
  }
22231
21409
  });
22232
21410
  const pdfConfig = proxy.$superdoc.config.modules?.pdf || {};
22233
- const flushPendingReplayTrackedChangeSync = () => {
22234
- if (!pendingReplayTrackedChangeSync.value) return;
22235
- pendingReplayTrackedChangeSync.value = false;
22236
- syncTrackedChangeComments({
22237
- superdoc: proxy.$superdoc,
22238
- editor: proxy.$superdoc?.activeEditor
22239
- });
22240
- };
22241
- const scheduleReplayTrackedChangeSync = () => {
22242
- pendingReplayTrackedChangeSync.value = true;
22243
- nextTick(() => {
22244
- flushPendingReplayTrackedChangeSync();
22245
- });
22246
- };
22247
21411
  const handleDocumentReady = (documentId, container) => {
22248
21412
  const doc = getDocument(documentId);
22249
21413
  if (!doc || doc.loadScope && !doc.loadScope.finish()) return;
@@ -23243,7 +22407,6 @@ var SuperDoc_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
23243
22407
  v2PageMetricsSnapshot.value = null;
23244
22408
  const clearedDocumentId = payload?.documentId == null ? null : String(payload.documentId);
23245
22409
  clearV2MutationRejectionNotifications(clearedDocumentId);
23246
- commentsStore.cancelImportedTrackedChangeBootstrap?.(clearedDocumentId ?? void 0);
23247
22410
  if (clearedDocumentId) v2MountStagesByDocumentId.delete(clearedDocumentId);
23248
22411
  if (latestV2MountStage && (clearedDocumentId == null || latestV2MountStage.dataset?.superdocV2DocumentId === clearedDocumentId)) latestV2MountStage = null;
23249
22412
  v2ReviewWindowController.reset("render-cleared");
@@ -23259,7 +22422,7 @@ var SuperDoc_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
23259
22422
  ...event,
23260
22423
  documentId: document?.id ?? null
23261
22424
  }));
23262
- if (event.type === "mutation:committed" && event.origin === "extension") return;
22425
+ if (event.type === "mutation:committed" && event.dryRun) return;
23263
22426
  const documentId = document?.id ?? null;
23264
22427
  if (event.type === "history:changed" && event.state) {
23265
22428
  proxy.$superdoc.emit("history-change", {
@@ -23423,6 +22586,7 @@ var SuperDoc_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
23423
22586
  case "collaboration-room-corrupt": return "SuperDoc v2 found a structurally invalid collaboration room. No changes were made.";
23424
22587
  case "collaboration-v2-room-missing": return "SuperDoc v2 could not find a committed v2 collaboration room. No changes were made. Use roomMode: \"create\" only when creating a new room.";
23425
22588
  case "collaboration-v2-room-already-exists": return "SuperDoc v2 was asked to create a collaboration room that already exists. Use roomMode: \"join\" to open it.";
22589
+ case "collaboration-session-invalidated": return "This collaboration session is no longer current. Please reopen the shared document with roomMode: \"join\".";
23426
22590
  case "collaboration-v2-room-initializing": return "The SuperDoc v2 collaboration room has not completed initialization. This open attempt did not modify it.";
23427
22591
  case "collaboration-v2-room-bootstrap-stalled": return "The SuperDoc v2 collaboration room bootstrap appears stalled. This open attempt did not modify it. Preserve the room data if a create retry cannot recover it.";
23428
22592
  case "collaboration-open-intent-invalid": return "SuperDoc v2 received an invalid collaboration room mode. No provider was connected.";
@@ -23433,10 +22597,17 @@ var SuperDoc_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
23433
22597
  const normalizeV2EditorFailureDetail = (detail) => typeof detail === "string" && detail.trim().length > 0 ? detail.trim() : null;
23434
22598
  const onV2EditorFailed = (payload) => {
23435
22599
  documents.value.find((doc) => doc.id === payload?.documentId)?.loadScope?.finish();
23436
- clearActiveV2EditorFacade(payload?.documentId ?? null);
23437
22600
  const reason = typeof payload?.reason === "string" && payload.reason.length > 0 ? payload.reason : "open-failed";
23438
22601
  const detail = normalizeV2EditorFailureDetail(payload?.detail);
23439
22602
  const documentId = typeof payload?.documentId === "string" && payload.documentId.length > 0 ? payload.documentId : null;
22603
+ const retiredDocument = reason === "collaboration-session-invalidated" && documentId ? getDocument(documentId) : null;
22604
+ const retiredExporter = retiredDocument?.getEditor?.();
22605
+ clearActiveV2EditorFacade(payload?.documentId ?? null);
22606
+ if (retiredExporter?.editorVersion === 2 && typeof retiredExporter.exportDocx === "function") {
22607
+ retiredDocument.isReady = false;
22608
+ if (v2Runtimes.has(documentId)) clearV2RuntimeRegistration(documentId);
22609
+ retiredDocument.setEditor?.(retiredExporter);
22610
+ }
23440
22611
  if (reason === "worker-transport-failed") {
23441
22612
  proxy.$superdoc.emit("exception", {
23442
22613
  error: /* @__PURE__ */ new Error("Worker transport failed."),
@@ -23463,7 +22634,7 @@ var SuperDoc_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
23463
22634
  ...workerFailure ? { workerFailure } : {},
23464
22635
  reason
23465
22636
  };
23466
- if (reason === "collaboration-v1-config-unsupported" || reason === "collaboration-room-format-unsupported" || reason === "collaboration-room-format-conflict" || reason === "collaboration-room-corrupt" || reason === "collaboration-v2-room-missing" || reason === "collaboration-v2-room-already-exists" || reason === "collaboration-v2-room-initializing" || reason === "collaboration-v2-room-bootstrap-stalled" || reason === "collaboration-open-intent-invalid" || reason === "collaboration-config-invalid") console.warn(`[SuperDoc] ${message}`, logContext);
22637
+ if (reason === "collaboration-v1-config-unsupported" || reason === "collaboration-room-format-unsupported" || reason === "collaboration-room-format-conflict" || reason === "collaboration-room-corrupt" || reason === "collaboration-v2-room-missing" || reason === "collaboration-v2-room-already-exists" || reason === "collaboration-session-invalidated" || reason === "collaboration-v2-room-initializing" || reason === "collaboration-v2-room-bootstrap-stalled" || reason === "collaboration-open-intent-invalid" || reason === "collaboration-config-invalid") console.warn(`[SuperDoc] ${message}`, logContext);
23467
22638
  else console.error(`[SuperDoc] ${message}`, logContext);
23468
22639
  proxy.$superdoc.emit("exception", collaborationException && reason !== "collaboration-config-invalid" ? collaborationException : {
23469
22640
  error: new Error(message),
@@ -23769,7 +22940,6 @@ var SuperDoc_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
23769
22940
  existingComment: null
23770
22941
  };
23771
22942
  };
23772
- if (type === "replayCompleted") scheduleReplayTrackedChangeSync();
23773
22943
  if (COMMENT_EVENTS?.ADD && type === COMMENT_EVENTS.ADD && commentPayload) {
23774
22944
  commentPayload = normalizeReplayCommentModelPayload(commentPayload);
23775
22945
  const currentUser = proxy.$superdoc?.user;
@@ -24078,7 +23248,6 @@ var SuperDoc_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
24078
23248
  handleFormattingMarksShortcut(e);
24079
23249
  }
24080
23250
  onBeforeUnmount(() => {
24081
- commentsStore.cancelImportedTrackedChangeBootstrap?.();
24082
23251
  passwordPrompt.destroy();
24083
23252
  findReplace.destroy();
24084
23253
  linkPopover.destroy();
@@ -24694,7 +23863,7 @@ var SuperDoc_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
24694
23863
  ], 46, _hoisted_1$17);
24695
23864
  };
24696
23865
  }
24697
- }, [["__scopeId", "data-v-f2db957f"]]);
23866
+ }, [["__scopeId", "data-v-f7cc9a3c"]]);
24698
23867
  //#endregion
24699
23868
  //#region src/core/create-app.js
24700
23869
  var PINIA_DEVTOOLS_SETUP_EVENT = "devtools-plugin:setup";
@@ -46394,7 +45563,7 @@ var SuperDoc = class extends import_eventemitter3.default {
46394
45563
  }
46395
45564
  this.userColorMap = /* @__PURE__ */ new Map();
46396
45565
  this.colorIndex = 0;
46397
- this.version = "2.28.0-next.11";
45566
+ this.version = "2.28.0-next.13";
46398
45567
  this.#log("🦋 [superdoc] Using SuperDoc version:", this.version);
46399
45568
  this.superdocId = config.superdocId || v4();
46400
45569
  this.colors = this.config.colors ?? [];
@@ -47101,7 +46270,8 @@ var SuperDoc = class extends import_eventemitter3.default {
47101
46270
  roomMode: target.roomMode,
47102
46271
  ...syncTimeoutOption,
47103
46272
  ...target.publicApiKey ? { publicApiKey: target.publicApiKey } : {},
47104
- ...target.authEndpoint ? { authEndpoint: target.authEndpoint } : {}
46273
+ ...target.authEndpoint ? { authEndpoint: target.authEndpoint } : {},
46274
+ ...target.baseUrl ? { baseUrl: target.baseUrl } : {}
47105
46275
  };
47106
46276
  if (target.providerFamily === "hocuspocus") return {
47107
46277
  providerType: "hocuspocus",
@@ -48417,23 +47587,6 @@ var SuperDoc = class extends import_eventemitter3.default {
48417
47587
  confirmed
48418
47588
  };
48419
47589
  }
48420
- const legacyReplaceFile = activeEditor && !isV2ActiveEditorFacade(activeEditor) ? activeEditor.replaceFile : null;
48421
- if (typeof legacyReplaceFile === "function") {
48422
- const result = await legacyReplaceFile.call(activeEditor, source);
48423
- const legacyState = result && typeof result === "object" ? result.state : void 0;
48424
- const legacyConfirmed = legacyState === void 0 || legacyState === null || legacyState === "review-ready" || legacyState === "editing-ready";
48425
- if (legacyConfirmed) {
48426
- this.#replaceActiveDocumentData(activeEditor, source);
48427
- this.emit("document-replaced", {
48428
- editor: activeEditor,
48429
- host: activeEditor?.host
48430
- });
48431
- }
48432
- return {
48433
- raw: result,
48434
- confirmed: legacyConfirmed
48435
- };
48436
- }
48437
47590
  throw new Error("SuperDoc: replaceFile is unavailable for the active editor");
48438
47591
  }
48439
47592
  /**
@@ -48446,19 +47599,6 @@ var SuperDoc = class extends import_eventemitter3.default {
48446
47599
  commentsType,
48447
47600
  isFinalDoc
48448
47601
  });
48449
- const uiStoreHydrated = this.config?.modules?.comments !== false;
48450
- let legacyComments;
48451
- let legacyCommentsComputed = false;
48452
- const getLegacyCommentsForV1 = () => {
48453
- if (legacyCommentsComputed) return legacyComments;
48454
- legacyCommentsComputed = true;
48455
- if (commentsType === "clean") legacyComments = [];
48456
- else if (uiStoreHydrated && this.commentsStore && typeof this.commentsStore.translateCommentsForExport === "function") {
48457
- legacyComments = this.commentsStore.translateCommentsForExport();
48458
- if (!Array.isArray(legacyComments)) legacyComments = [];
48459
- }
48460
- return legacyComments;
48461
- };
48462
47602
  const bridgedExportErrors = /* @__PURE__ */ new WeakSet();
48463
47603
  const rememberBridgedExportError = (payload) => {
48464
47604
  if ("editor" in payload && payload.error && typeof payload.error === "object") bridgedExportErrors.add(payload.error);
@@ -48469,7 +47609,7 @@ var SuperDoc = class extends import_eventemitter3.default {
48469
47609
  if (policies !== void 0 && documents.some((doc) => {
48470
47610
  if (doc.type !== "application/vnd.openxmlformats-officedocument.wordprocessingml.document") return false;
48471
47611
  const editor = doc.getEditor?.();
48472
- return editor?.editorVersion !== 2 || typeof editor.exportDocx !== "function";
47612
+ return !isV2ActiveEditorFacade(editor) || typeof editor.exportDocx !== "function";
48473
47613
  })) throw new Error("Independent DOCX export policies require a mounted V2 exporter for every document.");
48474
47614
  const docxPromises = documents.map(async (doc) => {
48475
47615
  if (!doc || doc.type !== "application/vnd.openxmlformats-officedocument.wordprocessingml.document") return null;
@@ -48482,19 +47622,13 @@ var SuperDoc = class extends import_eventemitter3.default {
48482
47622
  if (isDocumentByteSource(doc.data)) return this.#savedDocxToBlob(doc.data);
48483
47623
  return null;
48484
47624
  };
48485
- if (!editor || typeof editor.exportDocx !== "function") return fallbackDocx();
48486
- const isV2Editor = editor.editorVersion === 2;
47625
+ if (!isV2ActiveEditorFacade(editor) || typeof editor.exportDocx !== "function") return fallbackDocx();
48487
47626
  try {
48488
- const exported = await editor.exportDocx(isV2Editor ? {
47627
+ const exported = await editor.exportDocx({
48489
47628
  isFinalDoc,
48490
47629
  commentsType,
48491
47630
  policies,
48492
47631
  fieldsHighlightColor
48493
- } : {
48494
- isFinalDoc,
48495
- comments: getLegacyCommentsForV1(),
48496
- commentsType,
48497
- fieldsHighlightColor
48498
47632
  });
48499
47633
  if (exported) return exported;
48500
47634
  } catch (error) {
@@ -48508,7 +47642,7 @@ var SuperDoc = class extends import_eventemitter3.default {
48508
47642
  editor: null
48509
47643
  }));
48510
47644
  }
48511
- if (isV2Editor) throw error;
47645
+ throw error;
48512
47646
  }
48513
47647
  return fallbackDocx();
48514
47648
  });