@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
@@ -0,0 +1,238 @@
1
+ import { expectTableCellAttrs } from "../prosemirror/attrs/index.js";
2
+ import { markStructuralChange } from "../prosemirror/extensions/features/ParagraphChangeTrackerExtension.js";
3
+ import { standaloneTableCellToProseMirror } from "../prosemirror/conversion/toProseDoc.js";
4
+ import { standaloneTableCellFromProseMirror } from "../prosemirror/conversion/fromProseDoc.js";
5
+ import { tableRectanglesEqual } from "./table-mutation-plan.js";
6
+ import { tableRectangleCutsMergedCell } from "./table-targets.js";
7
+ import { Result } from "better-result";
8
+ import { TableMap } from "prosemirror-tables";
9
+ import { Fragment } from "prosemirror-model";
10
+ //#region src/ai-edits/table-cell-mutations.ts
11
+ const mergeTableRectangle = ({ tr, tablePosition, table, rectangle }) => {
12
+ const map = TableMap.get(table);
13
+ if (rectangle.left < 0 || rectangle.top < 0 || rectangle.right > map.width || rectangle.bottom > map.height || rectangle.left >= rectangle.right || rectangle.top >= rectangle.bottom || rectangle.right - rectangle.left === 1 && rectangle.bottom - rectangle.top === 1 || tableRectangleCutsMergedCell(map, rectangle)) return null;
14
+ const tableStart = tablePosition + 1;
15
+ const seen = /* @__PURE__ */ new Set();
16
+ const cells = [];
17
+ let appendedContent = Fragment.empty;
18
+ for (let row = rectangle.top; row < rectangle.bottom; row++) for (let column = rectangle.left; column < rectangle.right; column++) {
19
+ const cellPosition = map.map[row * map.width + column];
20
+ if (cellPosition === void 0 || seen.has(cellPosition)) continue;
21
+ const cell = table.nodeAt(cellPosition);
22
+ if (!cell) return null;
23
+ seen.add(cellPosition);
24
+ cells.push({
25
+ position: cellPosition,
26
+ cell
27
+ });
28
+ if (cells.length > 1 && !isEmptyTableCell(cell)) appendedContent = appendedContent.append(cell.content);
29
+ }
30
+ const merged = cells.at(0);
31
+ if (!merged || cells.length < 2) return null;
32
+ const colspan = merged.cell.attrs["colspan"];
33
+ const rowspan = merged.cell.attrs["rowspan"];
34
+ const colwidth = merged.cell.attrs["colwidth"];
35
+ if (typeof colspan !== "number" || !Number.isInteger(colspan) || colspan < 1 || typeof rowspan !== "number" || !Number.isInteger(rowspan) || rowspan < 1 || colwidth !== null && colwidth !== void 0 && (!Array.isArray(colwidth) || colwidth.length !== colspan || !colwidth.every((width) => typeof width === "number"))) return null;
36
+ const mergedColspan = rectangle.right - rectangle.left;
37
+ const nextColwidth = Array.isArray(colwidth) ? [...colwidth] : null;
38
+ while (nextColwidth && nextColwidth.length < mergedColspan) nextColwidth.push(0);
39
+ const mapFrom = tr.mapping.maps.length;
40
+ for (const { position: cellPosition, cell } of cells.slice(1)) {
41
+ const position = tr.mapping.slice(mapFrom).map(tableStart + cellPosition);
42
+ tr = tr.delete(position, position + cell.nodeSize);
43
+ }
44
+ const absoluteMergedPosition = tableStart + merged.position;
45
+ tr = tr.setNodeMarkup(absoluteMergedPosition, void 0, {
46
+ ...merged.cell.attrs,
47
+ colspan: mergedColspan,
48
+ rowspan: rectangle.bottom - rectangle.top,
49
+ colwidth: nextColwidth
50
+ });
51
+ if (appendedContent.size > 0) {
52
+ const contentEnd = absoluteMergedPosition + 1 + merged.cell.content.size;
53
+ const contentStart = isEmptyTableCell(merged.cell) ? absoluteMergedPosition + 1 : contentEnd;
54
+ tr = tr.replaceWith(contentStart, contentEnd, appendedContent);
55
+ }
56
+ return tr;
57
+ };
58
+ const mergeTrackedVerticalTableCells = ({ tr, tablePosition, table, rectangle, revisionId, author, date }) => {
59
+ const map = TableMap.get(table);
60
+ if (rectangle.right - rectangle.left !== 1 || rectangle.bottom - rectangle.top < 2 || rectangle.left < 0 || rectangle.top < 0 || rectangle.right > map.width || rectangle.bottom > map.height || tableRectangleCutsMergedCell(map, rectangle)) return null;
61
+ const cells = [];
62
+ for (let row = rectangle.top; row < rectangle.bottom; row++) {
63
+ const position = map.map[row * map.width + rectangle.left];
64
+ if (position === void 0) return null;
65
+ const cell = table.nodeAt(position);
66
+ if (!cell || !tableRectanglesEqual(map.findCell(position), {
67
+ left: rectangle.left,
68
+ top: row,
69
+ right: rectangle.right,
70
+ bottom: row + 1
71
+ })) return null;
72
+ const attrs = expectTableCellAttrs(cell);
73
+ if (attrs.colspan !== 1 || attrs.rowspan !== 1 || attrs.cellMarker !== void 0 || attrs._docxVMergeContinuationCells !== void 0 || attrs._preserveVMergeRestart === true || attrs._originalFormatting?.vMerge !== void 0) return null;
74
+ cells.push({
75
+ position,
76
+ cell
77
+ });
78
+ }
79
+ const origin = cells.at(0);
80
+ if (!origin || cells.length !== rectangle.bottom - rectangle.top || cells.some(({ cell }) => cell.type !== origin.cell.type) || cells.slice(1).some(({ cell }) => !isEmptyTableCell(cell))) return null;
81
+ const continuationCells = [];
82
+ for (const { cell } of cells.slice(1)) {
83
+ const continuation = standaloneTableCellFromProseMirror(cell);
84
+ continuation.formatting = {
85
+ ...continuation.formatting,
86
+ vMerge: "continue"
87
+ };
88
+ continuation.structuralChange = {
89
+ type: "tableCellMerge",
90
+ info: {
91
+ id: revisionId,
92
+ author,
93
+ date
94
+ },
95
+ verticalMerge: "continue",
96
+ verticalMergeOriginal: "rest"
97
+ };
98
+ continuationCells.push(continuation);
99
+ }
100
+ const nextTr = mergeTableRectangle({
101
+ tr,
102
+ tablePosition,
103
+ table,
104
+ rectangle
105
+ });
106
+ if (!nextTr) return null;
107
+ nextTr.setNodeAttribute(tablePosition + 1 + origin.position, "_docxVMergeContinuationCells", continuationCells);
108
+ markStructuralChange(nextTr);
109
+ return nextTr;
110
+ };
111
+ const splitTableRectangle = ({ tr, tablePosition, table, rectangle }) => {
112
+ const map = TableMap.get(table);
113
+ if (rectangle.left < 0 || rectangle.top < 0 || rectangle.right > map.width || rectangle.bottom > map.height || rectangle.left >= rectangle.right || rectangle.top >= rectangle.bottom || rectangle.right - rectangle.left === 1 && rectangle.bottom - rectangle.top === 1) return null;
114
+ const cellPosition = map.map[rectangle.top * map.width + rectangle.left];
115
+ if (cellPosition === void 0) return null;
116
+ if (!tableRectanglesEqual(map.findCell(cellPosition), rectangle)) return null;
117
+ const cell = table.nodeAt(cellPosition);
118
+ if (!cell) return null;
119
+ const colspan = cell.attrs["colspan"];
120
+ const rowspan = cell.attrs["rowspan"];
121
+ const colwidth = cell.attrs["colwidth"];
122
+ if (typeof colspan !== "number" || !Number.isInteger(colspan) || colspan !== rectangle.right - rectangle.left || typeof rowspan !== "number" || !Number.isInteger(rowspan) || rowspan !== rectangle.bottom - rectangle.top || colwidth !== null && colwidth !== void 0 && (!Array.isArray(colwidth) || colwidth.length !== colspan || !colwidth.every((width) => typeof width === "number"))) return null;
123
+ const baseAttrs = {
124
+ ...cell.attrs,
125
+ colspan: 1,
126
+ rowspan: 1,
127
+ _preserveVMergeRestart: null,
128
+ _docxVMergeContinuationCells: null
129
+ };
130
+ const attrsByColumn = Array.from({ length: colspan }, (_, index) => ({
131
+ ...baseAttrs,
132
+ colwidth: Array.isArray(colwidth) && typeof colwidth[index] === "number" && colwidth[index] > 0 ? [colwidth[index]] : null
133
+ }));
134
+ const tableStart = tablePosition + 1;
135
+ const insertions = [];
136
+ for (let row = rectangle.top; row < rectangle.bottom; row++) {
137
+ let position = map.positionAt(row, rectangle.left, table);
138
+ if (row === rectangle.top) position += cell.nodeSize;
139
+ for (let column = rectangle.left; column < rectangle.right; column++) {
140
+ if (row === rectangle.top && column === rectangle.left) continue;
141
+ const attrs = attrsByColumn[column - rectangle.left];
142
+ const nextCell = attrs ? cell.type.createAndFill(attrs) : null;
143
+ if (!nextCell) return null;
144
+ insertions.push({
145
+ position: tableStart + position,
146
+ cell: nextCell
147
+ });
148
+ }
149
+ }
150
+ const mapFrom = tr.mapping.maps.length;
151
+ for (const insertion of insertions) tr = tr.insert(tr.mapping.slice(mapFrom).map(insertion.position, 1), insertion.cell);
152
+ return tr.setNodeMarkup(tableStart + cellPosition, void 0, attrsByColumn[0]);
153
+ };
154
+ const splitTrackedVerticalTableCell = ({ tr, tablePosition, table, rectangle, revisionId, author, date }) => {
155
+ const map = TableMap.get(table);
156
+ if (rectangle.right - rectangle.left !== 1 || rectangle.bottom - rectangle.top < 2 || rectangle.left < 0 || rectangle.top < 0 || rectangle.right > map.width || rectangle.bottom > map.height) return null;
157
+ const relativeCellPosition = map.map[rectangle.top * map.width + rectangle.left];
158
+ if (relativeCellPosition === void 0) return null;
159
+ if (!tableRectanglesEqual(map.findCell(relativeCellPosition), rectangle)) return null;
160
+ const cell = table.nodeAt(relativeCellPosition);
161
+ if (!cell) return null;
162
+ const attrs = expectTableCellAttrs(cell);
163
+ if (attrs.colspan !== 1 || attrs.rowspan !== rectangle.bottom - rectangle.top || attrs.cellMarker !== void 0) return null;
164
+ const continuationCells = attrs._docxVMergeContinuationCells;
165
+ if (continuationCells !== void 0 && continuationCells.length !== rectangle.bottom - rectangle.top - 1) return null;
166
+ const marker = {
167
+ kind: "merge",
168
+ info: {
169
+ revisionId,
170
+ author,
171
+ date
172
+ },
173
+ verticalMergeOriginal: "continue"
174
+ };
175
+ const insertedCells = [];
176
+ for (let index = 0; index < rectangle.bottom - rectangle.top - 1; index++) {
177
+ const source = continuationCells?.[index];
178
+ if (source?.structuralChange !== void 0) return null;
179
+ const insertedCell = source ? trackedSplitCellFromStoredSource({
180
+ origin: cell,
181
+ source,
182
+ marker
183
+ }) : cell.type.createAndFill({
184
+ ...cell.attrs,
185
+ rowspan: 1,
186
+ cellMarker: marker,
187
+ _originalFormatting: formattingWithoutVerticalMerge(attrs._originalFormatting),
188
+ _preserveVMergeRestart: null,
189
+ _docxVMergeContinuationCells: null
190
+ });
191
+ if (!insertedCell) return null;
192
+ insertedCells.push(insertedCell);
193
+ }
194
+ const tableStart = tablePosition + 1;
195
+ const mapFrom = tr.mapping.maps.length;
196
+ for (const [index, insertedCell] of insertedCells.entries()) {
197
+ const row = rectangle.top + index + 1;
198
+ const position = tableStart + map.positionAt(row, rectangle.left, table);
199
+ tr = tr.insert(tr.mapping.slice(mapFrom).map(position, 1), insertedCell);
200
+ }
201
+ tr = tr.setNodeMarkup(tableStart + relativeCellPosition, void 0, {
202
+ ...cell.attrs,
203
+ rowspan: 1,
204
+ _originalFormatting: formattingWithoutVerticalMerge(attrs._originalFormatting),
205
+ _preserveVMergeRestart: null,
206
+ _docxVMergeContinuationCells: null
207
+ });
208
+ markStructuralChange(tr);
209
+ return tr;
210
+ };
211
+ const isEmptyTableCell = (cell) => cell.childCount === 1 && cell.firstChild?.isTextblock === true && cell.firstChild.childCount === 0;
212
+ const trackedSplitCellFromStoredSource = ({ origin, source, marker }) => {
213
+ if (source.formatting?.gridSpan !== void 0 && source.formatting.gridSpan > 1) return null;
214
+ const formatting = formattingWithoutVerticalMerge(source.formatting);
215
+ const converted = standaloneTableCellToProseMirror({
216
+ type: "tableCell",
217
+ ...formatting ? { formatting } : {},
218
+ ...source.propertyChanges ? { propertyChanges: source.propertyChanges } : {},
219
+ content: source.content
220
+ }, origin.type.name === "tableHeader" ? "tableHeader" : "tableCell");
221
+ const compatible = Result.try(() => origin.type.schema.nodeFromJSON(converted.toJSON())).unwrapOr(null);
222
+ if (!compatible) return null;
223
+ return compatible.type.create({
224
+ ...compatible.attrs,
225
+ rowspan: 1,
226
+ cellMarker: marker,
227
+ _preserveVMergeRestart: null,
228
+ _docxVMergeContinuationCells: null
229
+ }, compatible.content);
230
+ };
231
+ const formattingWithoutVerticalMerge = (formatting) => {
232
+ if (!formatting) return;
233
+ const next = { ...formatting };
234
+ delete next.vMerge;
235
+ return next;
236
+ };
237
+ //#endregion
238
+ export { mergeTableRectangle, mergeTrackedVerticalTableCells, splitTableRectangle, splitTrackedVerticalTableCell };
@@ -0,0 +1,38 @@
1
+ //#region src/ai-edits/table-mutation-plan.d.ts
2
+ type TableRectangle = {
3
+ left: number;
4
+ top: number;
5
+ right: number;
6
+ bottom: number;
7
+ };
8
+ type TableMutationPlanTarget = {
9
+ type: "none";
10
+ } | {
11
+ type: "tableStructure";
12
+ tablePosition: number;
13
+ } | {
14
+ type: "mergeCells";
15
+ tablePosition: number;
16
+ rectangle: TableRectangle;
17
+ } | {
18
+ type: "splitCell";
19
+ tablePosition: number;
20
+ rectangle: TableRectangle;
21
+ };
22
+ type TableMutationPlanCandidate<T> = {
23
+ item: T;
24
+ operationId: string;
25
+ target: TableMutationPlanTarget;
26
+ };
27
+ type TableMutationPlanSkip = {
28
+ id: string;
29
+ reason: "noopOperation" | "unsupportedBlock";
30
+ };
31
+ type TableMutationPlan<T> = {
32
+ executable: T[];
33
+ skipped: TableMutationPlanSkip[];
34
+ };
35
+ declare const planTableMutations: <T>(candidates: readonly TableMutationPlanCandidate<T>[]) => TableMutationPlan<T>;
36
+ declare const tableRectanglesEqual: (left: TableRectangle, right: TableRectangle) => boolean;
37
+ //#endregion
38
+ export { TableMutationPlanTarget, TableRectangle, planTableMutations, tableRectanglesEqual };
@@ -0,0 +1,90 @@
1
+ //#region src/ai-edits/table-mutation-plan.ts
2
+ const planTableMutations = (candidates) => {
3
+ const tableStructureMutations = /* @__PURE__ */ new Set();
4
+ const mergeTables = /* @__PURE__ */ new Set();
5
+ const splitTables = /* @__PURE__ */ new Set();
6
+ for (const { target } of candidates) switch (target.type) {
7
+ case "tableStructure":
8
+ tableStructureMutations.add(target.tablePosition);
9
+ break;
10
+ case "mergeCells":
11
+ mergeTables.add(target.tablePosition);
12
+ break;
13
+ case "splitCell":
14
+ splitTables.add(target.tablePosition);
15
+ break;
16
+ case "none": break;
17
+ }
18
+ const mergeRectanglesByTable = /* @__PURE__ */ new Map();
19
+ const splitRectanglesByTable = /* @__PURE__ */ new Map();
20
+ const executable = [];
21
+ const skipped = [];
22
+ for (const candidate of candidates) {
23
+ const { target } = candidate;
24
+ if (target.type === "mergeCells") {
25
+ if (tableStructureMutations.has(target.tablePosition) || splitTables.has(target.tablePosition)) {
26
+ skipped.push({
27
+ id: candidate.operationId,
28
+ reason: "unsupportedBlock"
29
+ });
30
+ continue;
31
+ }
32
+ const claimedRectangles = mergeRectanglesByTable.get(target.tablePosition) ?? [];
33
+ if (claimedRectangles.some((rectangle) => tableRectanglesEqual(rectangle, target.rectangle))) {
34
+ skipped.push({
35
+ id: candidate.operationId,
36
+ reason: "noopOperation"
37
+ });
38
+ continue;
39
+ }
40
+ if (claimedRectangles.some((rectangle) => tableRectanglesOverlap(rectangle, target.rectangle))) {
41
+ skipped.push({
42
+ id: candidate.operationId,
43
+ reason: "unsupportedBlock"
44
+ });
45
+ continue;
46
+ }
47
+ claimedRectangles.push(target.rectangle);
48
+ mergeRectanglesByTable.set(target.tablePosition, claimedRectangles);
49
+ executable.push(candidate.item);
50
+ continue;
51
+ }
52
+ if (target.type === "splitCell") {
53
+ if (tableStructureMutations.has(target.tablePosition) || mergeTables.has(target.tablePosition)) {
54
+ skipped.push({
55
+ id: candidate.operationId,
56
+ reason: "unsupportedBlock"
57
+ });
58
+ continue;
59
+ }
60
+ const claimedRectangles = splitRectanglesByTable.get(target.tablePosition) ?? [];
61
+ if (claimedRectangles.some((rectangle) => tableRectanglesEqual(rectangle, target.rectangle))) {
62
+ skipped.push({
63
+ id: candidate.operationId,
64
+ reason: "noopOperation"
65
+ });
66
+ continue;
67
+ }
68
+ if (claimedRectangles.some((rectangle) => tableRectanglesOverlap(rectangle, target.rectangle))) {
69
+ skipped.push({
70
+ id: candidate.operationId,
71
+ reason: "unsupportedBlock"
72
+ });
73
+ continue;
74
+ }
75
+ claimedRectangles.push(target.rectangle);
76
+ splitRectanglesByTable.set(target.tablePosition, claimedRectangles);
77
+ executable.push(candidate.item);
78
+ continue;
79
+ }
80
+ executable.push(candidate.item);
81
+ }
82
+ return {
83
+ executable,
84
+ skipped
85
+ };
86
+ };
87
+ const tableRectanglesOverlap = (left, right) => left.left < right.right && right.left < left.right && left.top < right.bottom && right.top < left.bottom;
88
+ const tableRectanglesEqual = (left, right) => left.left === right.left && left.top === right.top && left.right === right.right && left.bottom === right.bottom;
89
+ //#endregion
90
+ export { planTableMutations, tableRectanglesEqual };
@@ -0,0 +1,108 @@
1
+ import { TrackedChangeProvenance } from "../prosemirror/schema/marks.js";
2
+ import { TableRowTarget } from "./table-targets.js";
3
+ import { Transaction } from "prosemirror-state";
4
+ import { Node } from "prosemirror-model";
5
+
6
+ //#region src/ai-edits/table-row-column-mutations.d.ts
7
+ type TableRowInsertion = {
8
+ tableStart: number;
9
+ rowPosition: number;
10
+ rowType: Node["type"];
11
+ cells: readonly Node[];
12
+ rowspanUpdates: readonly number[];
13
+ };
14
+ type TableRowDeletion = Omit<TableRowTarget, "table">;
15
+ type TableColumnInsertion = {
16
+ tablePosition: number;
17
+ columnIndex: number;
18
+ };
19
+ type TableColumnDeletion = TableColumnInsertion;
20
+ type TableStructureRevision = {
21
+ revisionId: number;
22
+ author: string;
23
+ date: string; /** Optional author initials (w:initials), carried for round-trip. */
24
+ initials?: string;
25
+ /**
26
+ * `"suggested"` marks the produced `trIns`/`trDel`/`cellMarker` as an AI
27
+ * proposal that is stripped from serialized DOCX until accepted.
28
+ */
29
+ provenance?: TrackedChangeProvenance;
30
+ suggestionId?: string;
31
+ };
32
+ type TableRowColumnMutationResult = {
33
+ type: "applied";
34
+ transaction: Transaction;
35
+ revisionId: number | null;
36
+ } | {
37
+ type: "unsupported";
38
+ };
39
+ declare const getTableColumnCoordinateKey: ({
40
+ tablePosition,
41
+ columnIndex
42
+ }: TableColumnInsertion) => string;
43
+ type FindTableColumnInsertionOptions = {
44
+ doc: Node;
45
+ blockFrom: number;
46
+ position: "after" | "before";
47
+ };
48
+ declare const findTableColumnInsertion: ({
49
+ doc,
50
+ blockFrom,
51
+ position
52
+ }: FindTableColumnInsertionOptions) => (TableColumnInsertion & {
53
+ boundaryPosition: number;
54
+ }) | null;
55
+ type FindTableRowInsertionOptions = FindTableColumnInsertionOptions;
56
+ declare const findTableRowInsertion: ({
57
+ doc,
58
+ blockFrom,
59
+ position
60
+ }: FindTableRowInsertionOptions) => TableRowInsertion | null;
61
+ type ApplyTableRowInsertionOptions = {
62
+ tr: Transaction;
63
+ insertion: TableRowInsertion;
64
+ cellTexts: readonly string[] | undefined;
65
+ revision: TableStructureRevision | null;
66
+ };
67
+ declare const applyTableRowInsertion: ({
68
+ tr,
69
+ insertion,
70
+ cellTexts,
71
+ revision
72
+ }: ApplyTableRowInsertionOptions) => TableRowColumnMutationResult;
73
+ type ApplyTableColumnInsertionOptions = {
74
+ tr: Transaction;
75
+ insertion: TableColumnInsertion;
76
+ cellTexts: readonly string[] | undefined;
77
+ revision: TableStructureRevision | null;
78
+ };
79
+ declare const applyTableColumnInsertion: ({
80
+ tr,
81
+ insertion,
82
+ cellTexts,
83
+ revision
84
+ }: ApplyTableColumnInsertionOptions) => TableRowColumnMutationResult;
85
+ type ApplyTableColumnDeletionOptions = {
86
+ tr: Transaction;
87
+ deletion: TableColumnDeletion;
88
+ insertedColumnCount: number;
89
+ revision: TableStructureRevision | null;
90
+ };
91
+ declare const applyTableColumnDeletion: ({
92
+ tr,
93
+ deletion,
94
+ insertedColumnCount,
95
+ revision
96
+ }: ApplyTableColumnDeletionOptions) => TableRowColumnMutationResult;
97
+ type ApplyTableRowDeletionOptions = {
98
+ tr: Transaction;
99
+ deletion: TableRowDeletion;
100
+ revision: TableStructureRevision | null;
101
+ };
102
+ declare const applyTableRowDeletion: ({
103
+ tr,
104
+ deletion,
105
+ revision
106
+ }: ApplyTableRowDeletionOptions) => TableRowColumnMutationResult;
107
+ //#endregion
108
+ export { TableColumnDeletion, TableColumnInsertion, TableRowDeletion, TableRowInsertion, TableStructureRevision, applyTableColumnDeletion, applyTableColumnInsertion, applyTableRowDeletion, applyTableRowInsertion, findTableColumnInsertion, findTableRowInsertion, getTableColumnCoordinateKey };