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.
package/dist/superdoc.cjs CHANGED
@@ -260,7 +260,7 @@ var v_click_outside_default = {
260
260
  var DEFAULT_ENDPOINT = "https://ingest.superdoc.dev/v1/collect";
261
261
  function getSuperdocVersion() {
262
262
  try {
263
- return "2.28.0-next.11";
263
+ return "2.28.0-next.13";
264
264
  } catch {
265
265
  return "unknown";
266
266
  }
@@ -5529,13 +5529,22 @@ function resolveLiveblocksFamily(candidate, authEndpointBaseUrl) {
5529
5529
  reason: "mixed-auth",
5530
5530
  message: "SuperDoc v2 Liveblocks collaboration accepts exactly one auth mode; pass either publicApiKey or authEndpoint, not both."
5531
5531
  };
5532
+ const baseUrlRaw = candidate.baseUrl;
5533
+ const baseUrl = baseUrlRaw === void 0 ? void 0 : normalizeHttpUrl(baseUrlRaw);
5534
+ if (baseUrl === null) return {
5535
+ ok: false,
5536
+ reason: "invalid-base-url",
5537
+ message: "SuperDoc v2 Liveblocks collaboration requires baseUrl to be an absolute http(s) URL."
5538
+ };
5539
+ const baseUrlOption = baseUrl ? { baseUrl } : {};
5532
5540
  if (publicApiKey) return {
5533
5541
  ok: true,
5534
5542
  target: {
5535
5543
  providerFamily: "liveblocks",
5536
5544
  documentId,
5537
5545
  roomMode,
5538
- publicApiKey
5546
+ publicApiKey,
5547
+ ...baseUrlOption
5539
5548
  }
5540
5549
  };
5541
5550
  const authEndpoint = normalizeHttpUrl(authEndpointRaw, authEndpointBaseUrl);
@@ -5550,7 +5559,8 @@ function resolveLiveblocksFamily(candidate, authEndpointBaseUrl) {
5550
5559
  providerFamily: "liveblocks",
5551
5560
  documentId,
5552
5561
  roomMode,
5553
- authEndpoint
5562
+ authEndpoint,
5563
+ ...baseUrlOption
5554
5564
  }
5555
5565
  };
5556
5566
  }
@@ -6833,87 +6843,6 @@ var useSuperdocStore = defineStore("superdoc", () => {
6833
6843
  };
6834
6844
  });
6835
6845
  //#endregion
6836
- //#region src/helpers/group-changes.js
6837
- /**
6838
- * Track changes helper
6839
- * Combines replace transactions which are represented by insertion + deletion
6840
- *
6841
- * @param {Array} changes - Array of tracked changes from the editor
6842
- * @returns {Array} Grouped track changes array with combined replacements
6843
- */
6844
- var groupChanges = (changes) => {
6845
- const markMetaKeys = {
6846
- trackInsert: "insertedMark",
6847
- trackDelete: "deletionMark",
6848
- trackFormat: "formatMark"
6849
- };
6850
- const byId = /* @__PURE__ */ new Map();
6851
- for (const change of changes) {
6852
- const id = change.mark.attrs.id;
6853
- if (!byId.has(id)) byId.set(id, []);
6854
- byId.get(id).push(change);
6855
- }
6856
- const grouped = [];
6857
- for (const [, group] of byId) {
6858
- if (group.length === 1) {
6859
- const c = group[0];
6860
- const key = markMetaKeys[c.mark.type.name];
6861
- grouped.push({
6862
- from: c.from,
6863
- to: c.to,
6864
- [key]: c
6865
- });
6866
- continue;
6867
- }
6868
- const processed = /* @__PURE__ */ new Set();
6869
- for (let i = 0; i < group.length; i++) {
6870
- if (processed.has(i)) continue;
6871
- const c1 = group[i];
6872
- const c1Key = markMetaKeys[c1.mark.type.name];
6873
- const c2 = group[i + 1];
6874
- if (c2 && !processed.has(i + 1) && c1.to === c2.from && c1.mark.type.name !== c2.mark.type.name) {
6875
- const c2Key = markMetaKeys[c2.mark.type.name];
6876
- grouped.push({
6877
- from: c1.from,
6878
- to: c2.to,
6879
- [c1Key]: c1,
6880
- [c2Key]: c2
6881
- });
6882
- processed.add(i);
6883
- processed.add(i + 1);
6884
- continue;
6885
- }
6886
- let foundMatch = false;
6887
- for (let j = i + 1; j < group.length; j++) {
6888
- if (processed.has(j)) continue;
6889
- const cj = group[j];
6890
- if (c1.mark.type.name !== cj.mark.type.name) {
6891
- const cjKey = markMetaKeys[cj.mark.type.name];
6892
- grouped.push({
6893
- from: Math.min(c1.from, cj.from),
6894
- to: Math.max(c1.to, cj.to),
6895
- [c1Key]: c1,
6896
- [cjKey]: cj
6897
- });
6898
- processed.add(i);
6899
- processed.add(j);
6900
- foundMatch = true;
6901
- break;
6902
- }
6903
- }
6904
- if (!foundMatch) {
6905
- grouped.push({
6906
- from: c1.from,
6907
- to: c1.to,
6908
- [c1Key]: c1
6909
- });
6910
- processed.add(i);
6911
- }
6912
- }
6913
- }
6914
- return grouped;
6915
- };
6916
- //#endregion
6917
6846
  //#region src/stores/helpers/floating-comment-instances.js
6918
6847
  var HEADER_FOOTER_TRACKED_CHANGE_STORY_TYPE = "headerFooterPart";
6919
6848
  var toFinitePageIndex = (value) => {
@@ -7474,20 +7403,11 @@ var buildTrackedChangeDecisionLinkIndex = (allComments, previous = /* @__PURE__
7474
7403
  };
7475
7404
  //#endregion
7476
7405
  //#region src/stores/comments-store.js
7477
- var Editor = class {
7478
- constructor() {
7479
- throw new Error("SuperDoc v2 beta: v1 editor-backed comment import paths are not available.");
7480
- }
7481
- };
7482
7406
  var trackChangesHelpers = {
7483
7407
  getTrackChanges: () => [],
7484
7408
  enumerateStructuralRowChanges: () => []
7485
7409
  };
7486
- var CommentsPluginKey = Symbol("comments-plugin-disabled");
7487
- var getRichTextExtensions = () => [];
7488
- var createOrUpdateTrackedChangeComment = () => null;
7489
7410
  var getTrackedChangeIndex = () => null;
7490
- var resolveTrackedChangeInStory = () => null;
7491
7411
  var makeTrackedChangeAnchorKey = ({ storyKey, rawId }) => `tc::${storyKey}::${rawId}`;
7492
7412
  var COMMENT_DRAFT_BR_TAG = /<br(?:\s[^>]*)?\s*\/?>/gi;
7493
7413
  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;
@@ -7632,25 +7552,6 @@ var useCommentsStore = defineStore("comments", () => {
7632
7552
  rawId: String(rawId)
7633
7553
  });
7634
7554
  };
7635
- /**
7636
- * Compute the stable public id for a structural (whole-table) tracked change.
7637
- *
7638
- * This MUST match the public id the document-api projects for the same change
7639
- * (`tracked-change-resolver.groupTrackedChanges`), otherwise the right-rail
7640
- * accept/reject would route `trackChanges.decide` to a change that does not
7641
- * exist. The doc-api derives the public id as `word:structural:<sourceId>`
7642
- * for imported Word revisions, falling back to the per-import logical id.
7643
- * Reuse the exact rule here so the bubble id is the decide id.
7644
- *
7645
- * @param {{ sourceId?: string, id?: string }} structural
7646
- * @returns {string | null}
7647
- */
7648
- const buildStructuralTrackedChangeId = (structural) => {
7649
- if (!structural) return null;
7650
- const sourceId = structural.sourceId ? String(structural.sourceId) : "";
7651
- if (sourceId) return `word:structural:${sourceId}`;
7652
- return structural.id ? String(structural.id) : null;
7653
- };
7654
7555
  const superdocStore = useSuperdocStore();
7655
7556
  const commentsConfig = require__plugin_vue_export_helper.reactive({
7656
7557
  name: "comments",
@@ -7682,8 +7583,6 @@ var useCommentsStore = defineStore("comments", () => {
7682
7583
  const isDebugging = false;
7683
7584
  const debounceTimers = {};
7684
7585
  const trackedChangeResolutionSnapshots = /* @__PURE__ */ new WeakMap();
7685
- const importedTrackedChangeBootstrapTasks = /* @__PURE__ */ new Map();
7686
- let importedTrackedChangeBootstrapGeneration = 0;
7687
7586
  const isBenchmarkCommentsDebugEnabled = () => {
7688
7587
  if (typeof window === "undefined") return false;
7689
7588
  return "__labsSuperDocV2BenchmarkDebug" in window;
@@ -8545,38 +8444,6 @@ var useCommentsStore = defineStore("comments", () => {
8545
8444
  endInteractionSpan(span);
8546
8445
  }
8547
8446
  };
8548
- const collectTrackedChangeMarksByType = (trackedChanges = []) => ({
8549
- insertedMark: trackedChanges.find(({ mark }) => mark?.type?.name === "trackInsert")?.mark ?? null,
8550
- deletionMark: trackedChanges.find(({ mark }) => mark?.type?.name === "trackDelete")?.mark ?? null,
8551
- formatMark: trackedChanges.find(({ mark }) => mark?.type?.name === "trackFormat")?.mark ?? null
8552
- });
8553
- const refreshTrackedChangeCommentsByIds = ({ superdoc, editor, changeIds, broadcastChanges = true }) => {
8554
- if (!superdoc || !editor?.state || !Array.isArray(changeIds) || !changeIds.length) return;
8555
- const documentId = editor?.options?.documentId != null ? String(editor.options.documentId) : null;
8556
- if (!documentId) return;
8557
- for (const changeId of new Set(changeIds.map((id) => id != null ? String(id) : null).filter(Boolean))) {
8558
- const trackedChangesForId = trackChangesHelpers.getTrackChanges(editor.state, changeId);
8559
- if (!trackedChangesForId.length) continue;
8560
- const params = createOrUpdateTrackedChangeComment({
8561
- event: "update",
8562
- marks: collectTrackedChangeMarksByType(trackedChangesForId),
8563
- nodes: [],
8564
- newEditorState: editor.state,
8565
- documentId,
8566
- trackedChangesForId
8567
- });
8568
- if (!params) continue;
8569
- params.trackedChangeStory = BODY_TRACKED_CHANGE_STORY;
8570
- params.trackedChangeStoryKind = "body";
8571
- params.trackedChangeStoryLabel = "";
8572
- params.trackedChangeAnchorKey = buildBodyTrackedChangeAnchorKey(params.changeId ?? changeId);
8573
- handleTrackedChangeUpdate({
8574
- superdoc,
8575
- params,
8576
- broadcastChanges
8577
- });
8578
- }
8579
- };
8580
8447
  const requestInstantSidebarAlignment = (targetY = null, threadId = null, instanceId = null) => {
8581
8448
  const hasTargetY = Number.isFinite(targetY);
8582
8449
  instantSidebarAlignmentTargetY.value = hasTargetY ? targetY : null;
@@ -10186,178 +10053,6 @@ var useCommentsStore = defineStore("comments", () => {
10186
10053
  removePendingComment(superdoc);
10187
10054
  };
10188
10055
  /**
10189
- * Imported DOCX comments can omit the normalized author string.
10190
- * Strip the exporter suffix when present and tolerate missing metadata.
10191
- *
10192
- * @param {string | null | undefined} creatorName
10193
- * @returns {string | null}
10194
- */
10195
- const normalizeImportedCreatorName = (creatorName) => {
10196
- if (typeof creatorName !== "string") return null;
10197
- return creatorName.replace(/\s*\(imported\)\s*$/u, "").trim() || null;
10198
- };
10199
- /**
10200
- * Read the mounted editor view and state without touching `editor.state`.
10201
- * The editor convenience getter delegates to `view.state` and throws after
10202
- * teardown, which is precisely when a deferred import callback can run.
10203
- *
10204
- * @param {Object | null | undefined} editor
10205
- * @returns {{ view: Object, state: Object } | null}
10206
- */
10207
- const readMountedEditorSnapshot = (editor) => {
10208
- if (!editor) return null;
10209
- try {
10210
- if (editor.isDestroyed === true) return null;
10211
- const view = editor.view;
10212
- if (!view || view.isDestroyed === true || view.destroyed === true) return null;
10213
- const state = view.state;
10214
- if (!state) return null;
10215
- return {
10216
- view,
10217
- state
10218
- };
10219
- } catch {
10220
- return null;
10221
- }
10222
- };
10223
- const normalizeBootstrapDocumentId = (documentId) => documentId !== void 0 && documentId !== null && String(documentId).length > 0 ? String(documentId) : null;
10224
- /**
10225
- * Cancel deferred imported tracked-change comment work. Passing a document
10226
- * id cancels only that document; omitting it cancels every pending task.
10227
- *
10228
- * @param {string | null | undefined} documentId
10229
- * @returns {number} number of invalidated tasks
10230
- */
10231
- const cancelImportedTrackedChangeBootstrap = (documentId) => {
10232
- const normalizedDocumentId = normalizeBootstrapDocumentId(documentId);
10233
- const entries = normalizedDocumentId ? [[normalizedDocumentId, importedTrackedChangeBootstrapTasks.get(normalizedDocumentId)]] : Array.from(importedTrackedChangeBootstrapTasks.entries());
10234
- let canceled = 0;
10235
- for (const [taskDocumentId, task] of entries) {
10236
- if (!task) continue;
10237
- importedTrackedChangeBootstrapTasks.delete(taskDocumentId);
10238
- if (task.timeoutHandle !== null && task.timeoutHandle !== void 0) clearTimeout(task.timeoutHandle);
10239
- canceled += 1;
10240
- }
10241
- return canceled;
10242
- };
10243
- const captureImportedTrackedChangeBootstrapSnapshot = (editor) => {
10244
- const mountedEditor = readMountedEditorSnapshot(editor);
10245
- if (!mountedEditor) return null;
10246
- let trackedChanges = [];
10247
- try {
10248
- trackedChanges = trackChangesHelpers.getTrackChanges(mountedEditor.state) ?? [];
10249
- } catch {
10250
- return null;
10251
- }
10252
- const enumerateStructuralChanges = trackChangesHelpers?.enumerateStructuralRowChanges;
10253
- let structuralChanges = [];
10254
- if (typeof enumerateStructuralChanges === "function") try {
10255
- structuralChanges = enumerateStructuralChanges(mountedEditor.state) ?? [];
10256
- } catch {
10257
- structuralChanges = [];
10258
- }
10259
- let storySnapshots = [];
10260
- if (typeof getTrackedChangeIndex === "function") try {
10261
- storySnapshots = getTrackedChangeIndex(editor)?.getAll?.() ?? [];
10262
- } catch {
10263
- storySnapshots = [];
10264
- }
10265
- return {
10266
- ...mountedEditor,
10267
- trackedChanges,
10268
- structuralChanges,
10269
- storySnapshots
10270
- };
10271
- };
10272
- /**
10273
- * Bootstrap tracked-change comment threads after a DOCX import finishes.
10274
- *
10275
- * Initial import historically rebuilt only body tracked-change threads so
10276
- * resolved imported body comments stayed resolved. Header/footer and note
10277
- * tracked changes live outside the body PM state, so they need an additional
10278
- * story-aware bootstrap pass here.
10279
- *
10280
- * We intentionally keep the existing body-only rebuild instead of switching
10281
- * to the broader syncTrackedChangeComments() path so imported resolved body
10282
- * tracked-change threads preserve their initial resolved state.
10283
- *
10284
- * @param {Object | null | undefined} editor
10285
- * @param {Object | null | undefined} superdoc
10286
- * @param {Object | null | undefined} snapshot
10287
- * @returns {boolean}
10288
- */
10289
- const bootstrapImportedTrackedChangeComments = (editor, superdoc, snapshot = null) => {
10290
- if (!editor || !superdoc) return false;
10291
- const captured = snapshot ?? captureImportedTrackedChangeBootstrapSnapshot(editor);
10292
- if (!captured) return false;
10293
- createCommentForTrackChanges(editor, superdoc, captured.trackedChanges, {
10294
- editorState: captured.state,
10295
- editorView: captured.view
10296
- });
10297
- syncStoryTrackedChangeComments({
10298
- superdoc,
10299
- editor,
10300
- snapshots: captured.storySnapshots,
10301
- documentState: captured.state,
10302
- resolveFromEditor: false
10303
- });
10304
- syncStructuralTrackedChangeComments({
10305
- superdoc,
10306
- editor,
10307
- structuralChanges: captured.structuralChanges
10308
- });
10309
- return true;
10310
- };
10311
- const isCurrentImportedTrackedChangeBootstrap = (task) => {
10312
- if (!task) return false;
10313
- if (importedTrackedChangeBootstrapTasks.get(task.documentId) !== task) return false;
10314
- try {
10315
- const editorDocumentId = task.editor?.options?.documentId;
10316
- if (editorDocumentId != null && String(editorDocumentId) !== task.documentId) return false;
10317
- const mountedDocument = superdocStore.getDocument(task.documentId);
10318
- if (!mountedDocument) return false;
10319
- if (mountedDocument.getEditor?.() !== task.editor) return false;
10320
- } catch {
10321
- return false;
10322
- }
10323
- return true;
10324
- };
10325
- const runImportedTrackedChangeBootstrap = (task) => {
10326
- if (!isCurrentImportedTrackedChangeBootstrap(task)) {
10327
- if (importedTrackedChangeBootstrapTasks.get(task?.documentId) === task) importedTrackedChangeBootstrapTasks.delete(task.documentId);
10328
- return false;
10329
- }
10330
- const snapshot = captureImportedTrackedChangeBootstrapSnapshot(task.editor);
10331
- if (!snapshot || !isCurrentImportedTrackedChangeBootstrap(task)) {
10332
- if (importedTrackedChangeBootstrapTasks.get(task.documentId) === task) importedTrackedChangeBootstrapTasks.delete(task.documentId);
10333
- return false;
10334
- }
10335
- try {
10336
- return bootstrapImportedTrackedChangeComments(task.editor, task.superdoc, snapshot);
10337
- } finally {
10338
- if (importedTrackedChangeBootstrapTasks.get(task.documentId) === task) importedTrackedChangeBootstrapTasks.delete(task.documentId);
10339
- }
10340
- };
10341
- const scheduleImportedTrackedChangeBootstrap = ({ editor, superdoc, documentId, defer = true }) => {
10342
- const normalizedDocumentId = normalizeBootstrapDocumentId(documentId);
10343
- if (!normalizedDocumentId || !editor || !superdoc) return false;
10344
- cancelImportedTrackedChangeBootstrap(normalizedDocumentId);
10345
- const task = {
10346
- documentId: normalizedDocumentId,
10347
- editor,
10348
- superdoc,
10349
- generation: ++importedTrackedChangeBootstrapGeneration,
10350
- timeoutHandle: null
10351
- };
10352
- importedTrackedChangeBootstrapTasks.set(normalizedDocumentId, task);
10353
- if (!defer) return runImportedTrackedChangeBootstrap(task);
10354
- task.timeoutHandle = setTimeout(() => {
10355
- task.timeoutHandle = null;
10356
- runImportedTrackedChangeBootstrap(task);
10357
- }, 0);
10358
- return true;
10359
- };
10360
- /**
10361
10056
  * Drop imported threads and cached positions for one document id.
10362
10057
  *
10363
10058
  * Replace-file swaps call this before hydrating the replacement so stale
@@ -10374,7 +10069,6 @@ var useCommentsStore = defineStore("comments", () => {
10374
10069
  delete next[activeDocumentId];
10375
10070
  committedReviewPresentations.value = next;
10376
10071
  }
10377
- cancelImportedTrackedChangeBootstrap(activeDocumentId);
10378
10072
  const removedComments = commentsList.value.filter((comment) => belongsToDocument(comment, activeDocumentId, { allowSingleDocumentMismatch: true }));
10379
10073
  if (!removedComments.length) return;
10380
10074
  const removedAliasIds = /* @__PURE__ */ new Set();
@@ -10392,170 +10086,6 @@ var useCommentsStore = defineStore("comments", () => {
10392
10086
  const activeCommentId = activeComment.value != null ? String(activeComment.value) : null;
10393
10087
  if (activeCommentId && removedAliasIds.has(activeCommentId)) clearActiveCommentSelection();
10394
10088
  }
10395
- function resetCommentsForReplacedDocument(documentId) {
10396
- removeCommentsForDocument(documentId);
10397
- }
10398
- /**
10399
- * Initialize loaded comments into SuperDoc by mapping the imported
10400
- * comment data to SuperDoc useComment objects.
10401
- *
10402
- * Updates the commentsList ref with the new comments.
10403
- *
10404
- * @param {Object} param0
10405
- * @param {Array} param0.comments The comments to be loaded
10406
- * @param {String} param0.documentId The document ID
10407
- * @param {boolean} [param0.replacedFile] Whether this load replaces an existing document in place
10408
- * @returns {void}
10409
- */
10410
- const processLoadedDocxComments = async ({ superdoc, editor, comments, documentId, replacedFile = false }) => {
10411
- const document = superdocStore.getDocument(documentId);
10412
- if (document?.commentThreadingProfile) document.commentThreadingProfile.value = editor?.converter?.commentThreadingProfile || null;
10413
- if (replacedFile) resetCommentsForReplacedDocument(documentId);
10414
- comments.forEach((comment) => {
10415
- const textElements = Array.isArray(comment.elements) ? comment.elements : [];
10416
- const htmlContent = getHtmlFromComment(textElements);
10417
- if (!htmlContent && !comment.trackedChange) return;
10418
- const creatorName = normalizeImportedCreatorName(comment.creatorName);
10419
- const importedName = creatorName ? `${creatorName} (imported)` : null;
10420
- const newComment = useComment({
10421
- fileId: documentId,
10422
- fileType: document.type,
10423
- docxCommentJSON: textElements.length ? textElements : null,
10424
- commentId: comment.commentId,
10425
- isInternal: false,
10426
- parentCommentId: comment.parentCommentId,
10427
- trackedChangeParentId: comment.trackedChangeParentId,
10428
- trackedChangeThreadParentId: comment.trackedChangeThreadParentId,
10429
- creatorId: null,
10430
- creatorName,
10431
- createdTime: comment.createdTime,
10432
- creatorEmail: comment.creatorEmail,
10433
- importedAuthor: {
10434
- ...importedName ? { name: importedName } : {},
10435
- email: comment.creatorEmail
10436
- },
10437
- commentText: htmlContent,
10438
- resolvedTime: comment.isDone ? Date.now() : null,
10439
- resolvedById: null,
10440
- resolvedByEmail: comment.isDone ? comment.creatorEmail : null,
10441
- resolvedByName: comment.isDone ? importedName || "(Imported)" : null,
10442
- trackedChange: comment.trackedChange || false,
10443
- trackedChangeText: comment.trackedChangeText,
10444
- trackedChangeType: comment.trackedChangeType,
10445
- trackedChangeDisplayType: comment.trackedChangeDisplayType,
10446
- deletedText: comment.trackedDeletedText,
10447
- origin: comment.origin || "word",
10448
- threadingMethod: comment.threadingMethod,
10449
- threadingStyleOverride: comment.threadingStyleOverride,
10450
- threadingParentCommentId: comment.threadingParentCommentId,
10451
- originalXmlStructure: comment.originalXmlStructure
10452
- });
10453
- addHydratedComment({
10454
- superdoc,
10455
- comment: newComment
10456
- });
10457
- });
10458
- if (replacedFile) {
10459
- scheduleImportedTrackedChangeBootstrap({
10460
- editor,
10461
- superdoc,
10462
- documentId,
10463
- defer: false
10464
- });
10465
- return;
10466
- }
10467
- scheduleImportedTrackedChangeBootstrap({
10468
- editor,
10469
- superdoc,
10470
- documentId
10471
- });
10472
- };
10473
- const createCommentForTrackChanges = (editor, superdoc, trackedChangesOverride = null, options = {}) => {
10474
- const { reopenResolved = false, refreshExisting = false, broadcastChanges = true, editorState: editorStateOverride = null, editorView: editorViewOverride = null } = options;
10475
- const mountedEditor = editorStateOverride ? {
10476
- state: editorStateOverride,
10477
- view: editorViewOverride
10478
- } : readMountedEditorSnapshot(editor);
10479
- if (!mountedEditor?.state) return;
10480
- const editorState = mountedEditor.state;
10481
- const trackedChanges = trackedChangesOverride ?? trackChangesHelpers.getTrackChanges(editorState);
10482
- const groupedChanges = groupChanges(trackedChanges);
10483
- const activeDocumentId = editor?.options?.documentId != null ? String(editor.options.documentId) : null;
10484
- if (!activeDocumentId) return;
10485
- const skipIds = /* @__PURE__ */ new Set();
10486
- const existingTrackedChangeById = /* @__PURE__ */ new Map();
10487
- commentsList.value.forEach((comment) => {
10488
- if (!comment?.trackedChange) return;
10489
- if (!belongsToTrackedChangeSyncDocument(comment, activeDocumentId)) return;
10490
- if (!isBodyTrackedChangeComment(comment)) return;
10491
- const commentIds = [comment.commentId, comment.importedId].map((id) => id != null ? String(id) : null).filter(Boolean);
10492
- if (comment.resolvedTime) {
10493
- if (!reopenResolved) commentIds.forEach((id) => skipIds.add(id));
10494
- return;
10495
- }
10496
- commentIds.forEach((id) => {
10497
- existingTrackedChangeById.set(id, comment);
10498
- if (!refreshExisting) skipIds.add(id);
10499
- });
10500
- });
10501
- const changesByIdMap = /* @__PURE__ */ new Map();
10502
- for (const change of trackedChanges) {
10503
- const id = change.mark.attrs.id;
10504
- if (!changesByIdMap.has(id)) changesByIdMap.set(id, []);
10505
- changesByIdMap.get(id).push(change);
10506
- }
10507
- const documentId = activeDocumentId;
10508
- const processedIds = /* @__PURE__ */ new Set();
10509
- groupedChanges.forEach(({ insertedMark, deletionMark, formatMark }) => {
10510
- const id = insertedMark?.mark.attrs.id || deletionMark?.mark.attrs.id || formatMark?.mark.attrs.id;
10511
- if (id == null) return;
10512
- const normalizedId = String(id);
10513
- if (processedIds.has(normalizedId)) return;
10514
- processedIds.add(normalizedId);
10515
- if (!refreshExisting && skipIds.has(normalizedId)) return;
10516
- const existingTrackedChange = existingTrackedChangeById.get(normalizedId);
10517
- const marks = {
10518
- ...insertedMark && { insertedMark: insertedMark.mark },
10519
- ...deletionMark && { deletionMark: deletionMark.mark },
10520
- ...formatMark && { formatMark: formatMark.mark }
10521
- };
10522
- const params = createOrUpdateTrackedChangeComment({
10523
- event: existingTrackedChange ? "update" : "add",
10524
- marks,
10525
- nodes: [],
10526
- newEditorState: editorState,
10527
- documentId,
10528
- trackedChangesForId: changesByIdMap.get(id) || []
10529
- });
10530
- if (params) {
10531
- const anchorKey = buildBodyTrackedChangeAnchorKey(params.changeId ?? id);
10532
- params.trackedChangeStory = BODY_TRACKED_CHANGE_STORY;
10533
- params.trackedChangeStoryKind = "body";
10534
- params.trackedChangeStoryLabel = "";
10535
- params.trackedChangeAnchorKey = anchorKey;
10536
- handleTrackedChangeUpdate({
10537
- superdoc,
10538
- params,
10539
- broadcastChanges,
10540
- documentState: editorState
10541
- });
10542
- if (!existingTrackedChange) {
10543
- skipIds.add(normalizedId);
10544
- if (params.changeId != null) skipIds.add(String(params.changeId));
10545
- if (params.importedId != null) skipIds.add(String(params.importedId));
10546
- }
10547
- }
10548
- });
10549
- const editorView = mountedEditor.view;
10550
- try {
10551
- if (!editorView || editor.view !== editorView || editorView.isDestroyed === true || editorView.destroyed === true) return;
10552
- } catch {
10553
- return;
10554
- }
10555
- const { tr } = editorState;
10556
- tr.setMeta(CommentsPluginKey, { type: "force" });
10557
- editorView.dispatch(tr);
10558
- };
10559
10089
  /**
10560
10090
  * Remove inline tracked-change comments whose change id is subsumed by a
10561
10091
  * tracked whole-table change. Mirrors the deletion-event emission of
@@ -11458,286 +10988,6 @@ var useCommentsStore = defineStore("comments", () => {
11458
10988
  return rowDocumentId != null && String(rowDocumentId) === normalizedDocumentId;
11459
10989
  }).length;
11460
10990
  };
11461
- const syncTrackedChangeComments = ({ superdoc, editor, broadcastChanges = true }) => {
11462
- if (!superdoc || !editor) return;
11463
- const activeDocumentId = editor?.options?.documentId != null ? String(editor.options.documentId) : null;
11464
- if (!activeDocumentId) return;
11465
- const captured = captureImportedTrackedChangeBootstrapSnapshot(editor);
11466
- if (!captured) return;
11467
- const trackedChanges = captured.trackedChanges;
11468
- const liveTrackedChangeIds = /* @__PURE__ */ new Set();
11469
- trackedChanges.forEach((change) => {
11470
- const id = change?.mark?.attrs?.id;
11471
- if (id == null) return;
11472
- liveTrackedChangeIds.add(String(id));
11473
- });
11474
- const storySnapshots = captured.storySnapshots;
11475
- const liveTrackedChangeAnchorKeys = new Set(storySnapshots.map((snapshot) => snapshot?.anchorKey).filter((anchorKey) => typeof anchorKey === "string" && anchorKey.length > 0));
11476
- pruneStaleTrackedChangeComments(liveTrackedChangeIds, liveTrackedChangeAnchorKeys, activeDocumentId, superdoc, { broadcastChanges });
11477
- createCommentForTrackChanges(editor, superdoc, trackedChanges, {
11478
- reopenResolved: true,
11479
- refreshExisting: true,
11480
- broadcastChanges,
11481
- editorState: captured.state,
11482
- editorView: captured.view
11483
- });
11484
- syncStoryTrackedChangeComments({
11485
- superdoc,
11486
- editor,
11487
- broadcastChanges,
11488
- snapshots: storySnapshots,
11489
- documentState: captured.state
11490
- });
11491
- syncStructuralTrackedChangeComments({
11492
- superdoc,
11493
- editor,
11494
- broadcastChanges,
11495
- structuralChanges: captured.structuralChanges
11496
- });
11497
- };
11498
- /**
11499
- * Surface decidable whole-table structural tracked changes (table insert /
11500
- * table delete) as right-rail bubbles, mirroring the inline tracked-change
11501
- * path. Structural row revisions live on node attrs (not inline marks), so
11502
- * the inline `getTrackChanges` enumerator never sees them — they are
11503
- * enumerated separately here.
11504
- *
11505
- * Only `decidable` whole-table changes are surfaced; partial/mixed shapes are
11506
- * not actionable (the decision engine fails them closed) so they get no
11507
- * bubble. The bubble id is the document-api public id so accept/reject in the
11508
- * sidebar routes `trackChanges.decide` to the same change.
11509
- *
11510
- * Positioning: the bubble carries a body-story anchorKey (matching the
11511
- * tracked-change index snapshot) and a body PM range (table start/end). The
11512
- * DocumentRendererRuntime position pass emits a body-story position entry for that
11513
- * anchorKey, whose bounds resolve through the same `getRangeRects` path inline
11514
- * body comments/TC use — so it lines up with the table in layout-engine
11515
- * viewing mode.
11516
- */
11517
- const syncStructuralTrackedChangeComments = ({ superdoc, editor, broadcastChanges = true, structuralChanges: structuralChangesOverride = null }) => {
11518
- const activeDocumentId = editor?.options?.documentId != null ? String(editor.options.documentId) : null;
11519
- if (!activeDocumentId) return;
11520
- const enumerate = trackChangesHelpers?.enumerateStructuralRowChanges;
11521
- if (typeof enumerate !== "function") return;
11522
- let structuralChanges = structuralChangesOverride;
11523
- if (!Array.isArray(structuralChanges)) {
11524
- const mountedEditor = readMountedEditorSnapshot(editor);
11525
- if (!mountedEditor) return;
11526
- try {
11527
- structuralChanges = enumerate(mountedEditor.state) ?? [];
11528
- } catch {
11529
- structuralChanges = [];
11530
- }
11531
- }
11532
- for (const structural of structuralChanges) {
11533
- if (!structural?.decidable || !structural?.wholeTable) continue;
11534
- const publicId = buildStructuralTrackedChangeId(structural);
11535
- if (!publicId) continue;
11536
- const anchorKey = buildBodyTrackedChangeAnchorKey(publicId);
11537
- const displayType = structural.subtype === "table-insert" ? "tableInsert" : "tableDelete";
11538
- const trackedChangeType = structural.side === "insertion" ? "trackInsert" : "trackDelete";
11539
- const normalizedPublicId = String(publicId);
11540
- const normalizedAnchorKey = anchorKey != null ? String(anchorKey) : null;
11541
- const params = {
11542
- event: commentsList.value.find((comment) => {
11543
- if (!comment?.trackedChange) return false;
11544
- if (!belongsToTrackedChangeSyncDocument(comment, activeDocumentId)) return false;
11545
- const commentAnchorKey = comment.trackedChangeAnchorKey != null ? String(comment.trackedChangeAnchorKey) : null;
11546
- if (normalizedAnchorKey && commentAnchorKey) return commentAnchorKey === normalizedAnchorKey;
11547
- const commentId = comment.commentId != null ? String(comment.commentId) : null;
11548
- const importedId = comment.importedId != null ? String(comment.importedId) : null;
11549
- return commentId === normalizedPublicId || importedId === normalizedPublicId;
11550
- }) ? "update" : "add",
11551
- changeId: publicId,
11552
- trackedChangeText: "",
11553
- trackedChangeType,
11554
- trackedChangeDisplayType: displayType,
11555
- deletedText: null,
11556
- authorId: null,
11557
- authorEmail: structural.authorEmail || null,
11558
- authorImage: structural.authorImage || null,
11559
- date: structural.date || null,
11560
- author: structural.author || null,
11561
- importedAuthor: structural.importedAuthor ? { name: structural.importedAuthor } : null,
11562
- semanticColorKey: structural.semanticColorKey ?? null,
11563
- semanticColor: structural.semanticColor ?? null,
11564
- documentId: activeDocumentId,
11565
- coords: null,
11566
- trackedChangeStory: BODY_TRACKED_CHANGE_STORY,
11567
- trackedChangeStoryKind: "body",
11568
- trackedChangeStoryLabel: "",
11569
- trackedChangeAnchorKey: anchorKey
11570
- };
11571
- handleTrackedChangeUpdate({
11572
- superdoc,
11573
- params,
11574
- broadcastChanges
11575
- });
11576
- }
11577
- };
11578
- const syncStoryTrackedChangeComments = ({ superdoc, editor, broadcastChanges = true, snapshots = null, documentState = void 0, resolveFromEditor = true }) => {
11579
- const activeDocumentId = editor?.options?.documentId != null ? String(editor.options.documentId) : null;
11580
- if (!activeDocumentId) return;
11581
- let resolvedSnapshots = snapshots;
11582
- if (!Array.isArray(resolvedSnapshots)) {
11583
- if (typeof getTrackedChangeIndex !== "function") return;
11584
- if (!readMountedEditorSnapshot(editor)) return;
11585
- let index = null;
11586
- try {
11587
- index = getTrackedChangeIndex(editor);
11588
- } catch {
11589
- return;
11590
- }
11591
- if (!index) return;
11592
- try {
11593
- resolvedSnapshots = index.getAll();
11594
- } catch {
11595
- return;
11596
- }
11597
- }
11598
- for (const snapshot of resolvedSnapshots) {
11599
- if (snapshot.storyKind === "body") continue;
11600
- upsertStoryTrackedChangeComment({
11601
- superdoc,
11602
- editor,
11603
- snapshot,
11604
- documentId: activeDocumentId,
11605
- broadcastChanges,
11606
- documentState,
11607
- resolveFromEditor
11608
- });
11609
- }
11610
- };
11611
- const getStoryTrackedChangeDisplayType = (snapshot) => {
11612
- if (snapshot?.type !== "structural") return snapshot?.type ?? null;
11613
- return snapshot?.subtype === "table-delete" ? "tableDelete" : "tableInsert";
11614
- };
11615
- const getStoryTrackedChangeType = (snapshot) => {
11616
- if (snapshot?.type !== "structural") return snapshot?.type ?? null;
11617
- return snapshot?.subtype === "table-delete" ? "trackDelete" : "trackInsert";
11618
- };
11619
- const isStoryTrackedChangeDeletion = (snapshot) => {
11620
- if (!snapshot) return false;
11621
- if (snapshot.type === "delete") return true;
11622
- return snapshot.type === "structural" && snapshot.subtype === "table-delete";
11623
- };
11624
- const buildStoryTrackedChangeParams = ({ editor, snapshot, documentId, event, resolveFromEditor = true }) => {
11625
- const trackedChangeType = getStoryTrackedChangeType(snapshot);
11626
- const trackedChangeDisplayType = getStoryTrackedChangeDisplayType(snapshot);
11627
- const fallbackParams = {
11628
- event,
11629
- changeId: snapshot.runtimeRef.rawId,
11630
- trackedChangeText: isStoryTrackedChangeDeletion(snapshot) ? "" : snapshot.excerpt ?? "",
11631
- trackedChangeType,
11632
- trackedChangeDisplayType,
11633
- semanticColorKey: snapshot.semanticColorKey ?? null,
11634
- semanticColor: snapshot.semanticColor ?? null,
11635
- deletedText: isStoryTrackedChangeDeletion(snapshot) ? snapshot.excerpt ?? "" : null,
11636
- authorId: snapshot.authorId,
11637
- authorEmail: snapshot.authorEmail,
11638
- authorImage: snapshot.authorImage,
11639
- date: snapshot.date,
11640
- author: snapshot.author,
11641
- documentId,
11642
- coords: null,
11643
- trackedChangeStory: snapshot.story,
11644
- trackedChangeStoryKind: snapshot.storyKind,
11645
- trackedChangeStoryLabel: snapshot.storyLabel,
11646
- trackedChangeAnchorKey: snapshot.anchorKey
11647
- };
11648
- if (!resolveFromEditor || typeof resolveTrackedChangeInStory !== "function") return fallbackParams;
11649
- let resolvedChange = null;
11650
- try {
11651
- resolvedChange = resolveTrackedChangeInStory(editor, {
11652
- kind: "entity",
11653
- entityType: "trackedChange",
11654
- entityId: snapshot.runtimeRef.rawId,
11655
- story: snapshot.story
11656
- });
11657
- } catch {
11658
- resolvedChange = null;
11659
- }
11660
- const storyEditorState = resolvedChange?.editor?.state ?? null;
11661
- if (!storyEditorState) return fallbackParams;
11662
- let trackedChangesForId = [];
11663
- try {
11664
- trackedChangesForId = trackChangesHelpers.getTrackChanges(storyEditorState, resolvedChange.change.rawId) ?? [];
11665
- } catch {
11666
- trackedChangesForId = [];
11667
- }
11668
- const resolvedParams = createOrUpdateTrackedChangeComment({
11669
- event,
11670
- marks: collectTrackedChangeMarksByType(trackedChangesForId),
11671
- nodes: [],
11672
- newEditorState: storyEditorState,
11673
- documentId,
11674
- trackedChangesForId
11675
- });
11676
- if (!resolvedParams) return fallbackParams;
11677
- if (resolvedParams.semanticColorKey == null && snapshot.semanticColorKey != null) resolvedParams.semanticColorKey = snapshot.semanticColorKey;
11678
- if (resolvedParams.semanticColor == null && snapshot.semanticColor != null) resolvedParams.semanticColor = snapshot.semanticColor;
11679
- resolvedParams.trackedChangeStory = snapshot.story;
11680
- resolvedParams.trackedChangeStoryKind = snapshot.storyKind;
11681
- resolvedParams.trackedChangeStoryLabel = snapshot.storyLabel;
11682
- resolvedParams.trackedChangeAnchorKey = snapshot.anchorKey;
11683
- return resolvedParams;
11684
- };
11685
- const upsertStoryTrackedChangeComment = ({ superdoc, editor, snapshot, documentId, broadcastChanges, documentState, resolveFromEditor }) => {
11686
- if (!snapshot?.runtimeRef?.rawId) return;
11687
- const existingComment = commentsList.value.find((comment) => {
11688
- if (!comment?.trackedChange) return false;
11689
- const commentAnchorKey = comment.trackedChangeAnchorKey != null ? String(comment.trackedChangeAnchorKey) : null;
11690
- if (commentAnchorKey && snapshot.anchorKey) return commentAnchorKey === snapshot.anchorKey;
11691
- if (commentAnchorKey || snapshot.anchorKey) return false;
11692
- return comment.commentId === snapshot.runtimeRef.rawId || comment.importedId === snapshot.runtimeRef.rawId;
11693
- });
11694
- const params = buildStoryTrackedChangeParams({
11695
- editor,
11696
- snapshot,
11697
- documentId,
11698
- event: existingComment ? "update" : "add",
11699
- resolveFromEditor
11700
- });
11701
- handleTrackedChangeUpdate({
11702
- superdoc,
11703
- params,
11704
- broadcastChanges,
11705
- documentState
11706
- });
11707
- if (existingComment) {
11708
- existingComment.trackedChangeStory = snapshot.story;
11709
- existingComment.trackedChangeStoryKind = snapshot.storyKind;
11710
- existingComment.trackedChangeStoryLabel = snapshot.storyLabel;
11711
- existingComment.trackedChangeAnchorKey = snapshot.anchorKey;
11712
- }
11713
- };
11714
- const normalizeDocxSchemaForExport = (value) => {
11715
- if (!value) return [];
11716
- return (Array.isArray(value) ? value : [value]).filter(Boolean);
11717
- };
11718
- const translateCommentsForExport = () => {
11719
- const processedComments = [];
11720
- commentsList.value.forEach((comment) => {
11721
- const values = comment.getValues();
11722
- const richText = values.commentText;
11723
- const docxSchema = normalizeDocxSchemaForExport(values.docxCommentJSON);
11724
- const schema = docxSchema.length ? docxSchema : convertHtmlToSchema(richText);
11725
- processedComments.push({
11726
- ...values,
11727
- commentJSON: schema
11728
- });
11729
- });
11730
- return processedComments;
11731
- };
11732
- const convertHtmlToSchema = (commentHTML) => {
11733
- const json = new Editor({
11734
- mode: "text",
11735
- isHeadless: true,
11736
- content: commentHTML,
11737
- extensions: getRichTextExtensions()
11738
- }).getJSON();
11739
- return Array.isArray(json?.content) ? json.content.filter(Boolean) : [];
11740
- };
11741
10991
  /**
11742
10992
  * Triggered when the editor locations are updated
11743
10993
  * Updates floating comment locations from the editor
@@ -11988,75 +11238,6 @@ var useCommentsStore = defineStore("comments", () => {
11988
11238
  if (typeof commentsVisible === "boolean") viewingVisibility.commentsVisible = commentsVisible;
11989
11239
  if (typeof trackChangesVisible === "boolean") viewingVisibility.trackChangesVisible = trackChangesVisible;
11990
11240
  };
11991
- /**
11992
- * Get HTML content from the comment text JSON (which uses DOCX schema)
11993
- *
11994
- * @param {Object} commentTextJson The comment text JSON
11995
- * @returns {string} The HTML content
11996
- */
11997
- const normalizeCommentForEditor = (node) => {
11998
- if (Array.isArray(node)) return node.map((child) => normalizeCommentForEditor(child)).flat().filter(Boolean);
11999
- if (!node || typeof node !== "object") return node;
12000
- const stripTextStyleAttrs = (attrs) => {
12001
- if (!attrs) return attrs;
12002
- const rest = { ...attrs };
12003
- delete rest.fontSize;
12004
- delete rest.fontFamily;
12005
- delete rest.eastAsiaFontFamily;
12006
- return Object.keys(rest).length ? rest : void 0;
12007
- };
12008
- const normalizeMark = (mark) => {
12009
- if (!mark) return mark;
12010
- const typeName = typeof mark.type === "string" ? mark.type : mark.type?.name;
12011
- const attrs = mark?.attrs ? { ...mark.attrs } : void 0;
12012
- if (typeName === "textStyle" && attrs) return {
12013
- ...mark,
12014
- attrs: stripTextStyleAttrs(attrs)
12015
- };
12016
- return {
12017
- ...mark,
12018
- attrs
12019
- };
12020
- };
12021
- const cloneMarks = (marks) => Array.isArray(marks) ? marks.filter(Boolean).map((mark) => normalizeMark(mark)) : void 0;
12022
- const cloneAttrs = (attrs) => attrs && typeof attrs === "object" ? { ...attrs } : void 0;
12023
- if (!Array.isArray(node.content)) return {
12024
- type: node.type,
12025
- ...node.text !== void 0 ? { text: node.text } : {},
12026
- ...node.attrs ? { attrs: cloneAttrs(node.attrs) } : {},
12027
- ...node.marks ? { marks: cloneMarks(node.marks) } : {}
12028
- };
12029
- const normalizedChildren = node.content.map((child) => normalizeCommentForEditor(child)).flat().filter(Boolean);
12030
- if (node.type === "run") return normalizedChildren;
12031
- return {
12032
- type: node.type,
12033
- ...node.attrs ? { attrs: cloneAttrs(node.attrs) } : {},
12034
- ...node.marks ? { marks: cloneMarks(node.marks) } : {},
12035
- content: normalizedChildren
12036
- };
12037
- };
12038
- const getHtmlFromComment = (commentTextElements) => {
12039
- const elementsArray = Array.isArray(commentTextElements) ? commentTextElements : commentTextElements ? [commentTextElements] : [];
12040
- if (!elementsArray.some((element) => element?.content?.length)) return;
12041
- try {
12042
- const normalizedContent = normalizeCommentForEditor(elementsArray);
12043
- const contentArray = Array.isArray(normalizedContent) ? normalizedContent : normalizedContent ? [normalizedContent] : [];
12044
- if (!contentArray.length) return null;
12045
- return new Editor({
12046
- mode: "text",
12047
- isHeadless: true,
12048
- content: {
12049
- type: "doc",
12050
- content: contentArray
12051
- },
12052
- loadFromSchema: true,
12053
- extensions: getRichTextExtensions()
12054
- }).getHTML();
12055
- } catch (error) {
12056
- console.warn("Failed to convert comment", error);
12057
- return;
12058
- }
12059
- };
12060
11241
  return {
12061
11242
  COMMENT_EVENTS,
12062
11243
  isDebugging,
@@ -12125,23 +11306,18 @@ var useCommentsStore = defineStore("comments", () => {
12125
11306
  cancelComment,
12126
11307
  deleteComment,
12127
11308
  removePendingComment,
12128
- cancelImportedTrackedChangeBootstrap,
12129
11309
  removeCommentsForDocument,
12130
11310
  setReviewDirectoryFromV2,
12131
11311
  clearReviewDirectory,
12132
- processLoadedDocxComments,
12133
- translateCommentsForExport,
12134
11312
  handleEditorLocationsUpdate,
12135
11313
  clearEditorCommentPositions,
12136
11314
  handleTrackedChangeUpdate,
12137
- refreshTrackedChangeCommentsByIds,
12138
11315
  syncResolvedCommentsWithDocument,
12139
11316
  syncTrackedChangePositionsWithDocument,
12140
11317
  setActiveFloatingCommentInstance,
12141
11318
  requestInstantSidebarAlignment,
12142
11319
  peekInstantSidebarAlignment,
12143
11320
  clearInstantSidebarAlignment,
12144
- syncTrackedChangeComments,
12145
11321
  decideTrackedChangeFromSidebar,
12146
11322
  v2CommentsAdapter,
12147
11323
  setV2CommentsAdapter,
@@ -21261,8 +20437,11 @@ function translateRenderReadinessDiagnostic(diag, ctx = {}) {
21261
20437
  else if (severity === "error") diagnosticCode = "RENDER_ERROR";
21262
20438
  else return null;
21263
20439
  const message = reason || code;
20440
+ const error = new Error(typeof diag.error?.message === "string" ? diag.error.message : message);
20441
+ if (typeof diag.error?.name === "string") error.name = diag.error.name;
20442
+ if (typeof diag.error?.stack === "string") error.stack = diag.error.stack;
21264
20443
  return {
21265
- error: new Error(message),
20444
+ error,
21266
20445
  diagnosticCode,
21267
20446
  diagnosticStage: unusableFurniture ? "parse" : "render",
21268
20447
  severity,
@@ -22155,7 +21334,7 @@ var SuperDoc_default = /*#__PURE__*/ require__plugin_vue_export_helper._plugin_v
22155
21334
  }
22156
21335
  });
22157
21336
  const { getConfig, documentsWithConverations, commentsList, pendingComment, activeComment, skipSelectionUpdate, commentsByDocument, isCommentsListVisible, isFloatingCommentsReady, generalCommentIds, hasSyncedCollaborationComments, editorCommentPositions, hasInitializedLocations, isCommentHighlighted, hasOpenTrackedChanges } = storeToRefs(commentsStore);
22158
- const { showAddComment, handleEditorLocationsUpdate, handleTrackedChangeUpdate, refreshTrackedChangeCommentsByIds, syncTrackedChangePositionsWithDocument, syncTrackedChangeComments, addComment, addHydratedComment, getComment, resolveCommentPositionEntry, belongsToDocument, COMMENT_EVENTS, requestInstantSidebarAlignment, peekInstantSidebarAlignment, clearInstantSidebarAlignment } = commentsStore;
21337
+ const { showAddComment, handleEditorLocationsUpdate, handleTrackedChangeUpdate, syncTrackedChangePositionsWithDocument, addComment, addHydratedComment, getComment, resolveCommentPositionEntry, belongsToDocument, COMMENT_EVENTS, requestInstantSidebarAlignment, peekInstantSidebarAlignment, clearInstantSidebarAlignment } = commentsStore;
22159
21338
  const { proxy } = require__plugin_vue_export_helper.getCurrentInstance();
22160
21339
  commentsStore.proxy = proxy;
22161
21340
  const documentOpenTelemetry = createDocumentOpenTelemetry(proxy.$superdoc.config);
@@ -22207,7 +21386,6 @@ var SuperDoc_default = /*#__PURE__*/ require__plugin_vue_export_helper._plugin_v
22207
21386
  const layers = require__plugin_vue_export_helper.ref(null);
22208
21387
  const rightSidebarRef = require__plugin_vue_export_helper.ref(null);
22209
21388
  const pdfViewerRef = require__plugin_vue_export_helper.ref(null);
22210
- const pendingReplayTrackedChangeSync = require__plugin_vue_export_helper.ref(false);
22211
21389
  const toolsMenuPosition = require__plugin_vue_export_helper.reactive({
22212
21390
  top: null,
22213
21391
  right: "-25px",
@@ -22270,20 +21448,6 @@ var SuperDoc_default = /*#__PURE__*/ require__plugin_vue_export_helper._plugin_v
22270
21448
  }
22271
21449
  });
22272
21450
  const pdfConfig = proxy.$superdoc.config.modules?.pdf || {};
22273
- const flushPendingReplayTrackedChangeSync = () => {
22274
- if (!pendingReplayTrackedChangeSync.value) return;
22275
- pendingReplayTrackedChangeSync.value = false;
22276
- syncTrackedChangeComments({
22277
- superdoc: proxy.$superdoc,
22278
- editor: proxy.$superdoc?.activeEditor
22279
- });
22280
- };
22281
- const scheduleReplayTrackedChangeSync = () => {
22282
- pendingReplayTrackedChangeSync.value = true;
22283
- require__plugin_vue_export_helper.nextTick(() => {
22284
- flushPendingReplayTrackedChangeSync();
22285
- });
22286
- };
22287
21451
  const handleDocumentReady = (documentId, container) => {
22288
21452
  const doc = getDocument(documentId);
22289
21453
  if (!doc || doc.loadScope && !doc.loadScope.finish()) return;
@@ -23283,7 +22447,6 @@ var SuperDoc_default = /*#__PURE__*/ require__plugin_vue_export_helper._plugin_v
23283
22447
  v2PageMetricsSnapshot.value = null;
23284
22448
  const clearedDocumentId = payload?.documentId == null ? null : String(payload.documentId);
23285
22449
  clearV2MutationRejectionNotifications(clearedDocumentId);
23286
- commentsStore.cancelImportedTrackedChangeBootstrap?.(clearedDocumentId ?? void 0);
23287
22450
  if (clearedDocumentId) v2MountStagesByDocumentId.delete(clearedDocumentId);
23288
22451
  if (latestV2MountStage && (clearedDocumentId == null || latestV2MountStage.dataset?.superdocV2DocumentId === clearedDocumentId)) latestV2MountStage = null;
23289
22452
  v2ReviewWindowController.reset("render-cleared");
@@ -23299,7 +22462,7 @@ var SuperDoc_default = /*#__PURE__*/ require__plugin_vue_export_helper._plugin_v
23299
22462
  ...event,
23300
22463
  documentId: document?.id ?? null
23301
22464
  }));
23302
- if (event.type === "mutation:committed" && event.origin === "extension") return;
22465
+ if (event.type === "mutation:committed" && event.dryRun) return;
23303
22466
  const documentId = document?.id ?? null;
23304
22467
  if (event.type === "history:changed" && event.state) {
23305
22468
  proxy.$superdoc.emit("history-change", {
@@ -23463,6 +22626,7 @@ var SuperDoc_default = /*#__PURE__*/ require__plugin_vue_export_helper._plugin_v
23463
22626
  case "collaboration-room-corrupt": return "SuperDoc v2 found a structurally invalid collaboration room. No changes were made.";
23464
22627
  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.";
23465
22628
  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.";
22629
+ case "collaboration-session-invalidated": return "This collaboration session is no longer current. Please reopen the shared document with roomMode: \"join\".";
23466
22630
  case "collaboration-v2-room-initializing": return "The SuperDoc v2 collaboration room has not completed initialization. This open attempt did not modify it.";
23467
22631
  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.";
23468
22632
  case "collaboration-open-intent-invalid": return "SuperDoc v2 received an invalid collaboration room mode. No provider was connected.";
@@ -23473,10 +22637,17 @@ var SuperDoc_default = /*#__PURE__*/ require__plugin_vue_export_helper._plugin_v
23473
22637
  const normalizeV2EditorFailureDetail = (detail) => typeof detail === "string" && detail.trim().length > 0 ? detail.trim() : null;
23474
22638
  const onV2EditorFailed = (payload) => {
23475
22639
  documents.value.find((doc) => doc.id === payload?.documentId)?.loadScope?.finish();
23476
- clearActiveV2EditorFacade(payload?.documentId ?? null);
23477
22640
  const reason = typeof payload?.reason === "string" && payload.reason.length > 0 ? payload.reason : "open-failed";
23478
22641
  const detail = normalizeV2EditorFailureDetail(payload?.detail);
23479
22642
  const documentId = typeof payload?.documentId === "string" && payload.documentId.length > 0 ? payload.documentId : null;
22643
+ const retiredDocument = reason === "collaboration-session-invalidated" && documentId ? getDocument(documentId) : null;
22644
+ const retiredExporter = retiredDocument?.getEditor?.();
22645
+ clearActiveV2EditorFacade(payload?.documentId ?? null);
22646
+ if (retiredExporter?.editorVersion === 2 && typeof retiredExporter.exportDocx === "function") {
22647
+ retiredDocument.isReady = false;
22648
+ if (v2Runtimes.has(documentId)) clearV2RuntimeRegistration(documentId);
22649
+ retiredDocument.setEditor?.(retiredExporter);
22650
+ }
23480
22651
  if (reason === "worker-transport-failed") {
23481
22652
  proxy.$superdoc.emit("exception", {
23482
22653
  error: /* @__PURE__ */ new Error("Worker transport failed."),
@@ -23503,7 +22674,7 @@ var SuperDoc_default = /*#__PURE__*/ require__plugin_vue_export_helper._plugin_v
23503
22674
  ...workerFailure ? { workerFailure } : {},
23504
22675
  reason
23505
22676
  };
23506
- 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);
22677
+ 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);
23507
22678
  else console.error(`[SuperDoc] ${message}`, logContext);
23508
22679
  proxy.$superdoc.emit("exception", collaborationException && reason !== "collaboration-config-invalid" ? collaborationException : {
23509
22680
  error: new Error(message),
@@ -23809,7 +22980,6 @@ var SuperDoc_default = /*#__PURE__*/ require__plugin_vue_export_helper._plugin_v
23809
22980
  existingComment: null
23810
22981
  };
23811
22982
  };
23812
- if (type === "replayCompleted") scheduleReplayTrackedChangeSync();
23813
22983
  if (COMMENT_EVENTS?.ADD && type === COMMENT_EVENTS.ADD && commentPayload) {
23814
22984
  commentPayload = normalizeReplayCommentModelPayload(commentPayload);
23815
22985
  const currentUser = proxy.$superdoc?.user;
@@ -24118,7 +23288,6 @@ var SuperDoc_default = /*#__PURE__*/ require__plugin_vue_export_helper._plugin_v
24118
23288
  handleFormattingMarksShortcut(e);
24119
23289
  }
24120
23290
  require__plugin_vue_export_helper.onBeforeUnmount(() => {
24121
- commentsStore.cancelImportedTrackedChangeBootstrap?.();
24122
23291
  passwordPrompt.destroy();
24123
23292
  findReplace.destroy();
24124
23293
  linkPopover.destroy();
@@ -24734,7 +23903,7 @@ var SuperDoc_default = /*#__PURE__*/ require__plugin_vue_export_helper._plugin_v
24734
23903
  ], 46, _hoisted_1$17);
24735
23904
  };
24736
23905
  }
24737
- }, [["__scopeId", "data-v-f2db957f"]]);
23906
+ }, [["__scopeId", "data-v-f7cc9a3c"]]);
24738
23907
  //#endregion
24739
23908
  //#region src/core/create-app.js
24740
23909
  var PINIA_DEVTOOLS_SETUP_EVENT = "devtools-plugin:setup";
@@ -46466,7 +45635,7 @@ var SuperDoc = class extends require_eventemitter3.import_eventemitter3.default
46466
45635
  }
46467
45636
  this.userColorMap = /* @__PURE__ */ new Map();
46468
45637
  this.colorIndex = 0;
46469
- this.version = "2.28.0-next.11";
45638
+ this.version = "2.28.0-next.13";
46470
45639
  this.#log("🦋 [superdoc] Using SuperDoc version:", this.version);
46471
45640
  this.superdocId = config.superdocId || require_uuid.v4();
46472
45641
  this.colors = this.config.colors ?? [];
@@ -47173,7 +46342,8 @@ var SuperDoc = class extends require_eventemitter3.import_eventemitter3.default
47173
46342
  roomMode: target.roomMode,
47174
46343
  ...syncTimeoutOption,
47175
46344
  ...target.publicApiKey ? { publicApiKey: target.publicApiKey } : {},
47176
- ...target.authEndpoint ? { authEndpoint: target.authEndpoint } : {}
46345
+ ...target.authEndpoint ? { authEndpoint: target.authEndpoint } : {},
46346
+ ...target.baseUrl ? { baseUrl: target.baseUrl } : {}
47177
46347
  };
47178
46348
  if (target.providerFamily === "hocuspocus") return {
47179
46349
  providerType: "hocuspocus",
@@ -48489,23 +47659,6 @@ var SuperDoc = class extends require_eventemitter3.import_eventemitter3.default
48489
47659
  confirmed
48490
47660
  };
48491
47661
  }
48492
- const legacyReplaceFile = activeEditor && !isV2ActiveEditorFacade(activeEditor) ? activeEditor.replaceFile : null;
48493
- if (typeof legacyReplaceFile === "function") {
48494
- const result = await legacyReplaceFile.call(activeEditor, source);
48495
- const legacyState = result && typeof result === "object" ? result.state : void 0;
48496
- const legacyConfirmed = legacyState === void 0 || legacyState === null || legacyState === "review-ready" || legacyState === "editing-ready";
48497
- if (legacyConfirmed) {
48498
- this.#replaceActiveDocumentData(activeEditor, source);
48499
- this.emit("document-replaced", {
48500
- editor: activeEditor,
48501
- host: activeEditor?.host
48502
- });
48503
- }
48504
- return {
48505
- raw: result,
48506
- confirmed: legacyConfirmed
48507
- };
48508
- }
48509
47662
  throw new Error("SuperDoc: replaceFile is unavailable for the active editor");
48510
47663
  }
48511
47664
  /**
@@ -48518,19 +47671,6 @@ var SuperDoc = class extends require_eventemitter3.import_eventemitter3.default
48518
47671
  commentsType,
48519
47672
  isFinalDoc
48520
47673
  });
48521
- const uiStoreHydrated = this.config?.modules?.comments !== false;
48522
- let legacyComments;
48523
- let legacyCommentsComputed = false;
48524
- const getLegacyCommentsForV1 = () => {
48525
- if (legacyCommentsComputed) return legacyComments;
48526
- legacyCommentsComputed = true;
48527
- if (commentsType === "clean") legacyComments = [];
48528
- else if (uiStoreHydrated && this.commentsStore && typeof this.commentsStore.translateCommentsForExport === "function") {
48529
- legacyComments = this.commentsStore.translateCommentsForExport();
48530
- if (!Array.isArray(legacyComments)) legacyComments = [];
48531
- }
48532
- return legacyComments;
48533
- };
48534
47674
  const bridgedExportErrors = /* @__PURE__ */ new WeakSet();
48535
47675
  const rememberBridgedExportError = (payload) => {
48536
47676
  if ("editor" in payload && payload.error && typeof payload.error === "object") bridgedExportErrors.add(payload.error);
@@ -48541,7 +47681,7 @@ var SuperDoc = class extends require_eventemitter3.import_eventemitter3.default
48541
47681
  if (policies !== void 0 && documents.some((doc) => {
48542
47682
  if (doc.type !== "application/vnd.openxmlformats-officedocument.wordprocessingml.document") return false;
48543
47683
  const editor = doc.getEditor?.();
48544
- return editor?.editorVersion !== 2 || typeof editor.exportDocx !== "function";
47684
+ return !isV2ActiveEditorFacade(editor) || typeof editor.exportDocx !== "function";
48545
47685
  })) throw new Error("Independent DOCX export policies require a mounted V2 exporter for every document.");
48546
47686
  const docxPromises = documents.map(async (doc) => {
48547
47687
  if (!doc || doc.type !== "application/vnd.openxmlformats-officedocument.wordprocessingml.document") return null;
@@ -48554,19 +47694,13 @@ var SuperDoc = class extends require_eventemitter3.import_eventemitter3.default
48554
47694
  if (isDocumentByteSource(doc.data)) return this.#savedDocxToBlob(doc.data);
48555
47695
  return null;
48556
47696
  };
48557
- if (!editor || typeof editor.exportDocx !== "function") return fallbackDocx();
48558
- const isV2Editor = editor.editorVersion === 2;
47697
+ if (!isV2ActiveEditorFacade(editor) || typeof editor.exportDocx !== "function") return fallbackDocx();
48559
47698
  try {
48560
- const exported = await editor.exportDocx(isV2Editor ? {
47699
+ const exported = await editor.exportDocx({
48561
47700
  isFinalDoc,
48562
47701
  commentsType,
48563
47702
  policies,
48564
47703
  fieldsHighlightColor
48565
- } : {
48566
- isFinalDoc,
48567
- comments: getLegacyCommentsForV1(),
48568
- commentsType,
48569
- fieldsHighlightColor
48570
47704
  });
48571
47705
  if (exported) return exported;
48572
47706
  } catch (error) {
@@ -48580,7 +47714,7 @@ var SuperDoc = class extends require_eventemitter3.import_eventemitter3.default
48580
47714
  editor: null
48581
47715
  }));
48582
47716
  }
48583
- if (isV2Editor) throw error;
47717
+ throw error;
48584
47718
  }
48585
47719
  return fallbackDocx();
48586
47720
  });