docx-diff-editor 1.0.57 → 1.0.59

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -962,6 +962,67 @@ async function parseHtmlToJson(html, SuperDoc) {
962
962
  }, 50);
963
963
  });
964
964
  }
965
+ async function parseHtmlWithLinkedEditor(html, mainEditor) {
966
+ const container = document.createElement("div");
967
+ container.style.cssText = "position:absolute;top:-9999px;left:-9999px;width:800px;height:600px;visibility:hidden;";
968
+ document.body.appendChild(container);
969
+ return new Promise((resolve, reject) => {
970
+ let resolved = false;
971
+ let childEditor = null;
972
+ const cleanup = () => {
973
+ setTimeout(() => {
974
+ if (childEditor) {
975
+ try {
976
+ childEditor.destroy?.();
977
+ } catch {
978
+ }
979
+ childEditor = null;
980
+ }
981
+ if (container.parentNode) {
982
+ container.parentNode.removeChild(container);
983
+ }
984
+ }, TIMEOUTS.CLEANUP_DELAY);
985
+ };
986
+ try {
987
+ mainEditor.createChildEditor({
988
+ element: container,
989
+ html,
990
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
991
+ onCreate: ({ editor: localEditor }) => {
992
+ if (resolved) return;
993
+ try {
994
+ childEditor = localEditor;
995
+ const json = localEditor.getJSON();
996
+ const normalizedJson = normalizeRunProperties(json);
997
+ resolved = true;
998
+ cleanup();
999
+ resolve(normalizedJson);
1000
+ } catch (err) {
1001
+ resolved = true;
1002
+ cleanup();
1003
+ reject(err);
1004
+ }
1005
+ },
1006
+ onError: (error) => {
1007
+ if (resolved) return;
1008
+ resolved = true;
1009
+ cleanup();
1010
+ reject(error);
1011
+ }
1012
+ });
1013
+ setTimeout(() => {
1014
+ if (!resolved) {
1015
+ resolved = true;
1016
+ cleanup();
1017
+ reject(new Error("Linked HTML parsing timed out"));
1018
+ }
1019
+ }, TIMEOUTS.PARSE_TIMEOUT);
1020
+ } catch (err) {
1021
+ cleanup();
1022
+ reject(err);
1023
+ }
1024
+ });
1025
+ }
965
1026
  async function parseDocxFile(file, SuperDoc) {
966
1027
  const container = document.createElement("div");
967
1028
  container.style.cssText = "position:absolute;top:-9999px;left:-9999px;width:800px;height:600px;visibility:hidden;";
@@ -3305,36 +3366,59 @@ var DocxDiffEditor = forwardRef(
3305
3366
  setMergedJson(normalizedMerged);
3306
3367
  const diff = diffDocuments(cleanBaseline, cleanNewJson);
3307
3368
  setDiffResult(diff);
3369
+ let usedFallback = false;
3308
3370
  if (superdocRef.current?.activeEditor) {
3309
- setEditorContent(superdocRef.current.activeEditor, normalizedMerged);
3310
- enableReviewMode(superdocRef.current);
3311
- const sd = superdocRef.current;
3312
- if (sd.commentsStore?.processLoadedDocxComments) {
3313
- setTimeout(() => {
3314
- try {
3315
- sd.commentsStore.processLoadedDocxComments({
3316
- superdoc: sd,
3317
- editor: sd.activeEditor,
3318
- comments: [],
3319
- // Empty array - we just want to trigger createCommentForTrackChanges
3320
- documentId: sd.activeEditor?.options?.documentId || "primary"
3321
- });
3322
- } catch (err) {
3323
- console.warn("[DocxDiffEditor] Failed to process track changes for bubbles:", err);
3324
- }
3325
- }, 50);
3371
+ try {
3372
+ setEditorContent(superdocRef.current.activeEditor, normalizedMerged);
3373
+ enableReviewMode(superdocRef.current);
3374
+ const sd = superdocRef.current;
3375
+ if (sd.commentsStore?.processLoadedDocxComments) {
3376
+ setTimeout(() => {
3377
+ try {
3378
+ sd.commentsStore.processLoadedDocxComments({
3379
+ superdoc: sd,
3380
+ editor: sd.activeEditor,
3381
+ comments: [],
3382
+ // Empty array - we just want to trigger createCommentForTrackChanges
3383
+ documentId: sd.activeEditor?.options?.documentId || "primary"
3384
+ });
3385
+ } catch (err) {
3386
+ console.warn("[DocxDiffEditor] Failed to process track changes for bubbles:", err);
3387
+ }
3388
+ }, 50);
3389
+ }
3390
+ } catch (contentErr) {
3391
+ console.warn(
3392
+ "[DocxDiffEditor] Failed to apply merged content with track changes. Falling back to direct content update without track bubbles.",
3393
+ contentErr
3394
+ );
3395
+ usedFallback = true;
3396
+ try {
3397
+ setEditorContent(superdocRef.current.activeEditor, normalizedNewJson);
3398
+ setEditingMode(superdocRef.current);
3399
+ } catch (fallbackErr) {
3400
+ console.error("[DocxDiffEditor] Fallback content update also failed:", fallbackErr);
3401
+ throw contentErr;
3402
+ }
3326
3403
  }
3327
3404
  }
3328
- setStructuralChanges(structInfos);
3329
- setIsPaneDismissed(false);
3405
+ if (!usedFallback) {
3406
+ setStructuralChanges(structInfos);
3407
+ setIsPaneDismissed(false);
3408
+ } else {
3409
+ setStructuralChanges([]);
3410
+ }
3330
3411
  const insertions = diff.segments.filter((s) => s.type === "insert").length;
3331
3412
  const deletions = diff.segments.filter((s) => s.type === "delete").length;
3332
3413
  const formatChanges = diff.formatChanges?.length || 0;
3333
- const structuralChangeCount = structInfos.length;
3414
+ const structuralChangeCount = usedFallback ? 0 : structInfos.length;
3334
3415
  const combinedSummary = [...structuralResult.summary];
3335
3416
  if (diff.summary.length > 0 && structuralResult.summary.length === 0) {
3336
3417
  combinedSummary.push(...diff.summary);
3337
3418
  }
3419
+ if (usedFallback) {
3420
+ combinedSummary.push("Note: Track change visualization unavailable for this content");
3421
+ }
3338
3422
  const result = {
3339
3423
  totalChanges: insertions + deletions + formatChanges + structuralChangeCount,
3340
3424
  insertions,
@@ -3342,8 +3426,9 @@ var DocxDiffEditor = forwardRef(
3342
3426
  formatChanges,
3343
3427
  structuralChanges: structuralChangeCount,
3344
3428
  summary: combinedSummary,
3345
- mergedJson: merged,
3346
- structuralChangeInfos: structInfos
3429
+ mergedJson: usedFallback ? normalizedNewJson : merged,
3430
+ structuralChangeInfos: usedFallback ? [] : structInfos,
3431
+ usedFallback
3347
3432
  };
3348
3433
  onComparisonComplete?.(result);
3349
3434
  return result;
@@ -3640,13 +3725,30 @@ var DocxDiffEditor = forwardRef(
3640
3725
  }
3641
3726
  },
3642
3727
  /**
3643
- * Parse HTML string to ProseMirror JSON using a hidden SuperDoc instance.
3644
- * Useful for converting HTML content before using with other methods.
3728
+ * Parse HTML string to ProseMirror JSON.
3729
+ *
3730
+ * When the main editor is ready, this uses a linked child editor approach
3731
+ * which ensures list numbering definitions are synced to the main document.
3732
+ * This prevents crashes when parsed content with lists is spliced into
3733
+ * the main document via compareWith().
3734
+ *
3735
+ * Falls back to an isolated SuperDoc instance if the main editor isn't ready.
3645
3736
  */
3646
3737
  async parseHtml(html) {
3647
3738
  if (!SuperDocRef.current) {
3648
3739
  throw new Error("Editor not initialized");
3649
3740
  }
3741
+ const mainEditor = superdocRef.current?.activeEditor;
3742
+ if (mainEditor?.createChildEditor) {
3743
+ try {
3744
+ return await parseHtmlWithLinkedEditor(html, mainEditor);
3745
+ } catch (err) {
3746
+ console.warn(
3747
+ "[DocxDiffEditor] Linked HTML parsing failed, falling back to isolated approach:",
3748
+ err
3749
+ );
3750
+ }
3751
+ }
3650
3752
  return parseHtmlToJson(html, SuperDocRef.current);
3651
3753
  }
3652
3754
  }),