@stll/folio-core 0.32.2 → 0.33.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 (222) hide show
  1. package/dist/ai-edits/__fixtures__/paragraphs.d.ts +17 -0
  2. package/dist/ai-edits/__fixtures__/paragraphs.js +33 -0
  3. package/dist/ai-edits/apply.d.ts +49 -3
  4. package/dist/ai-edits/apply.js +649 -85
  5. package/dist/ai-edits/blockRange.d.ts +7 -3
  6. package/dist/ai-edits/blockRange.js +14 -6
  7. package/dist/ai-edits/headless.d.ts +39 -5
  8. package/dist/ai-edits/headless.js +76 -17
  9. package/dist/ai-edits/index.d.ts +6 -6
  10. package/dist/ai-edits/index.js +3 -3
  11. package/dist/ai-edits/read.d.ts +4 -0
  12. package/dist/ai-edits/read.js +30 -6
  13. package/dist/ai-edits/scoped-reading.js +4 -3
  14. package/dist/ai-edits/snapshot.d.ts +42 -2
  15. package/dist/ai-edits/snapshot.js +127 -62
  16. package/dist/ai-edits/table-row-column-mutations.d.ts +24 -1
  17. package/dist/ai-edits/table-row-column-mutations.js +98 -6
  18. package/dist/ai-edits/table-targets.d.ts +12 -3
  19. package/dist/ai-edits/table-targets.js +15 -5
  20. package/dist/ai-edits/types.d.ts +219 -15
  21. package/dist/ai-edits/word-diff.d.ts +54 -11
  22. package/dist/ai-edits/word-diff.js +221 -61
  23. package/dist/compare/__fixtures__/body-sequence.d.ts +33 -0
  24. package/dist/compare/__fixtures__/body-sequence.js +67 -0
  25. package/dist/compare/__fixtures__/nested-table.d.ts +16 -0
  26. package/dist/compare/__fixtures__/nested-table.js +50 -0
  27. package/dist/compare/__fixtures__/numbered-list.d.ts +34 -0
  28. package/dist/compare/__fixtures__/numbered-list.js +85 -0
  29. package/dist/compare/column-alignment.d.ts +27 -0
  30. package/dist/compare/column-alignment.js +162 -0
  31. package/dist/compare/compare.d.ts +107 -0
  32. package/dist/compare/compare.js +406 -0
  33. package/dist/compare/formatting.d.ts +29 -0
  34. package/dist/compare/formatting.js +84 -0
  35. package/dist/compare/plan.d.ts +22 -0
  36. package/dist/compare/plan.js +1059 -0
  37. package/dist/compare/reproducible-package.d.ts +17 -0
  38. package/dist/compare/reproducible-package.js +30 -0
  39. package/dist/compare/scenario.d.ts +77 -0
  40. package/dist/compare/scenario.js +263 -0
  41. package/dist/compare/types.d.ts +282 -0
  42. package/dist/compare/types.js +32 -0
  43. package/dist/compare/verification.d.ts +55 -0
  44. package/dist/compare/verification.js +146 -0
  45. package/dist/compat/eigenpal.d.ts +9 -6
  46. package/dist/compat/eigenpal.js +6 -3
  47. package/dist/controller/layoutPipeline.d.ts +13 -0
  48. package/dist/controller/layoutPipeline.js +15 -1
  49. package/dist/display-list/build/buildContext.d.ts +39 -0
  50. package/dist/display-list/build/buildContext.js +31 -0
  51. package/dist/display-list/build/buildDisplayList.d.ts +79 -0
  52. package/dist/display-list/build/buildDisplayList.js +283 -0
  53. package/dist/display-list/build/colors.d.ts +20 -0
  54. package/dist/display-list/build/colors.js +136 -0
  55. package/dist/display-list/build/floatingImages.d.ts +24 -0
  56. package/dist/display-list/build/floatingImages.js +41 -0
  57. package/dist/display-list/build/fontTable.d.ts +31 -0
  58. package/dist/display-list/build/fontTable.js +97 -0
  59. package/dist/display-list/build/furniture.d.ts +86 -0
  60. package/dist/display-list/build/furniture.js +98 -0
  61. package/dist/display-list/build/glyphs.d.ts +55 -0
  62. package/dist/display-list/build/glyphs.js +103 -0
  63. package/dist/display-list/build/headerFooterPrimitives.d.ts +17 -0
  64. package/dist/display-list/build/headerFooterPrimitives.js +40 -0
  65. package/dist/display-list/build/imagePrimitives.d.ts +35 -0
  66. package/dist/display-list/build/imagePrimitives.js +264 -0
  67. package/dist/display-list/build/pageBorderPrimitives.d.ts +23 -0
  68. package/dist/display-list/build/pageBorderPrimitives.js +111 -0
  69. package/dist/display-list/build/pageFurniture.d.ts +35 -0
  70. package/dist/display-list/build/pageFurniture.js +141 -0
  71. package/dist/display-list/build/paragraphPrimitives.d.ts +19 -0
  72. package/dist/display-list/build/paragraphPrimitives.js +819 -0
  73. package/dist/display-list/build/regions.d.ts +46 -0
  74. package/dist/display-list/build/regions.js +56 -0
  75. package/dist/display-list/build/storyPrimitives.d.ts +29 -0
  76. package/dist/display-list/build/storyPrimitives.js +279 -0
  77. package/dist/display-list/build/strokes.d.ts +19 -0
  78. package/dist/display-list/build/strokes.js +78 -0
  79. package/dist/display-list/build/tablePrimitives.d.ts +38 -0
  80. package/dist/display-list/build/tablePrimitives.js +409 -0
  81. package/dist/display-list/build/textBoxPrimitives.d.ts +14 -0
  82. package/dist/display-list/build/textBoxPrimitives.js +129 -0
  83. package/dist/display-list/build/textDecorations.d.ts +29 -0
  84. package/dist/display-list/build/textDecorations.js +29 -0
  85. package/dist/display-list/build/unsupported.d.ts +57 -0
  86. package/dist/display-list/build/unsupported.js +0 -0
  87. package/dist/display-list/build/watermarkPrimitives.d.ts +15 -0
  88. package/dist/display-list/build/watermarkPrimitives.js +128 -0
  89. package/dist/display-list/dom/renderDisplayListToDom.d.ts +26 -0
  90. package/dist/display-list/dom/renderDisplayListToDom.js +620 -0
  91. package/dist/display-list/editor/displayListPagePainter.d.ts +22 -0
  92. package/dist/display-list/editor/displayListPagePainter.js +63 -0
  93. package/dist/display-list/editor/pageRenderer.d.ts +24 -0
  94. package/dist/display-list/editor/pageRenderer.js +36 -0
  95. package/dist/display-list/primitives.d.ts +95 -0
  96. package/dist/display-list/primitives.js +127 -0
  97. package/dist/display-list/types.d.ts +472 -0
  98. package/dist/display-list/types.js +0 -0
  99. package/dist/document-operations.d.ts +39 -8
  100. package/dist/document-operations.js +169 -16
  101. package/dist/document-stories.d.ts +16 -0
  102. package/dist/document-stories.js +48 -4
  103. package/dist/docx/packageParts.d.ts +35 -0
  104. package/dist/docx/packageParts.js +120 -0
  105. package/dist/docx/paragraphParser.js +22 -22
  106. package/dist/docx/paragraphTraversal.js +1 -1
  107. package/dist/docx/renderedPageBreakNormalization.js +3 -1
  108. package/dist/docx/revisionIdNormalization.d.ts +13 -0
  109. package/dist/docx/revisionIdNormalization.js +103 -0
  110. package/dist/docx/rezip.js +26 -17
  111. package/dist/docx/selectiveSave.js +2 -2
  112. package/dist/docx/serializer/commentSerializer.js +6 -1
  113. package/dist/docx/serializer/paragraphSerializer.js +33 -4
  114. package/dist/docx/serializer/runSerializer.js +11 -10
  115. package/dist/docx/serializer/tableSerializer.js +2 -1
  116. package/dist/docx/server/applyDocxXmlPatchProposal.js +1 -1
  117. package/dist/docx/server/createBilingualDocx.js +3 -2
  118. package/dist/docx/streamingXmlParser.d.ts +13 -1
  119. package/dist/docx/streamingXmlParser.js +49 -11
  120. package/dist/docx/unzip.d.ts +1 -2
  121. package/dist/docx/unzip.js +25 -6
  122. package/dist/docx/xmlParser.d.ts +3 -1
  123. package/dist/docx/xmlParser.js +33 -27
  124. package/dist/export-pdf.d.ts +43 -0
  125. package/dist/export-pdf.js +98 -0
  126. package/dist/fonts/headlessMeasure.d.ts +76 -0
  127. package/dist/fonts/headlessMeasure.js +0 -0
  128. package/dist/fonts/sfnt/parse.d.ts +51 -0
  129. package/dist/fonts/sfnt/parse.js +525 -0
  130. package/dist/fonts/sfnt/subset.d.ts +20 -0
  131. package/dist/fonts/sfnt/subset.js +350 -0
  132. package/dist/fonts/sfnt/tables.d.ts +88 -0
  133. package/dist/fonts/sfnt/tables.js +131 -0
  134. package/dist/fonts/sfnt/woff.d.ts +14 -0
  135. package/dist/fonts/sfnt/woff.js +163 -0
  136. package/dist/generated/text_shaper.js +324 -0
  137. package/dist/generated/text_shaper_bg.wasm +0 -0
  138. package/dist/headless-layout.d.ts +75 -0
  139. package/dist/headless-layout.js +350 -0
  140. package/dist/index.d.ts +9 -6
  141. package/dist/index.js +6 -3
  142. package/dist/layout-bridge/convert/footnoteLayout.d.ts +1 -0
  143. package/dist/layout-bridge/convert/footnoteLayout.js +1 -0
  144. package/dist/layout-bridge/convert/headerFooterLayout.d.ts +1 -0
  145. package/dist/layout-bridge/convert/headerFooterLayout.js +2 -0
  146. package/dist/layout-bridge/convert/toFlowBlocks.d.ts +3 -1
  147. package/dist/layout-bridge/convert/toFlowBlocks.js +2 -0
  148. package/dist/layout-engine/measure/advanceComposition.d.ts +62 -0
  149. package/dist/layout-engine/measure/advanceComposition.js +148 -0
  150. package/dist/layout-engine/measure/cache.d.ts +2 -0
  151. package/dist/layout-engine/measure/measureContainer.js +13 -0
  152. package/dist/layout-engine/measure/measureParagraph.js +1 -2
  153. package/dist/layout-engine/measure/measureTypes.d.ts +12 -0
  154. package/dist/layout-engine/measure/tableInlinePlacement.d.ts +3 -2
  155. package/dist/layout-engine/measure/tableInlinePlacement.js +14 -1
  156. package/dist/layout-engine/tableIndentCompatibility.d.ts +5 -0
  157. package/dist/layout-engine/tableIndentCompatibility.js +15 -0
  158. package/dist/layout-engine/types.d.ts +8 -0
  159. package/dist/layout-painter/renderPage.d.ts +29 -1
  160. package/dist/layout-painter/renderPage.js +47 -19
  161. package/dist/layout-painter/renderParagraph.d.ts +21 -2
  162. package/dist/layout-painter/renderParagraph.js +1 -1
  163. package/dist/layout-painter/renderTable.js +37 -4
  164. package/dist/managers/editorShortcuts.d.ts +33 -1
  165. package/dist/managers/editorShortcuts.js +20 -1
  166. package/dist/markdown/renderRuns.js +7 -2
  167. package/dist/markdown/renderTable.js +5 -1
  168. package/dist/model.d.ts +3 -3
  169. package/dist/model.js +2 -2
  170. package/dist/pdf/contentStream.d.ts +73 -0
  171. package/dist/pdf/contentStream.js +143 -0
  172. package/dist/pdf/fonts.d.ts +96 -0
  173. package/dist/pdf/fonts.js +593 -0
  174. package/dist/pdf/images.d.ts +28 -0
  175. package/dist/pdf/images.js +439 -0
  176. package/dist/pdf/objects.d.ts +93 -0
  177. package/dist/pdf/objects.js +237 -0
  178. package/dist/pdf/pageSpace.d.ts +43 -0
  179. package/dist/pdf/pageSpace.js +57 -0
  180. package/dist/pdf/paint.d.ts +32 -0
  181. package/dist/pdf/paint.js +442 -0
  182. package/dist/pdf/writePdf.d.ts +56 -0
  183. package/dist/pdf/writePdf.js +345 -0
  184. package/dist/prosemirror/commands/comments.js +91 -6
  185. package/dist/prosemirror/conversion/fromProseDoc.js +41 -7
  186. package/dist/prosemirror/conversion/toProseDoc.js +41 -4
  187. package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.d.ts +15 -2
  188. package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.js +35 -6
  189. package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.js +2 -2
  190. package/dist/prosemirror/extensions/features/pasteCleanup.js +4 -3
  191. package/dist/prosemirror/extensions/nodes/BookmarkBoundaryExtension.d.ts +3 -1
  192. package/dist/prosemirror/extensions/nodes/BookmarkBoundaryExtension.js +5 -3
  193. package/dist/prosemirror/extensions/nodes/RenderedPageBreakExtension.d.ts +7 -1
  194. package/dist/prosemirror/extensions/nodes/RenderedPageBreakExtension.js +9 -3
  195. package/dist/prosemirror/extensions/nodes/TableExtension.js +56 -39
  196. package/dist/prosemirror/extensions/nodes/TextBoxAnchorExtension.d.ts +3 -1
  197. package/dist/prosemirror/extensions/nodes/TextBoxAnchorExtension.js +5 -3
  198. package/dist/prosemirror/plugins/suggestionMode.js +1 -0
  199. package/dist/prosemirror/revisionCarriers.js +19 -2
  200. package/dist/prosemirror/utils/extractTrackedChanges.d.ts +2 -2
  201. package/dist/prosemirror/utils/extractTrackedChanges.js +59 -23
  202. package/dist/prosemirror/validation.js +55 -27
  203. package/dist/prosemirror/zeroWidthAnchors.d.ts +10 -0
  204. package/dist/prosemirror/zeroWidthAnchors.js +23 -0
  205. package/dist/redline.js +12 -79
  206. package/dist/server.d.ts +3 -3
  207. package/dist/server.js +2 -2
  208. package/dist/shaping/placeRun.d.ts +51 -0
  209. package/dist/shaping/placeRun.js +84 -0
  210. package/dist/shaping/shaper.d.ts +92 -0
  211. package/dist/shaping/shaper.js +102 -0
  212. package/dist/types/block-id.d.ts +18 -2
  213. package/dist/types/block-id.js +49 -5
  214. package/dist/types/content.d.ts +2 -2
  215. package/dist/utils/clipboard.js +4 -3
  216. package/dist/utils/fontResolver.js +183 -0
  217. package/dist/utils/htmlComments.d.ts +17 -0
  218. package/dist/utils/htmlComments.js +22 -0
  219. package/dist/utils/scriptSegments.d.ts +12 -1
  220. package/dist/utils/scriptSegments.js +17 -1
  221. package/dist/version-comparison.d.ts +1 -1
  222. package/package.json +7 -3
@@ -10,6 +10,33 @@ type FolioAIBlockPreviewRun = {
10
10
  fontSizePt?: number;
11
11
  color?: string;
12
12
  };
13
+ /**
14
+ * Where a block sits inside its innermost enclosing table. Every index is
15
+ * zero-based: `tableIndex` counts tables in document order across the story,
16
+ * `rowIndex` is the row's index in that table, `cellIndex` is the cell's
17
+ * PHYSICAL index within the row (a merged cell occupies one slot, so this is
18
+ * not a grid column), and `paragraphIndex` orders the block among the cell's
19
+ * own blocks. Absent on a block that is not inside a table.
20
+ */
21
+ type FolioAIBlockTableLocation = {
22
+ /**
23
+ * Document-order index of the OUTERMOST table the block sits in — the same
24
+ * as `tableIndex` unless tables nest. A comparison aligns on this: a table
25
+ * inside a cell is part of its parent, not a structure of its own that can
26
+ * be paired against one somewhere else.
27
+ */
28
+ outerTableIndex: number;
29
+ tableIndex: number;
30
+ rowIndex: number;
31
+ cellIndex: number;
32
+ /** Grid column occupied by the cell's left edge, derived from `TableMap`. */
33
+ gridColumnIndex: number;
34
+ /** Number of grid columns occupied by this physical cell. */
35
+ columnSpan: number;
36
+ /** Number of grid rows occupied by this physical cell. */
37
+ rowSpan: number;
38
+ paragraphIndex: number;
39
+ };
13
40
  type FolioAIBlock = {
14
41
  id: string;
15
42
  kind: FolioAIBlockKind;
@@ -18,13 +45,42 @@ type FolioAIBlock = {
18
45
  headingLevel?: number;
19
46
  displayLabel?: string;
20
47
  styleId?: string;
48
+ /**
49
+ * `w:numPr/w:ilvl`: the block's list indent level. Present only on a block
50
+ * that carries numbering, and the only pPr property a redline can move
51
+ * without touching a word — a demoted list item reads as unchanged text and
52
+ * is not.
53
+ */
54
+ listLevel?: number;
21
55
  previewRuns?: FolioAIBlockPreviewRun[];
56
+ table?: FolioAIBlockTableLocation;
22
57
  };
58
+ /**
59
+ * The paragraph properties an operation may set. A subset of `w:pPrChange`'s
60
+ * scope: the two a comparison can see in a block projection, and the two an
61
+ * agent has a reason to change.
62
+ */
63
+ type FolioAIBlockParagraphProperties = {
64
+ /** `w:pStyle`. `null` clears the style back to the default. */
65
+ styleId?: string | null;
66
+ /**
67
+ * `w:numPr/w:ilvl`, zero-based. `null` removes `w:numPr` altogether: the
68
+ * paragraph stops being a list item rather than moving to another level.
69
+ */
70
+ listLevel?: number | null;
71
+ };
72
+ /**
73
+ * Every paragraph of one story, blank ones included.
74
+ *
75
+ * A blank paragraph is part of a document's shape: an empty cell is a column,
76
+ * an empty row is a row, and an operation or a comparison that cannot address
77
+ * them cannot describe what changed around them. A surface that reads the
78
+ * document for a person or a model wants only the paragraphs that carry text,
79
+ * and says so with `isFolioAIContentBlock`.
80
+ */
23
81
  type FolioAIEditSnapshot = {
24
82
  blocks: FolioAIBlock[];
25
83
  anchors: Record<string, FolioAIBlockAnchor>;
26
- /** Hidden empty paragraph used to anchor insertions when `blocks` is empty. */
27
- emptyDocumentAnchorId?: string;
28
84
  };
29
85
  type FolioAIBlockAnchor = {
30
86
  id: string;
@@ -113,6 +169,7 @@ type FolioAIInlineFormatting = {
113
169
  bold?: boolean;
114
170
  italic?: boolean;
115
171
  underline?: boolean;
172
+ strike?: boolean;
116
173
  };
117
174
  /**
118
175
  * A party in an `insertSignatureTable` op. Mirrors the
@@ -168,9 +225,20 @@ type FolioAIEditOperation = FolioAIEditReviewMeta & {
168
225
  * gets `styleId` / `inheritFormatting`, later ones use body
169
226
  * formatting. Blank lines are dropped. Reported as a
170
227
  * `splitMultilineText` normalization when it happens.
228
+ *
229
+ * `""` inserts a BLANK paragraph, and is a real edit: adding an empty
230
+ * line is a change a reader sees, and a document that has one where
231
+ * another does not differs. It is applied like any other insertion,
232
+ * with a tracked paragraph mark, so rejecting closes it away.
171
233
  */
172
234
  text: string;
173
235
  inheritFormatting?: boolean;
236
+ /**
237
+ * Links this insertion to the deletion that carries the same
238
+ * `moveId`: together they are one relocation, written as `w:moveTo`
239
+ * and `w:moveFrom`. See `deleteBlock`.
240
+ */
241
+ moveId?: string;
174
242
  /**
175
243
  * When true, mark the inserted paragraph with
176
244
  * `pageBreakBefore` so the layout engine starts it on a
@@ -181,9 +249,19 @@ type FolioAIEditOperation = FolioAIEditReviewMeta & {
181
249
  * Override the paragraph `styleId` attr of the inserted
182
250
  * block (e.g. `ClauseHeading1`). When omitted the inserted
183
251
  * block inherits the source block's styleId via
184
- * `inheritFormatting`.
252
+ * `inheritFormatting`; `null` gives it no style at all, which
253
+ * inheritance alone cannot say.
185
254
  */
186
- styleId?: string;
255
+ styleId?: string | null;
256
+ /**
257
+ * Override `w:numPr/w:ilvl` on the inserted block, keeping the
258
+ * anchor's `w:numId`. Without it the inserted paragraph takes the
259
+ * anchor's level, which is the wrong one whenever the new item sits
260
+ * beside a list item at a different depth. `null` gives it no
261
+ * numbering at all — an ordinary paragraph next to a list item, which
262
+ * inheritance alone cannot say.
263
+ */
264
+ listLevel?: number | null;
187
265
  comment?: FolioAIComment;
188
266
  } | {
189
267
  id: string;
@@ -193,11 +271,110 @@ type FolioAIEditOperation = FolioAIEditReviewMeta & {
193
271
  preserveFormatting?: boolean;
194
272
  styleId?: string;
195
273
  comment?: FolioAIComment;
196
- } | {
274
+ } |
275
+ /**
276
+ * Delete the whole block. A block with words loses them and its paragraph
277
+ * mark; a BLANK block has only a paragraph mark to lose, and loses it, so
278
+ * the empty line goes away rather than the operation doing nothing.
279
+ */
280
+ {
197
281
  id: string;
198
282
  type: "deleteBlock";
199
283
  blockId: string;
284
+ /**
285
+ * Links this deletion to the insertion that carries the same
286
+ * `moveId`: together they are one relocation, written as `w:moveFrom`
287
+ * and `w:moveTo` rather than as an unrelated deletion and insertion.
288
+ * A `moveId` that does not name exactly one of each is reported as an
289
+ * `unpairedMove` normalization and both halves apply plainly.
290
+ */
291
+ moveId?: string;
200
292
  comment?: FolioAIComment;
293
+ } |
294
+ /**
295
+ * Break the block in two at `offset`, moving a paragraph mark and no
296
+ * words. In tracked-changes mode the first half carries an INSERTED
297
+ * paragraph mark, so accepting keeps the break and rejecting closes it;
298
+ * the alternative — rewriting the first half and inserting the second —
299
+ * claims the tail was newly written when nobody touched it.
300
+ */
301
+ {
302
+ id: string;
303
+ type: "splitBlock";
304
+ /** Offset in the block's text. Must fall strictly inside it. */
305
+ offset: number;
306
+ /**
307
+ * Text at `offset` the break replaces — the space between the two
308
+ * halves, when the split consumed one. Deleted in `"direct"` mode and
309
+ * deletion-marked in tracked mode, so rejecting restores it.
310
+ */
311
+ separator?: string;
312
+ blockId: string;
313
+ } |
314
+ /**
315
+ * Add a whole table next to the anchor block, its rows marked inserted in
316
+ * tracked mode. `insertTableRow` can only grow a table that already
317
+ * exists; a comparison whose target gained one needs to say so.
318
+ */
319
+ {
320
+ id: string;
321
+ type: "insertTable";
322
+ blockId: string;
323
+ /** Place the table after the anchor (default) or before it. */
324
+ position?: "after" | "before";
325
+ /**
326
+ * Cell texts row by row. Every row must hold the same number of cells.
327
+ *
328
+ * A cell holds paragraphs, not lines: a line break in a cell's text
329
+ * starts a new paragraph in that cell, and a blank line is a blank
330
+ * paragraph. That is not the rule `insertAfterBlock` follows for
331
+ * prose, where a blank line between two model-written clauses is
332
+ * formatting noise and is dropped — a cell's text describes paragraphs
333
+ * that exist, so dropping one would lose a block.
334
+ */
335
+ rows: readonly (readonly string[])[];
336
+ } |
337
+ /**
338
+ * Remove the whole table the block sits in, its rows marked deleted in
339
+ * tracked mode. The mirror of `insertTable`.
340
+ */
341
+ {
342
+ id: string;
343
+ type: "deleteTable";
344
+ blockId: string;
345
+ } |
346
+ /**
347
+ * Replace the block's paragraph properties, recorded as a `w:pPrChange`
348
+ * in tracked mode so the previous set is restored on reject. The edit
349
+ * that moves no words: a list item demoted a level, a paragraph restyled
350
+ * as a heading.
351
+ */
352
+ {
353
+ id: string;
354
+ type: "setBlockParagraphProperties";
355
+ blockId: string;
356
+ properties: FolioAIBlockParagraphProperties;
357
+ } |
358
+ /**
359
+ * Join the block with the one after it, the mirror of `splitBlock`: in
360
+ * tracked-changes mode the block carries a DELETED paragraph mark, so
361
+ * accepting closes the break and rejecting keeps it.
362
+ *
363
+ * Refused when the block has no joinable sibling — the last paragraph of
364
+ * a table cell, or of the story — because a deleted mark there would
365
+ * accept into a join that cannot happen and leave a revision no reader
366
+ * can resolve.
367
+ */
368
+ {
369
+ id: string;
370
+ type: "mergeBlockWithNext";
371
+ /**
372
+ * Text the join inserts between the two halves — the space the
373
+ * paragraph break used to stand in for. Insertion-marked in tracked
374
+ * mode, so rejecting removes it along with the join.
375
+ */
376
+ separator?: string;
377
+ blockId: string;
201
378
  } | {
202
379
  id: string;
203
380
  type: "commentOnBlock";
@@ -222,7 +399,18 @@ type FolioAIEditOperation = FolioAIEditReviewMeta & {
222
399
  /** Stable paragraph anchor inside the row that receives the new sibling. */
223
400
  blockId: string;
224
401
  position?: "after" | "before";
225
- /** Initial text for each physical cell in source order; omitted cells stay empty. */
402
+ /**
403
+ * Initial text for each cell of the new row, in order — the same order
404
+ * a block's `table.cellIndex` counts. Cells left unnamed stay empty.
405
+ *
406
+ * Sized against the table's COLUMN count, which is the most cells any
407
+ * row of it could have: more texts than that is refused rather than
408
+ * silently truncated, and fewer is not, so a row the table can hold is
409
+ * no longer refused because a span makes it narrower than the table.
410
+ *
411
+ * A line break in a cell's text starts a new paragraph in that cell,
412
+ * as in `insertTable`.
413
+ */
226
414
  cellTexts?: string[];
227
415
  } | {
228
416
  id: string;
@@ -326,20 +514,36 @@ type FolioAIEditSkippedOperation = {
326
514
  id: string;
327
515
  reason: FolioAIEditSkipReason;
328
516
  };
329
- /** One automatic adjustment `apply.ts` made to an operation's input to keep the applied result well-formed. */
330
- type FolioAIEditNormalizationCode = "splitMultilineText";
331
517
  /**
332
- * A line-break in `insertAfterBlock` / `insertBeforeBlock`'s `text` cannot become
333
- * one paragraph with an embedded break (Word paragraphs are single lines); the
334
- * applier splits it into one paragraph per non-blank line instead and reports it
335
- * here so the caller can see what happened to the text it sent.
518
+ * One automatic adjustment `apply.ts` made to an operation's input to keep the
519
+ * applied result well-formed. Reported rather than applied silently: the
520
+ * caller asked for something the document could not hold, and gets told what
521
+ * it got instead.
522
+ */
523
+ type FolioAIEditNormalization =
524
+ /**
525
+ * A line-break in `insertAfterBlock` / `insertBeforeBlock`'s `text` cannot
526
+ * become one paragraph with an embedded break (Word paragraphs are single
527
+ * lines); the applier split it into one paragraph per non-blank line.
336
528
  */
337
- type FolioAIEditNormalization = {
529
+ {
338
530
  id: string;
339
- code: FolioAIEditNormalizationCode;
531
+ code: "splitMultilineText";
340
532
  /** Number of paragraphs the operation's `text` was split into. */
341
533
  paragraphCount: number;
534
+ } |
535
+ /**
536
+ * A `moveId` that did not name exactly one deletion and one insertion in
537
+ * the batch. The operation still applies, as an ordinary insertion or
538
+ * deletion: half a move pair is not a move, and `w:moveTo` without its
539
+ * `w:moveFrom` is a relocation from nowhere.
540
+ */
541
+ {
542
+ id: string;
543
+ code: "unpairedMove";
544
+ moveId: string;
342
545
  };
546
+ type FolioAIEditNormalizationCode = FolioAIEditNormalization["code"];
343
547
  type FolioAIEditApplyResult = {
344
548
  applied: FolioAIEditAppliedOperation[];
345
549
  skipped: FolioAIEditSkippedOperation[];
@@ -347,4 +551,4 @@ type FolioAIEditApplyResult = {
347
551
  normalizations?: FolioAIEditNormalization[];
348
552
  };
349
553
  //#endregion
350
- export { FolioAIBlock, FolioAIBlockAnchor, FolioAIBlockKind, FolioAIBlockPreviewRun, FolioAIComment, FolioAIEditAppliedOperation, FolioAIEditApplyMode, FolioAIEditApplyResult, FolioAIEditNormalization, FolioAIEditNormalizationCode, FolioAIEditOperation, FolioAIEditPrecondition, FolioAIEditReviewMeta, FolioAIEditSeverity, FolioAIEditSkipReason, FolioAIEditSkippedOperation, FolioAIEditSnapshot, FolioAIInlineFormatting, FolioAISignatureParty, FolioAITextRangeHandle, FolioDocumentNavigationTarget, FolioDocumentOutline, FolioDocumentOutlineEntry, FolioDocumentSection, FolioDocumentSectionHandle, FolioDocumentSectionReadResult };
554
+ export { FolioAIBlock, FolioAIBlockAnchor, FolioAIBlockKind, FolioAIBlockParagraphProperties, FolioAIBlockPreviewRun, FolioAIBlockTableLocation, FolioAIComment, FolioAIEditAppliedOperation, FolioAIEditApplyMode, FolioAIEditApplyResult, FolioAIEditNormalization, FolioAIEditNormalizationCode, FolioAIEditOperation, FolioAIEditPrecondition, FolioAIEditReviewMeta, FolioAIEditSeverity, FolioAIEditSkipReason, FolioAIEditSkippedOperation, FolioAIEditSnapshot, FolioAIInlineFormatting, FolioAISignatureParty, FolioAITextRangeHandle, FolioDocumentNavigationTarget, FolioDocumentOutline, FolioDocumentOutlineEntry, FolioDocumentSection, FolioDocumentSectionHandle, FolioDocumentSectionReadResult };
@@ -1,20 +1,63 @@
1
1
  //#region src/ai-edits/word-diff.d.ts
2
2
  /**
3
- * Word-level diff between two strings. Tokenises on whitespace
4
- * boundaries (preserving the whitespace as part of each token), runs
5
- * an LCS, and returns a left-to-right ordered list of segments where
6
- * shared runs render as `equal`, removed runs as `del`, and added
7
- * runs as `ins`. Used by both the panel (to render minimal-change
8
- * redlines) and the apply engine (so tracked changes only mark the
9
- * divergent tokens, not the whole replaced span).
3
+ * Diff between two strings, as the segments a redline is drawn from.
10
4
  *
11
- * O(n*m) on token counts; if a single replacement ever holds more
12
- * than a few hundred tokens, swap for a streaming diff.
5
+ * Tokenises (by default on whitespace boundaries, preserving the whitespace as
6
+ * part of each token), runs an LCS, and returns a left-to-right ordered list of
7
+ * segments where shared runs render as `equal`, removed runs as `del`, and
8
+ * added runs as `ins`. Used by the panel (to render minimal-change redlines),
9
+ * the version comparison, and the apply engine (so tracked changes mark only
10
+ * the divergent tokens, not the whole replaced span).
11
+ *
12
+ * ## The shortest diff is not the most readable one
13
+ *
14
+ * An LCS maximises matched characters, which on a rewritten sentence means
15
+ * matching every stray "the" and comma it can reach. The reader then gets a
16
+ * shredded paragraph — a dozen struck-through fragments interleaved with a
17
+ * dozen inserted ones — where one deletion followed by one insertion says the
18
+ * same thing and can actually be read. Three rules pull the output back:
19
+ *
20
+ * 1. A match made only of separators is not a match ({@link isSeparatorOnly}).
21
+ * 2. A match too short to carry meaning is dropped unless it opens the string,
22
+ * where it is the reader's anchor rather than an island.
23
+ * 3. When what survives is still too fragmented for its length, the whole
24
+ * paragraph is one replacement ({@link isTooFragmented}).
25
+ *
26
+ * O(n*m) on token counts; past {@link MAX_WORD_DIFF_CELLS} the DP is skipped
27
+ * for a single whole-string `del` + `ins` pair.
13
28
  */
14
29
  type WordDiffSegment = {
15
30
  type: "equal" | "del" | "ins";
16
31
  text: string;
17
32
  };
18
- declare const diffWordSegments: (before: string, after: string) => WordDiffSegment[];
33
+ /**
34
+ * What one token is. `"word"` tokenises on whitespace and is what a redline
35
+ * over prose should use; `"character"` marks the changed letters inside a
36
+ * word, which reads well for a reference number or a date and badly for a
37
+ * sentence.
38
+ */
39
+ declare const WORD_DIFF_GRANULARITIES: readonly ["word", "character"];
40
+ type WordDiffGranularity = (typeof WORD_DIFF_GRANULARITIES)[number];
41
+ /**
42
+ * Differences the caller does not want marked.
43
+ *
44
+ * A normalized run is reported as `equal` and carries the BEFORE string's
45
+ * text, so the before side still reconstructs exactly while the after side
46
+ * reconstructs only up to the normalization. A caller that must reproduce the
47
+ * after string — anything generating tracked changes — leaves both off.
48
+ */
49
+ type WordDiffNormalization = {
50
+ /** `"Shall"` and `"shall"` are the same token. */
51
+ case?: boolean;
52
+ /** Whitespace around and inside a token does not distinguish it. */
53
+ whitespace?: boolean;
54
+ };
55
+ type WordDiffOptions = {
56
+ /** Default `"word"`. */
57
+ granularity?: WordDiffGranularity;
58
+ /** Default: nothing normalized, so both strings reconstruct exactly. */
59
+ normalization?: WordDiffNormalization;
60
+ };
61
+ declare const diffWordSegments: (before: string, after: string, options?: WordDiffOptions) => WordDiffSegment[];
19
62
  //#endregion
20
- export { WordDiffSegment, diffWordSegments };
63
+ export { WORD_DIFF_GRANULARITIES, WordDiffGranularity, WordDiffNormalization, WordDiffOptions, WordDiffSegment, diffWordSegments };