@stll/folio-core 0.44.0 → 0.46.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/__fixtures__/paragraphs.js +2 -2
  2. package/dist/ai-edits/apply.js +59 -19
  3. package/dist/ai-edits/headless.js +2 -1
  4. package/dist/compare/compare.js +2 -5
  5. package/dist/compare/content-alignment.js +78 -53
  6. package/dist/compare/inline-atoms.js +34 -20
  7. package/dist/compare/scenario.js +2 -5
  8. package/dist/compare/types.d.ts +9 -1
  9. package/dist/compare/types.js +12 -1
  10. package/dist/compat/eigenpal.d.ts +2 -1
  11. package/dist/compat/eigenpal.js +2 -1
  12. package/dist/content-controls/checkboxDisplay.d.ts +11 -0
  13. package/dist/content-controls/checkboxDisplay.js +40 -0
  14. package/dist/content-controls/findContentControls.js +3 -1
  15. package/dist/content-controls/mutateContentControls.js +21 -4
  16. package/dist/controller/contentControlWidgetController.d.ts +1 -0
  17. package/dist/controller/contentControlWidgetController.js +3 -0
  18. package/dist/controller/hiddenEditorApi.js +3 -1
  19. package/dist/controller/hiddenEditorManager.d.ts +1 -1
  20. package/dist/controller/hiddenEditorManager.js +6 -3
  21. package/dist/display-list/build/buildDisplayList.js +20 -1
  22. package/dist/display-list/build/imagePrimitives.d.ts +1 -1
  23. package/dist/display-list/build/imagePrimitives.js +3 -1
  24. package/dist/display-list/build/paragraphPrimitives.js +21 -2
  25. package/dist/display-list/dom/renderDisplayListToDom.js +18 -10
  26. package/dist/display-list/types.d.ts +17 -0
  27. package/dist/document-operations.js +14 -3
  28. package/dist/docx/attributeRemainder.d.ts +43 -0
  29. package/dist/docx/attributeRemainder.js +65 -0
  30. package/dist/docx/blockContentParser.d.ts +1 -1
  31. package/dist/docx/blockContentParser.js +87 -63
  32. package/dist/docx/blockPlainText.d.ts +3 -4
  33. package/dist/docx/blockPlainText.js +1 -0
  34. package/dist/docx/bookmarkPlacement.js +2 -0
  35. package/dist/docx/borderParser.js +5 -5
  36. package/dist/docx/commentAnchorIndex.d.ts +30 -0
  37. package/dist/docx/commentAnchorIndex.js +50 -0
  38. package/dist/docx/commentParser.d.ts +1 -1
  39. package/dist/docx/commentParser.js +78 -50
  40. package/dist/docx/commentRangeIntegrity.d.ts +16 -1
  41. package/dist/docx/commentRangeIntegrity.js +42 -1
  42. package/dist/docx/commentRangeJoin.d.ts +9 -0
  43. package/dist/docx/commentRangeJoin.js +33 -0
  44. package/dist/docx/commentReferenceCompletion.d.ts +9 -0
  45. package/dist/docx/commentReferenceCompletion.js +47 -0
  46. package/dist/docx/commentReferenceNormalization.js +1 -0
  47. package/dist/docx/commentReplyMarkers.js +11 -19
  48. package/dist/docx/commentThreadKey.d.ts +18 -0
  49. package/dist/docx/commentThreadKey.js +22 -0
  50. package/dist/docx/compatibility.js +1 -0
  51. package/dist/docx/containerChildren.d.ts +111 -0
  52. package/dist/docx/containerChildren.gen.d.ts +28 -0
  53. package/dist/docx/containerChildren.gen.js +246 -0
  54. package/dist/docx/containerChildren.js +103 -0
  55. package/dist/docx/diagramPreview.js +87 -27
  56. package/dist/docx/documentParser.d.ts +1 -1
  57. package/dist/docx/documentParser.js +3 -3
  58. package/dist/docx/ensureParaIds.js +17 -7
  59. package/dist/docx/fieldParser.d.ts +1 -1
  60. package/dist/docx/fieldParser.js +4 -4
  61. package/dist/docx/fieldState.d.ts +26 -0
  62. package/dist/docx/fieldState.js +53 -0
  63. package/dist/docx/footnoteParser.d.ts +1 -1
  64. package/dist/docx/graphicFrameLocks.d.ts +16 -4
  65. package/dist/docx/graphicFrameLocks.js +19 -6
  66. package/dist/docx/groupDrawingParser.js +3 -3
  67. package/dist/docx/headerFooterParser.js +1 -1
  68. package/dist/docx/headerFooterReferenceNormalization.js +1 -0
  69. package/dist/docx/hyperlinkParser.d.ts +27 -8
  70. package/dist/docx/hyperlinkParser.js +78 -20
  71. package/dist/docx/imageParser.d.ts +9 -1
  72. package/dist/docx/imageParser.js +91 -20
  73. package/dist/docx/imageRawXml.d.ts +14 -1
  74. package/dist/docx/imageRawXml.js +30 -6
  75. package/dist/docx/inlineWrapperContent.d.ts +85 -0
  76. package/dist/docx/inlineWrapperContent.js +84 -0
  77. package/dist/docx/mathToMathml.js +12 -14
  78. package/dist/docx/nonVisualDrawingProps.d.ts +34 -0
  79. package/dist/docx/nonVisualDrawingProps.js +46 -0
  80. package/dist/docx/normalizeBaseDirection.js +10 -1
  81. package/dist/docx/paraIdAttribute.d.ts +21 -0
  82. package/dist/docx/paraIdAttribute.js +64 -0
  83. package/dist/docx/paragraphParser.d.ts +1 -1
  84. package/dist/docx/paragraphParser.js +277 -168
  85. package/dist/docx/paragraphPropertySource.js +5 -1
  86. package/dist/docx/paragraphTextBoxEnrichment.d.ts +1 -1
  87. package/dist/docx/paragraphTextBoxEnrichment.js +9 -52
  88. package/dist/docx/paragraphTraversal.js +7 -4
  89. package/dist/docx/parseWarningMessage.js +2 -1
  90. package/dist/docx/parser.js +2 -2
  91. package/dist/docx/preservedRunContent.d.ts +32 -0
  92. package/dist/docx/preservedRunContent.js +86 -0
  93. package/dist/docx/previewBudget.d.ts +64 -0
  94. package/dist/docx/previewBudget.js +88 -0
  95. package/dist/docx/renderedPageBreakNormalization.js +2 -4
  96. package/dist/docx/revisionIdNormalization.js +17 -5
  97. package/dist/docx/rezip.js +91 -36
  98. package/dist/docx/runParser.d.ts +1 -1
  99. package/dist/docx/runParser.js +16 -12
  100. package/dist/docx/sdtPropertiesPatch.js +24 -18
  101. package/dist/docx/sectionParser.js +8 -1
  102. package/dist/docx/sectionReferenceHistory.js +2 -2
  103. package/dist/docx/selectiveSave.js +6 -6
  104. package/dist/docx/selectiveXmlPatch.d.ts +46 -2
  105. package/dist/docx/selectiveXmlPatch.js +86 -39
  106. package/dist/docx/serializer/blockSdtSerializer.js +38 -26
  107. package/dist/docx/serializer/borderSerializer.d.ts +1 -1
  108. package/dist/docx/serializer/borderSerializer.js +15 -14
  109. package/dist/docx/serializer/commentSerializer.d.ts +41 -16
  110. package/dist/docx/serializer/commentSerializer.js +87 -92
  111. package/dist/docx/serializer/documentSerializer.js +8 -11
  112. package/dist/docx/serializer/fontTableSerializer.js +6 -6
  113. package/dist/docx/serializer/headerFooterSerializer.js +12 -14
  114. package/dist/docx/serializer/markupRangeAttributes.js +2 -2
  115. package/dist/docx/serializer/noteSerializer.js +8 -8
  116. package/dist/docx/serializer/numberingSerializer.js +7 -6
  117. package/dist/docx/serializer/paragraphSerializer.js +93 -72
  118. package/dist/docx/serializer/partNamespaces.js +2 -2
  119. package/dist/docx/serializer/runSerializer.js +73 -44
  120. package/dist/docx/serializer/sectionPropertiesSerializer.js +19 -14
  121. package/dist/docx/serializer/settingsSerializer.js +4 -3
  122. package/dist/docx/serializer/stylesSerializer.js +6 -6
  123. package/dist/docx/serializer/tableSerializer.js +28 -17
  124. package/dist/docx/serializer/textFormattingSerializer.js +29 -28
  125. package/dist/docx/serializer/themeSerializer.js +6 -6
  126. package/dist/docx/serializer/trackedChangeAttributes.js +2 -2
  127. package/dist/docx/serializer/xmlUtils.d.ts +1 -2
  128. package/dist/docx/serializer/xmlUtils.js +1 -13
  129. package/dist/docx/server/boundedArchive.d.ts +12 -0
  130. package/dist/docx/server/boundedArchive.js +20 -1
  131. package/dist/docx/server/createBilingualDocument.js +3 -1
  132. package/dist/docx/server/materializeYjsDocx.d.ts +1 -1
  133. package/dist/docx/server/materializeYjsDocx.js +9 -1
  134. package/dist/docx/server/migrateYjsAttrSchema.d.ts +55 -0
  135. package/dist/docx/server/migrateYjsAttrSchema.js +95 -0
  136. package/dist/docx/server/validateDocxConformance.js +22 -1
  137. package/dist/docx/shapeParser.js +12 -10
  138. package/dist/docx/tableParser.d.ts +1 -1
  139. package/dist/docx/tableParser.js +206 -85
  140. package/dist/docx/textBoxParser.d.ts +25 -2
  141. package/dist/docx/textBoxParser.js +59 -4
  142. package/dist/docx/unzip.d.ts +23 -0
  143. package/dist/docx/unzip.js +37 -26
  144. package/dist/docx/verbatimCapture.js +1 -1
  145. package/dist/docx/vmlImageParser.d.ts +17 -1
  146. package/dist/docx/vmlImageParser.js +20 -3
  147. package/dist/docx/vmlPreview.d.ts +1 -3
  148. package/dist/docx/vmlPreview.js +2 -30
  149. package/dist/docx/xmlEncoding.d.ts +5 -0
  150. package/dist/docx/xmlEncoding.js +12 -0
  151. package/dist/docx/xmlParser.d.ts +26 -2
  152. package/dist/docx/xmlParser.js +70 -27
  153. package/dist/docx/xmlResourceLimits.d.ts +89 -9
  154. package/dist/docx/xmlResourceLimits.js +105 -24
  155. package/dist/headless-layout.js +10 -1
  156. package/dist/index.d.ts +2 -1
  157. package/dist/index.js +2 -1
  158. package/dist/internal/pageBreakRunSourceDescendantIndex.js +5 -2
  159. package/dist/internal/paragraphFormattingSerialization.js +3 -2
  160. package/dist/layout-bridge/convert/toFlowBlocks.js +102 -12
  161. package/dist/layout-engine/measure/tableCellFloating.d.ts +2 -0
  162. package/dist/layout-engine/measure/tableCellFloating.js +2 -0
  163. package/dist/layout-engine/types.d.ts +23 -1
  164. package/dist/layout-painter/renderImage.d.ts +5 -1
  165. package/dist/layout-painter/renderImage.js +14 -6
  166. package/dist/layout-painter/renderPage.d.ts +2 -0
  167. package/dist/layout-painter/renderPage.js +4 -0
  168. package/dist/layout-painter/renderParagraph.d.ts +13 -1
  169. package/dist/layout-painter/renderParagraph.js +26 -6
  170. package/dist/managers/autoSaveCodec.d.ts +9 -1
  171. package/dist/managers/autoSaveCodec.js +14 -12
  172. package/dist/markdown/images.js +1 -4
  173. package/dist/markdown/renderBlock.js +1 -0
  174. package/dist/markdown/renderRuns.d.ts +1 -1
  175. package/dist/markdown/renderRuns.js +28 -5
  176. package/dist/markdown/renderTable.js +22 -5
  177. package/dist/markdown/trailers.js +4 -1
  178. package/dist/pdf/images.js +142 -6
  179. package/dist/prosemirror/attrs/index.d.ts +14 -3
  180. package/dist/prosemirror/attrs/index.js +224 -2
  181. package/dist/prosemirror/authoredTransformAttrs.d.ts +28 -0
  182. package/dist/prosemirror/authoredTransformAttrs.js +64 -0
  183. package/dist/prosemirror/commands/contentControls.js +10 -2
  184. package/dist/prosemirror/commands/image.d.ts +9 -2
  185. package/dist/prosemirror/commands/image.js +43 -28
  186. package/dist/prosemirror/commands/pageBreak.js +1 -1
  187. package/dist/prosemirror/commentReferenceAttrs.d.ts +8 -0
  188. package/dist/prosemirror/commentReferenceAttrs.js +33 -0
  189. package/dist/prosemirror/commentReferenceIntegrity.d.ts +47 -0
  190. package/dist/prosemirror/commentReferenceIntegrity.js +43 -0
  191. package/dist/prosemirror/conversion/fromProseDoc.d.ts +2 -13
  192. package/dist/prosemirror/conversion/fromProseDoc.js +338 -99
  193. package/dist/prosemirror/conversion/index.d.ts +2 -2
  194. package/dist/prosemirror/conversion/toProseDoc.d.ts +7 -9
  195. package/dist/prosemirror/conversion/toProseDoc.js +551 -327
  196. package/dist/prosemirror/extensions/StarterKit.js +8 -58
  197. package/dist/prosemirror/extensions/core/DocExtension.js +1 -1
  198. package/dist/prosemirror/extensions/core/ParagraphExtension.js +2 -1
  199. package/dist/prosemirror/extensions/features/BaseKeymapExtension.js +45 -27
  200. package/dist/prosemirror/extensions/features/EmptyParagraphFormatExtension.js +3 -1
  201. package/dist/prosemirror/extensions/features/ImagePasteExtension.js +5 -3
  202. package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.js +1 -0
  203. package/dist/prosemirror/extensions/markRegistry.d.ts +41 -0
  204. package/dist/prosemirror/extensions/markRegistry.js +75 -0
  205. package/dist/prosemirror/extensions/marks/HyperlinkExtension.js +2 -3
  206. package/dist/prosemirror/extensions/marks/InlineWrapperExtension.d.ts +18 -0
  207. package/dist/prosemirror/extensions/marks/InlineWrapperExtension.js +63 -0
  208. package/dist/prosemirror/extensions/marks/markUtils.d.ts +2 -1
  209. package/dist/prosemirror/extensions/marks/markUtils.js +47 -4
  210. package/dist/prosemirror/extensions/nodes/CommentReferenceExtension.d.ts +11 -0
  211. package/dist/prosemirror/extensions/nodes/CommentReferenceExtension.js +87 -0
  212. package/dist/prosemirror/extensions/nodes/FieldExtension.js +9 -7
  213. package/dist/prosemirror/extensions/nodes/ImageExtension.js +20 -0
  214. package/dist/prosemirror/extensions/nodes/PreservedBlockExtension.d.ts +32 -0
  215. package/dist/prosemirror/extensions/nodes/PreservedBlockExtension.js +67 -0
  216. package/dist/prosemirror/extensions/nodes/PreservedXmlExtension.d.ts +16 -0
  217. package/dist/prosemirror/extensions/nodes/PreservedXmlExtension.js +60 -0
  218. package/dist/prosemirror/extensions/nodes/ShapeExtension.js +10 -2
  219. package/dist/prosemirror/extensions/nodes/TableExtension.js +3 -2
  220. package/dist/prosemirror/extensions/nodes/TextBoxExtension.js +13 -5
  221. package/dist/prosemirror/inlineWrapperStack.d.ts +39 -0
  222. package/dist/prosemirror/inlineWrapperStack.js +75 -0
  223. package/dist/prosemirror/pageBreakRunProjection.d.ts +17 -7
  224. package/dist/prosemirror/pageBreakRunProjection.js +19 -9
  225. package/dist/prosemirror/paragraphFormattingProvenance.d.ts +6 -3
  226. package/dist/prosemirror/paragraphFormattingProvenance.js +12 -3
  227. package/dist/prosemirror/replacedAnnotations.d.ts +59 -0
  228. package/dist/prosemirror/replacedAnnotations.js +165 -0
  229. package/dist/prosemirror/runFormattingInlineCarriers.d.ts +3 -1
  230. package/dist/prosemirror/runFormattingInlineCarriers.js +5 -1
  231. package/dist/prosemirror/schema/index.d.ts +3 -3
  232. package/dist/prosemirror/schema/marks.d.ts +25 -1
  233. package/dist/prosemirror/schema/nodes.d.ts +139 -3
  234. package/dist/prosemirror/schema/nodes.js +16 -1
  235. package/dist/prosemirror/trackedRunInlineAtoms.d.ts +2 -0
  236. package/dist/prosemirror/trackedRunInlineAtoms.js +2 -0
  237. package/dist/prosemirror/validation.js +16 -2
  238. package/dist/prosemirror/yjsDocumentMetadata.d.ts +73 -0
  239. package/dist/prosemirror/yjsDocumentMetadata.js +171 -0
  240. package/dist/prosemirror/zeroWidthAnchors.js +2 -0
  241. package/dist/render-dom/commentAnchorAttributes.d.ts +37 -0
  242. package/dist/render-dom/commentAnchorAttributes.js +54 -0
  243. package/dist/server.d.ts +3 -1
  244. package/dist/server.js +3 -1
  245. package/dist/types/content.d.ts +2 -2
  246. package/dist/utils/base64.d.ts +36 -0
  247. package/dist/utils/base64.js +40 -0
  248. package/dist/utils/clipboard.d.ts +9 -1
  249. package/dist/utils/clipboard.js +29 -2
  250. package/dist/utils/findReplace.js +1 -1
  251. package/dist/utils/imageLuminance.d.ts +15 -0
  252. package/dist/utils/imageLuminance.js +32 -0
  253. package/dist/utils/mergeDocumentContent.js +7 -17
  254. package/dist/utils/replaceText.js +1 -0
  255. package/dist/utils/units.d.ts +10 -1
  256. package/dist/utils/units.js +12 -1
  257. package/dist/utils/urlSecurity.d.ts +8 -2
  258. package/dist/utils/urlSecurity.js +21 -3
  259. package/package.json +2 -2
  260. package/dist/docx/blockRangeMarkers.d.ts +0 -36
  261. package/dist/docx/blockRangeMarkers.js +0 -59
  262. package/dist/prosemirror/yjsParagraphSourceContract.d.ts +0 -9
  263. package/dist/prosemirror/yjsParagraphSourceContract.js +0 -26
@@ -21,6 +21,35 @@ type SymbolAttrs = {
21
21
  font: string;
22
22
  char: string;
23
23
  };
24
+ /** A run child folio does not model, carried through the editor untouched. */
25
+ /**
26
+ * Which container the captured markup came out of, and goes back into.
27
+ *
28
+ * `w:ruby` is a run child and has to be written back inside a `w:r`;
29
+ * `w:permStart` is a paragraph child and the schema admits none inside a run,
30
+ * so writing one there would produce a package Word repairs. One atom serves
31
+ * both because the editor treats them identically — opaque, zero-width unless
32
+ * the markup shows text, carrying whatever marks surround it — and only the
33
+ * save path has to tell them apart.
34
+ */
35
+ declare const PRESERVED_XML_LEVELS: {
36
+ readonly run: "run";
37
+ readonly inline: "inline";
38
+ };
39
+ type PreservedXmlLevel = (typeof PRESERVED_XML_LEVELS)[keyof typeof PRESERVED_XML_LEVELS];
40
+ /** A run or inline child folio does not model, carried through the editor untouched. */
41
+ type PreservedXmlAttrs = {
42
+ /** Replayable markup, as `captureVerbatimXml` wrote it. */
43
+ xml: string;
44
+ /** The visible text the markup puts on the line, empty when it shows none. */
45
+ text: string;
46
+ level: PreservedXmlLevel;
47
+ };
48
+ /** A block child folio does not model, carried through the editor untouched. */
49
+ type PreservedBlockAttrs = {
50
+ /** Replayable markup, as `captureVerbatimXml` wrote it. */
51
+ xml: string;
52
+ };
24
53
  type BookmarkBoundaryAttrs = {
25
54
  type: "start";
26
55
  id: number;
@@ -33,6 +62,14 @@ type BookmarkBoundaryAttrs = {
33
62
  id: number;
34
63
  displacedByCustomXml?: document_d_exports.DisplacedByCustomXml;
35
64
  };
65
+ /**
66
+ * The position of a comment's `w:commentReference`: the run that paints the
67
+ * visible comment mark. It is authored data, not a consequence of where the
68
+ * range ends, so the editor carries it as a node of its own.
69
+ */
70
+ type CommentReferenceAttrs = {
71
+ commentId: number;
72
+ };
36
73
  /**
37
74
  * Paragraph node attributes - maps to ParagraphFormatting
38
75
  */
@@ -213,6 +250,17 @@ type ParagraphAttrs = {
213
250
  /** Full section properties for paragraphs that end a section.
214
251
  * Used by layout engine for per-section column/page config and round-trip. */
215
252
  _sectionProperties?: document_d_exports.SectionProperties;
253
+ /**
254
+ * Attributes the authored `w:p` carried and the model has no field for
255
+ * (`w:rsidR` and its family), carried opaquely so an edit does not rewrite
256
+ * the document's revision history.
257
+ *
258
+ * The remainder follows the record. ProseMirror copies a node's attrs to
259
+ * both halves of a split, so `fromProseDoc` gives it to the first paragraph
260
+ * that carries it and to no other: a paragraph the editor created never had
261
+ * those attributes and must not inherit them from a neighbour.
262
+ */
263
+ _preservedAttributes?: document_d_exports.PreservedAttribute[];
216
264
  /** Paragraph-property-change tracking entries (`w:pPrChange`).
217
265
  * Preserved opaquely through ProseMirror — the editor does not surface
218
266
  * them in UI today, but stripping them on every edit would corrupt the
@@ -264,6 +312,25 @@ type ImagePositionAttrs = {
264
312
  align?: NonNullable<document_d_exports.ImagePosition["vertical"]["alignment"]>;
265
313
  };
266
314
  };
315
+ /**
316
+ * The EMUs a drawing's pixel attributes were projected from, keyed by the
317
+ * pixel attribute each one became.
318
+ *
319
+ * EMU → px → EMU does not land back on the same number: a size rounds to whole
320
+ * pixels, a stroke or an inset to two. Without the authored value beside the
321
+ * projected one, opening a document and saving it again moved every drawing
322
+ * off the number its author wrote. `fromProseDoc` writes the authored EMU back
323
+ * while the pixel attribute still projects from it, and converts the pixel
324
+ * attribute once an editor command has moved it.
325
+ *
326
+ * A key carries `undefined` when the source authored no such value, so an
327
+ * absent value stays absent rather than acquiring one the document never had.
328
+ */
329
+ type AuthoredEmuAttrs<Key extends string> = { readonly [K in Key]?: number | undefined; };
330
+ /** The pixel attributes a drawing's `wp:wrap*` insets are projected into. */
331
+ type WrapDistanceAttr = "distTop" | "distBottom" | "distLeft" | "distRight";
332
+ /** The pixel attributes a text box's internal margins are projected into. */
333
+ type TextBoxMarginAttr = "marginTop" | "marginBottom" | "marginLeft" | "marginRight";
267
334
  /**
268
335
  * Image node attributes
269
336
  */
@@ -283,13 +350,23 @@ type ImageAttrs = {
283
350
  displayMode?: "inline" | "float" | "block";
284
351
  /** CSS float direction for floating images */
285
352
  cssFloat?: "left" | "right" | "none";
286
- /** CSS transform string (rotation, flip) */
353
+ /** CSS transform string, derived from the authored transform below. */
287
354
  transform?: string;
355
+ /** Authored `a:xfrm@rot` in degrees; `null` when the drawing states none. */
356
+ docxRotation?: number | null;
357
+ /** Authored `a:xfrm@flipH`; `null` when the drawing states none. */
358
+ docxFlipH?: boolean | null;
359
+ /** Authored `a:xfrm@flipV`; `null` when the drawing states none. */
360
+ docxFlipV?: boolean | null;
288
361
  /**
289
362
  * Opacity in [0, 1] from `<a:alphaModFix amt>`. Undefined / 1 means fully
290
363
  * opaque (no CSS `opacity` emitted). eigenpal #424.
291
364
  */
292
365
  opacity?: number;
366
+ /** DrawingML `a:lum@bright` as a signed percentage in [-100, 100]. */
367
+ brightness?: number;
368
+ /** DrawingML `a:lum@contrast` as a signed percentage in [-100, 100]. */
369
+ contrast?: number;
293
370
  /** Distance from text above (pixels) */
294
371
  distTop?: number;
295
372
  /** Distance from text below (pixels) */
@@ -320,6 +397,16 @@ type ImageAttrs = {
320
397
  position?: ImagePositionAttrs;
321
398
  /** Use the containing table cell as the anchor's positioning scope (the OOXML default). */
322
399
  layoutInCell?: boolean;
400
+ /**
401
+ * The image carries no information, so assistive technology skips it
402
+ * (`wp:docPr`'s decorative extension). Not {@link hidden}: a decorative
403
+ * image is still displayed.
404
+ */
405
+ decorative?: boolean;
406
+ /** `wp:docPr @hidden`: the drawing is not displayed. */
407
+ hidden?: boolean;
408
+ /** `wp:docPr` extensions folio does not model, carried through verbatim. */
409
+ docPrExtensions?: string[];
323
410
  /**
324
411
  * Authored `a:graphicFrameLocks`. Carried through the editor so a resize,
325
412
  * which forces the serializer to regenerate DrawingML, cannot silently
@@ -328,6 +415,8 @@ type ImageAttrs = {
328
415
  frameLocks?: document_d_exports.ImageFrameLocks;
329
416
  /** Border width in pixels */
330
417
  borderWidth?: number;
418
+ /** The EMUs behind `width`, `height`, `borderWidth` and the wrap insets. */
419
+ _docxAuthoredEmu?: AuthoredEmuAttrs<"width" | "height" | "borderWidth" | WrapDistanceAttr>;
331
420
  /** Border color as CSS color string */
332
421
  borderColor?: string;
333
422
  /** Border style (CSS border-style value) */
@@ -468,6 +557,12 @@ type ShapeAttrs = {
468
557
  geometryAdjustments?: string;
469
558
  /** Unique identifier */
470
559
  shapeId?: string;
560
+ /** Authored non-visual drawing name (`wp:docPr@name` / `wps:cNvPr@name`) */
561
+ shapeName?: string;
562
+ /** Alt text for accessibility (`wp:docPr@descr`) */
563
+ alt?: string;
564
+ /** Authored non-visual drawing title (`wp:docPr@title`) */
565
+ title?: string;
471
566
  /** Width in pixels */
472
567
  width?: number;
473
568
  /** Height in pixels */
@@ -494,12 +589,20 @@ type ShapeAttrs = {
494
589
  outlineStyle?: OutlineStyleAttr;
495
590
  /** Line cap */
496
591
  outlineCap?: NonNullable<document_d_exports.ShapeOutline["cap"]>;
592
+ /** Line join */
593
+ outlineJoin?: NonNullable<document_d_exports.ShapeOutline["join"]>;
497
594
  /** Head arrow/end marker */
498
595
  outlineHeadEnd?: NonNullable<document_d_exports.ShapeOutline["headEnd"]>;
499
596
  /** Tail arrow/end marker */
500
597
  outlineTailEnd?: NonNullable<document_d_exports.ShapeOutline["tailEnd"]>;
501
- /** CSS transform */
598
+ /** CSS transform, derived from the authored transform below. */
502
599
  transform?: string;
600
+ /** Authored `a:xfrm@rot` in degrees; `null` when the drawing states none. */
601
+ docxRotation?: number | null;
602
+ /** Authored `a:xfrm@flipH`; `null` when the drawing states none. */
603
+ docxFlipH?: boolean | null;
604
+ /** Authored `a:xfrm@flipV`; `null` when the drawing states none. */
605
+ docxFlipV?: boolean | null;
503
606
  /** Display mode */
504
607
  displayMode?: "inline" | "float" | "block";
505
608
  /** CSS float */
@@ -538,6 +641,8 @@ type ShapeAttrs = {
538
641
  * census).
539
642
  */
540
643
  _docxRunFormatting?: document_d_exports.TextFormatting;
644
+ /** The EMUs behind `width`, `height`, `outlineWidth` and the wrap insets. */
645
+ _docxAuthoredEmu?: AuthoredEmuAttrs<"width" | "height" | "outlineWidth" | WrapDistanceAttr>;
541
646
  };
542
647
  /**
543
648
  * Text box node attributes
@@ -551,6 +656,8 @@ type TextBoxAttrs = {
551
656
  width?: number;
552
657
  /** Height in pixels */
553
658
  height?: number;
659
+ /** The EMUs behind the size, `outlineWidth`, the wrap insets and the margins. */
660
+ _docxAuthoredEmu?: AuthoredEmuAttrs<"width" | "height" | "outlineWidth" | WrapDistanceAttr | TextBoxMarginAttr>;
554
661
  /** Text fitting behavior */
555
662
  autoFit?: document_d_exports.ShapeTextBody["autoFit"];
556
663
  /** Authored DrawingML WordArt metadata. */
@@ -559,6 +666,12 @@ type TextBoxAttrs = {
559
666
  textWrap?: document_d_exports.ShapeTextBody["textWrap"];
560
667
  /** Unique identifier */
561
668
  textBoxId?: string;
669
+ /** Authored non-visual drawing name (`wp:docPr@name` / `wps:cNvPr@name`) */
670
+ textBoxName?: string;
671
+ /** Alt text for accessibility (`wp:docPr@descr`) */
672
+ alt?: string;
673
+ /** Authored non-visual drawing title (`wp:docPr@title`) */
674
+ title?: string;
562
675
  /** Fill color as CSS color */
563
676
  fillColor?: string;
564
677
  /** Outline width in pixels */
@@ -569,6 +682,12 @@ type TextBoxAttrs = {
569
682
  outlineStyle?: OutlineStyleAttr;
570
683
  /** DrawingML rotation and/or flips, serialized as CSS transform functions. */
571
684
  transform?: string;
685
+ /** Authored `a:xfrm@rot` in degrees; `null` when the drawing states none. */
686
+ docxRotation?: number | null;
687
+ /** Authored `a:xfrm@flipH`; `null` when the drawing states none. */
688
+ docxFlipH?: boolean | null;
689
+ /** Authored `a:xfrm@flipV`; `null` when the drawing states none. */
690
+ docxFlipV?: boolean | null;
572
691
  /** Internal margin top in pixels */
573
692
  marginTop?: number;
574
693
  /** Internal margin bottom in pixels */
@@ -625,6 +744,17 @@ type TextBoxAttrs = {
625
744
  };
626
745
  /** Original inline content-control ancestry for save-path reconstruction. */
627
746
  _docxInlineSdts?: SdtAttrs[];
747
+ /**
748
+ * The attribute remainder of the `w:p` this node was lifted out of.
749
+ *
750
+ * A paragraph whose only content was an anchored drawing has no paragraph
751
+ * node in the editor: this node stands in for it, so it carries the host's
752
+ * remainder the way `ParagraphAttrs._preservedAttributes` carries a
753
+ * paragraph's own. Only a `"standalone"` placement has a host to speak for;
754
+ * an `"inlineWithPrevious"` text box sits in a paragraph that is projected
755
+ * itself and keeps its own.
756
+ */
757
+ _preservedAttributes?: document_d_exports.PreservedAttribute[];
628
758
  };
629
759
  /** Internal inline position marker for an extracted text box block. */
630
760
  type TextBoxAnchorAttrs = {
@@ -699,6 +829,12 @@ type TableRowAttrs = {
699
829
  _originalFormatting?: document_d_exports.TableRowFormatting;
700
830
  /** Tracked row property changes (w:trPrChange) for round-trip + accept/reject */
701
831
  trPrChange?: document_d_exports.TableRowPropertyChange[];
832
+ /**
833
+ * Attributes the authored `w:tr` carried and the model has no field for
834
+ * (`w:rsidR`, `w:rsidDel`, `w:rsidTr`, `w:rsidRPr`), carried opaquely for
835
+ * the reason `ParagraphAttrs._preservedAttributes` gives.
836
+ */
837
+ _preservedAttributes?: document_d_exports.PreservedAttribute[];
702
838
  } & ({
703
839
  /**
704
840
  * Tracked structural row insertion (w:trPr/w:ins). A `"suggested"`
@@ -836,4 +972,4 @@ type TableCellAttrs = {
836
972
  _docxVMergeContinuationCells?: unknown;
837
973
  };
838
974
  //#endregion
839
- export { BlockSdtAttrs, BookmarkBoundaryAttrs, FieldAttrs, HardBreakAttrs, ImageAttrs, ImagePositionAttrs, MathAttrs, PageBreakRunAttrs, ParagraphAttrs, ParagraphPropertyChangeAttrs, SdtAttrs, ShapeAttrs, SuggestedStructuralMarker, SymbolAttrs, TEXT_BOX_TEXT_BODY_CONTENT_STATE_TYPES, TabAttrs, TableAttrs, TableCellAttrs, TableRowAttrs, TextBoxAnchorAttrs, TextBoxAttrs, TextBoxTextBodyContentState };
975
+ export { AuthoredEmuAttrs, BlockSdtAttrs, BookmarkBoundaryAttrs, CommentReferenceAttrs, FieldAttrs, HardBreakAttrs, ImageAttrs, ImagePositionAttrs, MathAttrs, PRESERVED_XML_LEVELS, PageBreakRunAttrs, ParagraphAttrs, ParagraphPropertyChangeAttrs, PreservedBlockAttrs, PreservedXmlAttrs, PreservedXmlLevel, SdtAttrs, ShapeAttrs, SuggestedStructuralMarker, SymbolAttrs, TEXT_BOX_TEXT_BODY_CONTENT_STATE_TYPES, TabAttrs, TableAttrs, TableCellAttrs, TableRowAttrs, TextBoxAnchorAttrs, TextBoxAttrs, TextBoxTextBodyContentState };
@@ -1,7 +1,22 @@
1
1
  //#region src/prosemirror/schema/nodes.ts
2
+ /** A run child folio does not model, carried through the editor untouched. */
3
+ /**
4
+ * Which container the captured markup came out of, and goes back into.
5
+ *
6
+ * `w:ruby` is a run child and has to be written back inside a `w:r`;
7
+ * `w:permStart` is a paragraph child and the schema admits none inside a run,
8
+ * so writing one there would produce a package Word repairs. One atom serves
9
+ * both because the editor treats them identically — opaque, zero-width unless
10
+ * the markup shows text, carrying whatever marks surround it — and only the
11
+ * save path has to tell them apart.
12
+ */
13
+ const PRESERVED_XML_LEVELS = {
14
+ run: "run",
15
+ inline: "inline"
16
+ };
2
17
  /**
3
18
  * Text box node attributes
4
19
  */
5
20
  const TEXT_BOX_TEXT_BODY_CONTENT_STATE_TYPES = Object.freeze(["source-empty", "authored"]);
6
21
  //#endregion
7
- export { TEXT_BOX_TEXT_BODY_CONTENT_STATE_TYPES };
22
+ export { PRESERVED_XML_LEVELS, TEXT_BOX_TEXT_BODY_CONTENT_STATE_TYPES };
@@ -11,11 +11,13 @@ type TrackedRunInlineAtomDisposition = "carry" | "field-carrier" | "outside-wrap
11
11
  */
12
12
  declare const TRACKED_RUN_INLINE_ATOM_DISPOSITIONS: Readonly<{
13
13
  readonly bookmarkBoundary: "carry";
14
+ readonly commentReference: "transparent";
14
15
  readonly field: "field-carrier";
15
16
  readonly hardBreak: "carry";
16
17
  readonly image: "carry";
17
18
  readonly math: "carry";
18
19
  readonly pageBreakRun: "page-break-carrier";
20
+ readonly preservedXml: "carry";
19
21
  readonly renderedPageBreak: "transparent";
20
22
  readonly shape: "carry";
21
23
  readonly structuredField: "carry";
@@ -10,11 +10,13 @@ import { panic } from "better-result";
10
10
  */
11
11
  const TRACKED_RUN_INLINE_ATOM_DISPOSITIONS = Object.freeze({
12
12
  bookmarkBoundary: "carry",
13
+ commentReference: "transparent",
13
14
  field: "field-carrier",
14
15
  hardBreak: "carry",
15
16
  image: "carry",
16
17
  math: "carry",
17
18
  pageBreakRun: "page-break-carrier",
19
+ preservedXml: "carry",
18
20
  renderedPageBreak: "transparent",
19
21
  shape: "carry",
20
22
  structuredField: "carry",
@@ -1,5 +1,6 @@
1
- import { readBlockSdtAttrs, readCharacterSpacingMarkAttrs, readCharacterStyleMarkAttrs, readCommentMarkAttrs, readEmphasisMarkAttrs, readFieldAttrs, readFontFamilyMarkAttrs, readFontSizeMarkAttrs, readFootnoteRefMarkAttrs, readHardBreakAttrs, readHighlightMarkAttrs, readHyperlinkMarkAttrs, readImageAttrs, readLanguageMarkAttrs, readMathAttrs, readPageBreakRunAttrs, readPageBreakRunOwnerMarkAttrs, readParagraphAttrs, readRunFormattingOverrideMarkAttrs, readRunPropertyChangeMarkAttrs, readRunShadingMarkAttrs, readSdtAttrs, readShapeAttrs, readStrikeMarkAttrs, readSymbolAttrs, readTabAttrs, readTableAttrs, readTableCellAttrs, readTableRowAttrs, readTextBoxAttrs, readTextColorMarkAttrs, readTextEffectMarkAttrs, readTrackedChangeMarkAttrs, readUnderlineMarkAttrs } from "./attrs/index.js";
1
+ import { readBlockSdtAttrs, readCharacterSpacingMarkAttrs, readCharacterStyleMarkAttrs, readCommentMarkAttrs, readEmphasisMarkAttrs, readFieldAttrs, readFontFamilyMarkAttrs, readFontSizeMarkAttrs, readFootnoteRefMarkAttrs, readHardBreakAttrs, readHighlightMarkAttrs, readHyperlinkMarkAttrs, readImageAttrs, readInlineWrapperMarkAttrs, readLanguageMarkAttrs, readMathAttrs, readPageBreakRunAttrs, readPageBreakRunOwnerMarkAttrs, readParagraphAttrs, readPreservedBlockAttrs, readPreservedXmlAttrs, readRunFormattingOverrideMarkAttrs, readRunPropertyChangeMarkAttrs, readRunShadingMarkAttrs, readSdtAttrs, readShapeAttrs, readStrikeMarkAttrs, readSymbolAttrs, readTabAttrs, readTableAttrs, readTableCellAttrs, readTableRowAttrs, readTextBoxAttrs, readTextColorMarkAttrs, readTextEffectMarkAttrs, readTrackedChangeMarkAttrs, readUnderlineMarkAttrs } from "./attrs/index.js";
2
2
  import { readBookmarkBoundaryAttrs } from "./bookmarkBoundaryAttrs.js";
3
+ import { readCommentReferenceAttrs } from "./commentReferenceAttrs.js";
3
4
  import { readTextBoxAnchorAttrs } from "./textBoxAnchorAttrs.js";
4
5
  //#region src/prosemirror/validation.ts
5
6
  var ProseMirrorDocumentValidationError = class extends Error {
@@ -142,12 +143,21 @@ const validateNodeAttrs = (node, path, issues) => {
142
143
  case "bookmarkBoundary":
143
144
  appendAttrIssues(path, readBookmarkBoundaryAttrs(node), issues);
144
145
  return;
146
+ case "commentReference":
147
+ appendAttrIssues(path, readCommentReferenceAttrs(node), issues);
148
+ return;
145
149
  case "tab":
146
150
  appendAttrIssues(path, readTabAttrs(node), issues);
147
151
  return;
148
152
  case "symbol":
149
153
  appendAttrIssues(path, readSymbolAttrs(node), issues);
150
154
  return;
155
+ case "preservedXml":
156
+ appendAttrIssues(path, readPreservedXmlAttrs(node), issues);
157
+ return;
158
+ case "preservedBlock":
159
+ appendAttrIssues(path, readPreservedBlockAttrs(node), issues);
160
+ return;
151
161
  case "hardBreak":
152
162
  appendAttrIssues(path, readHardBreakAttrs(node), issues);
153
163
  return;
@@ -184,6 +194,7 @@ const validateNodeAttrs = (node, path, issues) => {
184
194
  if (fieldAttrs.ok) {
185
195
  const hasStructuredHyperlink = node.content.content.some((child) => child.marks.some((mark) => mark.type.name === "hyperlink"));
186
196
  const hasPageBreakCarrier = node.content.content.some((child) => child.type.name === "pageBreakRun");
197
+ const hasPreservedCapture = node.content.content.some((child) => child.type.name === "preservedXml");
187
198
  if (fieldAttrs.value.fieldKind === "complex" && !hasPageBreakCarrier) issues.push({
188
199
  path: `${path}.content`,
189
200
  message: "Complex fields cannot contain structured result children."
@@ -192,7 +203,7 @@ const validateNodeAttrs = (node, path, issues) => {
192
203
  path: `${path}.content`,
193
204
  message: "Complex field results cannot contain hyperlink content."
194
205
  });
195
- else if (!hasStructuredHyperlink && !hasPageBreakCarrier) issues.push({
206
+ else if (!hasStructuredHyperlink && !hasPageBreakCarrier && !hasPreservedCapture) issues.push({
196
207
  path: `${path}.content`,
197
208
  message: "Structured simple fields require hyperlink content."
198
209
  });
@@ -314,6 +325,9 @@ const validateMarks = (marks, path, issues) => {
314
325
  case "hyperlink":
315
326
  appendAttrIssues(markPath, readHyperlinkMarkAttrs(mark), issues);
316
327
  continue;
328
+ case "inlineWrapper":
329
+ appendAttrIssues(markPath, readInlineWrapperMarkAttrs(mark), issues);
330
+ continue;
317
331
  default: issues.push({
318
332
  path: `${markPath}.type.name`,
319
333
  message: `Unsupported ProseMirror mark type ${mark.type.name}.`
@@ -0,0 +1,73 @@
1
+ import { Node } from "prosemirror-model";
2
+ import { Result } from "better-result";
3
+ import * as Y from "yjs";
4
+ //#region src/prosemirror/yjsDocumentMetadata.d.ts
5
+ /**
6
+ * Carry a snapshot written under `version` forward to the next version,
7
+ * rewriting the fragment in place and answering how many paragraphs changed.
8
+ */
9
+ type AttrSchemaMigrationStep = (fragment: Y.XmlFragment) => number;
10
+ /** Every attr-schema version this build reads, oldest first, with no gaps. */
11
+ declare const FOLIO_YJS_ATTR_SCHEMA_VERSIONS: readonly [0, 1, 2, 3];
12
+ /** An attr-schema version this build can read. */
13
+ type FolioYjsAttrSchemaVersion = (typeof FOLIO_YJS_ATTR_SCHEMA_VERSIONS)[number];
14
+ /**
15
+ * The attr-schema version this build writes. Derived against the migration map
16
+ * so the constant and the map cannot disagree.
17
+ */
18
+ declare const FOLIO_YJS_ATTR_SCHEMA_VERSION = 3;
19
+ /**
20
+ * The steps that carry a snapshot written under `fromVersion` up to
21
+ * {@link FOLIO_YJS_ATTR_SCHEMA_VERSION}, in order. Empty when the snapshot is
22
+ * already current.
23
+ */
24
+ declare const attrSchemaMigrationSteps: (fromVersion: FolioYjsAttrSchemaVersion) => readonly AttrSchemaMigrationStep[];
25
+ /**
26
+ * Carry a fragment this build is about to read or write up to the attr shape
27
+ * this build writes, and stamp the marker.
28
+ *
29
+ * Every entry point that hands a fragment to `initProseMirrorDoc` calls this,
30
+ * for two reasons that are the same reason. A step that rewrites values has to
31
+ * run before a node is built from them, or the build reads the old shape as
32
+ * the new one. And the marker has to say what the fragment may now hold before
33
+ * the first edit writes an attr of this build's shape into it, because an
34
+ * older build reading an unmarked snapshot drops what it does not know without
35
+ * a trace.
36
+ *
37
+ * Returns how many elements the steps rewrote.
38
+ */
39
+ declare const applyAttrSchemaMigrations: (ydoc: Y.Doc, fragment: Y.XmlFragment, fromVersion: FolioYjsAttrSchemaVersion) => number;
40
+ declare const FolioYjsAttrSchemaVersionError_base: import("better-result").TaggedErrorClass<"FolioYjsAttrSchemaVersionError">;
41
+ /** Raised when a snapshot's attr-schema marker is ahead of the running code. */
42
+ declare class FolioYjsAttrSchemaVersionError extends FolioYjsAttrSchemaVersionError_base<{
43
+ message: string;
44
+ /** The marker exactly as stored, so the host can log what it refused. */
45
+ marker: unknown;
46
+ /** The newest attr-schema version this build understands. */
47
+ supportedVersion: FolioYjsAttrSchemaVersion;
48
+ }> {}
49
+ /**
50
+ * The attr-schema version a collaboration document was written under.
51
+ *
52
+ * An absent marker is version 0: every snapshot predates the marker, so no
53
+ * backfill is needed to classify one. An older version loads, because
54
+ * {@link attrSchemaMigrationSteps} says what it means. A marker this
55
+ * build does not know is a snapshot written by newer code, and reading it would
56
+ * be a silent misread: ProseMirror copies unknown attr values into the node
57
+ * verbatim and drops unknown keys without a trace. It fails instead.
58
+ */
59
+ declare const readYjsAttrSchemaVersion: (ydoc: Y.Doc) => Result<FolioYjsAttrSchemaVersion, FolioYjsAttrSchemaVersionError>;
60
+ declare const proseDocumentParagraphSourceContract: (document: Node) => string | null;
61
+ /** Stamp the attr-schema version of the build that wrote the current fragment. */
62
+ declare const writeYjsAttrSchemaVersion: (ydoc: Y.Doc) => void;
63
+ /**
64
+ * Write both metadata bindings for a freshly seeded collaboration document.
65
+ * The attr-schema version is written unconditionally; the paragraph-source
66
+ * contract only when the seeding document carries one, because a document
67
+ * built in memory rather than parsed from a package has no source to bind to.
68
+ */
69
+ declare const writeYjsDocumentMetadata: (ydoc: Y.Doc, document: Node) => void;
70
+ declare const readYjsParagraphSourceContract: (ydoc: Y.Doc) => string | null;
71
+ declare const withParagraphSourceContract: (document: Node, contract: string) => Node;
72
+ //#endregion
73
+ export { FOLIO_YJS_ATTR_SCHEMA_VERSION, FolioYjsAttrSchemaVersion, FolioYjsAttrSchemaVersionError, applyAttrSchemaMigrations, attrSchemaMigrationSteps, proseDocumentParagraphSourceContract, readYjsAttrSchemaVersion, readYjsParagraphSourceContract, withParagraphSourceContract, writeYjsAttrSchemaVersion, writeYjsDocumentMetadata };
@@ -0,0 +1,171 @@
1
+ import { PROSE_PARAGRAPH_SOURCE_CONTRACT_ATTR, getProseDocumentParagraphPropertySourceContract } from "../docx/paragraphPropertySource.js";
2
+ import { Result, TaggedError, panic } from "better-result";
3
+ //#region src/prosemirror/yjsDocumentMetadata.ts
4
+ /**
5
+ * Folio's own keys inside a collaboration document: one map, two independent
6
+ * bindings.
7
+ *
8
+ * `paragraphSourceContract` binds the snapshot to the exact bytes of the DOCX
9
+ * it was seeded from. `attrSchemaVersion` binds it to the shape of the node
10
+ * attrs Folio persists. A snapshot can be current on one and stale on the
11
+ * other, so neither key may be derived from the other.
12
+ */
13
+ const FOLIO_YJS_METADATA_MAP_NAME = "folio:document-metadata";
14
+ const PARAGRAPH_SOURCE_CONTRACT_KEY = "paragraphSourceContract";
15
+ const ATTR_SCHEMA_VERSION_KEY = "attrSchemaVersion";
16
+ /**
17
+ * Version 0 is every snapshot written before the marker existed. The marker
18
+ * shipped without changing a single attr, so carrying a v0 snapshot to v1 is
19
+ * the identity: it only stamps the key.
20
+ */
21
+ const stampMarkerOnly = () => 0;
22
+ /** The node types whose `fldLock` and `dirty` attrs version 2 rewrites. */
23
+ const FIELD_ELEMENT_NAMES = /* @__PURE__ */ new Set(["field", "structuredField"]);
24
+ const STATED_FLAG_ATTRS = ["fldLock", "dirty"];
25
+ /**
26
+ * Version 1 stored `fldLock` and `dirty` as booleans defaulting to `false`,
27
+ * because the reader that filled them tested `=== true`. A field that authored
28
+ * an explicit `w:fldLock="0"` and one that authored nothing were both stored as
29
+ * `false`, so `false` never meant an explicit off and cannot be kept as one now
30
+ * that `null` is the absence: a v1 snapshot's `false` would start writing an
31
+ * attribute the document never carried.
32
+ */
33
+ const dropUnstatedFieldFlags = (fragment) => {
34
+ let rewritten = 0;
35
+ const visit = (node) => {
36
+ if ("nodeName" in node && FIELD_ELEMENT_NAMES.has(node.nodeName)) {
37
+ const attributes = node.getAttributes();
38
+ let changed = false;
39
+ for (const attr of STATED_FLAG_ATTRS) if (attributes[attr] === false) {
40
+ node.removeAttribute(attr);
41
+ changed = true;
42
+ }
43
+ if (changed) rewritten += 1;
44
+ }
45
+ for (const child of node.toArray()) if (typeof child !== "string" && "toArray" in child) visit(child);
46
+ };
47
+ visit(fragment);
48
+ return rewritten;
49
+ };
50
+ /**
51
+ * Version 3 adds `docxRotation`, `docxFlipH` and `docxFlipV` to the drawing
52
+ * nodes. A v2 snapshot states none of them, and `readAuthoredTransform` reads
53
+ * such a node from its `transform` CSS, which is the only record it ever had,
54
+ * so nothing has to be rewritten. The marker still moves: a v3 snapshot read
55
+ * by a v2 build would have the three attrs dropped without a trace.
56
+ */
57
+ const drawingTransformAttrsAreAdditive = () => 0;
58
+ /** Every attr-schema version this build reads, oldest first, with no gaps. */
59
+ const FOLIO_YJS_ATTR_SCHEMA_VERSIONS = [
60
+ 0,
61
+ 1,
62
+ 2,
63
+ 3
64
+ ];
65
+ /**
66
+ * The one place a persisted attr-shape change is decided.
67
+ *
68
+ * Changing the shape of any node or mark attr Folio persists means: append the
69
+ * new version to {@link FOLIO_YJS_ATTR_SCHEMA_VERSIONS}, map the previous
70
+ * version to the step that rewrites it, and map the new version to `"current"`.
71
+ * The map is total over the version union, so a version added without a
72
+ * decision does not compile, and `migrateFolioYjsSnapshot` picks the new step
73
+ * up without being touched.
74
+ */
75
+ const ATTR_SCHEMA_MIGRATIONS = {
76
+ 0: stampMarkerOnly,
77
+ 1: dropUnstatedFieldFlags,
78
+ 2: drawingTransformAttrsAreAdditive,
79
+ 3: "current"
80
+ };
81
+ /**
82
+ * The attr-schema version this build writes. Derived against the migration map
83
+ * so the constant and the map cannot disagree.
84
+ */
85
+ const FOLIO_YJS_ATTR_SCHEMA_VERSION = 3;
86
+ /**
87
+ * The steps that carry a snapshot written under `fromVersion` up to
88
+ * {@link FOLIO_YJS_ATTR_SCHEMA_VERSION}, in order. Empty when the snapshot is
89
+ * already current.
90
+ */
91
+ const attrSchemaMigrationSteps = (fromVersion) => FOLIO_YJS_ATTR_SCHEMA_VERSIONS.filter((version) => version >= fromVersion).flatMap((version) => {
92
+ const step = ATTR_SCHEMA_MIGRATIONS[version];
93
+ return step === "current" ? [] : [step];
94
+ });
95
+ /**
96
+ * Carry a fragment this build is about to read or write up to the attr shape
97
+ * this build writes, and stamp the marker.
98
+ *
99
+ * Every entry point that hands a fragment to `initProseMirrorDoc` calls this,
100
+ * for two reasons that are the same reason. A step that rewrites values has to
101
+ * run before a node is built from them, or the build reads the old shape as
102
+ * the new one. And the marker has to say what the fragment may now hold before
103
+ * the first edit writes an attr of this build's shape into it, because an
104
+ * older build reading an unmarked snapshot drops what it does not know without
105
+ * a trace.
106
+ *
107
+ * Returns how many elements the steps rewrote.
108
+ */
109
+ const applyAttrSchemaMigrations = (ydoc, fragment, fromVersion) => {
110
+ if (fromVersion === 3) return 0;
111
+ let rewritten = 0;
112
+ ydoc.transact(() => {
113
+ for (const step of attrSchemaMigrationSteps(fromVersion)) rewritten += step(fragment);
114
+ writeYjsAttrSchemaVersion(ydoc);
115
+ });
116
+ return rewritten;
117
+ };
118
+ /** Raised when a snapshot's attr-schema marker is ahead of the running code. */
119
+ var FolioYjsAttrSchemaVersionError = class extends TaggedError("FolioYjsAttrSchemaVersionError") {};
120
+ const isReadableVersion = (marker) => typeof marker === "number" && Number.isInteger(marker) && marker >= 0 && marker <= 3;
121
+ /**
122
+ * The attr-schema version a collaboration document was written under.
123
+ *
124
+ * An absent marker is version 0: every snapshot predates the marker, so no
125
+ * backfill is needed to classify one. An older version loads, because
126
+ * {@link attrSchemaMigrationSteps} says what it means. A marker this
127
+ * build does not know is a snapshot written by newer code, and reading it would
128
+ * be a silent misread: ProseMirror copies unknown attr values into the node
129
+ * verbatim and drops unknown keys without a trace. It fails instead.
130
+ */
131
+ const readYjsAttrSchemaVersion = (ydoc) => {
132
+ const marker = ydoc.getMap(FOLIO_YJS_METADATA_MAP_NAME).get(ATTR_SCHEMA_VERSION_KEY);
133
+ if (marker === void 0) return Result.ok(0);
134
+ if (isReadableVersion(marker)) return Result.ok(marker);
135
+ return Result.err(new FolioYjsAttrSchemaVersionError({
136
+ marker,
137
+ message: "The collaboration snapshot was written by a newer Folio attr schema than this build reads.",
138
+ supportedVersion: 3
139
+ }));
140
+ };
141
+ const proseDocumentParagraphSourceContract = (document) => {
142
+ return getProseDocumentParagraphPropertySourceContract(document);
143
+ };
144
+ /** Stamp the attr-schema version of the build that wrote the current fragment. */
145
+ const writeYjsAttrSchemaVersion = (ydoc) => {
146
+ ydoc.getMap(FOLIO_YJS_METADATA_MAP_NAME).set(ATTR_SCHEMA_VERSION_KEY, 3);
147
+ };
148
+ /**
149
+ * Write both metadata bindings for a freshly seeded collaboration document.
150
+ * The attr-schema version is written unconditionally; the paragraph-source
151
+ * contract only when the seeding document carries one, because a document
152
+ * built in memory rather than parsed from a package has no source to bind to.
153
+ */
154
+ const writeYjsDocumentMetadata = (ydoc, document) => {
155
+ writeYjsAttrSchemaVersion(ydoc);
156
+ const contract = proseDocumentParagraphSourceContract(document);
157
+ if (contract) ydoc.getMap(FOLIO_YJS_METADATA_MAP_NAME).set(PARAGRAPH_SOURCE_CONTRACT_KEY, contract);
158
+ };
159
+ const readYjsParagraphSourceContract = (ydoc) => {
160
+ const contract = ydoc.getMap(FOLIO_YJS_METADATA_MAP_NAME).get(PARAGRAPH_SOURCE_CONTRACT_KEY);
161
+ return typeof contract === "string" ? contract : null;
162
+ };
163
+ const withParagraphSourceContract = (document, contract) => {
164
+ if (document.type.name !== "doc") panic("A paragraph-property source contract can only attach to a document node");
165
+ return document.type.create({
166
+ ...document.attrs,
167
+ [PROSE_PARAGRAPH_SOURCE_CONTRACT_ATTR]: contract
168
+ }, document.content, document.marks);
169
+ };
170
+ //#endregion
171
+ export { FOLIO_YJS_ATTR_SCHEMA_VERSION, FolioYjsAttrSchemaVersionError, applyAttrSchemaMigrations, attrSchemaMigrationSteps, proseDocumentParagraphSourceContract, readYjsAttrSchemaVersion, readYjsParagraphSourceContract, withParagraphSourceContract, writeYjsAttrSchemaVersion, writeYjsDocumentMetadata };
@@ -1,9 +1,11 @@
1
1
  import { BOOKMARK_BOUNDARY_NODE_NAME } from "./extensions/nodes/BookmarkBoundaryExtension.js";
2
+ import { COMMENT_REFERENCE_NODE_NAME } from "./extensions/nodes/CommentReferenceExtension.js";
2
3
  import { RENDERED_PAGE_BREAK_NODE_NAME } from "./extensions/nodes/RenderedPageBreakExtension.js";
3
4
  import { TEXT_BOX_ANCHOR_NODE_NAME } from "./extensions/nodes/TextBoxAnchorExtension.js";
4
5
  //#region src/prosemirror/zeroWidthAnchors.ts
5
6
  const ZERO_WIDTH_ANCHOR_NODE_NAMES = /* @__PURE__ */ new Set([
6
7
  BOOKMARK_BOUNDARY_NODE_NAME,
8
+ COMMENT_REFERENCE_NODE_NAME,
7
9
  RENDERED_PAGE_BREAK_NODE_NAME,
8
10
  TEXT_BOX_ANCHOR_NODE_NAME
9
11
  ]);
@@ -0,0 +1,37 @@
1
+ //#region src/render-dom/commentAnchorAttributes.d.ts
2
+ /**
3
+ * How a painted run advertises which comments it sits inside.
4
+ *
5
+ * Comment ranges overlap: a run covered by two `w:commentRangeStart` /
6
+ * `w:commentRangeEnd` pairs belongs to both, and hover styling, the active
7
+ * highlight and the sidebar anchor all have to see both memberships.
8
+ *
9
+ * `data-comment-id` carries the first id, which is what every existing reader
10
+ * scrolls to and what keeps a single-range run's DOM exactly as the painter
11
+ * emitted it before. `data-comment-ids` carries the whole membership and is
12
+ * written only when there is more than one id. Readers ask through the
13
+ * helpers here instead of reading either attribute, so the two spellings
14
+ * cannot come to answer differently.
15
+ */
16
+ /** The painted anchors inside a container, whichever comment they belong to. */
17
+ declare const COMMENT_ANCHOR_SELECTOR = "[data-comment-id]";
18
+ /** What a painter, a reader and their test fakes all offer. */
19
+ type CommentAnchor = {
20
+ dataset: Record<string, string | undefined>;
21
+ };
22
+ /** Record the comments a painted run sits inside. */
23
+ declare const writeCommentAnchorIds: (element: CommentAnchor, commentIds: readonly number[]) => void;
24
+ /** Every comment id a painted anchor sits inside, first id first. */
25
+ declare const commentAnchorIds: (element: CommentAnchor) => readonly string[];
26
+ /**
27
+ * Selector for every painted anchor inside one comment, optionally scoped.
28
+ *
29
+ * `comment.id` is typed as a number, but a controlled `comments` prop supplied
30
+ * by the host app is not runtime-checked, so the value is escaped before it is
31
+ * spliced into the selector.
32
+ */
33
+ declare const commentAnchorSelector: (id: string | number, scope?: string) => string;
34
+ /** First painted anchor per comment id, in one pass over `container`. */
35
+ declare const indexCommentAnchors: (container: ParentNode) => Map<string, HTMLElement>;
36
+ //#endregion
37
+ export { COMMENT_ANCHOR_SELECTOR, commentAnchorIds, commentAnchorSelector, indexCommentAnchors, writeCommentAnchorIds };