docx-diff-editor 1.0.9 → 1.0.10

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.js CHANGED
@@ -723,6 +723,72 @@ var DocxDiffEditor = react.forwardRef(
723
723
  }
724
724
  readyRef.current = false;
725
725
  }, []);
726
+ const convertHtmlToDocxBlob = react.useCallback(
727
+ async (html) => {
728
+ if (!SuperDocRef.current) {
729
+ throw new Error("SuperDoc not loaded");
730
+ }
731
+ const hiddenContainer = document.createElement("div");
732
+ hiddenContainer.id = `dde-hidden-${Date.now()}`;
733
+ hiddenContainer.style.cssText = "position:absolute;top:-9999px;left:-9999px;width:800px;height:600px;visibility:hidden;pointer-events:none;";
734
+ document.body.appendChild(hiddenContainer);
735
+ return new Promise((resolve, reject) => {
736
+ let tempSuperdoc = null;
737
+ let timeoutId;
738
+ const cleanup = () => {
739
+ clearTimeout(timeoutId);
740
+ try {
741
+ tempSuperdoc?.destroy?.();
742
+ } catch {
743
+ }
744
+ hiddenContainer.parentNode?.removeChild(hiddenContainer);
745
+ };
746
+ try {
747
+ tempSuperdoc = new SuperDocRef.current({
748
+ selector: `#${hiddenContainer.id}`,
749
+ html,
750
+ documentMode: "editing",
751
+ rulers: false,
752
+ user: { name: "Converter", email: "converter@local" },
753
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
754
+ onReady: async ({ superdoc: sd }) => {
755
+ try {
756
+ const json = sd?.activeEditor?.getJSON() || { type: "doc", content: [] };
757
+ if (!sd?.activeEditor?.exportDocx) {
758
+ cleanup();
759
+ reject(new Error("exportDocx method not available"));
760
+ return;
761
+ }
762
+ const blob = await sd.activeEditor.exportDocx({ isFinalDoc: false });
763
+ if (!blob) {
764
+ cleanup();
765
+ reject(new Error("Export returned no data"));
766
+ return;
767
+ }
768
+ cleanup();
769
+ resolve({ blob, json });
770
+ } catch (err) {
771
+ cleanup();
772
+ reject(err);
773
+ }
774
+ },
775
+ onException: ({ error: err }) => {
776
+ cleanup();
777
+ reject(err);
778
+ }
779
+ });
780
+ timeoutId = setTimeout(() => {
781
+ cleanup();
782
+ reject(new Error("HTML to DOCX conversion timed out"));
783
+ }, TIMEOUTS.PARSE_TIMEOUT);
784
+ } catch (err) {
785
+ cleanup();
786
+ reject(err);
787
+ }
788
+ });
789
+ },
790
+ []
791
+ );
726
792
  const createSuperdoc = react.useCallback(
727
793
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
728
794
  async (options) => {
@@ -732,16 +798,31 @@ var DocxDiffEditor = react.forwardRef(
732
798
  if (!containerRef.current) {
733
799
  throw new Error("Container not available");
734
800
  }
801
+ containerRef.current.innerHTML = "";
802
+ if (toolbarRef.current) {
803
+ toolbarRef.current.innerHTML = "";
804
+ }
735
805
  containerRef.current.id = editorId;
736
806
  if (toolbarRef.current) {
737
807
  toolbarRef.current.id = toolbarId;
738
808
  }
809
+ let documentFile;
810
+ if (options.document) {
811
+ if (options.document instanceof File) {
812
+ documentFile = options.document;
813
+ } else {
814
+ documentFile = new File([options.document], "document.docx", {
815
+ type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
816
+ });
817
+ }
818
+ }
739
819
  return new Promise((resolve, reject) => {
820
+ let resolved = false;
740
821
  try {
741
822
  const superdoc = new SuperDocRef.current({
742
823
  selector: `#${editorId}`,
743
824
  toolbar: showToolbar ? `#${toolbarId}` : void 0,
744
- document: options.document,
825
+ document: documentFile,
745
826
  html: options.html,
746
827
  documentMode: "editing",
747
828
  role: "editor",
@@ -751,6 +832,8 @@ var DocxDiffEditor = react.forwardRef(
751
832
  // Enable comments module for track changes sidebar
752
833
  modules: { comments: {} },
753
834
  onReady: ({ superdoc: sd }) => {
835
+ if (resolved) return;
836
+ resolved = true;
754
837
  superdocRef.current = sd;
755
838
  readyRef.current = true;
756
839
  let json = { type: "doc", content: [] };
@@ -764,18 +847,24 @@ var DocxDiffEditor = react.forwardRef(
764
847
  resolve({ superdoc: sd, json });
765
848
  },
766
849
  onException: ({ error: err }) => {
850
+ if (resolved) return;
851
+ resolved = true;
767
852
  console.error("SuperDoc error:", err);
768
853
  reject(err);
769
854
  }
770
855
  });
771
856
  superdocRef.current = superdoc;
772
857
  setTimeout(() => {
773
- if (!readyRef.current) {
858
+ if (!resolved) {
859
+ resolved = true;
774
860
  reject(new Error("SuperDoc initialization timed out"));
775
861
  }
776
862
  }, TIMEOUTS.PARSE_TIMEOUT);
777
863
  } catch (err) {
778
- reject(err);
864
+ if (!resolved) {
865
+ resolved = true;
866
+ reject(err);
867
+ }
779
868
  }
780
869
  });
781
870
  },
@@ -799,12 +888,15 @@ var DocxDiffEditor = react.forwardRef(
799
888
  const { SuperDoc } = await import('superdoc');
800
889
  SuperDocRef.current = SuperDoc;
801
890
  let initOptions = {};
891
+ let extractedJson = null;
802
892
  if (initialSource) {
803
893
  const contentType = detectContentType(initialSource);
804
894
  if (contentType === "file") {
805
895
  initOptions = { document: initialSource };
806
896
  } else if (contentType === "html") {
807
- initOptions = { html: initialSource };
897
+ const { blob, json: htmlJson } = await convertHtmlToDocxBlob(initialSource);
898
+ initOptions = { document: blob };
899
+ extractedJson = htmlJson;
808
900
  } else if (contentType === "json") {
809
901
  initOptions = templateDocx ? { document: templateDocx } : {};
810
902
  }
@@ -819,8 +911,9 @@ var DocxDiffEditor = react.forwardRef(
819
911
  onSourceLoaded?.(initialSource);
820
912
  }
821
913
  } else {
822
- setSourceJson(json);
823
- onSourceLoaded?.(json);
914
+ const finalJson = extractedJson || json;
915
+ setSourceJson(finalJson);
916
+ onSourceLoaded?.(finalJson);
824
917
  }
825
918
  setIsLoading(false);
826
919
  onReady?.();
@@ -839,6 +932,7 @@ var DocxDiffEditor = react.forwardRef(
839
932
  onSourceLoaded,
840
933
  destroySuperdoc,
841
934
  createSuperdoc,
935
+ convertHtmlToDocxBlob,
842
936
  setEditorContent,
843
937
  handleError
844
938
  ]);
@@ -854,7 +948,11 @@ var DocxDiffEditor = react.forwardRef(
854
948
  ref,
855
949
  () => ({
856
950
  /**
857
- * Set the source/base document
951
+ * Set the source/base document.
952
+ *
953
+ * For HTML content, we convert to DOCX first using a hidden SuperDoc instance.
954
+ * This is critical because SuperDoc's track change infrastructure (including
955
+ * track bubbles) is only properly initialized when loading from a DOCX file.
858
956
  */
859
957
  async setSource(content) {
860
958
  if (!SuperDocRef.current) {
@@ -870,8 +968,15 @@ var DocxDiffEditor = react.forwardRef(
870
968
  const result = await createSuperdoc({ document: content });
871
969
  json = result.json;
872
970
  } else if (contentType === "html") {
873
- const result = await createSuperdoc({ html: content });
874
- json = result.json;
971
+ const { blob, json: extractedJson } = await convertHtmlToDocxBlob(content);
972
+ const result = await createSuperdoc({ document: blob });
973
+ json = extractedJson;
974
+ if (result.superdoc?.activeEditor) {
975
+ const editorJson = result.superdoc.activeEditor.getJSON();
976
+ if (!extractedJson.content || extractedJson.content.length === 0) {
977
+ json = editorJson;
978
+ }
979
+ }
875
980
  } else {
876
981
  const result = await createSuperdoc(templateDocx ? { document: templateDocx } : {});
877
982
  if (result.superdoc?.activeEditor && isProseMirrorJSON(content)) {
@@ -966,9 +1071,6 @@ var DocxDiffEditor = react.forwardRef(
966
1071
  const merged = mergeDocuments(sourceJson, newJson, diff, author);
967
1072
  setMergedJson(merged);
968
1073
  if (superdocRef.current?.activeEditor) {
969
- if (superdocRef.current.setDocumentMode) {
970
- superdocRef.current.setDocumentMode("suggesting");
971
- }
972
1074
  setEditorContent(superdocRef.current.activeEditor, merged);
973
1075
  enableReviewMode(superdocRef.current);
974
1076
  }
@@ -1061,6 +1163,7 @@ var DocxDiffEditor = react.forwardRef(
1061
1163
  author,
1062
1164
  destroySuperdoc,
1063
1165
  createSuperdoc,
1166
+ convertHtmlToDocxBlob,
1064
1167
  setEditorContent,
1065
1168
  enableReviewMode,
1066
1169
  setEditingMode,