docx-diff-editor 1.0.58 → 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/README.md CHANGED
@@ -269,6 +269,11 @@ Convert HTML strings to ProseMirror JSON without visible rendering. **Inline sty
269
269
  const json = await editorRef.current?.parseHtml('<h1>Title</h1><p>Content here</p>');
270
270
  console.log(json); // { type: 'doc', content: [...] }
271
271
 
272
+ // Lists work correctly - numbering definitions are synced to the main document
273
+ const listJson = await editorRef.current?.parseHtml(
274
+ '<ul><li>Item 1</li><li>Item 2</li></ul>'
275
+ );
276
+
272
277
  // Inline styles are converted to marks
273
278
  const styledJson = await editorRef.current?.parseHtml(
274
279
  '<p><span style="color: red; font-weight: bold;">styled text</span></p>'
@@ -283,6 +288,14 @@ import { parseHtmlToJson } from 'docx-diff-editor';
283
288
  const json = await parseHtmlToJson(htmlString, SuperDocClass);
284
289
  ```
285
290
 
291
+ ### Linked Parsing for Lists
292
+
293
+ When the main editor is ready, `parseHtml()` automatically uses a **linked child editor** approach. This ensures that list numbering definitions (for `<ol>` and `<ul>` elements) are synced to the main document's numbering store.
294
+
295
+ This prevents crashes when parsed content with lists is later spliced into the main document and rendered via `compareWith()`.
296
+
297
+ If the main editor isn't ready yet, the method falls back to an isolated SuperDoc instance.
298
+
286
299
  ### Supported Inline Styles
287
300
 
288
301
  | CSS Property | ProseMirror Mark |
package/dist/index.js CHANGED
@@ -970,6 +970,67 @@ async function parseHtmlToJson(html, SuperDoc) {
970
970
  }, 50);
971
971
  });
972
972
  }
973
+ async function parseHtmlWithLinkedEditor(html, mainEditor) {
974
+ const container = document.createElement("div");
975
+ container.style.cssText = "position:absolute;top:-9999px;left:-9999px;width:800px;height:600px;visibility:hidden;";
976
+ document.body.appendChild(container);
977
+ return new Promise((resolve, reject) => {
978
+ let resolved = false;
979
+ let childEditor = null;
980
+ const cleanup = () => {
981
+ setTimeout(() => {
982
+ if (childEditor) {
983
+ try {
984
+ childEditor.destroy?.();
985
+ } catch {
986
+ }
987
+ childEditor = null;
988
+ }
989
+ if (container.parentNode) {
990
+ container.parentNode.removeChild(container);
991
+ }
992
+ }, TIMEOUTS.CLEANUP_DELAY);
993
+ };
994
+ try {
995
+ mainEditor.createChildEditor({
996
+ element: container,
997
+ html,
998
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
999
+ onCreate: ({ editor: localEditor }) => {
1000
+ if (resolved) return;
1001
+ try {
1002
+ childEditor = localEditor;
1003
+ const json = localEditor.getJSON();
1004
+ const normalizedJson = normalizeRunProperties(json);
1005
+ resolved = true;
1006
+ cleanup();
1007
+ resolve(normalizedJson);
1008
+ } catch (err) {
1009
+ resolved = true;
1010
+ cleanup();
1011
+ reject(err);
1012
+ }
1013
+ },
1014
+ onError: (error) => {
1015
+ if (resolved) return;
1016
+ resolved = true;
1017
+ cleanup();
1018
+ reject(error);
1019
+ }
1020
+ });
1021
+ setTimeout(() => {
1022
+ if (!resolved) {
1023
+ resolved = true;
1024
+ cleanup();
1025
+ reject(new Error("Linked HTML parsing timed out"));
1026
+ }
1027
+ }, TIMEOUTS.PARSE_TIMEOUT);
1028
+ } catch (err) {
1029
+ cleanup();
1030
+ reject(err);
1031
+ }
1032
+ });
1033
+ }
973
1034
  async function parseDocxFile(file, SuperDoc) {
974
1035
  const container = document.createElement("div");
975
1036
  container.style.cssText = "position:absolute;top:-9999px;left:-9999px;width:800px;height:600px;visibility:hidden;";
@@ -3672,13 +3733,30 @@ var DocxDiffEditor = react.forwardRef(
3672
3733
  }
3673
3734
  },
3674
3735
  /**
3675
- * Parse HTML string to ProseMirror JSON using a hidden SuperDoc instance.
3676
- * Useful for converting HTML content before using with other methods.
3736
+ * Parse HTML string to ProseMirror JSON.
3737
+ *
3738
+ * When the main editor is ready, this uses a linked child editor approach
3739
+ * which ensures list numbering definitions are synced to the main document.
3740
+ * This prevents crashes when parsed content with lists is spliced into
3741
+ * the main document via compareWith().
3742
+ *
3743
+ * Falls back to an isolated SuperDoc instance if the main editor isn't ready.
3677
3744
  */
3678
3745
  async parseHtml(html) {
3679
3746
  if (!SuperDocRef.current) {
3680
3747
  throw new Error("Editor not initialized");
3681
3748
  }
3749
+ const mainEditor = superdocRef.current?.activeEditor;
3750
+ if (mainEditor?.createChildEditor) {
3751
+ try {
3752
+ return await parseHtmlWithLinkedEditor(html, mainEditor);
3753
+ } catch (err) {
3754
+ console.warn(
3755
+ "[DocxDiffEditor] Linked HTML parsing failed, falling back to isolated approach:",
3756
+ err
3757
+ );
3758
+ }
3759
+ }
3682
3760
  return parseHtmlToJson(html, SuperDocRef.current);
3683
3761
  }
3684
3762
  }),