@stll/folio-core 0.11.0 → 0.13.0

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.
Files changed (263) hide show
  1. package/dist/ai-edits/apply.d.ts +2 -1
  2. package/dist/ai-edits/apply.js +693 -63
  3. package/dist/ai-edits/block-identity.d.ts +4 -0
  4. package/dist/ai-edits/block-identity.js +9 -0
  5. package/dist/ai-edits/blockRange.d.ts +28 -1
  6. package/dist/ai-edits/blockRange.js +68 -2
  7. package/dist/ai-edits/clean-text.js +2 -1
  8. package/dist/ai-edits/headless.d.ts +4 -4
  9. package/dist/ai-edits/headless.js +9 -9
  10. package/dist/ai-edits/index.d.ts +2 -2
  11. package/dist/ai-edits/index.js +2 -2
  12. package/dist/ai-edits/read.d.ts +7 -7
  13. package/dist/ai-edits/read.js +110 -3
  14. package/dist/ai-edits/snapshot.js +21 -3
  15. package/dist/ai-edits/table-cell-mutations.d.ts +48 -0
  16. package/dist/ai-edits/table-cell-mutations.js +238 -0
  17. package/dist/ai-edits/table-mutation-plan.d.ts +38 -0
  18. package/dist/ai-edits/table-mutation-plan.js +90 -0
  19. package/dist/ai-edits/table-row-column-mutations.d.ts +108 -0
  20. package/dist/ai-edits/table-row-column-mutations.js +300 -0
  21. package/dist/ai-edits/table-targets.d.ts +32 -0
  22. package/dist/ai-edits/table-targets.js +70 -0
  23. package/dist/ai-edits/types.d.ts +62 -1
  24. package/dist/ai-edits/word-diff.js +21 -0
  25. package/dist/compat/eigenpal.d.ts +3 -3
  26. package/dist/compat/eigenpal.js +3 -3
  27. package/dist/content-controls/mutateContentControls.js +1 -1
  28. package/dist/controller/activeEditorStory.d.ts +36 -0
  29. package/dist/controller/activeEditorStory.js +30 -0
  30. package/dist/controller/contentControlWidgetController.d.ts +55 -0
  31. package/dist/controller/contentControlWidgetController.js +141 -0
  32. package/dist/controller/fontReadiness.js +2 -0
  33. package/dist/controller/headerFooterEditorManager.js +2 -2
  34. package/dist/controller/hiddenEditorApi.js +2 -2
  35. package/dist/controller/hiddenEditorManager.d.ts +12 -1
  36. package/dist/controller/hiddenEditorManager.js +44 -12
  37. package/dist/controller/layoutPipeline.d.ts +2 -0
  38. package/dist/controller/layoutPipeline.js +17 -2
  39. package/dist/controller/noteEditorManager.d.ts +36 -0
  40. package/dist/controller/noteEditorManager.js +210 -0
  41. package/dist/document-operations.d.ts +43 -11
  42. package/dist/document-operations.js +186 -18
  43. package/dist/docx/blockContentParser.js +21 -7
  44. package/dist/docx/commentParser.js +6 -1
  45. package/dist/docx/commentRangeIntegrity.d.ts +6 -0
  46. package/dist/docx/commentRangeIntegrity.js +186 -0
  47. package/dist/docx/conformance.js +62 -1
  48. package/dist/docx/documentGrid.d.ts +8 -0
  49. package/dist/docx/documentGrid.js +8 -0
  50. package/dist/docx/drawingUtils.js +1 -1
  51. package/dist/docx/encryption/agileDecryption.js +12 -2
  52. package/dist/docx/encryption/compoundFile.js +6 -1
  53. package/dist/docx/encryption/encryptionInfo.d.ts +9 -1
  54. package/dist/docx/encryption/encryptionInfo.js +18 -2
  55. package/dist/docx/encryption/openEncryptedDocx.js +1 -1
  56. package/dist/docx/ensureParaIds.js +8 -7
  57. package/dist/docx/fieldParser.js +1 -1
  58. package/dist/docx/groupDrawingParser.js +10 -5
  59. package/dist/docx/hyperlinkParser.js +1 -1
  60. package/dist/docx/imageParser.js +10 -6
  61. package/dist/docx/metadataPrivacy.js +17 -3
  62. package/dist/docx/notePropertiesParser.js +1 -1
  63. package/dist/docx/numberingParser.js +1 -1
  64. package/dist/docx/paragraphParser.js +70 -61
  65. package/dist/docx/paragraphTextBoxEnrichment.d.ts +2 -1
  66. package/dist/docx/paragraphTextBoxEnrichment.js +67 -13
  67. package/dist/docx/paragraphTraversal.js +1 -1
  68. package/dist/docx/parser.js +3 -3
  69. package/dist/docx/rezip.js +20 -9
  70. package/dist/docx/runParser.js +17 -6
  71. package/dist/docx/sdtProperties.js +1 -1
  72. package/dist/docx/sectionParser.js +18 -5
  73. package/dist/docx/selectiveSave.js +5 -1
  74. package/dist/docx/selectiveXmlPatch.d.ts +22 -1
  75. package/dist/docx/selectiveXmlPatch.js +61 -1
  76. package/dist/docx/serializer/blockSdtSerializer.js +3 -2
  77. package/dist/docx/serializer/commentSerializer.js +5 -6
  78. package/dist/docx/serializer/documentSerializer.js +2 -2
  79. package/dist/docx/serializer/headerFooterSerializer.js +2 -2
  80. package/dist/docx/serializer/noteSerializer.js +2 -2
  81. package/dist/docx/serializer/paragraphSerializer.js +23 -15
  82. package/dist/docx/serializer/runSerializer.js +25 -21
  83. package/dist/docx/serializer/sectionPropertiesSerializer.js +2 -1
  84. package/dist/docx/serializer/stylesSerializer.js +1 -1
  85. package/dist/docx/serializer/tableSerializer.d.ts +5 -4
  86. package/dist/docx/serializer/tableSerializer.js +26 -20
  87. package/dist/docx/serializer/xmlUtils.d.ts +13 -1
  88. package/dist/docx/serializer/xmlUtils.js +27 -1
  89. package/dist/docx/server/applyDocxXmlPatchProposal.d.ts +87 -0
  90. package/dist/docx/server/applyDocxXmlPatchProposal.js +204 -0
  91. package/dist/docx/server/boundedArchive.d.ts +14 -3
  92. package/dist/docx/server/boundedArchive.js +56 -11
  93. package/dist/docx/server/evaluateDocxXmlPatchProposal.d.ts +85 -0
  94. package/dist/docx/server/evaluateDocxXmlPatchProposal.js +361 -0
  95. package/dist/docx/server/extractDocxText.js +55 -8
  96. package/dist/docx/server/inspectDocxPackage.d.ts +70 -0
  97. package/dist/docx/server/inspectDocxPackage.js +217 -0
  98. package/dist/docx/server/validateDocxConformance.d.ts +41 -0
  99. package/dist/docx/server/validateDocxConformance.js +336 -0
  100. package/dist/docx/settingsParser.js +26 -3
  101. package/dist/docx/shapeParser.js +1 -1
  102. package/dist/docx/styleParser.js +4 -2
  103. package/dist/docx/tableParser.d.ts +8 -1
  104. package/dist/docx/tableParser.js +31 -10
  105. package/dist/docx/textBoxParser.d.ts +3 -3
  106. package/dist/docx/textBoxParser.js +16 -12
  107. package/dist/docx/unzip.js +1 -0
  108. package/dist/docx/vmlImageParser.js +11 -3
  109. package/dist/docx/xmlParser.js +11 -1
  110. package/dist/docx/xmlSafety.d.ts +5 -0
  111. package/dist/docx/xmlSafety.js +9 -0
  112. package/dist/fields/resolveFieldValues.js +1 -3
  113. package/dist/fonts/embeddedFonts.d.ts +33 -5
  114. package/dist/fonts/embeddedFonts.js +37 -8
  115. package/dist/i18n/messages/catalogs.gen.d.ts +17 -0
  116. package/dist/i18n/messages/catalogs.gen.js +17 -0
  117. package/dist/i18n/messages/messages.gen.d.ts +1 -0
  118. package/dist/index.d.ts +3 -3
  119. package/dist/index.js +3 -3
  120. package/dist/layout-bridge/convert/footnoteLayout.d.ts +1 -0
  121. package/dist/layout-bridge/convert/footnoteLayout.js +47 -40
  122. package/dist/layout-bridge/convert/headerFooterLayout.d.ts +1 -0
  123. package/dist/layout-bridge/convert/headerFooterLayout.js +3 -0
  124. package/dist/layout-bridge/convert/templatePreviewFlow.js +3 -3
  125. package/dist/layout-bridge/convert/toFlowBlocks.d.ts +4 -2
  126. package/dist/layout-bridge/convert/toFlowBlocks.js +151 -20
  127. package/dist/layout-bridge/dom/noteStoryDom.d.ts +6 -0
  128. package/dist/layout-bridge/dom/noteStoryDom.js +17 -0
  129. package/dist/layout-bridge/engine/clickToPosition.js +2 -2
  130. package/dist/layout-engine/index.d.ts +2 -2
  131. package/dist/layout-engine/index.js +58 -30
  132. package/dist/layout-engine/justificationCompatibility.d.ts +6 -0
  133. package/dist/layout-engine/justificationCompatibility.js +8 -0
  134. package/dist/layout-engine/keep-together.js +11 -1
  135. package/dist/layout-engine/measure/cache.js +23 -5
  136. package/dist/layout-engine/measure/effectiveLineBreakPolicy.js +8 -2
  137. package/dist/layout-engine/measure/lineBreakProvider.d.ts +2 -2
  138. package/dist/layout-engine/measure/lineBreakProvider.js +56 -37
  139. package/dist/layout-engine/measure/measureBlocks.js +15 -4
  140. package/dist/layout-engine/measure/measureContainer.js +1 -1
  141. package/dist/layout-engine/measure/measureHelpers.d.ts +11 -2
  142. package/dist/layout-engine/measure/measureHelpers.js +15 -4
  143. package/dist/layout-engine/measure/measureParagraph.js +85 -25
  144. package/dist/layout-engine/measure/measureProvider.js +4 -3
  145. package/dist/layout-engine/measure/tableCellFlow.js +5 -2
  146. package/dist/layout-engine/measure/textBoxParagraphLayout.d.ts +9 -7
  147. package/dist/layout-engine/measure/textBoxParagraphLayout.js +22 -6
  148. package/dist/layout-engine/measure/textMeasurementPolicy.d.ts +3 -1
  149. package/dist/layout-engine/measure/textMeasurementPolicy.js +7 -1
  150. package/dist/layout-engine/paginator.js +5 -1
  151. package/dist/layout-engine/paragraphSpacing.d.ts +28 -4
  152. package/dist/layout-engine/paragraphSpacing.js +107 -13
  153. package/dist/layout-engine/renderedBreakReconciliation.js +1 -1
  154. package/dist/layout-engine/types.d.ts +48 -15
  155. package/dist/layout-painter/registry/modules/textBox.js +5 -1
  156. package/dist/layout-painter/renderImage.d.ts +12 -1
  157. package/dist/layout-painter/renderImage.js +21 -4
  158. package/dist/layout-painter/renderPage.d.ts +5 -2
  159. package/dist/layout-painter/renderPage.js +59 -14
  160. package/dist/layout-painter/renderParagraph.js +55 -15
  161. package/dist/layout-painter/renderTable.d.ts +5 -1
  162. package/dist/layout-painter/renderTable.js +7 -3
  163. package/dist/layout-painter/renderTextBox.d.ts +2 -1
  164. package/dist/layout-painter/renderTextBox.js +25 -14
  165. package/dist/layout-painter/renderWatermark.d.ts +1 -1
  166. package/dist/layout-painter/renderWatermark.js +2 -1
  167. package/dist/managers/DocumentLoaderManager.js +1 -1
  168. package/dist/markdown/fromMarkdown.js +1 -1
  169. package/dist/model.js +1 -1
  170. package/dist/prosemirror/attrs/index.d.ts +4 -2
  171. package/dist/prosemirror/attrs/index.js +175 -18
  172. package/dist/prosemirror/commands/comments.d.ts +79 -4
  173. package/dist/prosemirror/commands/comments.js +622 -13
  174. package/dist/prosemirror/commands/contentControls.js +1 -1
  175. package/dist/prosemirror/commands/hyperlink.js +15 -1
  176. package/dist/prosemirror/commands/image.js +7 -1
  177. package/dist/prosemirror/commands/index.d.ts +2 -2
  178. package/dist/prosemirror/commands/index.js +2 -2
  179. package/dist/prosemirror/commands/pageBreak.js +1 -1
  180. package/dist/prosemirror/commands/propertyChangeScope.d.ts +2 -2
  181. package/dist/prosemirror/commands/propertyChangeScope.js +3 -2
  182. package/dist/prosemirror/commands/tableCellMergeResolution.d.ts +9 -0
  183. package/dist/prosemirror/commands/tableCellMergeResolution.js +181 -0
  184. package/dist/prosemirror/commentIdAllocator.js +13 -3
  185. package/dist/prosemirror/conversion/fromProseDoc.d.ts +2 -1
  186. package/dist/prosemirror/conversion/fromProseDoc.js +404 -62
  187. package/dist/prosemirror/conversion/index.js +1 -1
  188. package/dist/prosemirror/conversion/sdtAttrs.d.ts +9 -0
  189. package/dist/prosemirror/conversion/sdtAttrs.js +49 -0
  190. package/dist/prosemirror/conversion/toProseDoc.d.ts +2 -1
  191. package/dist/prosemirror/conversion/toProseDoc.js +364 -103
  192. package/dist/prosemirror/extensions/ExtensionManager.js +1 -1
  193. package/dist/prosemirror/extensions/StarterKit.js +6 -1
  194. package/dist/prosemirror/extensions/core/ParagraphExtension.js +6 -2
  195. package/dist/prosemirror/extensions/features/BaseKeymapExtension.js +1 -0
  196. package/dist/prosemirror/extensions/features/ImagePasteExtension.js +10 -2
  197. package/dist/prosemirror/extensions/features/ListExtension.js +1 -1
  198. package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.d.ts +10 -1
  199. package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.js +93 -2
  200. package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.d.ts +2 -1
  201. package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.js +6 -2
  202. package/dist/prosemirror/extensions/features/pasteCleanup.js +15 -2
  203. package/dist/prosemirror/extensions/marks/CharacterSpacingExtension.js +1 -1
  204. package/dist/prosemirror/extensions/marks/HyperlinkExtension.js +30 -4
  205. package/dist/prosemirror/extensions/marks/TrackedChangeExtensions.d.ts +9 -1
  206. package/dist/prosemirror/extensions/marks/TrackedChangeExtensions.js +70 -11
  207. package/dist/prosemirror/extensions/nodes/FieldExtension.js +1 -1
  208. package/dist/prosemirror/extensions/nodes/RenderedPageBreakExtension.d.ts +7 -0
  209. package/dist/prosemirror/extensions/nodes/RenderedPageBreakExtension.js +22 -0
  210. package/dist/prosemirror/extensions/nodes/TableExtension.d.ts +1 -1
  211. package/dist/prosemirror/extensions/nodes/TableExtension.js +14 -6
  212. package/dist/prosemirror/extensions/nodes/TextBoxAnchorExtension.d.ts +13 -0
  213. package/dist/prosemirror/extensions/nodes/TextBoxAnchorExtension.js +41 -0
  214. package/dist/prosemirror/extensions/nodes/TextBoxExtension.d.ts +5 -2
  215. package/dist/prosemirror/extensions/nodes/TextBoxExtension.js +4 -1
  216. package/dist/prosemirror/index.d.ts +1 -1
  217. package/dist/prosemirror/index.js +1 -1
  218. package/dist/prosemirror/plugins/contentControlWidgets.d.ts +36 -10
  219. package/dist/prosemirror/plugins/contentControlWidgets.js +128 -94
  220. package/dist/prosemirror/plugins/revisionIds.d.ts +23 -0
  221. package/dist/prosemirror/plugins/revisionIds.js +57 -0
  222. package/dist/prosemirror/plugins/selectionTracker.js +1 -0
  223. package/dist/prosemirror/plugins/suggestionMode.js +5 -4
  224. package/dist/prosemirror/runFormattingMarkNames.d.ts +14 -0
  225. package/dist/prosemirror/runFormattingMarkNames.js +40 -0
  226. package/dist/prosemirror/schema/index.d.ts +2 -2
  227. package/dist/prosemirror/schema/marks.d.ts +30 -3
  228. package/dist/prosemirror/schema/marks.js +15 -0
  229. package/dist/prosemirror/schema/nodes.d.ts +111 -6
  230. package/dist/prosemirror/selectionState.js +1 -0
  231. package/dist/prosemirror/styles/resolvedStyleAttrs.js +1 -0
  232. package/dist/prosemirror/tableCellMergeRevision.d.ts +9 -0
  233. package/dist/prosemirror/tableCellMergeRevision.js +22 -0
  234. package/dist/prosemirror/textBoxAnchorAttrs.d.ts +9 -0
  235. package/dist/prosemirror/textBoxAnchorAttrs.js +33 -0
  236. package/dist/prosemirror/utils/extractTrackedChanges.d.ts +1 -1
  237. package/dist/prosemirror/utils/extractTrackedChanges.js +62 -14
  238. package/dist/prosemirror/validation.js +9 -1
  239. package/dist/render-dom/RemoteSelectionOverlay.js +2 -2
  240. package/dist/server.d.ts +7 -3
  241. package/dist/server.js +7 -3
  242. package/dist/utils/clipboard.d.ts +10 -1
  243. package/dist/utils/clipboard.js +33 -6
  244. package/dist/utils/colorResolver.d.ts +8 -1
  245. package/dist/utils/colorResolver.js +35 -5
  246. package/dist/utils/fontFamilyMerge.js +9 -11
  247. package/dist/utils/fontLoader.js +3 -2
  248. package/dist/utils/fontResolver.d.ts +2 -1
  249. package/dist/utils/fontResolver.js +31 -7
  250. package/dist/utils/fontWeights.d.ts +1 -1
  251. package/dist/utils/fontWeights.js +1 -1
  252. package/dist/utils/hexId.d.ts +11 -1
  253. package/dist/utils/hexId.js +11 -1
  254. package/dist/utils/paragraphFormattingMerge.js +1 -0
  255. package/dist/utils/sanitizeImageSrc.d.ts +21 -0
  256. package/dist/utils/sanitizeImageSrc.js +30 -0
  257. package/dist/utils/stripXmlDeclarations.d.ts +11 -0
  258. package/dist/utils/stripXmlDeclarations.js +35 -0
  259. package/dist/version-comparison.d.ts +22 -2
  260. package/dist/version-comparison.js +41 -12
  261. package/dist/watermark/index.d.ts +11 -1
  262. package/dist/watermark/index.js +22 -1
  263. package/package.json +3 -2
@@ -1,12 +1,17 @@
1
1
  import { OUTLINE_STYLE_CSS_ALIASES } from "../../types/documentEnumValues.js";
2
+ import { directionToBidi } from "../paragraphDirection.js";
3
+ import { expectBlockSdtAttrs, expectCharacterSpacingMarkAttrs, expectCharacterStyleMarkAttrs, expectCommentMarkAttrs, expectEmphasisMarkAttrs, expectFieldAttrs, expectFontFamilyMarkAttrs, expectFontSizeMarkAttrs, expectFootnoteRefMarkAttrs, expectHardBreakAttrs, expectHighlightMarkAttrs, expectHyperlinkMarkAttrs, expectImageAttrs, expectLanguageMarkAttrs, expectMathAttrs, expectParagraphAttrs, expectRunFormattingOverrideMarkAttrs, expectRunPropertyChangeMarkAttrs, expectRunShadingMarkAttrs, expectSdtAttrs, expectShapeAttrs, expectStrikeMarkAttrs, expectTableAttrs, expectTableCellAttrs, expectTableRowAttrs, expectTextBoxAttrs, expectTextColorMarkAttrs, expectTextEffectMarkAttrs, expectTrackedChangeMarkAttrs, expectUnderlineMarkAttrs } from "../attrs/index.js";
2
4
  import { ShapeOutlineStyleSchema, narrowEnum } from "../../docx/parserEnums.js";
3
- import { pixelsToEmu } from "../../utils/units.js";
4
5
  import { numPrEqual } from "../../docx/numberingParser.js";
6
+ import { pixelsToEmu } from "../../utils/units.js";
5
7
  import { autospacingMatchesBase, hasAutospacingBaseSide } from "../autospacingBase.js";
6
- import { directionToBidi } from "../paragraphDirection.js";
7
- import { expectBlockSdtAttrs, expectCharacterSpacingMarkAttrs, expectCharacterStyleMarkAttrs, expectCommentMarkAttrs, expectEmphasisMarkAttrs, expectFieldAttrs, expectFontFamilyMarkAttrs, expectFontSizeMarkAttrs, expectFootnoteRefMarkAttrs, expectHardBreakAttrs, expectHighlightMarkAttrs, expectHyperlinkMarkAttrs, expectImageAttrs, expectLanguageMarkAttrs, expectMathAttrs, expectParagraphAttrs, expectRunFormattingOverrideMarkAttrs, expectRunShadingMarkAttrs, expectSdtAttrs, expectShapeAttrs, expectStrikeMarkAttrs, expectTableAttrs, expectTableCellAttrs, expectTableRowAttrs, expectTextBoxAttrs, expectTextColorMarkAttrs, expectTextEffectMarkAttrs, expectTrackedChangeMarkAttrs, expectUnderlineMarkAttrs } from "../attrs/index.js";
8
+ import { RUN_FORMATTING_MARK_NAMES } from "../runFormattingMarkNames.js";
9
+ import { expectTextBoxAnchorAttrs } from "../textBoxAnchorAttrs.js";
8
10
  import { assertValidProseMirrorDocument } from "../validation.js";
9
11
  import { runShadingAttrsToShading } from "./runShadingMark.js";
12
+ import { sdtPropertiesFromAttrs, sdtPropertiesMatchAttrs } from "./sdtAttrs.js";
13
+ import { textFormattingToMarks } from "./toProseDoc.js";
14
+ import { Fragment } from "prosemirror-model";
10
15
  //#region src/prosemirror/conversion/fromProseDoc.ts
11
16
  function normalizeShapeOutlineStyle(style) {
12
17
  if (!style) return;
@@ -69,12 +74,122 @@ function fromProseDoc(pmDoc, baseDocument) {
69
74
  };
70
75
  return { package: { document: documentBody } };
71
76
  }
77
+ const isSuggestedMark = (mark) => mark.attrs["provenance"] === "suggested";
78
+ const hasSuggestedInsertion = (marks) => marks.some((mark) => mark.type.name === "insertion" && isSuggestedMark(mark));
79
+ /**
80
+ * Compute the mark set an inline node should keep once its suggested tracked
81
+ * changes are stripped. Suggested deletions are dropped so their text survives
82
+ * as plain content; a suggested `runPropertyChange` is dropped and the run's
83
+ * live formatting is reverted to the recorded `previousFormatting`.
84
+ *
85
+ * Returns the input array unchanged when there is nothing to strip so callers
86
+ * can skip rebuilding the node.
87
+ */
88
+ function stripSuggestedInlineMarks(marks) {
89
+ const hasSuggestedDeletion = marks.some((mark) => mark.type.name === "deletion" && isSuggestedMark(mark));
90
+ const suggestedRunPropertyChange = marks.find((mark) => mark.type.name === "runPropertyChange" && isSuggestedMark(mark));
91
+ if (!hasSuggestedDeletion && !suggestedRunPropertyChange) return marks;
92
+ let next = marks.filter((mark) => !((mark.type.name === "deletion" || mark.type.name === "runPropertyChange") && isSuggestedMark(mark)));
93
+ if (suggestedRunPropertyChange) {
94
+ const previousFormatting = expectRunPropertyChangeMarkAttrs(suggestedRunPropertyChange).changes.at(0)?.previousFormatting;
95
+ next = next.filter((mark) => !RUN_FORMATTING_MARK_NAMES.has(mark.type.name));
96
+ for (const restored of textFormattingToMarks(previousFormatting)) next = restored.addToSet(next);
97
+ }
98
+ return next;
99
+ }
100
+ /**
101
+ * Compute the node attrs a block/structural node keeps once its suggested
102
+ * revision markers are neutralized. Returns `null` when nothing changes.
103
+ *
104
+ * - a suggested `trDel` / `cellMarker` (insertion or deletion) is cleared so
105
+ * the row/cell serializes as though the proposed change never happened;
106
+ * merge markers never carry suggestion provenance (structurally excluded);
107
+ * - suggested INSERT markers are handled by the caller, which drops the whole
108
+ * node instead of clearing an attr.
109
+ *
110
+ * Reads go through the typed attr readers (adapter-boundary convention).
111
+ */
112
+ function stripSuggestedNodeAttrs(node) {
113
+ const name = node.type.name;
114
+ if (name === "tableRow") {
115
+ const rowAttrs = expectTableRowAttrs(node);
116
+ if (rowAttrs.trDel?.provenance === "suggested") return {
117
+ ...rowAttrs,
118
+ trDel: null
119
+ };
120
+ return null;
121
+ }
122
+ if (name === "tableCell" || name === "tableHeader") {
123
+ const cellAttrs = expectTableCellAttrs(node);
124
+ const marker = cellAttrs.cellMarker;
125
+ if (marker && marker.kind !== "merge" && marker.info.provenance === "suggested") return {
126
+ ...cellAttrs,
127
+ cellMarker: null
128
+ };
129
+ }
130
+ return null;
131
+ }
132
+ /**
133
+ * Whether a block/structural node is a suggested whole-node INSERT and must be
134
+ * dropped from serialization entirely (paragraph, table, row, or column cell).
135
+ */
136
+ function isSuggestedInsertedNode(node) {
137
+ const name = node.type.name;
138
+ if (name === "paragraph") return expectParagraphAttrs(node)._suggestedInsert != null;
139
+ if (name === "table") return expectTableAttrs(node)._suggestedInsert != null;
140
+ if (name === "tableRow") return expectTableRowAttrs(node).trIns?.provenance === "suggested";
141
+ if (name === "tableCell" || name === "tableHeader") {
142
+ const marker = expectTableCellAttrs(node).cellMarker;
143
+ return marker?.kind === "ins" && marker.info.provenance === "suggested";
144
+ }
145
+ return false;
146
+ }
147
+ /**
148
+ * Recursively rewrite a ProseMirror node tree, removing every suggested
149
+ * tracked change. Returns `null` when the node itself must be dropped: a
150
+ * suggested-inserted inline node, or a suggested-inserted block/row/cell.
151
+ * Surviving block nodes are rebuilt with their suggested delete/merge markers
152
+ * cleared and their children stripped.
153
+ */
154
+ function mapSuggestionStrippedNode(node) {
155
+ if (node.isInline) {
156
+ if (hasSuggestedInsertion(node.marks)) return null;
157
+ const marks = stripSuggestedInlineMarks(node.marks);
158
+ return marks === node.marks ? node : node.mark(marks);
159
+ }
160
+ if (isSuggestedInsertedNode(node)) return null;
161
+ const nextAttrs = stripSuggestedNodeAttrs(node);
162
+ const children = [];
163
+ let changed = nextAttrs !== null;
164
+ node.forEach((child) => {
165
+ const mapped = mapSuggestionStrippedNode(child);
166
+ if (mapped === null) {
167
+ changed = true;
168
+ return;
169
+ }
170
+ if (mapped !== child) changed = true;
171
+ children.push(mapped);
172
+ });
173
+ if (!changed) return node;
174
+ const content = Fragment.fromArray(children);
175
+ return nextAttrs === null ? node.copy(content) : node.type.create(nextAttrs, content, node.marks);
176
+ }
177
+ /**
178
+ * Strip suggested (AI-proposed) tracked changes from a document so it
179
+ * serializes as though the suggestion never happened. See the call site in
180
+ * {@link extractBlocks} for why this is the sole serialization boundary.
181
+ */
182
+ function stripSuggestedProvenance(doc) {
183
+ return mapSuggestionStrippedNode(doc) ?? doc;
184
+ }
72
185
  /**
73
186
  * Extract block content (paragraphs, tables, block SDTs) from a ProseMirror
74
187
  * document.
75
188
  */
76
- function extractBlocks(pmDoc) {
189
+ function extractBlocks(inputDoc) {
190
+ const pmDoc = stripSuggestedProvenance(inputDoc);
77
191
  const blocks = [];
192
+ const textBoxAnchorMarkers = /* @__PURE__ */ new Map();
78
193
  const documentCounts = buildDocumentTrackedChangeCounts(pmDoc);
79
194
  let pendingPageBreaks = 0;
80
195
  let previousStandaloneTextBox = null;
@@ -96,7 +211,7 @@ function extractBlocks(pmDoc) {
96
211
  return;
97
212
  }
98
213
  if (node.type.name === "paragraph") {
99
- const paragraph = convertPMParagraph(node, documentCounts);
214
+ const paragraph = convertPMParagraph(node, documentCounts, textBoxAnchorMarkers);
100
215
  prependPageBreaks(paragraph, pendingPageBreaks);
101
216
  pendingPageBreaks = 0;
102
217
  blocks.push(paragraph);
@@ -108,7 +223,8 @@ function extractBlocks(pmDoc) {
108
223
  } else if (node.type.name === "textBox") {
109
224
  previousStandaloneTextBox = appendTextBoxBlock(blocks, node, {
110
225
  pendingPageBreaks,
111
- previousStandaloneTextBox
226
+ previousStandaloneTextBox,
227
+ textBoxAnchorMarkers
112
228
  });
113
229
  pendingPageBreaks = 0;
114
230
  } else if (node.type.name === "blockSdt") {
@@ -118,6 +234,7 @@ function extractBlocks(pmDoc) {
118
234
  }
119
235
  });
120
236
  if (pendingPageBreaks > 0 && !appendPendingPageBreaksToPreviousParagraph()) flushPendingPageBreaks();
237
+ removeUnresolvedTextBoxAnchors(blocks, textBoxAnchorMarkers);
121
238
  return blocks;
122
239
  }
123
240
  function convertPMBlockSdt(node) {
@@ -176,11 +293,18 @@ function appendTextBoxBlock(blocks, node, options) {
176
293
  const previousBlock = blocks.at(-1);
177
294
  if (attrs._docxPlacement === "inlineWithPrevious" && previousBlock?.type === "paragraph") {
178
295
  appendPageBreaks(previousBlock, options.pendingPageBreaks);
179
- previousBlock.content.push(...paragraph.content);
296
+ const anchorId = attrs._docxAnchorId;
297
+ const anchorMarker = anchorId ? options.textBoxAnchorMarkers.get(anchorId) : void 0;
298
+ const textBoxRun = findTextBoxShapeRun(paragraph.content);
299
+ if (anchorId && anchorMarker && textBoxRun && replaceTextBoxAnchorInBlocks(blocks, anchorMarker, textBoxRun)) {
300
+ options.textBoxAnchorMarkers.delete(anchorId);
301
+ return null;
302
+ }
303
+ if (!mergeTextBoxIntoTrailingInlineSdts(previousBlock, paragraph, attrs._docxInlineSdts ?? [])) previousBlock.content.push(...paragraph.content);
180
304
  return null;
181
305
  }
182
306
  if (attrs._docxPlacement === "standalone" && attrs._docxGroupId && options.previousStandaloneTextBox?.groupId === attrs._docxGroupId) {
183
- options.previousStandaloneTextBox.paragraph.content.push(...paragraph.content);
307
+ if (!mergeTextBoxIntoTrailingInlineSdts(options.previousStandaloneTextBox.paragraph, paragraph, attrs._docxInlineSdts ?? [])) options.previousStandaloneTextBox.paragraph.content.push(...paragraph.content);
184
308
  return options.previousStandaloneTextBox;
185
309
  }
186
310
  prependPageBreaks(paragraph, options.pendingPageBreaks);
@@ -190,6 +314,108 @@ function appendTextBoxBlock(blocks, node, options) {
190
314
  groupId: attrs._docxGroupId
191
315
  } : null;
192
316
  }
317
+ function mergeTextBoxIntoTrailingInlineSdts(target, incoming, inlineSdts) {
318
+ if (inlineSdts.length === 0 || incoming.content.length !== 1) return false;
319
+ const incomingSdt = incoming.content.at(0);
320
+ const outerAttrs = inlineSdts.at(0);
321
+ if (!outerAttrs || incomingSdt?.type !== "inlineSdt") return false;
322
+ let targetSdt;
323
+ for (let index = target.content.length - 1; index >= 0; index -= 1) {
324
+ const content = target.content[index];
325
+ if (content?.type === "inlineSdt" && sdtPropertiesMatchAttrs(content.properties, outerAttrs)) {
326
+ targetSdt = content;
327
+ break;
328
+ }
329
+ }
330
+ if (!targetSdt) return false;
331
+ return mergeInlineSdtNodes(targetSdt, incomingSdt, inlineSdts, 0);
332
+ }
333
+ function mergeInlineSdtNodes(target, incoming, inlineSdts, index) {
334
+ const attrs = inlineSdts[index];
335
+ if (!attrs || !sdtPropertiesMatchAttrs(target.properties, attrs) || !sdtPropertiesMatchAttrs(incoming.properties, attrs)) return false;
336
+ if (index === inlineSdts.length - 1) {
337
+ target.content.push(...incoming.content);
338
+ return true;
339
+ }
340
+ const incomingNested = incoming.content.at(0);
341
+ const nestedAttrs = inlineSdts[index + 1];
342
+ if (!nestedAttrs || incomingNested?.type !== "inlineSdt") return false;
343
+ let targetNested;
344
+ for (let nestedIndex = target.content.length - 1; nestedIndex >= 0; nestedIndex -= 1) {
345
+ const content = target.content[nestedIndex];
346
+ if (content?.type === "inlineSdt" && sdtPropertiesMatchAttrs(content.properties, nestedAttrs)) {
347
+ targetNested = content;
348
+ break;
349
+ }
350
+ }
351
+ if (!targetNested) {
352
+ target.content.push(incomingNested);
353
+ return true;
354
+ }
355
+ return mergeInlineSdtNodes(targetNested, incomingNested, inlineSdts, index + 1);
356
+ }
357
+ function findTextBoxShapeRun(content) {
358
+ for (const item of content) {
359
+ if (item.type === "run") {
360
+ if (item.content.some((runContent) => runContent.type === "shape" && runContent.shape.shapeType === "textBox")) return item;
361
+ continue;
362
+ }
363
+ if (item.type === "inlineSdt" || item.type === "hyperlink" || item.type === "insertion" || item.type === "deletion" || item.type === "moveFrom" || item.type === "moveTo") {
364
+ const run = findTextBoxShapeRun(item.type === "hyperlink" ? item.children : item.content);
365
+ if (run) return run;
366
+ }
367
+ }
368
+ }
369
+ function replaceTextBoxAnchorInBlocks(blocks, marker, textBoxRun) {
370
+ for (const block of blocks) {
371
+ if (block.type === "paragraph") {
372
+ if (editTextBoxAnchorInContent(block.content, marker, textBoxRun)) return true;
373
+ continue;
374
+ }
375
+ if (block.type === "table") {
376
+ for (const row of block.rows) for (const cell of row.cells) if (replaceTextBoxAnchorInBlocks(cell.content, marker, textBoxRun)) return true;
377
+ continue;
378
+ }
379
+ if (replaceTextBoxAnchorInBlocks(block.content, marker, textBoxRun)) return true;
380
+ }
381
+ return false;
382
+ }
383
+ function editTextBoxAnchorInContent(content, marker, replacement) {
384
+ for (let index = 0; index < content.length; index += 1) {
385
+ const item = content[index];
386
+ if (item === marker) {
387
+ content.splice(index, 1, ...replacement ? [replacement] : []);
388
+ return true;
389
+ }
390
+ let nestedContent;
391
+ if (item?.type === "hyperlink") nestedContent = item.children;
392
+ else if (item?.type === "inlineSdt" || item?.type === "insertion" || item?.type === "deletion" || item?.type === "moveFrom" || item?.type === "moveTo") nestedContent = item.content;
393
+ if (!nestedContent) continue;
394
+ const hadContent = nestedContent.length > 0;
395
+ if (editTextBoxAnchorInContent(nestedContent, marker, replacement)) {
396
+ if (!replacement && hadContent && nestedContent.length === 0) content.splice(index, 1);
397
+ return true;
398
+ }
399
+ }
400
+ return false;
401
+ }
402
+ function removeUnresolvedTextBoxAnchors(blocks, markers) {
403
+ for (const marker of markers.values()) removeTextBoxAnchorFromBlocks(blocks, marker);
404
+ }
405
+ function removeTextBoxAnchorFromBlocks(blocks, marker) {
406
+ for (const block of blocks) {
407
+ if (block.type === "paragraph") {
408
+ if (editTextBoxAnchorInContent(block.content, marker)) return true;
409
+ continue;
410
+ }
411
+ if (block.type === "table") {
412
+ for (const row of block.rows) for (const cell of row.cells) if (removeTextBoxAnchorFromBlocks(cell.content, marker)) return true;
413
+ continue;
414
+ }
415
+ if (removeTextBoxAnchorFromBlocks(block.content, marker)) return true;
416
+ }
417
+ return false;
418
+ }
193
419
  /**
194
420
  * Inverse of toProseDoc's listRendering → list* attrs flattening. Markdown
195
421
  * export (`toMarkdown`) and re-layout of the rebuilt Document key off
@@ -254,9 +480,9 @@ function appendPageBreaks(paragraph, count) {
254
480
  /**
255
481
  * Convert a ProseMirror paragraph node to our Paragraph type
256
482
  */
257
- function convertPMParagraph(node, documentCounts) {
483
+ function convertPMParagraph(node, documentCounts, textBoxAnchorMarkers) {
258
484
  const attrs = expectParagraphAttrs(node);
259
- let content = extractParagraphContent(node, documentCounts, attrs._emptyHyperlinks ?? void 0);
485
+ let content = extractParagraphContent(node, documentCounts, attrs._emptyHyperlinks ?? void 0, textBoxAnchorMarkers, attrs.renderedPageBreakBefore === true);
260
486
  const bookmarks = attrs.bookmarks;
261
487
  if (bookmarks && bookmarks.length > 0) {
262
488
  const starts = bookmarks.map((b) => ({
@@ -344,6 +570,7 @@ function paragraphAttrsToFormatting(attrs) {
344
570
  else delete result.styleId;
345
571
  assignBooleanToggle(result, attrs, orig, "pageBreakBefore");
346
572
  assignBooleanToggle(result, attrs, orig, "widowControl");
573
+ assignBooleanToggle(result, attrs, orig, "snapToGrid");
347
574
  assignBooleanToggle(result, attrs, orig, "kinsoku");
348
575
  assignBooleanToggle(result, attrs, orig, "overflowPunctuation");
349
576
  assignBooleanToggle(result, attrs, orig, "suppressAutoHyphens");
@@ -356,7 +583,7 @@ function paragraphAttrsToFormatting(attrs) {
356
583
  }
357
584
  const outlineLevel = Reflect.get(attrs, "outlineLevel");
358
585
  const bidi = directionToBidi(attrs.direction);
359
- if (!(attrs.alignment || shouldSerializeSpaceBefore || shouldSerializeSpaceAfter || beforeAutospacingEdited || afterAutospacingEdited || attrs.lineSpacing || attrs.indentLeft || attrs.indentRight || attrs.indentFirstLine || attrs.numPr || attrs.styleId || attrs.borders || attrs.shading || attrs.tabs || typeof outlineLevel === "number" || attrs.contextualSpacing || attrs.spacingExplicit || bidi != null || attrs.pageBreakBefore != null || attrs.widowControl != null || attrs.kinsoku != null || attrs.overflowPunctuation != null || attrs.suppressAutoHyphens != null)) return;
586
+ if (!(attrs.alignment || shouldSerializeSpaceBefore || shouldSerializeSpaceAfter || beforeAutospacingEdited || afterAutospacingEdited || attrs.lineSpacing || attrs.snapToGrid != null || attrs.indentLeft || attrs.indentRight || attrs.indentFirstLine || attrs.numPr || attrs.styleId || attrs.borders || attrs.shading || attrs.tabs || typeof outlineLevel === "number" || attrs.contextualSpacing || attrs.spacingExplicit || bidi != null || attrs.pageBreakBefore != null || attrs.widowControl != null || attrs.kinsoku != null || attrs.overflowPunctuation != null || attrs.suppressAutoHyphens != null)) return;
360
587
  const f = {};
361
588
  if (attrs.alignment) f.alignment = attrs.alignment;
362
589
  if (shouldSerializeSpaceBefore) f.spaceBefore = spaceBefore;
@@ -365,6 +592,7 @@ function paragraphAttrsToFormatting(attrs) {
365
592
  if (afterAutospacingEdited) f.afterAutospacing = false;
366
593
  if (attrs.lineSpacing) f.lineSpacing = attrs.lineSpacing;
367
594
  if (attrs.lineSpacingRule) f.lineSpacingRule = attrs.lineSpacingRule;
595
+ if (attrs.snapToGrid != null) f.snapToGrid = attrs.snapToGrid;
368
596
  if (attrs.spacingExplicit) f.spacingExplicit = attrs.spacingExplicit;
369
597
  if (attrs.indentLeft) f.indentLeft = attrs.indentLeft;
370
598
  if (attrs.indentRight) f.indentRight = attrs.indentRight;
@@ -391,13 +619,14 @@ function paragraphAttrsToFormatting(attrs) {
391
619
  * Coalesces consecutive text with the same marks into single Runs
392
620
  * for efficient DOCX representation.
393
621
  */
394
- function extractParagraphContent(paragraph, _documentCounts, emptyHyperlinks) {
622
+ function extractParagraphContent(paragraph, _documentCounts, emptyHyperlinks, textBoxAnchorMarkers, skipLeadingRenderedPageBreak = false) {
395
623
  const content = [];
396
624
  const sortedEmptyHyperlinks = (emptyHyperlinks ?? []).map((attrs, order) => ({
397
625
  attrs,
398
626
  order
399
627
  })).toSorted((left, right) => left.attrs.offset - right.attrs.offset || left.order - right.order);
400
628
  let nextEmptyHyperlink = 0;
629
+ let leadingRenderedPageBreakPending = skipLeadingRenderedPageBreak;
401
630
  let currentRun = null;
402
631
  let currentMarksKey = null;
403
632
  let currentHyperlink = null;
@@ -455,11 +684,54 @@ function extractParagraphContent(paragraph, _documentCounts, emptyHyperlinks) {
455
684
  }
456
685
  };
457
686
  const processInlineNode = (node, offset) => {
687
+ if (node.type.name === "renderedPageBreak" && leadingRenderedPageBreakPending) {
688
+ leadingRenderedPageBreakPending = false;
689
+ return;
690
+ }
691
+ leadingRenderedPageBreakPending = false;
458
692
  syncCommentRanges(node, offset);
459
693
  const linkMark = node.marks.find((m) => m.type.name === "hyperlink");
460
694
  const noteRefMark = node.marks.find((m) => m.type.name === "footnoteRef");
461
695
  const insertionMark = node.marks.find((m) => m.type.name === "insertion");
462
696
  const deletionMark = node.marks.find((m) => m.type.name === "deletion");
697
+ if (node.type.name === "textBoxAnchor") {
698
+ flushCurrentInline();
699
+ if (!textBoxAnchorMarkers) return;
700
+ const { anchorId } = expectTextBoxAnchorAttrs(node);
701
+ const marker = {
702
+ type: "run",
703
+ content: []
704
+ };
705
+ if (textBoxAnchorMarkers.has(anchorId)) return;
706
+ textBoxAnchorMarkers.set(anchorId, marker);
707
+ const anchoredContent = linkMark ? {
708
+ ...createHyperlink(linkMark),
709
+ children: [marker]
710
+ } : marker;
711
+ const changeMark = insertionMark ?? deletionMark;
712
+ if (!changeMark) {
713
+ content.push(anchoredContent);
714
+ return;
715
+ }
716
+ const changeAttrs = expectTrackedChangeMarkAttrs(changeMark);
717
+ const info = {
718
+ id: changeAttrs.revisionId,
719
+ author: changeAttrs.author || "Unknown",
720
+ ...changeAttrs.date ? { date: changeAttrs.date } : {},
721
+ ...changeAttrs.initials ? { initials: changeAttrs.initials } : {}
722
+ };
723
+ if (insertionMark) content.push({
724
+ type: changeAttrs.moveKind === "moveTo" ? "moveTo" : "insertion",
725
+ info,
726
+ content: [anchoredContent]
727
+ });
728
+ else content.push({
729
+ type: changeAttrs.moveKind === "moveFrom" ? "moveFrom" : "deletion",
730
+ info,
731
+ content: [anchoredContent]
732
+ });
733
+ return;
734
+ }
463
735
  if (insertionMark || deletionMark) {
464
736
  flushCurrentInline();
465
737
  const changeMark = insertionMark ?? deletionMark;
@@ -467,30 +739,35 @@ function extractParagraphContent(paragraph, _documentCounts, emptyHyperlinks) {
467
739
  const changeAttrs = expectTrackedChangeMarkAttrs(changeMark);
468
740
  const run = createTrackedChangeRun(node, node.marks.filter((m) => m.type.name !== "insertion" && m.type.name !== "deletion"));
469
741
  if (!run) return;
742
+ const trackedContent = linkMark ? {
743
+ ...createHyperlink(linkMark),
744
+ children: [run]
745
+ } : run;
470
746
  const info = {
471
747
  id: changeAttrs.revisionId,
472
748
  author: changeAttrs.author || "Unknown"
473
749
  };
474
750
  if (changeAttrs.date) info.date = changeAttrs.date;
751
+ if (changeAttrs.initials) info.initials = changeAttrs.initials;
475
752
  if (insertionMark) if (changeAttrs.moveKind === "moveTo") content.push({
476
753
  type: "moveTo",
477
754
  info,
478
- content: [run]
755
+ content: [trackedContent]
479
756
  });
480
757
  else content.push({
481
758
  type: "insertion",
482
759
  info,
483
- content: [run]
760
+ content: [trackedContent]
484
761
  });
485
762
  else if (changeAttrs.moveKind === "moveFrom") content.push({
486
763
  type: "moveFrom",
487
764
  info,
488
- content: [run]
765
+ content: [trackedContent]
489
766
  });
490
767
  else content.push({
491
768
  type: "deletion",
492
769
  info,
493
- content: [run]
770
+ content: [trackedContent]
494
771
  });
495
772
  return;
496
773
  }
@@ -530,12 +807,15 @@ function extractParagraphContent(paragraph, _documentCounts, emptyHyperlinks) {
530
807
  } else if (node.type.name === "tab") {
531
808
  flushCurrentInline();
532
809
  content.push(createTabRun());
810
+ } else if (node.type.name === "renderedPageBreak") {
811
+ flushCurrentInline();
812
+ content.push(createRenderedPageBreakRun());
533
813
  } else if (node.type.name === "field") {
534
814
  flushCurrentInline();
535
815
  content.push(createFieldFromNode(node, node.marks));
536
816
  } else if (node.type.name === "sdt") {
537
817
  flushCurrentInline();
538
- content.push(createInlineSdtFromNode(node));
818
+ content.push(createInlineSdtFromNode(node, textBoxAnchorMarkers));
539
819
  } else if (node.type.name === "math") {
540
820
  flushCurrentInline();
541
821
  content.push(createMathFromNode(node));
@@ -576,7 +856,7 @@ function createTrackedChangeRun(node, marks) {
576
856
  if (noteRefMark) return createNoteReferenceRun(noteRefMark, marks);
577
857
  if (node.isText) {
578
858
  const formatting = marksToTextFormatting(marks);
579
- return {
859
+ const run = {
580
860
  type: "run",
581
861
  content: node.text ? [{
582
862
  type: "text",
@@ -584,11 +864,14 @@ function createTrackedChangeRun(node, marks) {
584
864
  }] : [],
585
865
  ...Object.keys(formatting).length > 0 ? { formatting } : {}
586
866
  };
867
+ restoreRunPropertyChanges(run, marks);
868
+ return run;
587
869
  }
588
870
  if (node.type.name === "hardBreak") return createBreakRun(readHardBreakType(node));
589
871
  if (node.type.name === "image") return createImageRun(node);
590
872
  if (node.type.name === "shape") return createShapeRun(node);
591
873
  if (node.type.name === "tab") return createTabRun();
874
+ if (node.type.name === "renderedPageBreak") return createRenderedPageBreakRun();
592
875
  return null;
593
876
  }
594
877
  function createEmptyHyperlink(attrs) {
@@ -699,6 +982,10 @@ function addNodeToHyperlink(hyperlink, node) {
699
982
  hyperlink.children.push(createTabRun(nonLinkMarks));
700
983
  return;
701
984
  }
985
+ if (node.type.name === "renderedPageBreak") {
986
+ hyperlink.children.push(createRenderedPageBreakRun());
987
+ return;
988
+ }
702
989
  if (node.type.name === "image") {
703
990
  hyperlink.children.push(createImageRun(node));
704
991
  return;
@@ -736,8 +1023,16 @@ function createRunFromText(text, marks) {
736
1023
  }]
737
1024
  };
738
1025
  if (formatting) run.formatting = formatting;
1026
+ restoreRunPropertyChanges(run, marks);
739
1027
  return run;
740
1028
  }
1029
+ function restoreRunPropertyChanges(run, marks) {
1030
+ const changeMark = marks.find((mark) => mark.type.name === "runPropertyChange");
1031
+ if (!changeMark) return;
1032
+ const { changes } = expectRunPropertyChangeMarkAttrs(changeMark);
1033
+ if (changes.length === 0) return;
1034
+ run.propertyChanges = [...changes];
1035
+ }
741
1036
  function getRunFormattingFromMarks(marks) {
742
1037
  if (!marks || marks.length === 0) return;
743
1038
  const formatting = marksToTextFormatting(marks);
@@ -769,6 +1064,12 @@ function createBreakRun(breakType = "textWrapping", marks) {
769
1064
  if (formatting) run.formatting = formatting;
770
1065
  return run;
771
1066
  }
1067
+ function createRenderedPageBreakRun() {
1068
+ return {
1069
+ type: "run",
1070
+ content: [{ type: "renderedPageBreak" }]
1071
+ };
1072
+ }
772
1073
  function readHardBreakType(node) {
773
1074
  return expectHardBreakAttrs(node).breakType ?? "textWrapping";
774
1075
  }
@@ -848,41 +1149,13 @@ function createMathFromNode(node) {
848
1149
  /**
849
1150
  * Create an InlineSdt from a PM sdt node
850
1151
  */
851
- function createInlineSdtFromNode(node) {
852
- const attrs = expectSdtAttrs(node);
853
- const properties = { sdtType: attrs.sdtType };
854
- if (attrs.alias) properties.alias = attrs.alias;
855
- if (attrs.tag) properties.tag = attrs.tag;
856
- if (typeof attrs.id === "number") properties.id = attrs.id;
857
- if (attrs.lock) properties.lock = attrs.lock;
858
- if (attrs.placeholder) properties.placeholder = attrs.placeholder;
859
- if (attrs.showingPlaceholder !== void 0) properties.showingPlaceholder = attrs.showingPlaceholder;
860
- if (attrs.dateFormat) properties.dateFormat = attrs.dateFormat;
861
- if (attrs.dateValueISO) properties.dateValueISO = attrs.dateValueISO;
862
- if (attrs.listItems) properties.listItems = parseSdtListItems(attrs.listItems);
863
- if (typeof attrs.dropdownLastValue === "string") properties.dropdownLastValue = attrs.dropdownLastValue;
864
- if (typeof attrs.checked === "boolean") properties.checked = attrs.checked;
865
- if (attrs.rawPropertiesXml) properties.rawPropertiesXml = attrs.rawPropertiesXml;
866
- if (attrs.rawEndPropertiesXml) properties.rawEndPropertiesXml = attrs.rawEndPropertiesXml;
1152
+ function createInlineSdtFromNode(node, textBoxAnchorMarkers) {
867
1153
  return {
868
1154
  type: "inlineSdt",
869
- properties,
870
- content: extractParagraphContent(node).filter((c) => c.type === "run" || c.type === "hyperlink" || c.type === "simpleField" || c.type === "complexField" || c.type === "inlineSdt" || c.type === "insertion" || c.type === "deletion" || c.type === "mathEquation")
1155
+ properties: sdtPropertiesFromAttrs(expectSdtAttrs(node)),
1156
+ content: extractParagraphContent(node, void 0, void 0, textBoxAnchorMarkers).filter((c) => c.type === "run" || c.type === "hyperlink" || c.type === "simpleField" || c.type === "complexField" || c.type === "inlineSdt" || c.type === "insertion" || c.type === "deletion" || c.type === "moveFrom" || c.type === "moveTo" || c.type === "mathEquation")
871
1157
  };
872
1158
  }
873
- function parseSdtListItems(rawItems) {
874
- const parsed = JSON.parse(rawItems);
875
- if (!Array.isArray(parsed)) throw new TypeError("Invalid ProseMirror sdt attrs: listItems is not an array");
876
- return parsed.map((item) => {
877
- if (!item || typeof item !== "object" || Array.isArray(item)) throw new TypeError("Invalid ProseMirror sdt attrs: listItems contains an invalid item");
878
- const itemAttrs = item;
879
- if (typeof itemAttrs.displayText !== "string" || typeof itemAttrs.value !== "string") throw new TypeError("Invalid ProseMirror sdt attrs: listItems contains an invalid item");
880
- return {
881
- displayText: itemAttrs.displayText,
882
- value: itemAttrs.value
883
- };
884
- });
885
- }
886
1159
  /**
887
1160
  * Create a Run containing an image
888
1161
  */
@@ -1399,6 +1672,24 @@ function convertPMTableRow(node, documentCounts, activeVerticalMerges) {
1399
1672
  const rowFormatting = tableRowAttrsToFormatting(attrs);
1400
1673
  if (rowFormatting) row.formatting = rowFormatting;
1401
1674
  if (Array.isArray(attrs.trPrChange) && attrs.trPrChange.length > 0) row.propertyChanges = [...attrs.trPrChange];
1675
+ if (attrs.trIns) row.structuralChange = {
1676
+ type: "tableRowInsertion",
1677
+ info: {
1678
+ id: attrs.trIns.revisionId,
1679
+ author: attrs.trIns.author,
1680
+ ...attrs.trIns.date != null && { date: attrs.trIns.date },
1681
+ ...attrs.trIns.initials != null && { initials: attrs.trIns.initials }
1682
+ }
1683
+ };
1684
+ else if (attrs.trDel) row.structuralChange = {
1685
+ type: "tableRowDeletion",
1686
+ info: {
1687
+ id: attrs.trDel.revisionId,
1688
+ author: attrs.trDel.author,
1689
+ ...attrs.trDel.date != null && { date: attrs.trDel.date },
1690
+ ...attrs.trDel.initials != null && { initials: attrs.trDel.initials }
1691
+ }
1692
+ };
1402
1693
  return row;
1403
1694
  }
1404
1695
  function createVerticalMergeContinuationCell(colspan) {
@@ -1450,19 +1741,22 @@ function tableRowAttrsToFormatting(attrs) {
1450
1741
  function convertPMTableCell(node, documentCounts) {
1451
1742
  const attrs = expectTableCellAttrs(node);
1452
1743
  const content = [];
1744
+ const textBoxAnchorMarkers = /* @__PURE__ */ new Map();
1453
1745
  let previousStandaloneTextBox = null;
1454
1746
  node.forEach((contentNode) => {
1455
1747
  if (contentNode.type.name === "paragraph") {
1456
- content.push(convertPMParagraph(contentNode, documentCounts));
1748
+ content.push(convertPMParagraph(contentNode, documentCounts, textBoxAnchorMarkers));
1457
1749
  previousStandaloneTextBox = null;
1458
1750
  } else if (contentNode.type.name === "table") {
1459
1751
  content.push(convertPMTable(contentNode, documentCounts));
1460
1752
  previousStandaloneTextBox = null;
1461
1753
  } else if (contentNode.type.name === "textBox") previousStandaloneTextBox = appendTextBoxBlock(content, contentNode, {
1462
1754
  pendingPageBreaks: 0,
1463
- previousStandaloneTextBox
1755
+ previousStandaloneTextBox,
1756
+ textBoxAnchorMarkers
1464
1757
  });
1465
1758
  });
1759
+ removeUnresolvedTextBoxAnchors(content, textBoxAnchorMarkers);
1466
1760
  const cell = {
1467
1761
  type: "tableCell",
1468
1762
  content
@@ -1470,8 +1764,27 @@ function convertPMTableCell(node, documentCounts) {
1470
1764
  const cellFormatting = tableCellAttrsToFormatting(attrs);
1471
1765
  if (cellFormatting) cell.formatting = cellFormatting;
1472
1766
  if (Array.isArray(attrs.tcPrChange) && attrs.tcPrChange.length > 0) cell.propertyChanges = [...attrs.tcPrChange];
1767
+ if (attrs.cellMarker) {
1768
+ const info = {
1769
+ id: attrs.cellMarker.info.revisionId,
1770
+ author: attrs.cellMarker.info.author,
1771
+ ...attrs.cellMarker.info.date != null && { date: attrs.cellMarker.info.date },
1772
+ ...attrs.cellMarker.info.initials != null && { initials: attrs.cellMarker.info.initials }
1773
+ };
1774
+ if (attrs.cellMarker.kind === "merge") cell.structuralChange = {
1775
+ type: "tableCellMerge",
1776
+ info,
1777
+ ...attrs.cellMarker.verticalMerge !== void 0 ? { verticalMerge: attrs.cellMarker.verticalMerge } : {},
1778
+ ...attrs.cellMarker.verticalMergeOriginal !== void 0 ? { verticalMergeOriginal: attrs.cellMarker.verticalMergeOriginal } : {}
1779
+ };
1780
+ else cell.structuralChange = {
1781
+ type: attrs.cellMarker.kind === "ins" ? "tableCellInsertion" : "tableCellDeletion",
1782
+ info
1783
+ };
1784
+ }
1473
1785
  return cell;
1474
1786
  }
1787
+ const standaloneTableCellFromProseMirror = (node) => convertPMTableCell(node);
1475
1788
  const cellShadingFromAttrs = (attrs) => attrs.backgroundColor ? { fill: { rgb: attrs.backgroundColor } } : { pattern: "nil" };
1476
1789
  function tableCellAttrsToFormatting(attrs) {
1477
1790
  const backgroundChanged = attrs.backgroundColor !== attrs._resolvedBackgroundColor;
@@ -1479,6 +1792,7 @@ function tableCellAttrsToFormatting(attrs) {
1479
1792
  const orig = attrs._originalFormatting;
1480
1793
  const result = { ...orig };
1481
1794
  if (attrs.colspan > 1) result.gridSpan = attrs.colspan;
1795
+ else delete result.gridSpan;
1482
1796
  if (attrs.rowspan > 1) result.vMerge = "restart";
1483
1797
  else if (result.vMerge === "restart" && !attrs._preserveVMergeRestart) delete result.vMerge;
1484
1798
  const cellWidth = attrs.width;
@@ -1517,9 +1831,10 @@ function tableCellAttrsToFormatting(attrs) {
1517
1831
  */
1518
1832
  function convertPMTextBox(node) {
1519
1833
  const attrs = expectTextBoxAttrs(node);
1520
- const childParagraphs = [];
1834
+ const childBlocks = [];
1521
1835
  node.forEach((child) => {
1522
- if (child.type.name === "paragraph") childParagraphs.push(convertPMParagraph(child));
1836
+ if (child.type.name === "paragraph") childBlocks.push(convertPMParagraph(child));
1837
+ else if (child.type.name === "table") childBlocks.push(convertPMTable(child));
1523
1838
  });
1524
1839
  const shape = {
1525
1840
  type: "shape",
@@ -1529,7 +1844,7 @@ function convertPMTextBox(node) {
1529
1844
  height: attrs.height ? pixelsToEmu(attrs.height) : 0
1530
1845
  },
1531
1846
  textBody: {
1532
- content: childParagraphs.length > 0 ? childParagraphs : [{
1847
+ content: childBlocks.length > 0 ? childBlocks : [{
1533
1848
  type: "paragraph",
1534
1849
  content: []
1535
1850
  }],
@@ -1561,16 +1876,43 @@ function convertPMTextBox(node) {
1561
1876
  if (wrap) shape.wrap = wrap;
1562
1877
  const position = imagePositionFromAttrs(attrs.position);
1563
1878
  if (position) shape.position = position;
1564
- return {
1565
- type: "paragraph",
1879
+ const run = {
1880
+ type: "run",
1566
1881
  content: [{
1567
- type: "run",
1568
- content: [{
1569
- type: "shape",
1570
- shape
1571
- }]
1882
+ type: "shape",
1883
+ shape
1572
1884
  }]
1573
1885
  };
1886
+ const trackedChange = attrs._docxTrackedChange;
1887
+ const inlineSdts = attrs._docxInlineSdts ?? [];
1888
+ if (inlineSdts.length > 0) {
1889
+ let wrapped = trackedChange ? {
1890
+ type: trackedChange.type,
1891
+ info: trackedChange.info,
1892
+ content: [run]
1893
+ } : run;
1894
+ for (let index = inlineSdts.length - 1; index >= 0; index -= 1) {
1895
+ const sdtAttrs = inlineSdts[index];
1896
+ if (!sdtAttrs) continue;
1897
+ wrapped = {
1898
+ type: "inlineSdt",
1899
+ properties: sdtPropertiesFromAttrs(sdtAttrs),
1900
+ content: [wrapped]
1901
+ };
1902
+ }
1903
+ return {
1904
+ type: "paragraph",
1905
+ content: [wrapped]
1906
+ };
1907
+ }
1908
+ return {
1909
+ type: "paragraph",
1910
+ content: trackedChange ? [{
1911
+ type: trackedChange.type,
1912
+ info: trackedChange.info,
1913
+ content: [run]
1914
+ }] : [run]
1915
+ };
1574
1916
  }
1575
1917
  /**
1576
1918
  * Update a Document with content from a ProseMirror document
@@ -1590,4 +1932,4 @@ function proseDocToBlocks(pmDoc) {
1590
1932
  return extractBlocks(pmDoc);
1591
1933
  }
1592
1934
  //#endregion
1593
- export { fromProseDoc, marksToTextFormatting, proseDocToBlocks, updateDocumentContent };
1935
+ export { fromProseDoc, marksToTextFormatting, proseDocToBlocks, standaloneTableCellFromProseMirror, updateDocumentContent };