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.mjs
CHANGED
|
@@ -715,6 +715,74 @@ var DocxDiffEditor = forwardRef(
|
|
|
715
715
|
}
|
|
716
716
|
readyRef.current = false;
|
|
717
717
|
}, []);
|
|
718
|
+
const convertHtmlToDocxBlob = useCallback(
|
|
719
|
+
async (html) => {
|
|
720
|
+
if (!SuperDocRef.current) {
|
|
721
|
+
throw new Error("SuperDoc not loaded");
|
|
722
|
+
}
|
|
723
|
+
const hiddenContainer = document.createElement("div");
|
|
724
|
+
hiddenContainer.id = `dde-hidden-${Date.now()}`;
|
|
725
|
+
hiddenContainer.style.cssText = "position:absolute;top:-9999px;left:-9999px;width:800px;height:600px;visibility:hidden;pointer-events:none;";
|
|
726
|
+
document.body.appendChild(hiddenContainer);
|
|
727
|
+
return new Promise((resolve, reject) => {
|
|
728
|
+
let resolved = false;
|
|
729
|
+
let tempSuperdoc = null;
|
|
730
|
+
const cleanup = () => {
|
|
731
|
+
try {
|
|
732
|
+
tempSuperdoc?.destroy?.();
|
|
733
|
+
} catch {
|
|
734
|
+
}
|
|
735
|
+
hiddenContainer.parentNode?.removeChild(hiddenContainer);
|
|
736
|
+
};
|
|
737
|
+
try {
|
|
738
|
+
tempSuperdoc = new SuperDocRef.current({
|
|
739
|
+
selector: `#${hiddenContainer.id}`,
|
|
740
|
+
html,
|
|
741
|
+
documentMode: "editing",
|
|
742
|
+
rulers: false,
|
|
743
|
+
user: { name: "Converter", email: "converter@local" },
|
|
744
|
+
onReady: async ({ superdoc: sd }) => {
|
|
745
|
+
if (resolved) return;
|
|
746
|
+
try {
|
|
747
|
+
const json = sd?.activeEditor?.getJSON() || { type: "doc", content: [] };
|
|
748
|
+
const blob = await sd?.activeEditor?.exportDocx({ isFinalDoc: true });
|
|
749
|
+
if (!blob) {
|
|
750
|
+
throw new Error("Export returned no data");
|
|
751
|
+
}
|
|
752
|
+
resolved = true;
|
|
753
|
+
cleanup();
|
|
754
|
+
resolve({ blob, json });
|
|
755
|
+
} catch (err) {
|
|
756
|
+
resolved = true;
|
|
757
|
+
cleanup();
|
|
758
|
+
reject(err);
|
|
759
|
+
}
|
|
760
|
+
},
|
|
761
|
+
onException: ({ error: err }) => {
|
|
762
|
+
if (resolved) return;
|
|
763
|
+
resolved = true;
|
|
764
|
+
cleanup();
|
|
765
|
+
reject(err);
|
|
766
|
+
}
|
|
767
|
+
});
|
|
768
|
+
setTimeout(() => {
|
|
769
|
+
if (!resolved) {
|
|
770
|
+
resolved = true;
|
|
771
|
+
cleanup();
|
|
772
|
+
reject(new Error("HTML to DOCX conversion timed out"));
|
|
773
|
+
}
|
|
774
|
+
}, TIMEOUTS.PARSE_TIMEOUT);
|
|
775
|
+
} catch (err) {
|
|
776
|
+
if (!resolved) {
|
|
777
|
+
resolved = true;
|
|
778
|
+
cleanup();
|
|
779
|
+
reject(err);
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
});
|
|
783
|
+
},
|
|
784
|
+
[]
|
|
785
|
+
);
|
|
718
786
|
const createSuperdoc = useCallback(
|
|
719
787
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
720
788
|
async (options) => {
|
|
@@ -724,25 +792,29 @@ var DocxDiffEditor = forwardRef(
|
|
|
724
792
|
if (!containerRef.current) {
|
|
725
793
|
throw new Error("Container not available");
|
|
726
794
|
}
|
|
795
|
+
containerRef.current.innerHTML = "";
|
|
796
|
+
if (toolbarRef.current) {
|
|
797
|
+
toolbarRef.current.innerHTML = "";
|
|
798
|
+
}
|
|
727
799
|
containerRef.current.id = editorId;
|
|
728
800
|
if (toolbarRef.current) {
|
|
729
801
|
toolbarRef.current.id = toolbarId;
|
|
730
802
|
}
|
|
731
803
|
return new Promise((resolve, reject) => {
|
|
804
|
+
let resolved = false;
|
|
732
805
|
try {
|
|
733
806
|
const superdoc = new SuperDocRef.current({
|
|
734
807
|
selector: `#${editorId}`,
|
|
735
808
|
toolbar: showToolbar ? `#${toolbarId}` : void 0,
|
|
736
809
|
document: options.document,
|
|
737
|
-
html: options.html,
|
|
738
810
|
documentMode: "editing",
|
|
739
811
|
role: "editor",
|
|
740
812
|
rulers: showRulers,
|
|
741
813
|
user: DEFAULT_SUPERDOC_USER,
|
|
742
814
|
permissionResolver,
|
|
743
|
-
// Enable comments module for track changes sidebar
|
|
744
|
-
modules: { comments: {} },
|
|
745
815
|
onReady: ({ superdoc: sd }) => {
|
|
816
|
+
if (resolved) return;
|
|
817
|
+
resolved = true;
|
|
746
818
|
superdocRef.current = sd;
|
|
747
819
|
readyRef.current = true;
|
|
748
820
|
let json = { type: "doc", content: [] };
|
|
@@ -756,18 +828,24 @@ var DocxDiffEditor = forwardRef(
|
|
|
756
828
|
resolve({ superdoc: sd, json });
|
|
757
829
|
},
|
|
758
830
|
onException: ({ error: err }) => {
|
|
831
|
+
if (resolved) return;
|
|
832
|
+
resolved = true;
|
|
759
833
|
console.error("SuperDoc error:", err);
|
|
760
834
|
reject(err);
|
|
761
835
|
}
|
|
762
836
|
});
|
|
763
837
|
superdocRef.current = superdoc;
|
|
764
838
|
setTimeout(() => {
|
|
765
|
-
if (!
|
|
839
|
+
if (!resolved) {
|
|
840
|
+
resolved = true;
|
|
766
841
|
reject(new Error("SuperDoc initialization timed out"));
|
|
767
842
|
}
|
|
768
843
|
}, TIMEOUTS.PARSE_TIMEOUT);
|
|
769
844
|
} catch (err) {
|
|
770
|
-
|
|
845
|
+
if (!resolved) {
|
|
846
|
+
resolved = true;
|
|
847
|
+
reject(err);
|
|
848
|
+
}
|
|
771
849
|
}
|
|
772
850
|
});
|
|
773
851
|
},
|
|
@@ -791,12 +869,15 @@ var DocxDiffEditor = forwardRef(
|
|
|
791
869
|
const { SuperDoc } = await import('superdoc');
|
|
792
870
|
SuperDocRef.current = SuperDoc;
|
|
793
871
|
let initOptions = {};
|
|
872
|
+
let extractedJson = null;
|
|
794
873
|
if (initialSource) {
|
|
795
874
|
const contentType = detectContentType(initialSource);
|
|
796
875
|
if (contentType === "file") {
|
|
797
876
|
initOptions = { document: initialSource };
|
|
798
877
|
} else if (contentType === "html") {
|
|
799
|
-
|
|
878
|
+
const { blob, json: htmlJson } = await convertHtmlToDocxBlob(initialSource);
|
|
879
|
+
initOptions = { document: blob };
|
|
880
|
+
extractedJson = htmlJson;
|
|
800
881
|
} else if (contentType === "json") {
|
|
801
882
|
initOptions = templateDocx ? { document: templateDocx } : {};
|
|
802
883
|
}
|
|
@@ -811,8 +892,9 @@ var DocxDiffEditor = forwardRef(
|
|
|
811
892
|
onSourceLoaded?.(initialSource);
|
|
812
893
|
}
|
|
813
894
|
} else {
|
|
814
|
-
|
|
815
|
-
|
|
895
|
+
const sourceJsonToUse = extractedJson || json;
|
|
896
|
+
setSourceJson(sourceJsonToUse);
|
|
897
|
+
onSourceLoaded?.(sourceJsonToUse);
|
|
816
898
|
}
|
|
817
899
|
setIsLoading(false);
|
|
818
900
|
onReady?.();
|
|
@@ -831,6 +913,7 @@ var DocxDiffEditor = forwardRef(
|
|
|
831
913
|
onSourceLoaded,
|
|
832
914
|
destroySuperdoc,
|
|
833
915
|
createSuperdoc,
|
|
916
|
+
convertHtmlToDocxBlob,
|
|
834
917
|
setEditorContent,
|
|
835
918
|
handleError
|
|
836
919
|
]);
|
|
@@ -846,7 +929,10 @@ var DocxDiffEditor = forwardRef(
|
|
|
846
929
|
ref,
|
|
847
930
|
() => ({
|
|
848
931
|
/**
|
|
849
|
-
* Set the source/base document
|
|
932
|
+
* Set the source/base document.
|
|
933
|
+
*
|
|
934
|
+
* IMPORTANT: For HTML content, we convert to DOCX first using a hidden
|
|
935
|
+
* SuperDoc instance. This is required for track bubbles to work properly.
|
|
850
936
|
*/
|
|
851
937
|
async setSource(content) {
|
|
852
938
|
if (!SuperDocRef.current) {
|
|
@@ -862,8 +948,9 @@ var DocxDiffEditor = forwardRef(
|
|
|
862
948
|
const result = await createSuperdoc({ document: content });
|
|
863
949
|
json = result.json;
|
|
864
950
|
} else if (contentType === "html") {
|
|
865
|
-
const
|
|
866
|
-
|
|
951
|
+
const { blob, json: htmlJson } = await convertHtmlToDocxBlob(content);
|
|
952
|
+
const result = await createSuperdoc({ document: blob });
|
|
953
|
+
json = htmlJson;
|
|
867
954
|
} else {
|
|
868
955
|
const result = await createSuperdoc(templateDocx ? { document: templateDocx } : {});
|
|
869
956
|
if (result.superdoc?.activeEditor && isProseMirrorJSON(content)) {
|
|
@@ -958,11 +1045,24 @@ var DocxDiffEditor = forwardRef(
|
|
|
958
1045
|
const merged = mergeDocuments(sourceJson, newJson, diff, author);
|
|
959
1046
|
setMergedJson(merged);
|
|
960
1047
|
if (superdocRef.current?.activeEditor) {
|
|
961
|
-
if (superdocRef.current.setDocumentMode) {
|
|
962
|
-
superdocRef.current.setDocumentMode("suggesting");
|
|
963
|
-
}
|
|
964
1048
|
setEditorContent(superdocRef.current.activeEditor, merged);
|
|
965
1049
|
enableReviewMode(superdocRef.current);
|
|
1050
|
+
const sd = superdocRef.current;
|
|
1051
|
+
if (sd.commentsStore?.processLoadedDocxComments) {
|
|
1052
|
+
setTimeout(() => {
|
|
1053
|
+
try {
|
|
1054
|
+
sd.commentsStore.processLoadedDocxComments({
|
|
1055
|
+
superdoc: sd,
|
|
1056
|
+
editor: sd.activeEditor,
|
|
1057
|
+
comments: [],
|
|
1058
|
+
// Empty array - we just want to trigger createCommentForTrackChanges
|
|
1059
|
+
documentId: sd.activeEditor?.options?.documentId || "primary"
|
|
1060
|
+
});
|
|
1061
|
+
} catch (err) {
|
|
1062
|
+
console.warn("[DocxDiffEditor] Failed to process track changes for bubbles:", err);
|
|
1063
|
+
}
|
|
1064
|
+
}, 50);
|
|
1065
|
+
}
|
|
966
1066
|
}
|
|
967
1067
|
const insertions = diff.segments.filter((s) => s.type === "insert").length;
|
|
968
1068
|
const deletions = diff.segments.filter((s) => s.type === "delete").length;
|
|
@@ -1053,6 +1153,7 @@ var DocxDiffEditor = forwardRef(
|
|
|
1053
1153
|
author,
|
|
1054
1154
|
destroySuperdoc,
|
|
1055
1155
|
createSuperdoc,
|
|
1156
|
+
convertHtmlToDocxBlob,
|
|
1056
1157
|
setEditorContent,
|
|
1057
1158
|
enableReviewMode,
|
|
1058
1159
|
setEditingMode,
|