@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,6 +1,6 @@
1
- import { formatDate } from "../../docx/fieldParser.js";
2
1
  import { expectBlockSdtAttrs } from "../attrs/index.js";
3
2
  import { ContentControlBoundError, ContentControlLockedError, ContentControlTypeError } from "../../content-controls/errors.js";
3
+ import { formatDate } from "../../docx/fieldParser.js";
4
4
  import { SUGGESTION_BYPASS_META } from "../plugins/suggestionMode.js";
5
5
  //#region src/prosemirror/commands/contentControls.ts
6
6
  function nodeMatchesFilter(node, pos, filter) {
@@ -1,7 +1,21 @@
1
1
  import { expectHyperlinkMarkAttrs } from "../attrs/index.js";
2
+ import { normalizeUserUrl } from "../../utils/urlSecurity.js";
2
3
  //#region src/prosemirror/commands/hyperlink.ts
3
4
  const hyperlinkHref = (mark) => expectHyperlinkMarkAttrs(mark).href;
4
5
  /**
6
+ * Normalize/sanitize a URL typed by a user (hyperlink popup edit) before it
7
+ * is written into a mark. Internal bookmark anchors (`#name`) bypass
8
+ * `normalizeUserUrl` (which parses via the `URL` constructor and would
9
+ * reject a bare fragment); protocol-less input (e.g. "example.com") is
10
+ * accepted and normalized to https; anything resolving to a disallowed
11
+ * scheme (javascript:, data:, file:, ...) is dropped to an empty href.
12
+ */
13
+ const normalizeHyperlinkInput = (rawHref) => {
14
+ const trimmed = rawHref.trim();
15
+ if (trimmed.startsWith("#")) return trimmed;
16
+ return normalizeUserUrl(trimmed);
17
+ };
18
+ /**
5
19
  * Contiguous ranges of text nodes in `parent` (starting at `parentStart`) that
6
20
  * carry a hyperlink mark with the given `href`.
7
21
  */
@@ -44,7 +58,7 @@ const editHyperlinkAtCursor = (view, { displayText, href }) => {
44
58
  if (!targetRange) return false;
45
59
  const { tooltip } = expectHyperlinkMarkAttrs(linkMark);
46
60
  const newMark = hlType.create({
47
- href,
61
+ href: normalizeHyperlinkInput(href),
48
62
  tooltip
49
63
  });
50
64
  const textNode = view.state.schema.text(displayText, [...$from.marks().filter((m) => m.type !== hlType), newMark]);
@@ -1,5 +1,6 @@
1
1
  import { IMAGE_HORIZONTAL_ALIGNMENT_VALUES, IMAGE_HORIZONTAL_RELATIVE_TO_VALUES, IMAGE_VERTICAL_ALIGNMENT_VALUES, IMAGE_VERTICAL_RELATIVE_TO_VALUES } from "../../types/documentEnumValues.js";
2
2
  import { expectImageAttrs, mergeImageAttrs } from "../attrs/index.js";
3
+ import { sanitizeImageSrc } from "../../utils/sanitizeImageSrc.js";
3
4
  import { isSafeImageFile } from "../../utils/imageValidation.js";
4
5
  //#region src/prosemirror/commands/image.ts
5
6
  /** Map a toolbar wrap selection to the image's wrapType/displayMode/cssFloat, or null when unknown. */
@@ -203,6 +204,11 @@ function readFileAsDataUrl(file) {
203
204
  }
204
205
  function loadImageDimensions(src) {
205
206
  return new Promise((resolve, reject) => {
207
+ const safeSrc = sanitizeImageSrc(src);
208
+ if (!safeSrc) {
209
+ reject(/* @__PURE__ */ new Error("Rejected unsafe image source"));
210
+ return;
211
+ }
206
212
  const img = new Image();
207
213
  img.addEventListener("load", () => {
208
214
  resolve({
@@ -213,7 +219,7 @@ function loadImageDimensions(src) {
213
219
  img.addEventListener("error", () => {
214
220
  reject(/* @__PURE__ */ new Error("Failed to load image"));
215
221
  });
216
- img.src = src;
222
+ img.src = safeSrc;
217
223
  });
218
224
  }
219
225
  //#endregion
@@ -1,4 +1,4 @@
1
- import { acceptAIEditRevision, acceptAllChanges, acceptChange, addCommentMark, findAIEditRevisionRange, findNextChange, findPreviousChange, rejectAIEditRevision, rejectAllChanges, rejectChange, removeCommentMark } from "./comments.js";
1
+ import { AcceptSuggestionOptions, FolioSuggestion, SuggestionAppliedAs, SuggestionKind, acceptAIEditRevision, acceptAllChanges, acceptAllSuggestions, acceptChange, acceptSuggestion, addCommentMark, findAIEditRevisionRange, findNextChange, findPreviousChange, findSuggestionRange, getSuggestions, rejectAIEditRevision, rejectAllChanges, rejectAllSuggestions, rejectChange, rejectSuggestion, removeCommentMark } from "./comments.js";
2
2
  import { PAINTABLE_MARK_NAMES, applyFormatMarks, captureFormatMarks } from "./formatPainter.js";
3
3
  import { clearFormatting, createRemoveMarkCommand, createSetMarkCommand, getMarkAttr, isMarkActive } from "../extensions/marks/markUtils.js";
4
4
  import { getHyperlinkAttrs, getSelectedText, isHyperlinkActive } from "../extensions/marks/HyperlinkExtension.js";
@@ -10,4 +10,4 @@ import { BorderPreset, TableBorderPreset, TableContextInfo, getTableContext, isI
10
10
  import { addColumnLeft, addColumnRight, addRowAbove, addRowBelow, applyTableStyle, autoFitContents, deleteColumn, deleteRow, deleteTable, distributeColumns, insertTable, mergeCells, removeTableBorders, selectColumn, selectRow, selectTable, setAllTableBorders, setCellBorder, setCellFillColor, setCellMargins, setCellTextDirection, setCellVerticalAlign, setInsideTableBorders, setOutsideTableBorders, setRowHeight, setTableBorderColor, setTableBorderPreset, setTableBorderWidth, setTableBorders, setTableProperties, splitCell, toggleHeaderRow, toggleNoWrap } from "./table.js";
11
11
  import { insertPageBreak } from "./pageBreak.js";
12
12
  import { CLIPBOARD_READ_ERROR_EVENT, buildPlainTextSlice, pasteWithoutFormatting } from "./pastePlainText.js";
13
- export { type BorderPreset, CLIPBOARD_READ_ERROR_EVENT, PAINTABLE_MARK_NAMES, type ResolvedStyleAttrs, type TableBorderPreset, type TableContextInfo, acceptAIEditRevision, acceptAllChanges, acceptChange, addColumnLeft, addColumnRight, addCommentMark, addRowAbove, addRowBelow, addTabStop, alignCenter, alignJustify, alignLeft, alignRight, applyFormatMarks, applyStyle, applyTableStyle, autoFitContents, buildPlainTextSlice, captureFormatMarks, clearFontFamily, clearFontSize, clearFormatting, clearHighlight, clearStyle, clearTextColor, createRemoveMarkCommand, createSetMarkCommand, decreaseIndent, decreaseListLevel, deleteColumn, deleteRow, deleteTable, distributeColumns, doubleSpacing, findAIEditRevisionRange, findNextChange, findPreviousChange, generateTOC, getHyperlinkAttrs, getListInfo, getMarkAttr, getParagraphAlignment, getParagraphBidi, getSelectedText, getStyleId, getTableContext, increaseIndent, increaseListLevel, insertHyperlink, insertPageBreak, insertTable, isHyperlinkActive, isInList, isInTableCell as isInTable, isMarkActive, mergeCells, oneAndHalfSpacing, pasteWithoutFormatting, rejectAIEditRevision, rejectAllChanges, rejectChange, removeCommentMark, removeHyperlink, removeList, removeTabStop, removeTableBorders, selectColumn, selectRow, selectTable, setAlignment, setAllTableBorders, setCellBorder, setCellFillColor, setCellMargins, setCellTextDirection, setCellVerticalAlign, setFontFamily, setFontSize, setHighlight, setHyperlink, setIndentFirstLine, setIndentLeft, setIndentRight, setInsideTableBorders, setLineSpacing, setLtr, setOutsideTableBorders, setRowHeight, setRtl, setSpaceAfter, setSpaceBefore, setTableBorderColor, setTableBorderPreset, setTableBorderWidth, setTableBorders, setTableProperties, setTextColor, setUnderlineStyle, singleSpacing, splitCell, toggleBidi, toggleBold, toggleBulletList, toggleHeaderRow, toggleItalic, toggleNoWrap, toggleNumberedList, toggleStrike, toggleSubscript, toggleSuperscript, toggleUnderline };
13
+ export { type AcceptSuggestionOptions, type BorderPreset, CLIPBOARD_READ_ERROR_EVENT, type FolioSuggestion, PAINTABLE_MARK_NAMES, type ResolvedStyleAttrs, type SuggestionAppliedAs, type SuggestionKind, type TableBorderPreset, type TableContextInfo, acceptAIEditRevision, acceptAllChanges, acceptAllSuggestions, acceptChange, acceptSuggestion, addColumnLeft, addColumnRight, addCommentMark, addRowAbove, addRowBelow, addTabStop, alignCenter, alignJustify, alignLeft, alignRight, applyFormatMarks, applyStyle, applyTableStyle, autoFitContents, buildPlainTextSlice, captureFormatMarks, clearFontFamily, clearFontSize, clearFormatting, clearHighlight, clearStyle, clearTextColor, createRemoveMarkCommand, createSetMarkCommand, decreaseIndent, decreaseListLevel, deleteColumn, deleteRow, deleteTable, distributeColumns, doubleSpacing, findAIEditRevisionRange, findNextChange, findPreviousChange, findSuggestionRange, generateTOC, getHyperlinkAttrs, getListInfo, getMarkAttr, getParagraphAlignment, getParagraphBidi, getSelectedText, getStyleId, getSuggestions, getTableContext, increaseIndent, increaseListLevel, insertHyperlink, insertPageBreak, insertTable, isHyperlinkActive, isInList, isInTableCell as isInTable, isMarkActive, mergeCells, oneAndHalfSpacing, pasteWithoutFormatting, rejectAIEditRevision, rejectAllChanges, rejectAllSuggestions, rejectChange, rejectSuggestion, removeCommentMark, removeHyperlink, removeList, removeTabStop, removeTableBorders, selectColumn, selectRow, selectTable, setAlignment, setAllTableBorders, setCellBorder, setCellFillColor, setCellMargins, setCellTextDirection, setCellVerticalAlign, setFontFamily, setFontSize, setHighlight, setHyperlink, setIndentFirstLine, setIndentLeft, setIndentRight, setInsideTableBorders, setLineSpacing, setLtr, setOutsideTableBorders, setRowHeight, setRtl, setSpaceAfter, setSpaceBefore, setTableBorderColor, setTableBorderPreset, setTableBorderWidth, setTableBorders, setTableProperties, setTextColor, setUnderlineStyle, singleSpacing, splitCell, toggleBidi, toggleBold, toggleBulletList, toggleHeaderRow, toggleItalic, toggleNoWrap, toggleNumberedList, toggleStrike, toggleSubscript, toggleSuperscript, toggleUnderline };
@@ -1,13 +1,13 @@
1
- import { acceptAIEditRevision, acceptAllChanges, acceptChange, addCommentMark, findAIEditRevisionRange, findNextChange, findPreviousChange, rejectAIEditRevision, rejectAllChanges, rejectChange, removeCommentMark } from "./comments.js";
2
1
  import { getParagraphAlignment, getParagraphBidi, getStyleId } from "../extensions/core/ParagraphExtension.js";
3
2
  import { clearFormatting, createRemoveMarkCommand, createSetMarkCommand, getMarkAttr, isMarkActive } from "../extensions/marks/markUtils.js";
4
3
  import { getTableContext, isInTable as isInTableCell } from "../extensions/nodes/TableExtension.js";
5
4
  import { getListInfo, isInList } from "../extensions/features/ListExtension.js";
6
5
  import { CLIPBOARD_READ_ERROR_EVENT, buildPlainTextSlice, pasteWithoutFormatting } from "./pastePlainText.js";
7
6
  import { getHyperlinkAttrs, getSelectedText, isHyperlinkActive } from "../extensions/marks/HyperlinkExtension.js";
7
+ import { acceptAIEditRevision, acceptAllChanges, acceptAllSuggestions, acceptChange, acceptSuggestion, addCommentMark, findAIEditRevisionRange, findNextChange, findPreviousChange, findSuggestionRange, getSuggestions, rejectAIEditRevision, rejectAllChanges, rejectAllSuggestions, rejectChange, rejectSuggestion, removeCommentMark } from "./comments.js";
8
8
  import { addColumnLeft, addColumnRight, addRowAbove, addRowBelow, applyTableStyle, autoFitContents, deleteColumn, deleteRow, deleteTable, distributeColumns, insertTable, mergeCells, removeTableBorders, selectColumn, selectRow, selectTable, setAllTableBorders, setCellBorder, setCellFillColor, setCellMargins, setCellTextDirection, setCellVerticalAlign, setInsideTableBorders, setOutsideTableBorders, setRowHeight, setTableBorderColor, setTableBorderPreset, setTableBorderWidth, setTableBorders, setTableProperties, splitCell, toggleHeaderRow, toggleNoWrap } from "./table.js";
9
9
  import { clearFontFamily, clearFontSize, clearHighlight, clearTextColor, insertHyperlink, removeHyperlink, setFontFamily, setFontSize, setHighlight, setHyperlink, setTextColor, setUnderlineStyle, toggleBold, toggleItalic, toggleStrike, toggleSubscript, toggleSuperscript, toggleUnderline } from "./formatting.js";
10
10
  import { addTabStop, alignCenter, alignJustify, alignLeft, alignRight, applyStyle, clearStyle, decreaseIndent, decreaseListLevel, doubleSpacing, generateTOC, increaseIndent, increaseListLevel, oneAndHalfSpacing, removeList, removeTabStop, setAlignment, setIndentFirstLine, setIndentLeft, setIndentRight, setLineSpacing, setLtr, setRtl, setSpaceAfter, setSpaceBefore, singleSpacing, toggleBidi, toggleBulletList, toggleNumberedList } from "./paragraph.js";
11
11
  import { PAINTABLE_MARK_NAMES, applyFormatMarks, captureFormatMarks } from "./formatPainter.js";
12
12
  import { insertPageBreak } from "./pageBreak.js";
13
- export { CLIPBOARD_READ_ERROR_EVENT, PAINTABLE_MARK_NAMES, acceptAIEditRevision, acceptAllChanges, acceptChange, addColumnLeft, addColumnRight, addCommentMark, addRowAbove, addRowBelow, addTabStop, alignCenter, alignJustify, alignLeft, alignRight, applyFormatMarks, applyStyle, applyTableStyle, autoFitContents, buildPlainTextSlice, captureFormatMarks, clearFontFamily, clearFontSize, clearFormatting, clearHighlight, clearStyle, clearTextColor, createRemoveMarkCommand, createSetMarkCommand, decreaseIndent, decreaseListLevel, deleteColumn, deleteRow, deleteTable, distributeColumns, doubleSpacing, findAIEditRevisionRange, findNextChange, findPreviousChange, generateTOC, getHyperlinkAttrs, getListInfo, getMarkAttr, getParagraphAlignment, getParagraphBidi, getSelectedText, getStyleId, getTableContext, increaseIndent, increaseListLevel, insertHyperlink, insertPageBreak, insertTable, isHyperlinkActive, isInList, isInTableCell as isInTable, isMarkActive, mergeCells, oneAndHalfSpacing, pasteWithoutFormatting, rejectAIEditRevision, rejectAllChanges, rejectChange, removeCommentMark, removeHyperlink, removeList, removeTabStop, removeTableBorders, selectColumn, selectRow, selectTable, setAlignment, setAllTableBorders, setCellBorder, setCellFillColor, setCellMargins, setCellTextDirection, setCellVerticalAlign, setFontFamily, setFontSize, setHighlight, setHyperlink, setIndentFirstLine, setIndentLeft, setIndentRight, setInsideTableBorders, setLineSpacing, setLtr, setOutsideTableBorders, setRowHeight, setRtl, setSpaceAfter, setSpaceBefore, setTableBorderColor, setTableBorderPreset, setTableBorderWidth, setTableBorders, setTableProperties, setTextColor, setUnderlineStyle, singleSpacing, splitCell, toggleBidi, toggleBold, toggleBulletList, toggleHeaderRow, toggleItalic, toggleNoWrap, toggleNumberedList, toggleStrike, toggleSubscript, toggleSuperscript, toggleUnderline };
13
+ export { CLIPBOARD_READ_ERROR_EVENT, PAINTABLE_MARK_NAMES, acceptAIEditRevision, acceptAllChanges, acceptAllSuggestions, acceptChange, acceptSuggestion, addColumnLeft, addColumnRight, addCommentMark, addRowAbove, addRowBelow, addTabStop, alignCenter, alignJustify, alignLeft, alignRight, applyFormatMarks, applyStyle, applyTableStyle, autoFitContents, buildPlainTextSlice, captureFormatMarks, clearFontFamily, clearFontSize, clearFormatting, clearHighlight, clearStyle, clearTextColor, createRemoveMarkCommand, createSetMarkCommand, decreaseIndent, decreaseListLevel, deleteColumn, deleteRow, deleteTable, distributeColumns, doubleSpacing, findAIEditRevisionRange, findNextChange, findPreviousChange, findSuggestionRange, generateTOC, getHyperlinkAttrs, getListInfo, getMarkAttr, getParagraphAlignment, getParagraphBidi, getSelectedText, getStyleId, getSuggestions, getTableContext, increaseIndent, increaseListLevel, insertHyperlink, insertPageBreak, insertTable, isHyperlinkActive, isInList, isInTableCell as isInTable, isMarkActive, mergeCells, oneAndHalfSpacing, pasteWithoutFormatting, rejectAIEditRevision, rejectAllChanges, rejectAllSuggestions, rejectChange, rejectSuggestion, removeCommentMark, removeHyperlink, removeList, removeTabStop, removeTableBorders, selectColumn, selectRow, selectTable, setAlignment, setAllTableBorders, setCellBorder, setCellFillColor, setCellMargins, setCellTextDirection, setCellVerticalAlign, setFontFamily, setFontSize, setHighlight, setHyperlink, setIndentFirstLine, setIndentLeft, setIndentRight, setInsideTableBorders, setLineSpacing, setLtr, setOutsideTableBorders, setRowHeight, setRtl, setSpaceAfter, setSpaceBefore, setTableBorderColor, setTableBorderPreset, setTableBorderWidth, setTableBorders, setTableProperties, setTextColor, setUnderlineStyle, singleSpacing, splitCell, toggleBidi, toggleBold, toggleBulletList, toggleHeaderRow, toggleItalic, toggleNoWrap, toggleNumberedList, toggleStrike, toggleSubscript, toggleSuperscript, toggleUnderline };
@@ -1,5 +1,5 @@
1
- import { TextSelection } from "prosemirror-state";
2
1
  import { Fragment } from "prosemirror-model";
2
+ import { TextSelection } from "prosemirror-state";
3
3
  //#region src/prosemirror/commands/pageBreak.ts
4
4
  /**
5
5
  * Page Break Commands
@@ -18,9 +18,9 @@ type AttrPatch = Record<string, unknown>;
18
18
  * `runInWithNext` (`w:specVanish` lives in that rPr)
19
19
  * - load-time style/numbering bookkeeping the command layer cannot recompute
20
20
  * without a style resolver: `numPrFromStyle`, the `list*` rendering attrs,
21
- * `spacingFromDocDefaults`
21
+ * `spacingFromDocDefaults`, `spacingFromImplicitDefaultStyle`
22
22
  */
23
- declare const PPR_CHANGE_SCOPED_ATTR_KEYS: readonly ["styleId", "numPr", "alignment", "spaceBefore", "spaceAfter", "lineSpacing", "lineSpacingRule", "spacingExplicit", "indentLeft", "indentRight", "indentFirstLine", "hangingIndent", "borders", "shading", "tabs", "pageBreakBefore", "keepNext", "keepLines", "widowControl", "contextualSpacing", "outlineLevel", "direction", "_autospacingBase"];
23
+ declare const PPR_CHANGE_SCOPED_ATTR_KEYS: readonly ["styleId", "numPr", "alignment", "spaceBefore", "spaceAfter", "lineSpacing", "lineSpacingRule", "snapToGrid", "spacingExplicit", "indentLeft", "indentRight", "indentFirstLine", "hangingIndent", "borders", "shading", "tabs", "pageBreakBefore", "keepNext", "keepLines", "widowControl", "contextualSpacing", "outlineLevel", "direction", "_autospacingBase"];
24
24
  /**
25
25
  * Build the attr patch that rejecting one pPrChange applies to a paragraph:
26
26
  * every in-scope key set to the stored previous value, or reset to `null`
@@ -1,5 +1,5 @@
1
- import { setAutospacingBaseValue } from "../autospacingBase.js";
2
1
  import { directionFromBidi } from "../paragraphDirection.js";
2
+ import { setAutospacingBaseValue } from "../autospacingBase.js";
3
3
  //#region src/prosemirror/commands/propertyChangeScope.ts
4
4
  /**
5
5
  * Paragraph attrs governed by a `w:pPrChange` — the attrs
@@ -17,7 +17,7 @@ import { directionFromBidi } from "../paragraphDirection.js";
17
17
  * `runInWithNext` (`w:specVanish` lives in that rPr)
18
18
  * - load-time style/numbering bookkeeping the command layer cannot recompute
19
19
  * without a style resolver: `numPrFromStyle`, the `list*` rendering attrs,
20
- * `spacingFromDocDefaults`
20
+ * `spacingFromDocDefaults`, `spacingFromImplicitDefaultStyle`
21
21
  */
22
22
  const PPR_CHANGE_SCOPED_ATTR_KEYS = [
23
23
  "styleId",
@@ -27,6 +27,7 @@ const PPR_CHANGE_SCOPED_ATTR_KEYS = [
27
27
  "spaceAfter",
28
28
  "lineSpacing",
29
29
  "lineSpacingRule",
30
+ "snapToGrid",
30
31
  "spacingExplicit",
31
32
  "indentLeft",
32
33
  "indentRight",
@@ -0,0 +1,9 @@
1
+ import { Transaction } from "prosemirror-state";
2
+ import { Node } from "prosemirror-model";
3
+
4
+ //#region src/prosemirror/commands/tableCellMergeResolution.d.ts
5
+ declare const hasMatchingCollapsedTableCellMerge: (node: Node, revisionSet: Set<number> | null) => boolean;
6
+ declare const resolveVisibleTableCellMerge: (tr: Transaction, cellPos: number, mode: "accept" | "reject") => boolean;
7
+ declare const resolveCollapsedTableCellMerge: (tr: Transaction, cellPos: number, mode: "accept" | "reject", revisionSet: Set<number> | null) => boolean;
8
+ //#endregion
9
+ export { hasMatchingCollapsedTableCellMerge, resolveCollapsedTableCellMerge, resolveVisibleTableCellMerge };
@@ -0,0 +1,181 @@
1
+ import { standaloneTableCellToProseMirror } from "../conversion/toProseDoc.js";
2
+ import { standaloneTableCellFromProseMirror } from "../conversion/fromProseDoc.js";
3
+ import { getTableCellMergeChange } from "../tableCellMergeRevision.js";
4
+ import { Result } from "better-result";
5
+ import { TableMap } from "prosemirror-tables";
6
+ //#region src/prosemirror/commands/tableCellMergeResolution.ts
7
+ const hasMatchingCollapsedTableCellMerge = (node, revisionSet) => {
8
+ const continuationCells = node.attrs["_docxVMergeContinuationCells"];
9
+ if (!Array.isArray(continuationCells)) return false;
10
+ return continuationCells.some((cell) => {
11
+ const change = getTableCellMergeChange(cell);
12
+ return change !== null && (revisionSet === null || revisionSet.has(change.info.id));
13
+ });
14
+ };
15
+ const isTableCellMergeRevisionAttr = (value) => {
16
+ if (typeof value !== "object" || value === null || !("kind" in value) || value.kind !== "merge" || !("info" in value)) return false;
17
+ const info = value.info;
18
+ return typeof info === "object" && info !== null && "revisionId" in info && typeof info.revisionId === "number";
19
+ };
20
+ const tableCellContext = (doc, cellPos) => {
21
+ const resolved = doc.resolve(cellPos);
22
+ for (let depth = resolved.depth; depth > 0; depth -= 1) {
23
+ const node = resolved.node(depth);
24
+ if (node.type.spec["tableRole"] !== "table") continue;
25
+ const tablePos = resolved.before(depth);
26
+ return {
27
+ table: node,
28
+ tableStart: tablePos + 1,
29
+ relativeCellPos: cellPos - tablePos - 1
30
+ };
31
+ }
32
+ return null;
33
+ };
34
+ const resolveVisibleTableCellMerge = (tr, cellPos, mode) => {
35
+ const cell = tr.doc.nodeAt(cellPos);
36
+ const marker = cell?.attrs["cellMarker"];
37
+ if (!cell || !isTableCellMergeRevisionAttr(marker)) return false;
38
+ if (mode === "accept") {
39
+ tr.setNodeAttribute(cellPos, "cellMarker", null);
40
+ return true;
41
+ }
42
+ if ((marker.verticalMergeOriginal ?? "rest") === "continue") return mergeTableCellWithCellAbove(tr, cellPos);
43
+ const originalFormatting = cell.attrs["_originalFormatting"];
44
+ let nextOriginalFormatting = originalFormatting;
45
+ if (typeof originalFormatting === "object" && originalFormatting !== null) {
46
+ nextOriginalFormatting = { ...originalFormatting };
47
+ delete nextOriginalFormatting.vMerge;
48
+ }
49
+ tr.setNodeMarkup(cellPos, void 0, {
50
+ ...cell.attrs,
51
+ cellMarker: null,
52
+ _originalFormatting: nextOriginalFormatting
53
+ });
54
+ return true;
55
+ };
56
+ const mergeTableCellWithCellAbove = (tr, cellPos) => {
57
+ const context = tableCellContext(tr.doc, cellPos);
58
+ const cell = tr.doc.nodeAt(cellPos);
59
+ if (!context || !cell) return false;
60
+ const map = TableMap.get(context.table);
61
+ const rectangle = map.findCell(context.relativeCellPos);
62
+ if (rectangle.top === 0) return false;
63
+ const aboveRelativePos = map.map[(rectangle.top - 1) * map.width + rectangle.left];
64
+ if (aboveRelativePos === void 0 || aboveRelativePos === context.relativeCellPos) return false;
65
+ const aboveRectangle = map.findCell(aboveRelativePos);
66
+ if (aboveRectangle.left !== rectangle.left || aboveRectangle.right !== rectangle.right || aboveRectangle.bottom !== rectangle.top) return false;
67
+ const abovePos = context.tableStart + aboveRelativePos;
68
+ const aboveCell = tr.doc.nodeAt(abovePos);
69
+ const aboveRowspan = aboveCell?.attrs["rowspan"];
70
+ const cellRowspan = cell.attrs["rowspan"];
71
+ if (!aboveCell || typeof aboveRowspan !== "number" || typeof cellRowspan !== "number" || aboveRowspan < 1 || cellRowspan < 1) return false;
72
+ const continuationCells = tableCellContinuationCells(aboveCell, aboveRowspan);
73
+ continuationCells.push(tableCellContinuationFromNode(cell));
74
+ const nestedContinuations = cell.attrs["_docxVMergeContinuationCells"];
75
+ if (Array.isArray(nestedContinuations)) continuationCells.push(...nestedContinuations);
76
+ tr.delete(cellPos, cellPos + cell.nodeSize);
77
+ tr.setNodeMarkup(abovePos, void 0, {
78
+ ...aboveCell.attrs,
79
+ rowspan: aboveRowspan + cellRowspan,
80
+ _docxVMergeContinuationCells: continuationCells
81
+ });
82
+ return true;
83
+ };
84
+ const tableCellContinuationCells = (cell, rowspan) => {
85
+ const stored = cell.attrs["_docxVMergeContinuationCells"];
86
+ const cells = Array.isArray(stored) ? [...stored] : [];
87
+ while (cells.length < rowspan - 1) cells.push(emptyVerticalMergeContinuation());
88
+ return cells;
89
+ };
90
+ const tableCellContinuationFromNode = (cell) => {
91
+ const continuation = standaloneTableCellFromProseMirror(cell);
92
+ const formatting = {
93
+ ...continuation.formatting,
94
+ vMerge: "continue"
95
+ };
96
+ const colspan = cell.attrs["colspan"];
97
+ if (typeof colspan === "number" && colspan > 1) formatting.gridSpan = colspan;
98
+ continuation.formatting = formatting;
99
+ delete continuation.structuralChange;
100
+ return continuation;
101
+ };
102
+ const emptyVerticalMergeContinuation = () => ({
103
+ type: "tableCell",
104
+ formatting: { vMerge: "continue" },
105
+ content: [{
106
+ type: "paragraph",
107
+ content: []
108
+ }]
109
+ });
110
+ const resolveCollapsedTableCellMerge = (tr, cellPos, mode, revisionSet) => {
111
+ const cell = tr.doc.nodeAt(cellPos);
112
+ const stored = cell?.attrs["_docxVMergeContinuationCells"];
113
+ if (!cell || !Array.isArray(stored)) return false;
114
+ const matchingIndices = [];
115
+ const nextCells = stored.map((continuationCell, index) => {
116
+ const change = getTableCellMergeChange(continuationCell);
117
+ if (!change || revisionSet !== null && !revisionSet.has(change.info.id)) return continuationCell;
118
+ matchingIndices.push(index);
119
+ const nextCell = { ...continuationCell };
120
+ delete nextCell.structuralChange;
121
+ return nextCell;
122
+ });
123
+ if (matchingIndices.length === 0) return false;
124
+ if (mode === "accept") {
125
+ tr.setNodeAttribute(cellPos, "_docxVMergeContinuationCells", nextCells);
126
+ return true;
127
+ }
128
+ const splitIndices = matchingIndices.filter((index) => {
129
+ const change = getTableCellMergeChange(stored[index]);
130
+ return change?.verticalMerge === "continue" && (change.verticalMergeOriginal ?? "rest") === "rest";
131
+ });
132
+ if (splitIndices.length === 0) {
133
+ tr.setNodeAttribute(cellPos, "_docxVMergeContinuationCells", nextCells);
134
+ return true;
135
+ }
136
+ const firstSplitIndex = splitIndices.at(0);
137
+ if (firstSplitIndex === void 0 || splitIndices.length !== stored.length - firstSplitIndex || splitIndices.some((index, offset) => index !== firstSplitIndex + offset)) return false;
138
+ const context = tableCellContext(tr.doc, cellPos);
139
+ if (!context) return false;
140
+ const map = TableMap.get(context.table);
141
+ const rectangle = map.findCell(context.relativeCellPos);
142
+ const rowspan = cell.attrs["rowspan"];
143
+ if (typeof rowspan !== "number" || rowspan !== stored.length + 1 || rectangle.bottom - rectangle.top !== rowspan) return false;
144
+ const restorations = [];
145
+ for (const index of splitIndices) {
146
+ const source = nextCells[index];
147
+ if (!source) return false;
148
+ const restoredCell = createRestoredTableCell(cell, source);
149
+ if (!restoredCell) return false;
150
+ restorations.push({
151
+ index,
152
+ cell: restoredCell
153
+ });
154
+ }
155
+ const mapFrom = tr.mapping.maps.length;
156
+ for (const restoration of restorations) {
157
+ const row = rectangle.top + restoration.index + 1;
158
+ const insertionPos = context.tableStart + map.positionAt(row, rectangle.left, context.table);
159
+ tr.insert(tr.mapping.slice(mapFrom).map(insertionPos, 1), restoration.cell);
160
+ }
161
+ const remainingCells = nextCells.slice(0, firstSplitIndex);
162
+ tr.setNodeMarkup(cellPos, void 0, {
163
+ ...cell.attrs,
164
+ rowspan: firstSplitIndex + 1,
165
+ _docxVMergeContinuationCells: remainingCells.length > 0 ? remainingCells : null
166
+ });
167
+ return true;
168
+ };
169
+ const createRestoredTableCell = (origin, source) => {
170
+ const formatting = source.formatting ? { ...source.formatting } : void 0;
171
+ if (formatting) delete formatting.vMerge;
172
+ const restored = standaloneTableCellToProseMirror({
173
+ type: "tableCell",
174
+ ...formatting ? { formatting } : {},
175
+ ...source.propertyChanges ? { propertyChanges: source.propertyChanges } : {},
176
+ content: source.content
177
+ }, origin.type.name === "tableHeader" ? "tableHeader" : "tableCell");
178
+ return Result.try(() => origin.type.schema.nodeFromJSON(restored.toJSON())).unwrapOr(null);
179
+ };
180
+ //#endregion
181
+ export { hasMatchingCollapsedTableCellMerge, resolveCollapsedTableCellMerge, resolveVisibleTableCellMerge };
@@ -1,3 +1,5 @@
1
+ import { seedRevisionIdsAbove } from "./plugins/revisionIds.js";
2
+ import { MAX_REVISION_ID } from "@stll/docx-core/model";
1
3
  //#region src/prosemirror/commentIdAllocator.ts
2
4
  /** Sentinel ID for a comment that hasn't been persisted yet (anchored to selection). */
3
5
  const PENDING_COMMENT_ID = -1;
@@ -9,8 +11,12 @@ const PENDING_COMMENT_ID = -1;
9
11
  function createCommentIdAllocator() {
10
12
  let nextId = 1;
11
13
  return {
12
- next: () => nextId++,
14
+ next: () => {
15
+ if (nextId > MAX_REVISION_ID) nextId = 1;
16
+ return nextId++;
17
+ },
13
18
  seedAbove(maxId) {
19
+ if (!Number.isInteger(maxId) || maxId < 0 || maxId >= MAX_REVISION_ID) return;
14
20
  if (maxId >= nextId) nextId = maxId + 1;
15
21
  }
16
22
  };
@@ -25,11 +31,15 @@ function createCommentIdAllocator() {
25
31
  */
26
32
  function seedCommentAllocator(allocator, comments, view) {
27
33
  let max = 0;
28
- for (const comment of comments ?? []) max = Math.max(max, comment.id);
34
+ for (const comment of comments ?? []) if (Number.isInteger(comment.id) && comment.id > max && comment.id <= MAX_REVISION_ID) max = comment.id;
29
35
  if (view) view.state.doc.descendants((node) => {
30
- for (const mark of node.marks) if (mark.attrs["revisionId"] != null) max = Math.max(max, mark.attrs["revisionId"]);
36
+ for (const mark of node.marks) {
37
+ const revisionId = mark.attrs["revisionId"];
38
+ if (typeof revisionId === "number" && Number.isInteger(revisionId) && revisionId > max && revisionId <= MAX_REVISION_ID) max = revisionId;
39
+ }
31
40
  });
32
41
  allocator.seedAbove(max);
42
+ seedRevisionIdsAbove(max);
33
43
  }
34
44
  //#endregion
35
45
  export { PENDING_COMMENT_ID, createCommentIdAllocator, seedCommentAllocator };
@@ -10,6 +10,7 @@ declare function fromProseDoc(pmDoc: Node, baseDocument?: document_d_exports.Doc
10
10
  * Convert ProseMirror marks to TextFormatting
11
11
  */
12
12
  declare function marksToTextFormatting(marks: readonly Mark[]): document_d_exports.TextFormatting;
13
+ declare const standaloneTableCellFromProseMirror: (node: Node) => document_d_exports.TableCell;
13
14
  /**
14
15
  * Update a Document with content from a ProseMirror document
15
16
  * Preserves all non-content parts of the original document
@@ -24,4 +25,4 @@ declare function updateDocumentContent(originalDocument: document_d_exports.Docu
24
25
  */
25
26
  declare function proseDocToBlocks(pmDoc: Node): document_d_exports.BlockContent[];
26
27
  //#endregion
27
- export { fromProseDoc, marksToTextFormatting, proseDocToBlocks, updateDocumentContent };
28
+ export { fromProseDoc, marksToTextFormatting, proseDocToBlocks, standaloneTableCellFromProseMirror, updateDocumentContent };