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 +115 -12
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +115 -12
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
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:
|
|
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 (!
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
823
|
-
|
|
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
|
|
874
|
-
|
|
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,
|