@stll/folio-core 0.45.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 (207) hide show
  1. package/dist/ai-edits/apply.js +59 -19
  2. package/dist/ai-edits/headless.js +1 -1
  3. package/dist/compare/compare.js +2 -5
  4. package/dist/compare/scenario.js +2 -5
  5. package/dist/compare/types.d.ts +9 -1
  6. package/dist/compare/types.js +12 -1
  7. package/dist/compat/eigenpal.d.ts +2 -1
  8. package/dist/compat/eigenpal.js +2 -1
  9. package/dist/content-controls/checkboxDisplay.d.ts +11 -0
  10. package/dist/content-controls/checkboxDisplay.js +40 -0
  11. package/dist/content-controls/findContentControls.js +3 -1
  12. package/dist/content-controls/mutateContentControls.js +17 -2
  13. package/dist/controller/contentControlWidgetController.d.ts +1 -0
  14. package/dist/controller/contentControlWidgetController.js +3 -0
  15. package/dist/controller/hiddenEditorApi.js +3 -1
  16. package/dist/controller/hiddenEditorManager.d.ts +1 -1
  17. package/dist/controller/hiddenEditorManager.js +6 -3
  18. package/dist/display-list/build/buildDisplayList.js +20 -1
  19. package/dist/display-list/build/imagePrimitives.d.ts +1 -1
  20. package/dist/display-list/build/imagePrimitives.js +3 -1
  21. package/dist/display-list/build/paragraphPrimitives.js +21 -2
  22. package/dist/display-list/dom/renderDisplayListToDom.js +10 -2
  23. package/dist/display-list/types.d.ts +17 -0
  24. package/dist/docx/attributeRemainder.d.ts +43 -0
  25. package/dist/docx/attributeRemainder.js +65 -0
  26. package/dist/docx/blockContentParser.d.ts +1 -1
  27. package/dist/docx/blockContentParser.js +87 -63
  28. package/dist/docx/blockPlainText.d.ts +3 -4
  29. package/dist/docx/blockPlainText.js +1 -0
  30. package/dist/docx/bookmarkPlacement.js +2 -0
  31. package/dist/docx/commentAnchorIndex.d.ts +30 -0
  32. package/dist/docx/commentAnchorIndex.js +50 -0
  33. package/dist/docx/commentParser.d.ts +1 -1
  34. package/dist/docx/commentParser.js +54 -37
  35. package/dist/docx/commentRangeIntegrity.d.ts +16 -1
  36. package/dist/docx/commentRangeIntegrity.js +42 -1
  37. package/dist/docx/commentRangeJoin.d.ts +9 -0
  38. package/dist/docx/commentRangeJoin.js +33 -0
  39. package/dist/docx/commentReferenceCompletion.d.ts +9 -0
  40. package/dist/docx/commentReferenceCompletion.js +47 -0
  41. package/dist/docx/commentReferenceNormalization.js +1 -0
  42. package/dist/docx/commentReplyMarkers.js +11 -19
  43. package/dist/docx/compatibility.js +1 -0
  44. package/dist/docx/containerChildren.d.ts +111 -0
  45. package/dist/docx/containerChildren.gen.d.ts +28 -0
  46. package/dist/docx/containerChildren.gen.js +246 -0
  47. package/dist/docx/containerChildren.js +103 -0
  48. package/dist/docx/documentParser.d.ts +1 -1
  49. package/dist/docx/documentParser.js +3 -3
  50. package/dist/docx/ensureParaIds.js +17 -7
  51. package/dist/docx/fieldParser.d.ts +1 -1
  52. package/dist/docx/fieldParser.js +4 -4
  53. package/dist/docx/fieldState.d.ts +26 -0
  54. package/dist/docx/fieldState.js +53 -0
  55. package/dist/docx/footnoteParser.d.ts +1 -1
  56. package/dist/docx/graphicFrameLocks.d.ts +16 -4
  57. package/dist/docx/graphicFrameLocks.js +19 -6
  58. package/dist/docx/headerFooterParser.js +1 -1
  59. package/dist/docx/headerFooterReferenceNormalization.js +1 -0
  60. package/dist/docx/hyperlinkParser.d.ts +27 -8
  61. package/dist/docx/hyperlinkParser.js +76 -18
  62. package/dist/docx/imageParser.js +33 -8
  63. package/dist/docx/inlineWrapperContent.d.ts +85 -0
  64. package/dist/docx/inlineWrapperContent.js +84 -0
  65. package/dist/docx/normalizeBaseDirection.js +10 -1
  66. package/dist/docx/paraIdAttribute.d.ts +21 -0
  67. package/dist/docx/paraIdAttribute.js +64 -0
  68. package/dist/docx/paragraphParser.d.ts +1 -1
  69. package/dist/docx/paragraphParser.js +277 -168
  70. package/dist/docx/paragraphPropertySource.js +5 -1
  71. package/dist/docx/paragraphTextBoxEnrichment.d.ts +1 -1
  72. package/dist/docx/paragraphTextBoxEnrichment.js +6 -52
  73. package/dist/docx/paragraphTraversal.js +7 -4
  74. package/dist/docx/parseWarningMessage.js +2 -1
  75. package/dist/docx/preservedRunContent.d.ts +32 -0
  76. package/dist/docx/preservedRunContent.js +86 -0
  77. package/dist/docx/renderedPageBreakNormalization.js +2 -4
  78. package/dist/docx/rezip.js +74 -18
  79. package/dist/docx/runParser.d.ts +1 -1
  80. package/dist/docx/runParser.js +16 -12
  81. package/dist/docx/sectionParser.js +8 -1
  82. package/dist/docx/selectiveXmlPatch.d.ts +46 -2
  83. package/dist/docx/selectiveXmlPatch.js +86 -39
  84. package/dist/docx/serializer/borderSerializer.js +2 -2
  85. package/dist/docx/serializer/commentSerializer.js +5 -7
  86. package/dist/docx/serializer/documentSerializer.js +8 -11
  87. package/dist/docx/serializer/headerFooterSerializer.js +7 -9
  88. package/dist/docx/serializer/noteSerializer.js +8 -8
  89. package/dist/docx/serializer/paragraphSerializer.js +76 -56
  90. package/dist/docx/serializer/runSerializer.js +25 -16
  91. package/dist/docx/serializer/sectionPropertiesSerializer.js +8 -4
  92. package/dist/docx/serializer/tableSerializer.js +18 -8
  93. package/dist/docx/server/createBilingualDocument.js +3 -1
  94. package/dist/docx/server/materializeYjsDocx.d.ts +1 -1
  95. package/dist/docx/server/materializeYjsDocx.js +9 -1
  96. package/dist/docx/server/migrateYjsAttrSchema.d.ts +55 -0
  97. package/dist/docx/server/migrateYjsAttrSchema.js +95 -0
  98. package/dist/docx/shapeParser.js +5 -5
  99. package/dist/docx/tableParser.d.ts +1 -1
  100. package/dist/docx/tableParser.js +206 -85
  101. package/dist/docx/textBoxParser.d.ts +25 -2
  102. package/dist/docx/textBoxParser.js +52 -2
  103. package/dist/docx/unzip.js +5 -4
  104. package/dist/docx/vmlImageParser.d.ts +17 -1
  105. package/dist/docx/vmlImageParser.js +17 -1
  106. package/dist/docx/xmlEncoding.d.ts +5 -0
  107. package/dist/docx/xmlEncoding.js +12 -0
  108. package/dist/docx/xmlParser.d.ts +10 -1
  109. package/dist/docx/xmlParser.js +14 -1
  110. package/dist/headless-layout.js +10 -1
  111. package/dist/index.d.ts +2 -1
  112. package/dist/index.js +2 -1
  113. package/dist/internal/pageBreakRunSourceDescendantIndex.js +5 -2
  114. package/dist/layout-bridge/convert/toFlowBlocks.js +102 -12
  115. package/dist/layout-engine/measure/tableCellFloating.d.ts +2 -0
  116. package/dist/layout-engine/measure/tableCellFloating.js +2 -0
  117. package/dist/layout-engine/types.d.ts +23 -1
  118. package/dist/layout-painter/renderImage.d.ts +5 -1
  119. package/dist/layout-painter/renderImage.js +10 -3
  120. package/dist/layout-painter/renderPage.d.ts +2 -0
  121. package/dist/layout-painter/renderPage.js +4 -0
  122. package/dist/layout-painter/renderParagraph.d.ts +13 -1
  123. package/dist/layout-painter/renderParagraph.js +22 -3
  124. package/dist/managers/autoSaveCodec.d.ts +9 -1
  125. package/dist/managers/autoSaveCodec.js +12 -4
  126. package/dist/markdown/renderBlock.js +1 -0
  127. package/dist/markdown/renderRuns.d.ts +1 -1
  128. package/dist/markdown/renderRuns.js +28 -5
  129. package/dist/markdown/renderTable.js +22 -5
  130. package/dist/markdown/trailers.js +4 -1
  131. package/dist/pdf/images.js +142 -6
  132. package/dist/prosemirror/attrs/index.d.ts +14 -3
  133. package/dist/prosemirror/attrs/index.js +155 -2
  134. package/dist/prosemirror/authoredTransformAttrs.d.ts +28 -0
  135. package/dist/prosemirror/authoredTransformAttrs.js +64 -0
  136. package/dist/prosemirror/commands/contentControls.js +10 -2
  137. package/dist/prosemirror/commands/image.d.ts +9 -2
  138. package/dist/prosemirror/commands/image.js +42 -28
  139. package/dist/prosemirror/commands/pageBreak.js +1 -1
  140. package/dist/prosemirror/commentReferenceAttrs.d.ts +8 -0
  141. package/dist/prosemirror/commentReferenceAttrs.js +33 -0
  142. package/dist/prosemirror/commentReferenceIntegrity.d.ts +47 -0
  143. package/dist/prosemirror/commentReferenceIntegrity.js +43 -0
  144. package/dist/prosemirror/conversion/fromProseDoc.d.ts +2 -13
  145. package/dist/prosemirror/conversion/fromProseDoc.js +269 -70
  146. package/dist/prosemirror/conversion/index.d.ts +2 -2
  147. package/dist/prosemirror/conversion/toProseDoc.d.ts +7 -9
  148. package/dist/prosemirror/conversion/toProseDoc.js +468 -308
  149. package/dist/prosemirror/extensions/StarterKit.js +8 -58
  150. package/dist/prosemirror/extensions/core/DocExtension.js +1 -1
  151. package/dist/prosemirror/extensions/core/ParagraphExtension.js +2 -1
  152. package/dist/prosemirror/extensions/features/BaseKeymapExtension.js +45 -27
  153. package/dist/prosemirror/extensions/features/EmptyParagraphFormatExtension.js +3 -1
  154. package/dist/prosemirror/extensions/features/ImagePasteExtension.js +5 -3
  155. package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.js +1 -0
  156. package/dist/prosemirror/extensions/markRegistry.d.ts +41 -0
  157. package/dist/prosemirror/extensions/markRegistry.js +75 -0
  158. package/dist/prosemirror/extensions/marks/InlineWrapperExtension.d.ts +18 -0
  159. package/dist/prosemirror/extensions/marks/InlineWrapperExtension.js +63 -0
  160. package/dist/prosemirror/extensions/marks/markUtils.d.ts +2 -1
  161. package/dist/prosemirror/extensions/marks/markUtils.js +47 -4
  162. package/dist/prosemirror/extensions/nodes/CommentReferenceExtension.d.ts +11 -0
  163. package/dist/prosemirror/extensions/nodes/CommentReferenceExtension.js +87 -0
  164. package/dist/prosemirror/extensions/nodes/FieldExtension.js +9 -7
  165. package/dist/prosemirror/extensions/nodes/ImageExtension.js +16 -0
  166. package/dist/prosemirror/extensions/nodes/PreservedBlockExtension.d.ts +32 -0
  167. package/dist/prosemirror/extensions/nodes/PreservedBlockExtension.js +67 -0
  168. package/dist/prosemirror/extensions/nodes/PreservedXmlExtension.d.ts +16 -0
  169. package/dist/prosemirror/extensions/nodes/PreservedXmlExtension.js +60 -0
  170. package/dist/prosemirror/extensions/nodes/ShapeExtension.js +3 -0
  171. package/dist/prosemirror/extensions/nodes/TableExtension.js +3 -2
  172. package/dist/prosemirror/extensions/nodes/TextBoxExtension.js +5 -1
  173. package/dist/prosemirror/inlineWrapperStack.d.ts +39 -0
  174. package/dist/prosemirror/inlineWrapperStack.js +75 -0
  175. package/dist/prosemirror/pageBreakRunProjection.d.ts +17 -7
  176. package/dist/prosemirror/pageBreakRunProjection.js +19 -9
  177. package/dist/prosemirror/replacedAnnotations.d.ts +59 -0
  178. package/dist/prosemirror/replacedAnnotations.js +165 -0
  179. package/dist/prosemirror/runFormattingInlineCarriers.d.ts +3 -1
  180. package/dist/prosemirror/runFormattingInlineCarriers.js +5 -1
  181. package/dist/prosemirror/schema/index.d.ts +3 -3
  182. package/dist/prosemirror/schema/marks.d.ts +25 -1
  183. package/dist/prosemirror/schema/nodes.d.ts +90 -3
  184. package/dist/prosemirror/schema/nodes.js +16 -1
  185. package/dist/prosemirror/trackedRunInlineAtoms.d.ts +2 -0
  186. package/dist/prosemirror/trackedRunInlineAtoms.js +2 -0
  187. package/dist/prosemirror/validation.js +16 -2
  188. package/dist/prosemirror/yjsDocumentMetadata.d.ts +73 -0
  189. package/dist/prosemirror/yjsDocumentMetadata.js +171 -0
  190. package/dist/prosemirror/zeroWidthAnchors.js +2 -0
  191. package/dist/render-dom/commentAnchorAttributes.d.ts +37 -0
  192. package/dist/render-dom/commentAnchorAttributes.js +54 -0
  193. package/dist/server.d.ts +3 -1
  194. package/dist/server.js +3 -1
  195. package/dist/types/content.d.ts +2 -2
  196. package/dist/utils/clipboard.d.ts +9 -1
  197. package/dist/utils/clipboard.js +27 -1
  198. package/dist/utils/findReplace.js +1 -1
  199. package/dist/utils/imageLuminance.d.ts +15 -0
  200. package/dist/utils/imageLuminance.js +32 -0
  201. package/dist/utils/mergeDocumentContent.js +7 -17
  202. package/dist/utils/replaceText.js +1 -0
  203. package/package.json +2 -2
  204. package/dist/docx/blockRangeMarkers.d.ts +0 -36
  205. package/dist/docx/blockRangeMarkers.js +0 -59
  206. package/dist/prosemirror/yjsParagraphSourceContract.d.ts +0 -9
  207. package/dist/prosemirror/yjsParagraphSourceContract.js +0 -26
@@ -10,6 +10,7 @@ import { directParagraphIndentation, paragraphIndentationAttrPatch, paragraphInd
10
10
  import { directParagraphSpacing, paragraphSpacingAttrPatch, paragraphSpacingEqual, paragraphSpacingFromFormatting, withDirectParagraphSpacing } from "../prosemirror/paragraphSpacing.js";
11
11
  import { getDocumentNumbering } from "../prosemirror/plugins/documentNumbering.js";
12
12
  import { getDocumentStyleResolver } from "../prosemirror/plugins/documentStyles.js";
13
+ import { addCarriedMarks, annotatedReplacement, hasReplacedAnnotations, inheritedReplacementMarks, surveyReplacedAnnotations } from "../prosemirror/replacedAnnotations.js";
13
14
  import { applyMarksToRunFormattingRepresentation, runFormattingInlineControlNodeName, selectRunFormattingCarrierRepresentations } from "../prosemirror/runFormattingInlineCarriers.js";
14
15
  import { readAuthoredRunFormatting, reconcileRunFormattingMarks } from "../prosemirror/runFormattingReconciliation.js";
15
16
  import { paragraphRunStyleContext, paragraphRunStyleContextAt } from "../prosemirror/runStyleFormatting.js";
@@ -949,6 +950,14 @@ const buildEmphasisInlineContent = (schema, text, baseMarks) => {
949
950
  }
950
951
  return nodes.length > 0 ? nodes : [schema.text(text, [...baseMarks])];
951
952
  };
953
+ /**
954
+ * Inline content for a block the applier rebuilds whole, carrying over the
955
+ * annotations the block's old content held (see `replacedAnnotations`).
956
+ */
957
+ const rebuiltBlockContent = ({ doc, blockFrom, blockTo, content }) => annotatedReplacement({
958
+ annotations: surveyReplacedAnnotations(doc, blockFrom + 1, blockTo - 1),
959
+ content: Fragment.fromArray([...content])
960
+ }).fragment;
952
961
  const isBatchableParagraphInsertion = (item, mode) => {
953
962
  if (item.operation.type !== "insertAfterBlock" && item.operation.type !== "insertBeforeBlock") return false;
954
963
  if (item.commentText !== void 0) return false;
@@ -1608,7 +1617,12 @@ const applyFolioAIEditOperationsInternal = ({ view, snapshot, operations, mode =
1608
1617
  const replacement = item.operation.text;
1609
1618
  const paragraphType = view.state.schema.nodes["paragraph"];
1610
1619
  if (paragraphType) {
1611
- const node = paragraphType.create(null, replacement.length === 0 ? null : buildEmphasisInlineContent(view.state.schema, replacement, commentMark ? [commentMark] : []));
1620
+ const node = paragraphType.create(null, rebuiltBlockContent({
1621
+ doc: tr.doc,
1622
+ blockFrom: item.blockFrom,
1623
+ blockTo: item.blockTo,
1624
+ content: replacement.length === 0 ? [] : buildEmphasisInlineContent(view.state.schema, replacement, commentMark ? [commentMark] : [])
1625
+ }));
1612
1626
  tr = tr.replaceWith(item.blockFrom, item.blockTo, node);
1613
1627
  tr = applyReplaceBlockStyleId({
1614
1628
  item,
@@ -1619,7 +1633,12 @@ const applyFolioAIEditOperationsInternal = ({ view, snapshot, operations, mode =
1619
1633
  }
1620
1634
  }
1621
1635
  if (mode === "direct" && hasInlineEmphasis(item.operation.text)) {
1622
- const node = item.blockNode.type.create({ ...item.blockNode.attrs }, buildEmphasisInlineContent(view.state.schema, item.operation.text, commentMark ? [commentMark] : []));
1636
+ const node = item.blockNode.type.create({ ...item.blockNode.attrs }, rebuiltBlockContent({
1637
+ doc: tr.doc,
1638
+ blockFrom: item.blockFrom,
1639
+ blockTo: item.blockTo,
1640
+ content: buildEmphasisInlineContent(view.state.schema, item.operation.text, commentMark ? [commentMark] : [])
1641
+ }));
1623
1642
  tr = tr.replaceWith(item.blockFrom, item.blockTo, node);
1624
1643
  tr = applyReplaceBlockStyleId({
1625
1644
  item,
@@ -2342,18 +2361,28 @@ const cleanTextInlineNodes = ({ schema, text, marks = [] }) => {
2342
2361
  if (trailing.length > 0) nodes.push(schema.text(trailing, marks));
2343
2362
  return nodes;
2344
2363
  };
2345
- const insertCleanText = ({ tr, from, to, text }) => {
2346
- if (!hasCleanTextControls(text)) return {
2364
+ const insertCleanText = ({ tr, from, to, text, standsInFor }) => {
2365
+ const annotations = surveyReplacedAnnotations(tr.doc, from, to);
2366
+ const replaced = standsInFor ? surveyReplacedAnnotations(tr.doc, standsInFor.from, standsInFor.to).carried : [];
2367
+ if (!hasReplacedAnnotations(annotations) && replaced.length === 0 && !hasCleanTextControls(text)) return {
2347
2368
  transaction: tr.insertText(text, from, to),
2369
+ start: from,
2348
2370
  end: from + text.length
2349
2371
  };
2350
- const content = Fragment.fromArray(cleanTextInlineNodes({
2351
- schema: tr.doc.type.schema,
2352
- text
2353
- }));
2372
+ const schema = tr.doc.type.schema;
2373
+ const { fragment, leadingSize, contentSize } = annotatedReplacement({
2374
+ annotations,
2375
+ content: Fragment.fromArray(cleanTextInlineNodes({
2376
+ schema,
2377
+ text,
2378
+ marks: addCarriedMarks(inheritedReplacementMarks(tr.doc, from, to), replaced)
2379
+ }))
2380
+ });
2381
+ const start = from + leadingSize;
2354
2382
  return {
2355
- transaction: tr.replaceWith(from, to, content),
2356
- end: from + content.size
2383
+ transaction: tr.replaceWith(from, to, fragment),
2384
+ start,
2385
+ end: start + contentSize
2357
2386
  };
2358
2387
  };
2359
2388
  const applyTextReplacement = ({ tr, item, mode, author, date, revisionIdDelete, revisionIdInsert, commentMark, suggestionId = null, initials, diffText }) => {
@@ -2365,8 +2394,11 @@ const applyTextReplacement = ({ tr, item, mode, author, date, revisionIdDelete,
2365
2394
  })());
2366
2395
  if (mode === "direct") {
2367
2396
  if ((item.operation.type === "replaceInBlock" || item.operation.type === "replaceRange") && hasInlineEmphasis(item.operation.replace)) {
2368
- const content = buildEmphasisInlineContent(nextTr.doc.type.schema, item.operation.replace, commentMark ? [commentMark] : []);
2369
- return nextTr.replaceWith(item.from, item.to, content);
2397
+ const { fragment } = annotatedReplacement({
2398
+ annotations: surveyReplacedAnnotations(nextTr.doc, item.from, item.to),
2399
+ content: Fragment.fromArray(buildEmphasisInlineContent(nextTr.doc.type.schema, item.operation.replace, commentMark ? [commentMark] : []))
2400
+ });
2401
+ return nextTr.replaceWith(item.from, item.to, fragment);
2370
2402
  }
2371
2403
  const inserted = insertCleanText({
2372
2404
  tr: nextTr,
@@ -2375,7 +2407,7 @@ const applyTextReplacement = ({ tr, item, mode, author, date, revisionIdDelete,
2375
2407
  text: replacement
2376
2408
  });
2377
2409
  nextTr = inserted.transaction;
2378
- if (commentMark && replacement.length > 0) nextTr = nextTr.addMark(item.from, inserted.end, commentMark);
2410
+ if (commentMark && replacement.length > 0) nextTr = nextTr.addMark(inserted.start, inserted.end, commentMark);
2379
2411
  return nextTr;
2380
2412
  }
2381
2413
  const insertionType = nextTr.doc.type.schema.marks["insertion"];
@@ -2465,11 +2497,15 @@ const applyTextReplacement = ({ tr, item, mode, author, date, revisionIdDelete,
2465
2497
  tr: nextTr,
2466
2498
  from: step.at,
2467
2499
  to: step.at,
2468
- text: step.text
2500
+ text: step.text,
2501
+ standsInFor: {
2502
+ from: item.from,
2503
+ to: item.to
2504
+ }
2469
2505
  });
2470
2506
  nextTr = inserted.transaction;
2471
- nextTr = nextTr.addMark(step.at, inserted.end, insertionType.create(insAttrs));
2472
- if (commentMark) nextTr = nextTr.addMark(step.at, inserted.end, commentMark);
2507
+ nextTr = nextTr.addMark(inserted.start, inserted.end, insertionType.create(insAttrs));
2508
+ if (commentMark) nextTr = nextTr.addMark(inserted.start, inserted.end, commentMark);
2473
2509
  }
2474
2510
  }
2475
2511
  return nextTr;
@@ -2480,11 +2516,15 @@ const applyTextReplacement = ({ tr, item, mode, author, date, revisionIdDelete,
2480
2516
  tr: nextTr,
2481
2517
  from: item.to,
2482
2518
  to: item.to,
2483
- text: replacement
2519
+ text: replacement,
2520
+ standsInFor: {
2521
+ from: item.from,
2522
+ to: item.to
2523
+ }
2484
2524
  });
2485
2525
  nextTr = inserted.transaction;
2486
- nextTr = nextTr.addMark(item.to, inserted.end, insertionType.create(insAttrs));
2487
- if (commentMark) nextTr = nextTr.addMark(item.to, inserted.end, commentMark);
2526
+ nextTr = nextTr.addMark(inserted.start, inserted.end, insertionType.create(insAttrs));
2527
+ if (commentMark) nextTr = nextTr.addMark(inserted.start, inserted.end, commentMark);
2488
2528
  }
2489
2529
  if (item.to > item.from && deletionType) {
2490
2530
  nextTr = nextTr.addMark(item.from, item.to, deletionType.create(delAttrs));
@@ -1544,7 +1544,7 @@ var FolioDocxReviewer = class FolioDocxReviewer {
1544
1544
  * same states, so the text now describes exactly what a save would write.
1545
1545
  */
1546
1546
  storyBlocks(state, source) {
1547
- return state ? proseDocToBlocks(state.doc, source.content, this.baseDocument.package.styles, { emptyFieldResult: "authored" }) : source.content;
1547
+ return state ? proseDocToBlocks(state.doc, source.content, this.baseDocument.package.styles) : source.content;
1548
1548
  }
1549
1549
  getHeaderFooterStoryText(story, source) {
1550
1550
  const state = this.secondaryStoryStates.get(headerFooterStoryKey(story))?.state;
@@ -15,7 +15,7 @@ import { sameAuthoredInlineProvenance } from "./inline-provenance.js";
15
15
  import { planStoryCompare } from "./plan.js";
16
16
  import { withFixedPackageDates } from "./reproducible-package.js";
17
17
  import { compareSectionBoundaryProperties } from "./section-boundary-properties.js";
18
- import { CompareDocxApplyError, CompareDocxFinalParagraphMarkError, CompareDocxOperationLimitError, CompareDocxParseError, CompareDocxRoundTripError, CompareDocxSerializeError, InvalidCompareDocxOptionsError } from "./types.js";
18
+ import { CompareDocxApplyError, CompareDocxFinalParagraphMarkError, CompareDocxOperationLimitError, CompareDocxParseError, CompareDocxRoundTripError, InvalidCompareDocxOptionsError, compareDocxSerializeError } from "./types.js";
19
19
  import { classifyGeometryMismatch, classifyProjectionMismatch, revisedFinalParagraphMarks } from "./verification.js";
20
20
  import { Result, panic } from "better-result";
21
21
  //#region src/compare/compare.ts
@@ -903,10 +903,7 @@ const serializeComparison = async ({ baseBuffer, baseCarriedRevisions, reviewer,
903
903
  }));
904
904
  return await Result.tryPromise({
905
905
  try: async () => await withFixedPackageDates(await reviewer.toBuffer(), packageDate),
906
- catch: (cause) => new CompareDocxSerializeError({
907
- message: "The compared document could not be serialized.",
908
- cause
909
- })
906
+ catch: (cause) => compareDocxSerializeError("The compared document could not be serialized", cause)
910
907
  });
911
908
  };
912
909
  /**
@@ -1,6 +1,6 @@
1
1
  import { FolioDocxReviewer } from "../ai-edits/headless.js";
2
2
  import { createFolioAITextRangeHandle } from "../ai-edits/snapshot.js";
3
- import { CompareDocxParseError, CompareDocxSerializeError } from "./types.js";
3
+ import { CompareDocxParseError, compareDocxSerializeError } from "./types.js";
4
4
  import { Result, panic } from "better-result";
5
5
  //#region src/compare/scenario.ts
6
6
  /**
@@ -252,10 +252,7 @@ const applyEditScript = async (base, script) => {
252
252
  }
253
253
  const serialized = await Result.tryPromise({
254
254
  try: async () => await reviewer.toBuffer(),
255
- catch: (cause) => new CompareDocxSerializeError({
256
- message: "The edit script's target document could not be serialized.",
257
- cause
258
- })
255
+ catch: (cause) => compareDocxSerializeError("The edit script's target document could not be serialized", cause)
259
256
  });
260
257
  return serialized.isErr() ? Result.err(serialized.error) : Result.ok({
261
258
  buffer: serialized.value,
@@ -316,6 +316,14 @@ declare class CompareDocxSerializeError extends CompareDocxSerializeError_base<{
316
316
  message: string;
317
317
  cause: unknown;
318
318
  }> {}
319
+ /**
320
+ * A serialize failure whose message names the reason.
321
+ *
322
+ * `cause` is structured context a caller can branch on, but a log line, a
323
+ * report and the corpus census read the message, and a constant one collapses
324
+ * every distinct save failure into a single undiagnosable row.
325
+ */
326
+ declare const compareDocxSerializeError: (context: string, cause: unknown) => CompareDocxSerializeError;
319
327
  declare const CompareDocxFinalParagraphMarkError_base: import("better-result").TaggedErrorClass<"CompareDocxFinalParagraphMarkError">;
320
328
  /**
321
329
  * A container's final paragraph mark carries a revision, so the package would
@@ -335,4 +343,4 @@ declare class CompareDocxFinalParagraphMarkError extends CompareDocxFinalParagra
335
343
  }> {}
336
344
  type CompareDocxError = CompareDocxApplyError | CompareDocxFinalParagraphMarkError | CompareDocxOperationLimitError | CompareDocxParseError | CompareDocxRoundTripError | CompareDocxSerializeError | InvalidCompareDocxOptionsError;
337
345
  //#endregion
338
- export { COMPARE_REVISION_FORMATS, COMPARE_UNSUPPORTED_REASONS, CompareChange, CompareChangeLocation, CompareCompatibility, CompareDocxApplyError, CompareDocxError, CompareDocxFinalParagraphMarkError, CompareDocxOperationLimitError, CompareDocxOptions, CompareDocxParseError, CompareDocxRoundTripError, CompareDocxSerializeError, CompareFolioRequirement, CompareResult, CompareRevisionFormat, CompareUnsupportedPart, CompareUnsupportedReason, InvalidCompareDocxOptionsError };
346
+ export { COMPARE_REVISION_FORMATS, COMPARE_UNSUPPORTED_REASONS, CompareChange, CompareChangeLocation, CompareCompatibility, CompareDocxApplyError, CompareDocxError, CompareDocxFinalParagraphMarkError, CompareDocxOperationLimitError, CompareDocxOptions, CompareDocxParseError, CompareDocxRoundTripError, CompareDocxSerializeError, CompareFolioRequirement, CompareResult, CompareRevisionFormat, CompareUnsupportedPart, CompareUnsupportedReason, InvalidCompareDocxOptionsError, compareDocxSerializeError };
@@ -31,6 +31,17 @@ var CompareDocxRoundTripError = class extends TaggedError("CompareDocxRoundTripE
31
31
  var CompareDocxOperationLimitError = class extends TaggedError("CompareDocxOperationLimitError") {};
32
32
  var CompareDocxSerializeError = class extends TaggedError("CompareDocxSerializeError") {};
33
33
  /**
34
+ * A serialize failure whose message names the reason.
35
+ *
36
+ * `cause` is structured context a caller can branch on, but a log line, a
37
+ * report and the corpus census read the message, and a constant one collapses
38
+ * every distinct save failure into a single undiagnosable row.
39
+ */
40
+ const compareDocxSerializeError = (context, cause) => new CompareDocxSerializeError({
41
+ message: `${context}: ${cause instanceof Error ? cause.message : String(cause)}`,
42
+ cause
43
+ });
44
+ /**
34
45
  * A container's final paragraph mark carries a revision, so the package would
35
46
  * not open, or would open carrying one no reader can resolve.
36
47
  *
@@ -43,4 +54,4 @@ var CompareDocxSerializeError = class extends TaggedError("CompareDocxSerializeE
43
54
  */
44
55
  var CompareDocxFinalParagraphMarkError = class extends TaggedError("CompareDocxFinalParagraphMarkError") {};
45
56
  //#endregion
46
- export { COMPARE_REVISION_FORMATS, COMPARE_UNSUPPORTED_REASONS, CompareDocxApplyError, CompareDocxFinalParagraphMarkError, CompareDocxOperationLimitError, CompareDocxParseError, CompareDocxRoundTripError, CompareDocxSerializeError, InvalidCompareDocxOptionsError };
57
+ export { COMPARE_REVISION_FORMATS, COMPARE_UNSUPPORTED_REASONS, CompareDocxApplyError, CompareDocxFinalParagraphMarkError, CompareDocxOperationLimitError, CompareDocxParseError, CompareDocxRoundTripError, CompareDocxSerializeError, InvalidCompareDocxOptionsError, compareDocxSerializeError };
@@ -37,7 +37,8 @@ import { fromMarkdown } from "../markdown/fromMarkdown.js";
37
37
  import { toMarkdown, toMarkdownResult } from "../markdown/index.js";
38
38
  import { EmbeddedFont, EmbeddedFontParts, buildEmbeddedFontFamilyMap, extractEmbeddedFonts, getEmbeddedFontFaces, scopeEmbeddedFontFamily } from "../fonts/embeddedFonts.js";
39
39
  import { getGoogleFontsEnabled, setEmbeddedFontFamilyMap, setGoogleFontsEnabled } from "../utils/fontResolver.js";
40
+ import { FOLIO_YJS_ATTR_SCHEMA_VERSION, FolioYjsAttrSchemaVersion, FolioYjsAttrSchemaVersionError } from "../prosemirror/yjsDocumentMetadata.js";
40
41
  import { DOCX_CONFORMANCE_CLASSES } from "../index.js";
41
42
  type Document = document_d_exports.Document;
42
43
  type DocxConformanceClass = document_d_exports.DocxConformanceClass;
43
- export { type AIBarStatus, type AIChatMode, type AICitation, type AICitationRange, type AICitationSource, type AIGenerateInput, type AISuggestion, type AISuggestionApplyMode, type AISuggestionPreset, type AISuggestionSeverity, type AISuggestionStatus, type AcceptAutocompleteResult, type AnonymizationMatch, type AnonymizationTerm, type ApplyFolioDocumentOperationsOptions, type ApplyResult, type AutocompleteSuggestionPluginOptions, type AutocompleteSuggestionState, type AutocompleteSuggestionStatus, type AutocompleteTriggerCheck, type AutocompleteTriggerOptions, type AutocompleteTriggerSkipReason, type BlockRect, COMPARE_REVISION_FORMATS, COMPARE_UNSUPPORTED_REASONS, COMPARE_VERIFICATION_CAUSES, COMPARE_VERIFICATION_INVARIANTS, type CompareChange, type CompareChangeLocation, type CompareCompatibility, type CompareContentOptions, CompareDocxApplyError, type CompareDocxError, CompareDocxFinalParagraphMarkError, CompareDocxOperationLimitError, type CompareDocxOptions, CompareDocxParseError, CompareDocxRoundTripError, CompareDocxSerializeError, type CompareFolioRequirement, type CompareResult, type CompareRevisionFormat, type CompareUnsupportedPart, type CompareUnsupportedReason, type CompareVerification, type CompareVerificationCause, type CompareVerificationFailure, type CompareVerificationInvariant, type CreateEmptyDocumentOptions, DEFAULT_AI_SUGGESTION_PRESETS, DEFAULT_AUTOCOMPLETE_DEAD_ZONE_NODES, DOCUMENT_PRESET_VERSION, DOCUMENT_STYLE_SET_VERSION, DOCX_CONFORMANCE_CLASSES, DRAWING_SAFETY_CLASSES, type DeriveBlockIdInput, type DirectiveKind, type DirectiveRange, type Document, type DocumentPreset, type DocumentPropertiesOptions, type DocumentStyleCatalog, type DocumentStyleCatalogEntry, type DocumentStyleSet, type DocxCompatibility, type DocxCompatibilityContext, type DocxCompatibilityIssue, type DocxCompatibilityLocation, type DocxCompatibilityPart, type DocxConformanceClass, type DocxDrawingClassification, type DrawingSafetyClass, type EmbeddedFont, type EmbeddedFontParts, type ExtractDocumentStyleSetOptions, FOLIO_CONTENT_COMPARISON_LIMITS, FOLIO_DOCUMENT_OPERATION_BATCH_MODES, FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION, FOLIO_DOCUMENT_OPERATION_MODES, FOLIO_DOCUMENT_OPERATION_MODES_BY_TYPE, FOLIO_DOCUMENT_OPERATION_PRECONDITIONS, FOLIO_DOCUMENT_OPERATION_STORIES, FOLIO_DOCUMENT_OPERATION_TYPES, FOLIO_LINE_SPACING_RULE_VALUES, FOLIO_PARAGRAPH_ALIGNMENT_VALUES, type FinalParagraphMarkRevision, type FolioAIBlock, type FolioAIBlockAnchor, type FolioAIBlockKind, type FolioAIBlockPreviewRun, type FolioAIBlockStructuralBoundary, type FolioAIBlockTableLocation, type FolioAIComment, type FolioAIEditAppliedOperation, type FolioAIEditApplyMode, type FolioAIEditApplyOutcome, type FolioAIEditApplyResult, type FolioAIEditNormalization, type FolioAIEditNormalizationCode, type FolioAIEditOperation, type FolioAIEditPrecondition, type FolioAIEditReviewMeta, type FolioAIEditSeverity, type FolioAIEditSkipReason, type FolioAIEditSkippedOperation, type FolioAIEditSnapshot, type FolioAIInlineBooleanProperty, type FolioAIInlineFormatting, type FolioAIInlineFormattingPatch, type FolioAIParagraphSpacing, type FolioAISignatureParty, type FolioBlockId, type FolioContentBlock, type FolioContentBlockProperty, type FolioContentComparison, type FolioContentComparisonError, type FolioContentComparisonEvent, type FolioContentComparisonLimit, FolioContentComparisonLimitError, type FolioContentContainerPathEntry, type FolioContentFormatRange, type FolioContentFormattingChange, type FolioContentIdStability, type FolioContentInlineBooleanProperty, type FolioContentInlineComparisonResult, type FolioContentInlineFormatting, type FolioContentInlineFormattingPatch, FolioContentInlinePresentationProjectionError, type FolioContentLineSpacingRule, type FolioContentParagraphAlignment, type FolioContentParagraphFormattingPatch, type FolioContentParagraphKind, type FolioContentParagraphSpacing, type FolioContentRun, type FolioContentSnapshot, type FolioContentStructuralChange, type FolioContentTableLocation, type FolioContentTextSegment, type FolioDocumentOperation, type FolioDocumentOperationAffectedTarget, type FolioDocumentOperationBatch, type FolioDocumentOperationCapabilities, type FolioDocumentOperationIssue, type FolioDocumentOperationMode, type FolioDocumentOperationPrecondition, type FolioDocumentOperationReceipt, type FolioDocumentOperationRecovery, type FolioDocumentOperationResult, type FolioDocumentOperationResultBase, type FolioDocumentOperationStatus, type FolioDocumentOperationStory, type FolioDocumentOperationType, type FolioDocumentOperationUndoFailureReason, type FolioDocumentOperationUndoHandle, type FolioDocumentOperationUndoResult, type FolioDocxCompatibilityHost, type FolioDocxCompatibilityProfile, type FolioRevisionStamp, type FolioWordDiffOptions, type ImageMeta, type ImageRef, type InspectDocxCompatibilityOptions, InvalidCompareDocxOptionsError, InvalidFolioContentComparisonError, InvalidFolioDocumentOperationBatchError, MAX_COMPARE_OPERATIONS, type MarkdownOptions, type MarkdownResult, type PositionalText, type ResolvedAnchor, STELLA_STYLE_SET_NAME, type TemplatePreviewHiddenRange, type TemplatePreviewSpan, type TemplatePreviewValue, type TemplatePreviewValues, type TemplateSlashMenuKeyAction, type TemplateSlashMenuState, UnsupportedFolioDocumentOperationVersionError, WORD_DIFF_GRANULARITIES, type WordDiffGranularity, type WordDiffNormalization, type WordDiffOptions, type WordDiffSegment, acceptAutocompleteSuggestion, acceptAutocompleteWord, anonymizationDecorationsKey, appendAutocompleteToken, applyFolioAIEditOperations, applyFolioDocumentOperations, applySuggestions, assertSupportedFolioDocumentOperationVersion, autocompleteSuggestionKey, autocompleteSuggestionPlugin, buildEmbeddedFontFamilyMap, buildPositionalText, clearAutocompleteSuggestion, clearTemplateSlashMenu, compareContent, compareDocx, consumeTemplateSlashQuery, createAICitationDecorationsPlugin, createDocx, createEmptyDocument, createFolioAIEditSnapshot, createStellaStyleDocumentPreset, createStellaStyleSet, currentFolioBlockId, deriveBlockId, diffWordSegments, extractDocumentStyleSet, extractDocumentStyleSetFromDocx, extractEmbeddedFonts, finishAutocompleteSuggestion, fromMarkdown, getAnonymizationMatches, getAutocompleteSuggestion, getEmbeddedFontFaces, getFolioCaretViewportRect, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, getFolioParaIdFromBlockId, getFolioSelectionViewportRect, getGoogleFontsEnabled, getTemplateDirectives, getTemplateSlashMenu, hashFolioAIBlockText, inspectDocumentStyles, inspectDocumentStylesFromDocx, inspectDocxCompatibility, isFolioAIContentBlock, isFolioBlockId, isFolioDocumentOperationModeSupported, isSequentialFolioBlockId, isSuggestionStale, isSupportedFolioDocumentOperationVersion, mergeDocumentContent, normalizeFolioAIBlockText, parseFolioDocumentOperationBatch, resetTemplateSlashQuery, resolveSuggestionAnchor, scanDirectives, scopeEmbeddedFontFamily, scrollFolioPositionIntoView, setAICitationsMeta, setAISuggestionsMeta, setActiveCitationMeta, setAnonymizationTermsMeta, setEmbeddedFontFamilyMap, setFocusedSuggestionMeta, setGoogleFontsEnabled, setTemplatePreviewValues, shouldTriggerAutocomplete, startAutocompleteSuggestion, templateSlashMenuKey, toMarkdown, toMarkdownResult };
44
+ export { type AIBarStatus, type AIChatMode, type AICitation, type AICitationRange, type AICitationSource, type AIGenerateInput, type AISuggestion, type AISuggestionApplyMode, type AISuggestionPreset, type AISuggestionSeverity, type AISuggestionStatus, type AcceptAutocompleteResult, type AnonymizationMatch, type AnonymizationTerm, type ApplyFolioDocumentOperationsOptions, type ApplyResult, type AutocompleteSuggestionPluginOptions, type AutocompleteSuggestionState, type AutocompleteSuggestionStatus, type AutocompleteTriggerCheck, type AutocompleteTriggerOptions, type AutocompleteTriggerSkipReason, type BlockRect, COMPARE_REVISION_FORMATS, COMPARE_UNSUPPORTED_REASONS, COMPARE_VERIFICATION_CAUSES, COMPARE_VERIFICATION_INVARIANTS, type CompareChange, type CompareChangeLocation, type CompareCompatibility, type CompareContentOptions, CompareDocxApplyError, type CompareDocxError, CompareDocxFinalParagraphMarkError, CompareDocxOperationLimitError, type CompareDocxOptions, CompareDocxParseError, CompareDocxRoundTripError, CompareDocxSerializeError, type CompareFolioRequirement, type CompareResult, type CompareRevisionFormat, type CompareUnsupportedPart, type CompareUnsupportedReason, type CompareVerification, type CompareVerificationCause, type CompareVerificationFailure, type CompareVerificationInvariant, type CreateEmptyDocumentOptions, DEFAULT_AI_SUGGESTION_PRESETS, DEFAULT_AUTOCOMPLETE_DEAD_ZONE_NODES, DOCUMENT_PRESET_VERSION, DOCUMENT_STYLE_SET_VERSION, DOCX_CONFORMANCE_CLASSES, DRAWING_SAFETY_CLASSES, type DeriveBlockIdInput, type DirectiveKind, type DirectiveRange, type Document, type DocumentPreset, type DocumentPropertiesOptions, type DocumentStyleCatalog, type DocumentStyleCatalogEntry, type DocumentStyleSet, type DocxCompatibility, type DocxCompatibilityContext, type DocxCompatibilityIssue, type DocxCompatibilityLocation, type DocxCompatibilityPart, type DocxConformanceClass, type DocxDrawingClassification, type DrawingSafetyClass, type EmbeddedFont, type EmbeddedFontParts, type ExtractDocumentStyleSetOptions, FOLIO_CONTENT_COMPARISON_LIMITS, FOLIO_DOCUMENT_OPERATION_BATCH_MODES, FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION, FOLIO_DOCUMENT_OPERATION_MODES, FOLIO_DOCUMENT_OPERATION_MODES_BY_TYPE, FOLIO_DOCUMENT_OPERATION_PRECONDITIONS, FOLIO_DOCUMENT_OPERATION_STORIES, FOLIO_DOCUMENT_OPERATION_TYPES, FOLIO_LINE_SPACING_RULE_VALUES, FOLIO_PARAGRAPH_ALIGNMENT_VALUES, FOLIO_YJS_ATTR_SCHEMA_VERSION, type FinalParagraphMarkRevision, type FolioAIBlock, type FolioAIBlockAnchor, type FolioAIBlockKind, type FolioAIBlockPreviewRun, type FolioAIBlockStructuralBoundary, type FolioAIBlockTableLocation, type FolioAIComment, type FolioAIEditAppliedOperation, type FolioAIEditApplyMode, type FolioAIEditApplyOutcome, type FolioAIEditApplyResult, type FolioAIEditNormalization, type FolioAIEditNormalizationCode, type FolioAIEditOperation, type FolioAIEditPrecondition, type FolioAIEditReviewMeta, type FolioAIEditSeverity, type FolioAIEditSkipReason, type FolioAIEditSkippedOperation, type FolioAIEditSnapshot, type FolioAIInlineBooleanProperty, type FolioAIInlineFormatting, type FolioAIInlineFormattingPatch, type FolioAIParagraphSpacing, type FolioAISignatureParty, type FolioBlockId, type FolioContentBlock, type FolioContentBlockProperty, type FolioContentComparison, type FolioContentComparisonError, type FolioContentComparisonEvent, type FolioContentComparisonLimit, FolioContentComparisonLimitError, type FolioContentContainerPathEntry, type FolioContentFormatRange, type FolioContentFormattingChange, type FolioContentIdStability, type FolioContentInlineBooleanProperty, type FolioContentInlineComparisonResult, type FolioContentInlineFormatting, type FolioContentInlineFormattingPatch, FolioContentInlinePresentationProjectionError, type FolioContentLineSpacingRule, type FolioContentParagraphAlignment, type FolioContentParagraphFormattingPatch, type FolioContentParagraphKind, type FolioContentParagraphSpacing, type FolioContentRun, type FolioContentSnapshot, type FolioContentStructuralChange, type FolioContentTableLocation, type FolioContentTextSegment, type FolioDocumentOperation, type FolioDocumentOperationAffectedTarget, type FolioDocumentOperationBatch, type FolioDocumentOperationCapabilities, type FolioDocumentOperationIssue, type FolioDocumentOperationMode, type FolioDocumentOperationPrecondition, type FolioDocumentOperationReceipt, type FolioDocumentOperationRecovery, type FolioDocumentOperationResult, type FolioDocumentOperationResultBase, type FolioDocumentOperationStatus, type FolioDocumentOperationStory, type FolioDocumentOperationType, type FolioDocumentOperationUndoFailureReason, type FolioDocumentOperationUndoHandle, type FolioDocumentOperationUndoResult, type FolioDocxCompatibilityHost, type FolioDocxCompatibilityProfile, type FolioRevisionStamp, type FolioWordDiffOptions, type FolioYjsAttrSchemaVersion, FolioYjsAttrSchemaVersionError, type ImageMeta, type ImageRef, type InspectDocxCompatibilityOptions, InvalidCompareDocxOptionsError, InvalidFolioContentComparisonError, InvalidFolioDocumentOperationBatchError, MAX_COMPARE_OPERATIONS, type MarkdownOptions, type MarkdownResult, type PositionalText, type ResolvedAnchor, STELLA_STYLE_SET_NAME, type TemplatePreviewHiddenRange, type TemplatePreviewSpan, type TemplatePreviewValue, type TemplatePreviewValues, type TemplateSlashMenuKeyAction, type TemplateSlashMenuState, UnsupportedFolioDocumentOperationVersionError, WORD_DIFF_GRANULARITIES, type WordDiffGranularity, type WordDiffNormalization, type WordDiffOptions, type WordDiffSegment, acceptAutocompleteSuggestion, acceptAutocompleteWord, anonymizationDecorationsKey, appendAutocompleteToken, applyFolioAIEditOperations, applyFolioDocumentOperations, applySuggestions, assertSupportedFolioDocumentOperationVersion, autocompleteSuggestionKey, autocompleteSuggestionPlugin, buildEmbeddedFontFamilyMap, buildPositionalText, clearAutocompleteSuggestion, clearTemplateSlashMenu, compareContent, compareDocx, consumeTemplateSlashQuery, createAICitationDecorationsPlugin, createDocx, createEmptyDocument, createFolioAIEditSnapshot, createStellaStyleDocumentPreset, createStellaStyleSet, currentFolioBlockId, deriveBlockId, diffWordSegments, extractDocumentStyleSet, extractDocumentStyleSetFromDocx, extractEmbeddedFonts, finishAutocompleteSuggestion, fromMarkdown, getAnonymizationMatches, getAutocompleteSuggestion, getEmbeddedFontFaces, getFolioCaretViewportRect, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, getFolioParaIdFromBlockId, getFolioSelectionViewportRect, getGoogleFontsEnabled, getTemplateDirectives, getTemplateSlashMenu, hashFolioAIBlockText, inspectDocumentStyles, inspectDocumentStylesFromDocx, inspectDocxCompatibility, isFolioAIContentBlock, isFolioBlockId, isFolioDocumentOperationModeSupported, isSequentialFolioBlockId, isSuggestionStale, isSupportedFolioDocumentOperationVersion, mergeDocumentContent, normalizeFolioAIBlockText, parseFolioDocumentOperationBatch, resetTemplateSlashQuery, resolveSuggestionAnchor, scanDirectives, scopeEmbeddedFontFamily, scrollFolioPositionIntoView, setAICitationsMeta, setAISuggestionsMeta, setActiveCitationMeta, setAnonymizationTermsMeta, setEmbeddedFontFamilyMap, setFocusedSuggestionMeta, setGoogleFontsEnabled, setTemplatePreviewValues, shouldTriggerAutocomplete, startAutocompleteSuggestion, templateSlashMenuKey, toMarkdown, toMarkdownResult };
@@ -26,6 +26,7 @@ import { DEFAULT_AUTOCOMPLETE_DEAD_ZONE_NODES, acceptAutocompleteSuggestion, acc
26
26
  import { getTemplateDirectives, scanDirectives } from "../prosemirror/plugins/templateDirectives.js";
27
27
  import { setTemplatePreviewValues } from "../prosemirror/plugins/templatePreviewValues.js";
28
28
  import { clearTemplateSlashMenu, consumeTemplateSlashQuery, getTemplateSlashMenu, resetTemplateSlashQuery, templateSlashMenuKey } from "../prosemirror/plugins/templateSlashMenu.js";
29
+ import { FOLIO_YJS_ATTR_SCHEMA_VERSION, FolioYjsAttrSchemaVersionError } from "../prosemirror/yjsDocumentMetadata.js";
29
30
  import { extractDocumentStyleSet, extractDocumentStyleSetFromDocx, inspectDocumentStyles, inspectDocumentStylesFromDocx } from "../style-sets/extract.js";
30
31
  import { STELLA_STYLE_SET_NAME, createStellaStyleDocumentPreset, createStellaStyleSet } from "../style-sets/stellaStyle.js";
31
32
  import { DOCUMENT_PRESET_VERSION, DOCUMENT_STYLE_SET_VERSION } from "../style-sets/types.js";
@@ -33,4 +34,4 @@ import { currentFolioBlockId, deriveBlockId, getFolioParaIdFromBlockId, isFolioB
33
34
  import { createEmptyDocument } from "../utils/createDocument.js";
34
35
  import { getGoogleFontsEnabled, setEmbeddedFontFamilyMap, setGoogleFontsEnabled } from "../utils/fontResolver.js";
35
36
  import { mergeDocumentContent } from "../utils/mergeDocumentContent.js";
36
- export { COMPARE_REVISION_FORMATS, COMPARE_UNSUPPORTED_REASONS, COMPARE_VERIFICATION_CAUSES, COMPARE_VERIFICATION_INVARIANTS, CompareDocxApplyError, CompareDocxFinalParagraphMarkError, CompareDocxOperationLimitError, CompareDocxParseError, CompareDocxRoundTripError, CompareDocxSerializeError, DEFAULT_AI_SUGGESTION_PRESETS, DEFAULT_AUTOCOMPLETE_DEAD_ZONE_NODES, DOCUMENT_PRESET_VERSION, DOCUMENT_STYLE_SET_VERSION, DOCX_CONFORMANCE_CLASSES, DRAWING_SAFETY_CLASSES, FOLIO_CONTENT_COMPARISON_LIMITS, FOLIO_DOCUMENT_OPERATION_BATCH_MODES, FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION, FOLIO_DOCUMENT_OPERATION_MODES, FOLIO_DOCUMENT_OPERATION_MODES_BY_TYPE, FOLIO_DOCUMENT_OPERATION_PRECONDITIONS, FOLIO_DOCUMENT_OPERATION_STORIES, FOLIO_DOCUMENT_OPERATION_TYPES, FOLIO_LINE_SPACING_RULE_VALUES, FOLIO_PARAGRAPH_ALIGNMENT_VALUES, FolioContentComparisonLimitError, FolioContentInlinePresentationProjectionError, InvalidCompareDocxOptionsError, InvalidFolioContentComparisonError, InvalidFolioDocumentOperationBatchError, MAX_COMPARE_OPERATIONS, STELLA_STYLE_SET_NAME, UnsupportedFolioDocumentOperationVersionError, WORD_DIFF_GRANULARITIES, acceptAutocompleteSuggestion, acceptAutocompleteWord, anonymizationDecorationsKey, appendAutocompleteToken, applyFolioAIEditOperations, applyFolioDocumentOperations, applySuggestions, assertSupportedFolioDocumentOperationVersion, autocompleteSuggestionKey, autocompleteSuggestionPlugin, buildEmbeddedFontFamilyMap, buildPositionalText, clearAutocompleteSuggestion, clearTemplateSlashMenu, compareContent, compareDocx, consumeTemplateSlashQuery, createAICitationDecorationsPlugin, createDocx, createEmptyDocument, createFolioAIEditSnapshot, createStellaStyleDocumentPreset, createStellaStyleSet, currentFolioBlockId, deriveBlockId, diffWordSegments, extractDocumentStyleSet, extractDocumentStyleSetFromDocx, extractEmbeddedFonts, finishAutocompleteSuggestion, fromMarkdown, getAnonymizationMatches, getAutocompleteSuggestion, getEmbeddedFontFaces, getFolioCaretViewportRect, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, getFolioParaIdFromBlockId, getFolioSelectionViewportRect, getGoogleFontsEnabled, getTemplateDirectives, getTemplateSlashMenu, hashFolioAIBlockText, inspectDocumentStyles, inspectDocumentStylesFromDocx, inspectDocxCompatibility, isFolioAIContentBlock, isFolioBlockId, isFolioDocumentOperationModeSupported, isSequentialFolioBlockId, isSuggestionStale, isSupportedFolioDocumentOperationVersion, mergeDocumentContent, normalizeFolioAIBlockText, parseFolioDocumentOperationBatch, resetTemplateSlashQuery, resolveSuggestionAnchor, scanDirectives, scopeEmbeddedFontFamily, scrollFolioPositionIntoView, setAICitationsMeta, setAISuggestionsMeta, setActiveCitationMeta, setAnonymizationTermsMeta, setEmbeddedFontFamilyMap, setFocusedSuggestionMeta, setGoogleFontsEnabled, setTemplatePreviewValues, shouldTriggerAutocomplete, startAutocompleteSuggestion, templateSlashMenuKey, toMarkdown, toMarkdownResult };
37
+ export { COMPARE_REVISION_FORMATS, COMPARE_UNSUPPORTED_REASONS, COMPARE_VERIFICATION_CAUSES, COMPARE_VERIFICATION_INVARIANTS, CompareDocxApplyError, CompareDocxFinalParagraphMarkError, CompareDocxOperationLimitError, CompareDocxParseError, CompareDocxRoundTripError, CompareDocxSerializeError, DEFAULT_AI_SUGGESTION_PRESETS, DEFAULT_AUTOCOMPLETE_DEAD_ZONE_NODES, DOCUMENT_PRESET_VERSION, DOCUMENT_STYLE_SET_VERSION, DOCX_CONFORMANCE_CLASSES, DRAWING_SAFETY_CLASSES, FOLIO_CONTENT_COMPARISON_LIMITS, FOLIO_DOCUMENT_OPERATION_BATCH_MODES, FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION, FOLIO_DOCUMENT_OPERATION_MODES, FOLIO_DOCUMENT_OPERATION_MODES_BY_TYPE, FOLIO_DOCUMENT_OPERATION_PRECONDITIONS, FOLIO_DOCUMENT_OPERATION_STORIES, FOLIO_DOCUMENT_OPERATION_TYPES, FOLIO_LINE_SPACING_RULE_VALUES, FOLIO_PARAGRAPH_ALIGNMENT_VALUES, FOLIO_YJS_ATTR_SCHEMA_VERSION, FolioContentComparisonLimitError, FolioContentInlinePresentationProjectionError, FolioYjsAttrSchemaVersionError, InvalidCompareDocxOptionsError, InvalidFolioContentComparisonError, InvalidFolioDocumentOperationBatchError, MAX_COMPARE_OPERATIONS, STELLA_STYLE_SET_NAME, UnsupportedFolioDocumentOperationVersionError, WORD_DIFF_GRANULARITIES, acceptAutocompleteSuggestion, acceptAutocompleteWord, anonymizationDecorationsKey, appendAutocompleteToken, applyFolioAIEditOperations, applyFolioDocumentOperations, applySuggestions, assertSupportedFolioDocumentOperationVersion, autocompleteSuggestionKey, autocompleteSuggestionPlugin, buildEmbeddedFontFamilyMap, buildPositionalText, clearAutocompleteSuggestion, clearTemplateSlashMenu, compareContent, compareDocx, consumeTemplateSlashQuery, createAICitationDecorationsPlugin, createDocx, createEmptyDocument, createFolioAIEditSnapshot, createStellaStyleDocumentPreset, createStellaStyleSet, currentFolioBlockId, deriveBlockId, diffWordSegments, extractDocumentStyleSet, extractDocumentStyleSetFromDocx, extractEmbeddedFonts, finishAutocompleteSuggestion, fromMarkdown, getAnonymizationMatches, getAutocompleteSuggestion, getEmbeddedFontFaces, getFolioCaretViewportRect, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, getFolioParaIdFromBlockId, getFolioSelectionViewportRect, getGoogleFontsEnabled, getTemplateDirectives, getTemplateSlashMenu, hashFolioAIBlockText, inspectDocumentStyles, inspectDocumentStylesFromDocx, inspectDocxCompatibility, isFolioAIContentBlock, isFolioBlockId, isFolioDocumentOperationModeSupported, isSequentialFolioBlockId, isSuggestionStale, isSupportedFolioDocumentOperationVersion, mergeDocumentContent, normalizeFolioAIBlockText, parseFolioDocumentOperationBatch, resetTemplateSlashQuery, resolveSuggestionAnchor, scanDirectives, scopeEmbeddedFontFamily, scrollFolioPositionIntoView, setAICitationsMeta, setAISuggestionsMeta, setActiveCitationMeta, setAnonymizationTermsMeta, setEmbeddedFontFamilyMap, setFocusedSuggestionMeta, setGoogleFontsEnabled, setTemplatePreviewValues, shouldTriggerAutocomplete, startAutocompleteSuggestion, templateSlashMenuKey, toMarkdown, toMarkdownResult };
@@ -0,0 +1,11 @@
1
+ import { document_d_exports } from "../types/document.js";
2
+ //#region src/content-controls/checkboxDisplay.d.ts
3
+ type CheckboxDisplayContent = Extract<document_d_exports.RunContent, {
4
+ type: "symbol";
5
+ } | {
6
+ type: "text";
7
+ }>;
8
+ /** Resolve the authored checkbox state into the run payload Word expects. */
9
+ declare const checkboxDisplayContent: (rawPropertiesXml: string | undefined, checked: boolean) => CheckboxDisplayContent;
10
+ //#endregion
11
+ export { checkboxDisplayContent };
@@ -0,0 +1,40 @@
1
+ import { NAMESPACES, OOXML_NAMESPACE_SCOPE, WORDPROCESSINGML_NAMESPACE_URIS, findChildByNamespaceUri, getAttributeByNamespaceUri, parseXml } from "../docx/xmlParser.js";
2
+ //#region src/content-controls/checkboxDisplay.ts
3
+ const CHECKBOX_NAMESPACE_URIS = /* @__PURE__ */ new Set([NAMESPACES.w14, ...WORDPROCESSINGML_NAMESPACE_URIS]);
4
+ const DEFAULT_CHECKED_CHARACTER = "2612";
5
+ const DEFAULT_UNCHECKED_CHARACTER = "2610";
6
+ const DEFAULT_CHECKBOX_FONT = "MS Gothic";
7
+ const HEX_CODE_POINT = /^[\dA-Fa-f]{1,6}$/u;
8
+ const MAX_CHECKBOX_PROPERTIES_CHARACTERS = 65536;
9
+ const defaultDisplay = (checked) => ({
10
+ type: "symbol",
11
+ char: checked ? DEFAULT_CHECKED_CHARACTER : DEFAULT_UNCHECKED_CHARACTER,
12
+ font: DEFAULT_CHECKBOX_FONT
13
+ });
14
+ /** Resolve the authored checkbox state into the run payload Word expects. */
15
+ const checkboxDisplayContent = (rawPropertiesXml, checked) => {
16
+ if (!rawPropertiesXml || rawPropertiesXml.length > MAX_CHECKBOX_PROPERTIES_CHARACTERS) return defaultDisplay(checked);
17
+ let root;
18
+ try {
19
+ root = parseXml(rawPropertiesXml, OOXML_NAMESPACE_SCOPE);
20
+ } catch {
21
+ return defaultDisplay(checked);
22
+ }
23
+ const state = findChildByNamespaceUri(findChildByNamespaceUri(findChildByNamespaceUri(root, WORDPROCESSINGML_NAMESPACE_URIS, "sdtPr"), CHECKBOX_NAMESPACE_URIS, "checkbox"), CHECKBOX_NAMESPACE_URIS, checked ? "checkedState" : "uncheckedState");
24
+ const rawCharacter = getAttributeByNamespaceUri(state, CHECKBOX_NAMESPACE_URIS, "val");
25
+ if (!rawCharacter || !HEX_CODE_POINT.test(rawCharacter)) return defaultDisplay(checked);
26
+ const codePoint = Number.parseInt(rawCharacter, 16);
27
+ if (!Number.isInteger(codePoint) || codePoint > 1114111 || codePoint >= 55296 && codePoint <= 57343) return defaultDisplay(checked);
28
+ const font = getAttributeByNamespaceUri(state, CHECKBOX_NAMESPACE_URIS, "font") ?? DEFAULT_CHECKBOX_FONT;
29
+ if (codePoint <= 65535) return {
30
+ type: "symbol",
31
+ char: codePoint.toString(16).toUpperCase().padStart(4, "0"),
32
+ font
33
+ };
34
+ return {
35
+ type: "text",
36
+ text: String.fromCodePoint(codePoint)
37
+ };
38
+ };
39
+ //#endregion
40
+ export { checkboxDisplayContent };
@@ -1,3 +1,4 @@
1
+ import { decodeOoxmlSymbolCharacter } from "../utils/ooxmlSymbol.js";
1
2
  //#region src/content-controls/findContentControls.ts
2
3
  function matches(control, filter) {
3
4
  if (filter.pmPos !== void 0) return false;
@@ -63,10 +64,11 @@ function getContentControlText(control) {
63
64
  const paraText = [];
64
65
  for (const item of block.content) if (item.type === "run") {
65
66
  for (const child of item.content) if (child.type === "text") paraText.push(child.text);
67
+ else if (child.type === "symbol") paraText.push(decodeOoxmlSymbolCharacter(child.char) ?? "");
66
68
  }
67
69
  parts.push(paraText.join(""));
68
70
  } else if (block.type === "table") for (const row of block.rows) for (const cell of row.cells) visit(cell.content);
69
- else visit(block.content);
71
+ else if (block.type === "blockSdt") visit(block.content);
70
72
  };
71
73
  visit(control.content);
72
74
  return parts.join("\n");
@@ -1,4 +1,6 @@
1
1
  import { formatDate } from "../docx/fieldParser.js";
2
+ import { cloneParagraphWithPropertySource } from "../docx/paragraphPropertySource.js";
3
+ import { checkboxDisplayContent } from "./checkboxDisplay.js";
2
4
  import { ContentControlBoundError, ContentControlLockedError, ContentControlTypeError } from "./errors.js";
3
5
  import { sanitizeXmlCharacters } from "@stll/docx-core";
4
6
  //#region src/content-controls/mutateContentControls.ts
@@ -234,6 +236,20 @@ function makeParagraphFromText(rawText) {
234
236
  }]
235
237
  };
236
238
  }
239
+ function makeCheckboxParagraph(control, checked) {
240
+ const paragraph = control.content.find((block) => block.type === "paragraph");
241
+ const run = paragraph?.content.find((item) => item.type === "run");
242
+ const content = [{
243
+ type: "run",
244
+ ...run?.formatting !== void 0 ? { formatting: run.formatting } : {},
245
+ content: [checkboxDisplayContent(control.properties.rawPropertiesXml, checked)]
246
+ }];
247
+ if (!paragraph) return {
248
+ type: "paragraph",
249
+ content
250
+ };
251
+ return cloneParagraphWithPropertySource(paragraph, { content });
252
+ }
237
253
  function cloneBlock(block) {
238
254
  return structuredClone(block);
239
255
  }
@@ -317,7 +333,6 @@ function setContentControlValue(doc, filter, input, options = {}) {
317
333
  ...control.properties.tag !== void 0 ? { tag: control.properties.tag } : {},
318
334
  ...control.properties.alias !== void 0 ? { alias: control.properties.alias } : {}
319
335
  });
320
- const glyph = input.checked ? "☒" : "☐";
321
336
  return {
322
337
  ...control,
323
338
  properties: {
@@ -326,7 +341,7 @@ function setContentControlValue(doc, filter, input, options = {}) {
326
341
  showingPlaceholder: false,
327
342
  ...strippedRawPropertiesXml !== void 0 ? { rawPropertiesXml: strippedRawPropertiesXml } : {}
328
343
  },
329
- content: [makeParagraphFromText(glyph)]
344
+ content: [makeCheckboxParagraph(control, input.checked)]
330
345
  };
331
346
  }
332
347
  if (sdtType !== "date") throw new ContentControlTypeError({
@@ -46,6 +46,7 @@ declare class ContentControlWidgetController extends Subscribable<ContentControl
46
46
  private readonly onPaintedClick;
47
47
  private readonly onKeyDown;
48
48
  private readonly onScroll;
49
+ private readonly onPointerDown;
49
50
  private open;
50
51
  private removeDismissListeners;
51
52
  private unbindView;
@@ -113,15 +113,18 @@ var ContentControlWidgetController = class extends Subscribable {
113
113
  if (event.key === "Escape") this.close();
114
114
  };
115
115
  onScroll = () => this.close();
116
+ onPointerDown = () => this.close();
116
117
  open(snapshot) {
117
118
  this.removeDismissListeners();
118
119
  this.ownerWindow = this.viewDom?.ownerDocument.defaultView ?? null;
119
120
  this.ownerWindow?.addEventListener("keydown", this.onKeyDown);
121
+ this.ownerWindow?.addEventListener("pointerdown", this.onPointerDown);
120
122
  this.ownerWindow?.addEventListener("scroll", this.onScroll, true);
121
123
  this.setSnapshot(snapshot);
122
124
  }
123
125
  removeDismissListeners() {
124
126
  this.ownerWindow?.removeEventListener("keydown", this.onKeyDown);
127
+ this.ownerWindow?.removeEventListener("pointerdown", this.onPointerDown);
125
128
  this.ownerWindow?.removeEventListener("scroll", this.onScroll, true);
126
129
  this.ownerWindow = null;
127
130
  }
@@ -45,7 +45,9 @@ const createHiddenEditorApi = (deps) => {
45
45
  return stateToDocument(view.state, deps.getDocumentContext());
46
46
  },
47
47
  focus: () => {
48
- deps.getView()?.focus();
48
+ const view = deps.getView();
49
+ if (!view || view.hasFocus()) return;
50
+ view.focus();
49
51
  },
50
52
  blur: () => {
51
53
  const view = deps.getView();
@@ -5,9 +5,9 @@ import { RemoteSelection } from "../types/remote-selection.js";
5
5
  import { HiddenEditorApi } from "./hiddenEditorApi.js";
6
6
  import { EditorState, Plugin, Transaction } from "prosemirror-state";
7
7
  import { EditorView } from "prosemirror-view";
8
- import * as YProseMirror from "y-prosemirror";
9
8
  import * as Yjs from "yjs";
10
9
  import { XmlFragment } from "yjs";
10
+ import * as YProseMirror from "y-prosemirror";
11
11
  //#region src/controller/hiddenEditorManager.d.ts
12
12
  type YProseMirrorModule = typeof YProseMirror;
13
13
  type YjsModule = typeof Yjs;
@@ -8,7 +8,7 @@ import { createDocumentNumberingPlugin } from "../prosemirror/plugins/documentNu
8
8
  import { createDocumentStylesPlugin } from "../prosemirror/plugins/documentStyles.js";
9
9
  import { schema } from "../prosemirror/schema/index.js";
10
10
  import { createTextInputPlugin } from "../prosemirror/textInput.js";
11
- import { proseDocumentParagraphSourceContract, readYjsParagraphSourceContract, withParagraphSourceContract, writeYjsParagraphSourceContract } from "../prosemirror/yjsParagraphSourceContract.js";
11
+ import { applyAttrSchemaMigrations, proseDocumentParagraphSourceContract, readYjsAttrSchemaVersion, readYjsParagraphSourceContract, withParagraphSourceContract, writeYjsDocumentMetadata } from "../prosemirror/yjsDocumentMetadata.js";
12
12
  import { createHiddenEditorApi } from "./hiddenEditorApi.js";
13
13
  import { panic } from "better-result";
14
14
  import { EditorState } from "prosemirror-state";
@@ -129,12 +129,15 @@ function createHiddenEditorState(options) {
129
129
  collaborationModules.yProseMirror.prosemirrorToYXmlFragment(seedState.doc, collaboration.yXmlFragment);
130
130
  const collaborationDocument = collaboration.yXmlFragment.doc;
131
131
  if (!collaborationDocument) panic("A collaboration fragment must belong to a Yjs document before seeding.");
132
- if (proseDocumentParagraphSourceContract(seedState.doc)) writeYjsParagraphSourceContract(collaborationDocument, seedState.doc);
132
+ writeYjsDocumentMetadata(collaborationDocument, seedState.doc);
133
133
  collaboration.onSeeded?.();
134
134
  }
135
- let { doc } = collaborationModules.yProseMirror.initProseMirrorDoc(collaboration.yXmlFragment, activeSchema);
136
135
  const collaborationDocument = collaboration.yXmlFragment.doc;
137
136
  if (!collaborationDocument) panic("A collaboration fragment must belong to a Yjs document before loading.");
137
+ const attrSchemaVersion = readYjsAttrSchemaVersion(collaborationDocument);
138
+ if (attrSchemaVersion.isErr()) throw attrSchemaVersion.error;
139
+ applyAttrSchemaMigrations(collaborationDocument, collaboration.yXmlFragment, attrSchemaVersion.value);
140
+ let { doc } = collaborationModules.yProseMirror.initProseMirrorDoc(collaboration.yXmlFragment, activeSchema);
138
141
  const collaborationContract = readYjsParagraphSourceContract(collaborationDocument);
139
142
  const localContract = proseDocumentParagraphSourceContract(localDoc);
140
143
  if (localContract && collaborationContract !== localContract) panic("The collaboration state belongs to a different paragraph-property source.");
@@ -1,3 +1,4 @@
1
+ import { isHeadingOutlineLevel } from "../../docx/builtInStyles.js";
1
2
  import { HIT_REGION_KINDS } from "../primitives.js";
2
3
  import { AuthorColorTable } from "./buildContext.js";
3
4
  import { DOC_CANVAS } from "./colors.js";
@@ -12,6 +13,19 @@ import { paintTableFragment } from "./tablePrimitives.js";
12
13
  import { paintTextBoxFragment } from "./textBoxPrimitives.js";
13
14
  import { UNSUPPORTED_CONSTRUCT, UnsupportedCollector } from "./unsupported.js";
14
15
  //#region src/display-list/build/buildDisplayList.ts
16
+ /**
17
+ * `Layout` + `BlockLookup` → `DisplayList`.
18
+ *
19
+ * The single source of truth for painting. Two backends consume the result and
20
+ * neither may look behind it, so anything missing here is painted nowhere.
21
+ *
22
+ * Purity is a hard requirement, not a preference: no clock, no randomness, no
23
+ * `globalThis.document`. The font and image tables intern in first-use page
24
+ * order, and author colours are assigned per build, so two builds of one layout
25
+ * are deeply equal. The one impure edge is the measure provider, which the
26
+ * composition root installs and which is deterministic for a given font set;
27
+ * that is the same seam line breaking already ran through, which is the point.
28
+ */
15
29
  /** Document-wide gaps are attributed to the first page, the only one certain to exist. */
16
30
  const FIRST_PAGE_INDEX = 0;
17
31
  /**
@@ -60,6 +74,11 @@ const paragraphTextOf = (block) => block.runs.map((run) => run.kind === "text" ?
60
74
  * Resolve everything that needs the whole document before any page is painted:
61
75
  * where each bookmark lands (a `#name` hyperlink cannot become a page target
62
76
  * until then) and the heading outline.
77
+ *
78
+ * The outline takes the levels {@link isHeadingOutlineLevel} accepts and no
79
+ * others: `w:outlineLvl` 9 is the reserved body-text value, not a tenth level,
80
+ * and a `TOC Heading` paragraph carrying it would otherwise become a PDF
81
+ * bookmark nested nine deep.
63
82
  */
64
83
  const collectDocumentTargets = (layout, blockLookup) => {
65
84
  const bookmarkTargets = /* @__PURE__ */ new Map();
@@ -74,7 +93,7 @@ const collectDocumentTargets = (layout, blockLookup) => {
74
93
  yPx: fragment.y
75
94
  });
76
95
  const level = block.attrs?.outlineLevel;
77
- if (level !== void 0 && fragment.continuesFromPrev !== true) {
96
+ if (isHeadingOutlineLevel(level) && fragment.continuesFromPrev !== true) {
78
97
  const title = paragraphTextOf(block);
79
98
  if (title.length > 0) outline.push({
80
99
  title,
@@ -15,7 +15,7 @@ declare class ImageTable {
15
15
  failureFor(src: string): string | undefined;
16
16
  snapshot(): readonly DisplayImageSource[];
17
17
  }
18
- type ImageVisualSource = Pick<ImageBlock, "src" | "opacity" | "cropTop" | "cropRight" | "cropBottom" | "cropLeft" | "borderWidth" | "borderColor" | "borderStyle" | "transform">;
18
+ type ImageVisualSource = Pick<ImageBlock, "src" | "opacity" | "brightness" | "contrast" | "cropTop" | "cropRight" | "cropBottom" | "cropLeft" | "borderWidth" | "borderColor" | "borderStyle" | "transform">;
19
19
  type PaintImageOptions = {
20
20
  readonly source: ImageVisualSource;
21
21
  readonly rect: DisplayRect;
@@ -213,7 +213,9 @@ const paintImage = ({ source, rect, context, label }) => {
213
213
  image: ref,
214
214
  rect,
215
215
  ...crop === void 0 ? {} : { crop },
216
- opacity: source.opacity == null ? 1 : Math.min(1, Math.max(0, source.opacity))
216
+ opacity: source.opacity == null ? 1 : Math.min(1, Math.max(0, source.opacity)),
217
+ ...source.brightness == null ? {} : { brightness: source.brightness },
218
+ ...source.contrast == null ? {} : { contrast: source.contrast }
217
219
  };
218
220
  const degrees = parseRotationDegrees(source.transform);
219
221
  if (degrees === 0) primitives.push(image);