docx-diff-editor 1.0.9 → 1.0.14
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 +115 -14
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +115 -14
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -723,6 +723,74 @@ 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 resolved = false;
|
|
737
|
+
let tempSuperdoc = null;
|
|
738
|
+
const cleanup = () => {
|
|
739
|
+
try {
|
|
740
|
+
tempSuperdoc?.destroy?.();
|
|
741
|
+
} catch {
|
|
742
|
+
}
|
|
743
|
+
hiddenContainer.parentNode?.removeChild(hiddenContainer);
|
|
744
|
+
};
|
|
745
|
+
try {
|
|
746
|
+
tempSuperdoc = new SuperDocRef.current({
|
|
747
|
+
selector: `#${hiddenContainer.id}`,
|
|
748
|
+
html,
|
|
749
|
+
documentMode: "editing",
|
|
750
|
+
rulers: false,
|
|
751
|
+
user: { name: "Converter", email: "converter@local" },
|
|
752
|
+
onReady: async ({ superdoc: sd }) => {
|
|
753
|
+
if (resolved) return;
|
|
754
|
+
try {
|
|
755
|
+
const json = sd?.activeEditor?.getJSON() || { type: "doc", content: [] };
|
|
756
|
+
const blob = await sd?.activeEditor?.exportDocx({ isFinalDoc: true });
|
|
757
|
+
if (!blob) {
|
|
758
|
+
throw new Error("Export returned no data");
|
|
759
|
+
}
|
|
760
|
+
resolved = true;
|
|
761
|
+
cleanup();
|
|
762
|
+
resolve({ blob, json });
|
|
763
|
+
} catch (err) {
|
|
764
|
+
resolved = true;
|
|
765
|
+
cleanup();
|
|
766
|
+
reject(err);
|
|
767
|
+
}
|
|
768
|
+
},
|
|
769
|
+
onException: ({ error: err }) => {
|
|
770
|
+
if (resolved) return;
|
|
771
|
+
resolved = true;
|
|
772
|
+
cleanup();
|
|
773
|
+
reject(err);
|
|
774
|
+
}
|
|
775
|
+
});
|
|
776
|
+
setTimeout(() => {
|
|
777
|
+
if (!resolved) {
|
|
778
|
+
resolved = true;
|
|
779
|
+
cleanup();
|
|
780
|
+
reject(new Error("HTML to DOCX conversion timed out"));
|
|
781
|
+
}
|
|
782
|
+
}, TIMEOUTS.PARSE_TIMEOUT);
|
|
783
|
+
} catch (err) {
|
|
784
|
+
if (!resolved) {
|
|
785
|
+
resolved = true;
|
|
786
|
+
cleanup();
|
|
787
|
+
reject(err);
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
});
|
|
791
|
+
},
|
|
792
|
+
[]
|
|
793
|
+
);
|
|
726
794
|
const createSuperdoc = react.useCallback(
|
|
727
795
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
728
796
|
async (options) => {
|
|
@@ -732,25 +800,29 @@ var DocxDiffEditor = react.forwardRef(
|
|
|
732
800
|
if (!containerRef.current) {
|
|
733
801
|
throw new Error("Container not available");
|
|
734
802
|
}
|
|
803
|
+
containerRef.current.innerHTML = "";
|
|
804
|
+
if (toolbarRef.current) {
|
|
805
|
+
toolbarRef.current.innerHTML = "";
|
|
806
|
+
}
|
|
735
807
|
containerRef.current.id = editorId;
|
|
736
808
|
if (toolbarRef.current) {
|
|
737
809
|
toolbarRef.current.id = toolbarId;
|
|
738
810
|
}
|
|
739
811
|
return new Promise((resolve, reject) => {
|
|
812
|
+
let resolved = false;
|
|
740
813
|
try {
|
|
741
814
|
const superdoc = new SuperDocRef.current({
|
|
742
815
|
selector: `#${editorId}`,
|
|
743
816
|
toolbar: showToolbar ? `#${toolbarId}` : void 0,
|
|
744
817
|
document: options.document,
|
|
745
|
-
html: options.html,
|
|
746
818
|
documentMode: "editing",
|
|
747
819
|
role: "editor",
|
|
748
820
|
rulers: showRulers,
|
|
749
821
|
user: DEFAULT_SUPERDOC_USER,
|
|
750
822
|
permissionResolver,
|
|
751
|
-
// Enable comments module for track changes sidebar
|
|
752
|
-
modules: { comments: {} },
|
|
753
823
|
onReady: ({ superdoc: sd }) => {
|
|
824
|
+
if (resolved) return;
|
|
825
|
+
resolved = true;
|
|
754
826
|
superdocRef.current = sd;
|
|
755
827
|
readyRef.current = true;
|
|
756
828
|
let json = { type: "doc", content: [] };
|
|
@@ -764,18 +836,24 @@ var DocxDiffEditor = react.forwardRef(
|
|
|
764
836
|
resolve({ superdoc: sd, json });
|
|
765
837
|
},
|
|
766
838
|
onException: ({ error: err }) => {
|
|
839
|
+
if (resolved) return;
|
|
840
|
+
resolved = true;
|
|
767
841
|
console.error("SuperDoc error:", err);
|
|
768
842
|
reject(err);
|
|
769
843
|
}
|
|
770
844
|
});
|
|
771
845
|
superdocRef.current = superdoc;
|
|
772
846
|
setTimeout(() => {
|
|
773
|
-
if (!
|
|
847
|
+
if (!resolved) {
|
|
848
|
+
resolved = true;
|
|
774
849
|
reject(new Error("SuperDoc initialization timed out"));
|
|
775
850
|
}
|
|
776
851
|
}, TIMEOUTS.PARSE_TIMEOUT);
|
|
777
852
|
} catch (err) {
|
|
778
|
-
|
|
853
|
+
if (!resolved) {
|
|
854
|
+
resolved = true;
|
|
855
|
+
reject(err);
|
|
856
|
+
}
|
|
779
857
|
}
|
|
780
858
|
});
|
|
781
859
|
},
|
|
@@ -799,12 +877,15 @@ var DocxDiffEditor = react.forwardRef(
|
|
|
799
877
|
const { SuperDoc } = await import('superdoc');
|
|
800
878
|
SuperDocRef.current = SuperDoc;
|
|
801
879
|
let initOptions = {};
|
|
880
|
+
let extractedJson = null;
|
|
802
881
|
if (initialSource) {
|
|
803
882
|
const contentType = detectContentType(initialSource);
|
|
804
883
|
if (contentType === "file") {
|
|
805
884
|
initOptions = { document: initialSource };
|
|
806
885
|
} else if (contentType === "html") {
|
|
807
|
-
|
|
886
|
+
const { blob, json: htmlJson } = await convertHtmlToDocxBlob(initialSource);
|
|
887
|
+
initOptions = { document: blob };
|
|
888
|
+
extractedJson = htmlJson;
|
|
808
889
|
} else if (contentType === "json") {
|
|
809
890
|
initOptions = templateDocx ? { document: templateDocx } : {};
|
|
810
891
|
}
|
|
@@ -819,8 +900,9 @@ var DocxDiffEditor = react.forwardRef(
|
|
|
819
900
|
onSourceLoaded?.(initialSource);
|
|
820
901
|
}
|
|
821
902
|
} else {
|
|
822
|
-
|
|
823
|
-
|
|
903
|
+
const sourceJsonToUse = extractedJson || json;
|
|
904
|
+
setSourceJson(sourceJsonToUse);
|
|
905
|
+
onSourceLoaded?.(sourceJsonToUse);
|
|
824
906
|
}
|
|
825
907
|
setIsLoading(false);
|
|
826
908
|
onReady?.();
|
|
@@ -839,6 +921,7 @@ var DocxDiffEditor = react.forwardRef(
|
|
|
839
921
|
onSourceLoaded,
|
|
840
922
|
destroySuperdoc,
|
|
841
923
|
createSuperdoc,
|
|
924
|
+
convertHtmlToDocxBlob,
|
|
842
925
|
setEditorContent,
|
|
843
926
|
handleError
|
|
844
927
|
]);
|
|
@@ -854,7 +937,10 @@ var DocxDiffEditor = react.forwardRef(
|
|
|
854
937
|
ref,
|
|
855
938
|
() => ({
|
|
856
939
|
/**
|
|
857
|
-
* Set the source/base document
|
|
940
|
+
* Set the source/base document.
|
|
941
|
+
*
|
|
942
|
+
* IMPORTANT: For HTML content, we convert to DOCX first using a hidden
|
|
943
|
+
* SuperDoc instance. This is required for track bubbles to work properly.
|
|
858
944
|
*/
|
|
859
945
|
async setSource(content) {
|
|
860
946
|
if (!SuperDocRef.current) {
|
|
@@ -870,8 +956,9 @@ var DocxDiffEditor = react.forwardRef(
|
|
|
870
956
|
const result = await createSuperdoc({ document: content });
|
|
871
957
|
json = result.json;
|
|
872
958
|
} else if (contentType === "html") {
|
|
873
|
-
const
|
|
874
|
-
|
|
959
|
+
const { blob, json: htmlJson } = await convertHtmlToDocxBlob(content);
|
|
960
|
+
const result = await createSuperdoc({ document: blob });
|
|
961
|
+
json = htmlJson;
|
|
875
962
|
} else {
|
|
876
963
|
const result = await createSuperdoc(templateDocx ? { document: templateDocx } : {});
|
|
877
964
|
if (result.superdoc?.activeEditor && isProseMirrorJSON(content)) {
|
|
@@ -966,11 +1053,24 @@ var DocxDiffEditor = react.forwardRef(
|
|
|
966
1053
|
const merged = mergeDocuments(sourceJson, newJson, diff, author);
|
|
967
1054
|
setMergedJson(merged);
|
|
968
1055
|
if (superdocRef.current?.activeEditor) {
|
|
969
|
-
if (superdocRef.current.setDocumentMode) {
|
|
970
|
-
superdocRef.current.setDocumentMode("suggesting");
|
|
971
|
-
}
|
|
972
1056
|
setEditorContent(superdocRef.current.activeEditor, merged);
|
|
973
1057
|
enableReviewMode(superdocRef.current);
|
|
1058
|
+
const sd = superdocRef.current;
|
|
1059
|
+
if (sd.commentsStore?.processLoadedDocxComments) {
|
|
1060
|
+
setTimeout(() => {
|
|
1061
|
+
try {
|
|
1062
|
+
sd.commentsStore.processLoadedDocxComments({
|
|
1063
|
+
superdoc: sd,
|
|
1064
|
+
editor: sd.activeEditor,
|
|
1065
|
+
comments: [],
|
|
1066
|
+
// Empty array - we just want to trigger createCommentForTrackChanges
|
|
1067
|
+
documentId: sd.activeEditor?.options?.documentId || "primary"
|
|
1068
|
+
});
|
|
1069
|
+
} catch (err) {
|
|
1070
|
+
console.warn("[DocxDiffEditor] Failed to process track changes for bubbles:", err);
|
|
1071
|
+
}
|
|
1072
|
+
}, 50);
|
|
1073
|
+
}
|
|
974
1074
|
}
|
|
975
1075
|
const insertions = diff.segments.filter((s) => s.type === "insert").length;
|
|
976
1076
|
const deletions = diff.segments.filter((s) => s.type === "delete").length;
|
|
@@ -1061,6 +1161,7 @@ var DocxDiffEditor = react.forwardRef(
|
|
|
1061
1161
|
author,
|
|
1062
1162
|
destroySuperdoc,
|
|
1063
1163
|
createSuperdoc,
|
|
1164
|
+
convertHtmlToDocxBlob,
|
|
1064
1165
|
setEditorContent,
|
|
1065
1166
|
enableReviewMode,
|
|
1066
1167
|
setEditingMode,
|