@stll/folio-core 0.52.0 → 0.54.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 (389) hide show
  1. package/README.md +23 -0
  2. package/dist/ai-edits/apply.d.ts +26 -1
  3. package/dist/ai-edits/apply.js +1779 -141
  4. package/dist/ai-edits/batch-claims.d.ts +145 -0
  5. package/dist/ai-edits/batch-claims.js +275 -0
  6. package/dist/ai-edits/blockRange.js +9 -3
  7. package/dist/ai-edits/character-boundaries.d.ts +43 -0
  8. package/dist/ai-edits/character-boundaries.js +95 -0
  9. package/dist/ai-edits/clean-text.d.ts +33 -3
  10. package/dist/ai-edits/clean-text.js +52 -6
  11. package/dist/ai-edits/comment-lifecycle.d.ts +18 -0
  12. package/dist/ai-edits/comment-lifecycle.js +52 -0
  13. package/dist/ai-edits/headless.d.ts +91 -7
  14. package/dist/ai-edits/headless.js +520 -51
  15. package/dist/ai-edits/index.d.ts +2 -1
  16. package/dist/ai-edits/index.js +2 -1
  17. package/dist/ai-edits/minimal-replacement.d.ts +21 -6
  18. package/dist/ai-edits/minimal-replacement.js +134 -15
  19. package/dist/ai-edits/newListNumbering.d.ts +23 -0
  20. package/dist/ai-edits/newListNumbering.js +94 -0
  21. package/dist/ai-edits/note-references.d.ts +96 -0
  22. package/dist/ai-edits/note-references.js +139 -0
  23. package/dist/ai-edits/pending-suggestions.d.ts +79 -0
  24. package/dist/ai-edits/pending-suggestions.js +306 -0
  25. package/dist/ai-edits/read.d.ts +6 -4
  26. package/dist/ai-edits/read.js +113 -50
  27. package/dist/ai-edits/result-validation.d.ts +29 -0
  28. package/dist/ai-edits/result-validation.js +164 -0
  29. package/dist/ai-edits/revisionStretches.d.ts +17 -0
  30. package/dist/ai-edits/revisionStretches.js +80 -0
  31. package/dist/ai-edits/snapshot.d.ts +36 -3
  32. package/dist/ai-edits/snapshot.js +180 -25
  33. package/dist/ai-edits/table-cell-mutations.d.ts +4 -2
  34. package/dist/ai-edits/table-cell-mutations.js +6 -2
  35. package/dist/ai-edits/table-geometry.d.ts +1 -1
  36. package/dist/ai-edits/table-row-column-mutations.d.ts +44 -17
  37. package/dist/ai-edits/table-row-column-mutations.js +86 -34
  38. package/dist/ai-edits/types.d.ts +155 -16
  39. package/dist/compare/compare.d.ts +1 -1
  40. package/dist/compare/compare.js +65 -16
  41. package/dist/compare/content-alignment.d.ts +5 -1
  42. package/dist/compare/content-alignment.js +52 -34
  43. package/dist/compare/content-types.d.ts +7 -0
  44. package/dist/compare/content.d.ts +4 -1
  45. package/dist/compare/content.js +6 -1
  46. package/dist/compare/formatting.js +2 -1
  47. package/dist/compare/inline-atoms.d.ts +21 -4
  48. package/dist/compare/inline-atoms.js +138 -16
  49. package/dist/compare/inline-provenance.js +1 -1
  50. package/dist/compare/plan.js +10 -5
  51. package/dist/compare/scenario.js +14 -3
  52. package/dist/compare/section-boundary-properties.js +1 -1
  53. package/dist/compare/types.d.ts +4 -2
  54. package/dist/compare/types.js +2 -1
  55. package/dist/compare/verification.d.ts +1 -1
  56. package/dist/compare/verification.js +15 -3
  57. package/dist/controller/committedLayoutDiff.d.ts +25 -0
  58. package/dist/controller/committedLayoutDiff.js +71 -0
  59. package/dist/controller/contentControlWidgetController.d.ts +1 -1
  60. package/dist/controller/folioEditor.d.ts +1 -1
  61. package/dist/controller/fontReadiness.d.ts +70 -3
  62. package/dist/controller/fontReadiness.js +100 -10
  63. package/dist/controller/headerFooterEditorManager.js +6 -1
  64. package/dist/controller/layoutPipeline.d.ts +12 -10
  65. package/dist/controller/layoutPipeline.js +65 -11
  66. package/dist/controller/layoutRunOptions.d.ts +24 -0
  67. package/dist/controller/layoutRunOptions.js +17 -0
  68. package/dist/controller/layoutScheduler.d.ts +19 -14
  69. package/dist/controller/layoutScheduler.js +15 -12
  70. package/dist/controller/layoutSession.d.ts +26 -2
  71. package/dist/controller/layoutSession.js +1 -1
  72. package/dist/controller/noteEditorManager.js +8 -3
  73. package/dist/document-operations.d.ts +11 -2
  74. package/dist/document-operations.js +230 -21
  75. package/dist/docx/altChunk.d.ts +8 -0
  76. package/dist/docx/altChunk.js +17 -0
  77. package/dist/docx/archiveInflation.d.ts +127 -0
  78. package/dist/docx/archiveInflation.js +181 -0
  79. package/dist/docx/attributeRemainder.d.ts +1 -1
  80. package/dist/docx/blockContentParser.d.ts +64 -1
  81. package/dist/docx/blockContentParser.js +17 -4
  82. package/dist/docx/blockCustomXmlShell.d.ts +7 -0
  83. package/dist/docx/blockCustomXmlShell.js +14 -0
  84. package/dist/docx/blockPlainText.js +7 -0
  85. package/dist/docx/commentAnchorIndex.js +1 -1
  86. package/dist/docx/commentRangeIntegrity.js +8 -3
  87. package/dist/docx/commentReferenceNormalization.js +1 -1
  88. package/dist/docx/commentReplyMarkers.js +20 -1
  89. package/dist/docx/compatibility.d.ts +1 -1
  90. package/dist/docx/compatibility.js +34 -13
  91. package/dist/docx/containerChildren.gen.d.ts +1 -1
  92. package/dist/docx/containerChildren.gen.js +1 -0
  93. package/dist/docx/documentParser.js +12 -12
  94. package/dist/docx/drawingIdNormalization.d.ts +3 -1
  95. package/dist/docx/drawingIdNormalization.js +6 -1
  96. package/dist/docx/ensureParaIds.js +119 -97
  97. package/dist/docx/footnoteParser.js +8 -4
  98. package/dist/docx/headerFooterParser.js +3 -3
  99. package/dist/docx/headerFooterReferenceNormalization.d.ts +20 -1
  100. package/dist/docx/headerFooterReferenceNormalization.js +52 -27
  101. package/dist/docx/hyperlinkParser.d.ts +1 -1
  102. package/dist/docx/index.d.ts +1 -1
  103. package/dist/docx/listNumberingInstances.d.ts +59 -0
  104. package/dist/docx/listNumberingInstances.js +249 -0
  105. package/dist/docx/metadataPrivacy.js +24 -1
  106. package/dist/docx/normalizeBaseDirection.js +2 -1
  107. package/dist/docx/noteReferenceMark.d.ts +15 -0
  108. package/dist/docx/noteReferenceMark.js +48 -0
  109. package/dist/docx/opaqueCarrier.d.ts +7 -0
  110. package/dist/docx/opaqueCarrier.js +38 -0
  111. package/dist/docx/packageParts.js +4 -1
  112. package/dist/docx/paragraphParser.js +96 -27
  113. package/dist/docx/paragraphPropertySource.d.ts +4 -2
  114. package/dist/docx/paragraphPropertySource.js +10 -2
  115. package/dist/docx/paragraphTraversal.js +1 -0
  116. package/dist/docx/parseWarningMessage.js +4 -1
  117. package/dist/docx/parser.js +175 -22
  118. package/dist/docx/rezip.js +31 -7
  119. package/dist/docx/sdtProperties.js +1 -1
  120. package/dist/docx/sdtPropertiesPatch.js +3 -0
  121. package/dist/docx/selectiveSave.js +16 -9
  122. package/dist/docx/selectiveXmlPatch.d.ts +3 -1
  123. package/dist/docx/selectiveXmlPatch.js +186 -39
  124. package/dist/docx/serializer/blockCustomXmlSerializer.d.ts +5 -0
  125. package/dist/docx/serializer/blockCustomXmlSerializer.js +4 -0
  126. package/dist/docx/serializer/documentSerializer.js +2 -0
  127. package/dist/docx/serializer/headerFooterSerializer.js +2 -0
  128. package/dist/docx/serializer/noteSerializer.js +3 -1
  129. package/dist/docx/serializer/paragraphSerializer.js +33 -9
  130. package/dist/docx/serializer/tableSerializer.js +25 -38
  131. package/dist/docx/server/boundedArchive.d.ts +8 -13
  132. package/dist/docx/server/boundedArchive.js +70 -59
  133. package/dist/docx/server/createBilingualDocument.js +3 -3
  134. package/dist/docx/server/extractDocxText.d.ts +8 -2
  135. package/dist/docx/server/extractDocxText.js +2 -2
  136. package/dist/docx/server/validateDocxConformance.d.ts +1 -1
  137. package/dist/docx/server/validateDocxConformance.js +1 -0
  138. package/dist/docx/tableParser.d.ts +157 -1
  139. package/dist/docx/tableParser.js +89 -10
  140. package/dist/docx/textBoxParser.js +1 -1
  141. package/dist/docx/unzip.d.ts +20 -2
  142. package/dist/docx/unzip.js +136 -25
  143. package/dist/docx/wordprocessingPrefixes.d.ts +78 -0
  144. package/dist/docx/wordprocessingPrefixes.js +286 -0
  145. package/dist/fonts/embeddedFonts.js +1 -1
  146. package/dist/i18n/messages/catalogs.gen.d.ts +170 -34
  147. package/dist/i18n/messages/catalogs.gen.js +187 -51
  148. package/dist/i18n/messages/messages.gen.d.ts +10 -2
  149. package/dist/internal/compare/inline-presentation.d.ts +2 -1
  150. package/dist/internal/compare/inline-presentation.js +11 -10
  151. package/dist/internal/headlessRevisionResolutionGuard.d.ts +2 -8
  152. package/dist/internal/headlessRevisionResolutionGuard.js +2 -11
  153. package/dist/internal/indexedPositionMap.d.ts +11 -0
  154. package/dist/internal/indexedPositionMap.js +42 -0
  155. package/dist/internal/pageBreakRunSourceDescendantIndex.js +2 -1
  156. package/dist/internal/revisionResolutionEdits.d.ts +13 -0
  157. package/dist/internal/revisionResolutionEdits.js +19 -0
  158. package/dist/internal/revisionResolutionInline.d.ts +24 -0
  159. package/dist/internal/{headlessRevisionResolution.js → revisionResolutionInline.js} +61 -43
  160. package/dist/internal/revisionResolutionStep.d.ts +34 -0
  161. package/dist/internal/revisionResolutionStep.js +282 -0
  162. package/dist/internal/revisionResolutionTracking.d.ts +11 -0
  163. package/dist/internal/revisionResolutionTracking.js +124 -0
  164. package/dist/internal/wholeStoryRevisionResolution.d.ts +56 -0
  165. package/dist/internal/wholeStoryRevisionResolution.js +600 -0
  166. package/dist/layout-bridge/convert/markupViewFlow.d.ts +20 -0
  167. package/dist/layout-bridge/convert/markupViewFlow.js +123 -0
  168. package/dist/layout-bridge/convert/tableConversion.js +1 -1
  169. package/dist/layout-bridge/convert/toFlowBlocks.js +10 -1
  170. package/dist/layout-engine/layoutInstrumentation.d.ts +9 -1
  171. package/dist/layout-engine/layoutInstrumentation.js +4 -1
  172. package/dist/layout-engine/measure/cache.d.ts +18 -1
  173. package/dist/layout-engine/measure/cache.js +31 -1
  174. package/dist/layout-engine/measure/font-metrics.worker.js +3 -7
  175. package/dist/layout-engine/measure/measureContainer.js +7 -47
  176. package/dist/layout-engine/measure/measureHelpers.d.ts +6 -1
  177. package/dist/layout-engine/measure/measureHelpers.js +22 -2
  178. package/dist/layout-engine/measure/measureParagraph.js +2 -2
  179. package/dist/layout-engine/measure/measureWorker.js +2 -3
  180. package/dist/layout-engine/measure/measureWorkerProtocol.d.ts +6 -7
  181. package/dist/layout-engine/measure/measureWorkerProtocol.js +1 -2
  182. package/dist/layout-engine/measure/paragraphMeasureShared.d.ts +12 -1
  183. package/dist/layout-engine/measure/paragraphMeasureShared.js +14 -1
  184. package/dist/layout-engine/types.d.ts +6 -0
  185. package/dist/layout-painter/renderPage.js +1 -0
  186. package/dist/layout-painter/renderParagraph.js +1 -1
  187. package/dist/managers/ContextMenuManager.js +5 -2
  188. package/dist/managers/types.d.ts +3 -0
  189. package/dist/markdown/escape.d.ts +2 -2
  190. package/dist/markdown/escape.js +4 -5
  191. package/dist/markdown/fromMarkdown.js +2 -1
  192. package/dist/markdown/internals.d.ts +11 -1
  193. package/dist/markdown/internals.js +24 -3
  194. package/dist/markdown/renderBlock.js +121 -25
  195. package/dist/markdown/renderParagraph.d.ts +13 -1
  196. package/dist/markdown/renderParagraph.js +85 -38
  197. package/dist/markdown/renderRuns.d.ts +10 -1
  198. package/dist/markdown/renderRuns.js +323 -69
  199. package/dist/markdown/renderTable.js +24 -12
  200. package/dist/markdown/trailers.js +2 -2
  201. package/dist/markdown/types.d.ts +29 -7
  202. package/dist/paged-layout/incrementalMeasure.d.ts +1 -2
  203. package/dist/paged-layout/incrementalMeasure.js +1 -9
  204. package/dist/paged-layout/transactionDirtyRange.d.ts +1 -3
  205. package/dist/paged-layout/transactionDirtyRange.js +29 -41
  206. package/dist/panel-layout.d.ts +83 -0
  207. package/dist/panel-layout.js +96 -0
  208. package/dist/prosemirror/anchoredTextBoxes.d.ts +37 -0
  209. package/dist/prosemirror/anchoredTextBoxes.js +156 -0
  210. package/dist/prosemirror/attrs/index.d.ts +6 -2
  211. package/dist/prosemirror/attrs/index.js +172 -1
  212. package/dist/prosemirror/clearRunColor.d.ts +6 -0
  213. package/dist/prosemirror/clearRunColor.js +46 -0
  214. package/dist/prosemirror/commands/comments.d.ts +7 -8
  215. package/dist/prosemirror/commands/comments.js +281 -212
  216. package/dist/prosemirror/commands/contentControls.d.ts +1 -1
  217. package/dist/prosemirror/commands/formatPainter.d.ts +1 -1
  218. package/dist/prosemirror/commands/formatPainter.js +1 -1
  219. package/dist/prosemirror/commands/formatting.d.ts +1 -1
  220. package/dist/prosemirror/commands/hyperlink.js +2 -1
  221. package/dist/prosemirror/commands/index.d.ts +2 -2
  222. package/dist/prosemirror/commands/index.js +2 -2
  223. package/dist/prosemirror/commands/paragraph.d.ts +7 -1
  224. package/dist/prosemirror/commands/paragraph.js +9 -1
  225. package/dist/prosemirror/commands/paragraphBookmarkJoin.d.ts +13 -0
  226. package/dist/prosemirror/commands/paragraphBookmarkJoin.js +22 -0
  227. package/dist/prosemirror/commands/pastePlainText.d.ts +1 -1
  228. package/dist/prosemirror/commands/propertyChangeScope.d.ts +3 -2
  229. package/dist/prosemirror/commands/propertyChangeScope.js +24 -3
  230. package/dist/prosemirror/commands/resolveAllTableChanges.d.ts +40 -0
  231. package/dist/prosemirror/commands/resolveAllTableChanges.js +620 -0
  232. package/dist/prosemirror/commands/resolveNodePropertyChangeAttrs.d.ts +15 -0
  233. package/dist/prosemirror/commands/resolveNodePropertyChangeAttrs.js +46 -0
  234. package/dist/prosemirror/commands/resolveParagraphProperties.d.ts +16 -0
  235. package/dist/prosemirror/commands/resolveParagraphProperties.js +73 -0
  236. package/dist/prosemirror/commands/sectionBreak.js +2 -1
  237. package/dist/prosemirror/commands/tableCellMergeResolution.d.ts +15 -2
  238. package/dist/prosemirror/commands/tableCellMergeResolution.js +23 -7
  239. package/dist/prosemirror/containerFinalParagraph.d.ts +11 -5
  240. package/dist/prosemirror/containerFinalParagraph.js +7 -6
  241. package/dist/prosemirror/contentControlRevisions.d.ts +1 -1
  242. package/dist/prosemirror/conversion/fromProseDoc.d.ts +2 -13
  243. package/dist/prosemirror/conversion/fromProseDoc.js +177 -605
  244. package/dist/prosemirror/conversion/toProseDoc.d.ts +4 -11
  245. package/dist/prosemirror/conversion/toProseDoc.js +70 -154
  246. package/dist/prosemirror/documentSchema.d.ts +8 -0
  247. package/dist/prosemirror/documentSchema.js +18 -0
  248. package/dist/prosemirror/emptyFieldResultRuns.d.ts +18 -0
  249. package/dist/prosemirror/emptyFieldResultRuns.js +33 -0
  250. package/dist/prosemirror/extensions/ExtensionManager.d.ts +1 -1
  251. package/dist/prosemirror/extensions/ExtensionManager.js +3 -1
  252. package/dist/prosemirror/extensions/StarterKit.js +5 -1
  253. package/dist/prosemirror/extensions/core/DocExtension.js +1 -1
  254. package/dist/prosemirror/extensions/core/ParagraphExtension.js +116 -63
  255. package/dist/prosemirror/extensions/features/BaseKeymapExtension.js +4 -1
  256. package/dist/prosemirror/extensions/features/EmptyParagraphFormatExtension.js +24 -3
  257. package/dist/prosemirror/extensions/features/JoinedRunStyleExtension.d.ts +20 -0
  258. package/dist/prosemirror/extensions/features/JoinedRunStyleExtension.js +43 -0
  259. package/dist/prosemirror/extensions/features/ListExtension.js +167 -128
  260. package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.d.ts +19 -2
  261. package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.js +33 -20
  262. package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.d.ts +31 -2
  263. package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.js +270 -99
  264. package/dist/prosemirror/extensions/features/PasteCleanupExtension.js +3 -2
  265. package/dist/prosemirror/extensions/features/pasteCleanup.js +2 -1
  266. package/dist/prosemirror/extensions/features/pastedHeadingStyles.js +1 -1
  267. package/dist/prosemirror/extensions/features/pastedHtmlLists.d.ts +12 -0
  268. package/dist/prosemirror/extensions/features/pastedHtmlLists.js +124 -0
  269. package/dist/prosemirror/extensions/marks/FootnoteRefExtension.js +33 -11
  270. package/dist/prosemirror/extensions/marks/HyperlinkExtension.js +8 -4
  271. package/dist/prosemirror/extensions/marks/RunIdentityExtension.d.ts +21 -18
  272. package/dist/prosemirror/extensions/marks/RunIdentityExtension.js +37 -17
  273. package/dist/prosemirror/extensions/marks/StrikeExtension.js +2 -2
  274. package/dist/prosemirror/extensions/marks/SubscriptExtension.js +2 -2
  275. package/dist/prosemirror/extensions/marks/SuperscriptExtension.js +2 -2
  276. package/dist/prosemirror/extensions/marks/TextColorExtension.js +4 -3
  277. package/dist/prosemirror/extensions/marks/markUtils.d.ts +15 -8
  278. package/dist/prosemirror/extensions/marks/markUtils.js +25 -10
  279. package/dist/prosemirror/extensions/marks/noteReferenceDeletion.d.ts +12 -0
  280. package/dist/prosemirror/extensions/marks/noteReferenceDeletion.js +46 -0
  281. package/dist/prosemirror/extensions/nodes/BlockCustomXmlExtension.d.ts +6 -0
  282. package/dist/prosemirror/extensions/nodes/BlockCustomXmlExtension.js +52 -0
  283. package/dist/prosemirror/extensions/nodes/CommentReferenceExtension.js +2 -2
  284. package/dist/prosemirror/extensions/nodes/FieldExtension.d.ts +3 -3
  285. package/dist/prosemirror/extensions/nodes/FieldExtension.js +50 -15
  286. package/dist/prosemirror/extensions/nodes/HardBreakExtension.js +5 -3
  287. package/dist/prosemirror/extensions/nodes/PreservedBlockExtension.js +4 -1
  288. package/dist/prosemirror/extensions/nodes/TableExtension.d.ts +1 -1
  289. package/dist/prosemirror/extensions/nodes/TableExtension.js +121 -226
  290. package/dist/prosemirror/extensions/types.d.ts +11 -1
  291. package/dist/prosemirror/findReplaceSelection.js +1 -1
  292. package/dist/prosemirror/hyperlinkRemoval.d.ts +9 -0
  293. package/dist/prosemirror/hyperlinkRemoval.js +129 -0
  294. package/dist/prosemirror/index.d.ts +5 -3
  295. package/dist/prosemirror/index.js +5 -3
  296. package/dist/prosemirror/indexedNodeLookup.d.ts +17 -0
  297. package/dist/prosemirror/indexedNodeLookup.js +103 -0
  298. package/dist/prosemirror/listAutoformatMarkers.d.ts +19 -0
  299. package/dist/prosemirror/listAutoformatMarkers.js +98 -0
  300. package/dist/prosemirror/listInstanceReferences.d.ts +12 -0
  301. package/dist/prosemirror/listInstanceReferences.js +72 -0
  302. package/dist/prosemirror/listLabels.d.ts +24 -0
  303. package/dist/prosemirror/listLabels.js +111 -0
  304. package/dist/prosemirror/listNumbering.d.ts +92 -0
  305. package/dist/prosemirror/listNumbering.js +330 -0
  306. package/dist/prosemirror/listRendering.d.ts +27 -0
  307. package/dist/prosemirror/listRendering.js +27 -0
  308. package/dist/prosemirror/listRenderingAttrs.d.ts +11 -2
  309. package/dist/prosemirror/listRenderingAttrs.js +8 -1
  310. package/dist/prosemirror/markupViewNotes.d.ts +8 -0
  311. package/dist/prosemirror/markupViewNotes.js +49 -0
  312. package/dist/prosemirror/markupViewProjection.d.ts +97 -0
  313. package/dist/prosemirror/markupViewProjection.js +88 -0
  314. package/dist/prosemirror/noteReferenceReview.d.ts +77 -0
  315. package/dist/prosemirror/noteReferenceReview.js +332 -0
  316. package/dist/prosemirror/numberingAttr.d.ts +9 -1
  317. package/dist/prosemirror/numberingAttr.js +9 -1
  318. package/dist/prosemirror/outlineLevelAttr.js +1 -1
  319. package/dist/prosemirror/paragraphIndentation.d.ts +10 -1
  320. package/dist/prosemirror/paragraphIndentation.js +32 -7
  321. package/dist/prosemirror/paragraphMarkJoin.d.ts +21 -0
  322. package/dist/prosemirror/paragraphMarkJoin.js +26 -0
  323. package/dist/prosemirror/paragraphPropertyCarry.d.ts +64 -0
  324. package/dist/prosemirror/paragraphPropertyCarry.js +158 -0
  325. package/dist/prosemirror/plugins/createDocScanPlugin.d.ts +1 -1
  326. package/dist/prosemirror/plugins/documentNumbering.d.ts +27 -1
  327. package/dist/prosemirror/plugins/documentNumbering.js +97 -11
  328. package/dist/prosemirror/plugins/documentStyleState.d.ts +26 -0
  329. package/dist/prosemirror/plugins/documentStyleState.js +32 -0
  330. package/dist/prosemirror/plugins/documentStyles.d.ts +3 -13
  331. package/dist/prosemirror/plugins/documentStyles.js +67 -17
  332. package/dist/prosemirror/plugins/index.d.ts +2 -1
  333. package/dist/prosemirror/plugins/index.js +2 -1
  334. package/dist/prosemirror/plugins/paragraphStyleResolution.d.ts +15 -0
  335. package/dist/prosemirror/plugins/paragraphStyleResolution.js +230 -0
  336. package/dist/prosemirror/plugins/suggestionMode.d.ts +27 -3
  337. package/dist/prosemirror/plugins/suggestionMode.js +490 -63
  338. package/dist/prosemirror/plugins/templateDirectives.d.ts +1 -1
  339. package/dist/prosemirror/plugins/transactionInvariants.d.ts +32 -0
  340. package/dist/prosemirror/plugins/transactionInvariants.js +86 -0
  341. package/dist/prosemirror/positionSweep.d.ts +24 -0
  342. package/dist/prosemirror/positionSweep.js +222 -0
  343. package/dist/prosemirror/rebaseParagraphRunFormatting.d.ts +23 -3
  344. package/dist/prosemirror/rebaseParagraphRunFormatting.js +39 -13
  345. package/dist/prosemirror/rebaseParagraphRuns.d.ts +36 -0
  346. package/dist/prosemirror/rebaseParagraphRuns.js +99 -0
  347. package/dist/prosemirror/rejoinRunCarriers.d.ts +1 -1
  348. package/dist/prosemirror/replacedAnnotations.d.ts +33 -1
  349. package/dist/prosemirror/replacedAnnotations.js +170 -1
  350. package/dist/prosemirror/runFormattingFromMarks.d.ts +18 -0
  351. package/dist/prosemirror/runFormattingFromMarks.js +567 -0
  352. package/dist/prosemirror/runFormattingInlineCarriers.d.ts +1 -1
  353. package/dist/prosemirror/runFormattingReconciliation.js +10 -9
  354. package/dist/prosemirror/schema/index.d.ts +2 -2
  355. package/dist/prosemirror/schema/index.js +3 -0
  356. package/dist/prosemirror/schema/nodes.d.ts +44 -11
  357. package/dist/prosemirror/sectionMarkEdits.d.ts +20 -0
  358. package/dist/prosemirror/sectionMarkEdits.js +59 -0
  359. package/dist/prosemirror/storyListNumbering.d.ts +17 -0
  360. package/dist/prosemirror/storyListNumbering.js +102 -0
  361. package/dist/prosemirror/styles/paragraphStyleCascade.d.ts +59 -0
  362. package/dist/prosemirror/styles/paragraphStyleCascade.js +145 -0
  363. package/dist/prosemirror/styles/resolvedStyleAttrs.d.ts +21 -2
  364. package/dist/prosemirror/styles/resolvedStyleAttrs.js +38 -1
  365. package/dist/prosemirror/styles/tableStyleRegions.d.ts +31 -0
  366. package/dist/prosemirror/styles/tableStyleRegions.js +55 -0
  367. package/dist/prosemirror/tableCellPaste.d.ts +74 -0
  368. package/dist/prosemirror/tableCellPaste.js +525 -0
  369. package/dist/prosemirror/tableGridMutation.d.ts +87 -2
  370. package/dist/prosemirror/tableGridMutation.js +255 -2
  371. package/dist/prosemirror/tableRunIn.d.ts +51 -0
  372. package/dist/prosemirror/tableRunIn.js +165 -0
  373. package/dist/prosemirror/textInput.js +11 -2
  374. package/dist/prosemirror/trackedRevisionPath.d.ts +17 -0
  375. package/dist/prosemirror/trackedRevisionPath.js +32 -0
  376. package/dist/prosemirror/validation.js +5 -1
  377. package/dist/redline.js +93 -9
  378. package/dist/render-dom/BodySelectionOverlay.d.ts +4 -1
  379. package/dist/render-dom/BodySelectionOverlay.js +3 -2
  380. package/dist/server.d.ts +2 -2
  381. package/dist/utils/findReplace.js +2 -2
  382. package/dist/utils/mergeDocumentContent.js +1 -1
  383. package/dist/utils/noteReferenceLabels.d.ts +36 -0
  384. package/dist/utils/noteReferenceLabels.js +32 -0
  385. package/dist/utils/replaceText.js +1 -1
  386. package/dist/version-comparison.d.ts +1 -0
  387. package/dist/version-comparison.js +1 -0
  388. package/package.json +6 -5
  389. package/dist/internal/headlessRevisionResolution.d.ts +0 -23
@@ -0,0 +1,123 @@
1
+ import { indexedPositionMap } from "../../internal/indexedPositionMap.js";
2
+ //#region src/layout-bridge/convert/markupViewFlow.ts
3
+ /**
4
+ * Re-address blocks built from a view projection in editor positions, and mark
5
+ * the paragraphs the view flags with a change bar.
6
+ */
7
+ function remapMarkupViewBlocks(blocks, { positionMap, changeBarRanges }) {
8
+ const inverse = positionMap.invert();
9
+ const cutSet = /* @__PURE__ */ new Set();
10
+ inverse.forEach((oldStart, oldEnd) => {
11
+ cutSet.add(oldStart);
12
+ cutSet.add(oldEnd);
13
+ });
14
+ const context = {
15
+ toSource: indexedPositionMap(inverse),
16
+ cuts: [...cutSet].sort((left, right) => left - right),
17
+ changeBarRanges
18
+ };
19
+ return blocks.map((block) => remapBlock(block, context));
20
+ }
21
+ const touchesChangeBar = (block, ranges) => {
22
+ const { pmStart, pmEnd } = block;
23
+ if (pmStart === void 0 || pmEnd === void 0) return false;
24
+ return ranges.some((range) => range.from < pmEnd && range.to > pmStart);
25
+ };
26
+ /** A node's own positions: its start after any hidden content before it, its end before any after. */
27
+ const remapNodeRange = (range, toSource) => {
28
+ if (range.pmStart === void 0 || range.pmEnd === void 0) return {};
29
+ const pmStart = toSource(range.pmStart, 1);
30
+ return {
31
+ pmStart,
32
+ pmEnd: Math.max(pmStart, toSource(range.pmEnd, -1))
33
+ };
34
+ };
35
+ const remapSdtGroups = (groups, toSource) => groups === void 0 ? {} : { sdtGroups: groups.map((group) => ({
36
+ ...group,
37
+ pmPos: toSource(group.pmPos, 1)
38
+ })) };
39
+ function remapBlock(block, context) {
40
+ switch (block.kind) {
41
+ case "paragraph": return remapParagraph(block, context);
42
+ case "table": return remapTable(block, context);
43
+ case "image":
44
+ case "pageBreak":
45
+ case "columnBreak": return {
46
+ ...block,
47
+ ...remapNodeRange(block, context.toSource)
48
+ };
49
+ case "textBox": return {
50
+ ...block,
51
+ ...remapNodeRange(block, context.toSource),
52
+ content: block.content.map((contentBlock) => contentBlock.kind === "table" ? remapTable(contentBlock, context) : remapParagraph(contentBlock, context))
53
+ };
54
+ case "sectionBreak": return block;
55
+ default: return block;
56
+ }
57
+ }
58
+ function remapTable(block, context) {
59
+ return {
60
+ ...block,
61
+ ...remapNodeRange(block, context.toSource),
62
+ ...remapSdtGroups(block.sdtGroups, context.toSource),
63
+ rows: block.rows.map((row) => ({
64
+ ...row,
65
+ cells: row.cells.map((cell) => ({
66
+ ...cell,
67
+ blocks: cell.blocks.map((cellBlock) => remapBlock(cellBlock, context))
68
+ }))
69
+ }))
70
+ };
71
+ }
72
+ function remapParagraph(block, context) {
73
+ const runs = [];
74
+ for (const run of block.runs) pushRemappedRun(run, context, runs);
75
+ return {
76
+ ...block,
77
+ ...remapNodeRange(block, context.toSource),
78
+ ...remapSdtGroups(block.sdtGroups, context.toSource),
79
+ ...touchesChangeBar(block, context.changeBarRanges) ? { reviewIndicator: "change-bar" } : {},
80
+ runs
81
+ };
82
+ }
83
+ /** Index of the first cut strictly after `position`. */
84
+ const firstCutAfter = (cuts, position) => {
85
+ let low = 0;
86
+ let high = cuts.length;
87
+ while (low < high) {
88
+ const middle = Math.floor((low + high) / 2);
89
+ const cut = cuts.at(middle);
90
+ if (cut !== void 0 && cut <= position) low = middle + 1;
91
+ else high = middle;
92
+ }
93
+ return low;
94
+ };
95
+ /** Whether each character of the run occupies exactly one position. */
96
+ const addressesPerCharacter = (run) => run.pmStart !== void 0 && run.pmEnd !== void 0 && run.templatePreview === void 0 && run.text.length === run.pmEnd - run.pmStart;
97
+ function pushRemappedRun(run, context, out) {
98
+ if (run.kind !== "text" || !addressesPerCharacter(run)) {
99
+ out.push({
100
+ ...run,
101
+ ...remapNodeRange(run, context.toSource)
102
+ });
103
+ return;
104
+ }
105
+ const { pmStart, pmEnd } = run;
106
+ let pieceStart = pmStart;
107
+ for (let index = firstCutAfter(context.cuts, pmStart);; index++) {
108
+ const cut = context.cuts.at(index);
109
+ const pieceEnd = cut === void 0 || cut >= pmEnd ? pmEnd : cut;
110
+ out.push({
111
+ ...run,
112
+ text: run.text.slice(pieceStart - pmStart, pieceEnd - pmStart),
113
+ ...remapNodeRange({
114
+ pmStart: pieceStart,
115
+ pmEnd: pieceEnd
116
+ }, context.toSource)
117
+ });
118
+ if (pieceEnd === pmEnd) return;
119
+ pieceStart = pieceEnd;
120
+ }
121
+ }
122
+ //#endregion
123
+ export { remapMarkupViewBlocks };
@@ -65,7 +65,7 @@ function convertTableCell(node, startPos, options, tableCellMargins) {
65
65
  blocks.push(block);
66
66
  } else if (child.type.name === "table") blocks.push(convertTable(child, childStart, options));
67
67
  else if (child.type.name === "textBox") blocks.push(convertTextBoxNode(child, childStart, options));
68
- else if (child.type.name === "blockSdt") {
68
+ else if (child.type.name === "blockSdt" || child.type.name === "blockCustomXml") {
69
69
  let sdtChildStart = childStart + 1;
70
70
  child.forEach((sdtChild) => {
71
71
  convertCellChild(sdtChild, sdtChildStart);
@@ -192,13 +192,22 @@ function toFlowBlocks(doc, options = {}) {
192
192
  trailingPageBreakSectionPositions.add(childStart);
193
193
  consumedPageBreakPositions.add(childStart + child.nodeSize);
194
194
  }
195
- if (child.type.name === "blockSdt") collectTrailingPageBreakSections(child, childStart + 1);
195
+ if (child.type.name === "blockSdt" || child.type.name === "blockCustomXml") collectTrailingPageBreakSections(child, childStart + 1);
196
196
  childStart += child.nodeSize;
197
197
  }
198
198
  };
199
199
  collectTrailingPageBreakSections(doc, offset);
200
200
  const visit = (node, pos) => {
201
201
  switch (node.type.name) {
202
+ case "blockCustomXml": {
203
+ let childOffset = pos + 1;
204
+ for (let i = 0; i < node.childCount; i += 1) {
205
+ const child = node.child(i);
206
+ visit(child, childOffset);
207
+ childOffset += child.nodeSize;
208
+ }
209
+ return;
210
+ }
202
211
  case "blockSdt": {
203
212
  const attrs = expectBlockSdtAttrs(node);
204
213
  sdtSeq += 1;
@@ -32,6 +32,13 @@ type LayoutInstrumentation = {
32
32
  onLayoutStart?: (event: {
33
33
  reason: LayoutRunReason;
34
34
  }) => void;
35
+ /**
36
+ * A review view (the editor's `DisplayMode`) laid out part of the story as
37
+ * authored: a revision there has no resolution.
38
+ */
39
+ onMarkupViewIncomplete?: (event: {
40
+ view: string;
41
+ }) => void;
35
42
  onLayoutPhase?: (event: {
36
43
  durationMs: number;
37
44
  phase: LayoutPhase;
@@ -55,6 +62,7 @@ declare function recordMeasureBlockError(blockIndex: number, block: FlowBlock, e
55
62
  declare function recordLayoutComplete(reason?: LayoutRunReason): void;
56
63
  declare function recordLayoutStart(reason: LayoutRunReason): void;
57
64
  declare function recordLayoutError(reason: LayoutRunReason, error: unknown): void;
65
+ declare function recordMarkupViewIncomplete(view: string): void;
58
66
  /** A dictionary failed to load; layout continues without hyphenating that language. */
59
67
  declare function recordHyphenationDictionaryError(dictionary: string, error: Error): void;
60
68
  declare function recordLayoutPhase(reason: LayoutRunReason, phase: LayoutPhase, durationMs: number): void;
@@ -62,4 +70,4 @@ declare function recordHiddenEditorStateCreate(reason: HiddenEditorStateReason):
62
70
  declare function recordHiddenEditorPhase(reason: HiddenEditorStateReason, phase: HiddenEditorPhase, durationMs: number): void;
63
71
  declare function recordDocumentLoadPhase(phase: DocumentLoadPhase, durationMs: number): void;
64
72
  //#endregion
65
- export { DocumentLoadPhase, HiddenEditorPhase, HiddenEditorStateReason, LayoutInstrumentation, LayoutPhase, LayoutRunReason, recordDocumentLoadPhase, recordHiddenEditorPhase, recordHiddenEditorStateCreate, recordHyphenationDictionaryError, recordLayoutComplete, recordLayoutError, recordLayoutPhase, recordLayoutStart, recordMeasureBlock, recordMeasureBlockError };
73
+ export { DocumentLoadPhase, HiddenEditorPhase, HiddenEditorStateReason, LayoutInstrumentation, LayoutPhase, LayoutRunReason, recordDocumentLoadPhase, recordHiddenEditorPhase, recordHiddenEditorStateCreate, recordHyphenationDictionaryError, recordLayoutComplete, recordLayoutError, recordLayoutPhase, recordLayoutStart, recordMarkupViewIncomplete, recordMeasureBlock, recordMeasureBlockError };
@@ -25,6 +25,9 @@ function recordLayoutError(reason, error) {
25
25
  reason
26
26
  });
27
27
  }
28
+ function recordMarkupViewIncomplete(view) {
29
+ globalThis.__folioLayoutInstrumentation?.onMarkupViewIncomplete?.({ view });
30
+ }
28
31
  /** A dictionary failed to load; layout continues without hyphenating that language. */
29
32
  function recordHyphenationDictionaryError(dictionary, error) {
30
33
  globalThis.__folioLayoutInstrumentation?.onHyphenationDictionaryError?.({
@@ -56,4 +59,4 @@ function recordDocumentLoadPhase(phase, durationMs) {
56
59
  });
57
60
  }
58
61
  //#endregion
59
- export { recordDocumentLoadPhase, recordHiddenEditorPhase, recordHiddenEditorStateCreate, recordHyphenationDictionaryError, recordLayoutComplete, recordLayoutError, recordLayoutPhase, recordLayoutStart, recordMeasureBlock, recordMeasureBlockError };
62
+ export { recordDocumentLoadPhase, recordHiddenEditorPhase, recordHiddenEditorStateCreate, recordHyphenationDictionaryError, recordLayoutComplete, recordLayoutError, recordLayoutPhase, recordLayoutStart, recordMarkupViewIncomplete, recordMeasureBlock, recordMeasureBlockError };
@@ -83,9 +83,26 @@ declare function getParagraphCacheSize(): number;
83
83
  * Call when fonts change, page width changes, or for testing
84
84
  */
85
85
  declare function clearAllCaches(): void;
86
+ /**
87
+ * Bind the caches to the font set the next measurements are taken in. When a
88
+ * face has loaded (or been added or removed) since the cached entries were
89
+ * measured, they are dropped: a width measured in a fallback cannot be served
90
+ * once the face it stood in for is available. Entries measured before the
91
+ * caches were first bound are dropped too: nothing records their font set.
92
+ * Returns whether it cleared.
93
+ */
94
+ declare function syncMeasureCachesToFontSet(fontSet: string): boolean;
95
+ /**
96
+ * Rename the font set the cached entries were measured in, without dropping
97
+ * them: for a layout run that has just measured, whose signature now also
98
+ * names the families it measured first. Only valid within the run that bound
99
+ * the caches with {@link syncMeasureCachesToFontSet}, since no face can load
100
+ * during a synchronous run.
101
+ */
102
+ declare function labelMeasureCachesFontSet(fontSet: string): void;
86
103
  /**
87
104
  * Get total size of all caches
88
105
  */
89
106
  declare function getTotalCacheSize(): number;
90
107
  //#endregion
91
- export { clearAllCaches, clearFontMetricsCache, clearParagraphMeasureCache, clearTextWidthCache, getCachedFontMetrics, getCachedParagraphMeasure, getCachedTextWidth, getFontCacheSize, getParagraphCacheSize, getTextCacheSize, getTextWidthCacheGeneration, getTotalCacheSize, hashParagraphBlock, setCachedFontMetrics, setCachedParagraphMeasure, setCachedTextWidth, setFontCacheSize, setParagraphCacheSize, setTextCacheSize };
108
+ export { clearAllCaches, clearFontMetricsCache, clearParagraphMeasureCache, clearTextWidthCache, getCachedFontMetrics, getCachedParagraphMeasure, getCachedTextWidth, getFontCacheSize, getParagraphCacheSize, getTextCacheSize, getTextWidthCacheGeneration, getTotalCacheSize, hashParagraphBlock, labelMeasureCachesFontSet, setCachedFontMetrics, setCachedParagraphMeasure, setCachedTextWidth, setFontCacheSize, setParagraphCacheSize, setTextCacheSize, syncMeasureCachesToFontSet };
@@ -259,6 +259,11 @@ function getParagraphCacheSize() {
259
259
  return paragraphMeasureCache.size;
260
260
  }
261
261
  /**
262
+ * The font set (a `readFontSetSignature` value) every cached measurement was
263
+ * taken in; `null` once the caches are cleared and before anything measures.
264
+ */
265
+ let cachedFontSet = null;
266
+ /**
262
267
  * Clear all measurement caches
263
268
  * Call when fonts change, page width changes, or for testing
264
269
  */
@@ -267,6 +272,31 @@ function clearAllCaches() {
267
272
  clearFontMetricsCache();
268
273
  clearParagraphMeasureCache();
269
274
  clearFontResolvedCache();
275
+ cachedFontSet = null;
276
+ }
277
+ /**
278
+ * Bind the caches to the font set the next measurements are taken in. When a
279
+ * face has loaded (or been added or removed) since the cached entries were
280
+ * measured, they are dropped: a width measured in a fallback cannot be served
281
+ * once the face it stood in for is available. Entries measured before the
282
+ * caches were first bound are dropped too: nothing records their font set.
283
+ * Returns whether it cleared.
284
+ */
285
+ function syncMeasureCachesToFontSet(fontSet) {
286
+ if (cachedFontSet === fontSet) return false;
287
+ clearAllCaches();
288
+ cachedFontSet = fontSet;
289
+ return true;
290
+ }
291
+ /**
292
+ * Rename the font set the cached entries were measured in, without dropping
293
+ * them: for a layout run that has just measured, whose signature now also
294
+ * names the families it measured first. Only valid within the run that bound
295
+ * the caches with {@link syncMeasureCachesToFontSet}, since no face can load
296
+ * during a synchronous run.
297
+ */
298
+ function labelMeasureCachesFontSet(fontSet) {
299
+ cachedFontSet = fontSet;
270
300
  }
271
301
  /**
272
302
  * Get total size of all caches
@@ -275,4 +305,4 @@ function getTotalCacheSize() {
275
305
  return getTextCacheSize() + getFontCacheSize() + getParagraphCacheSize();
276
306
  }
277
307
  //#endregion
278
- export { clearAllCaches, clearFontMetricsCache, clearParagraphMeasureCache, clearTextWidthCache, getCachedFontMetrics, getCachedParagraphMeasure, getCachedTextWidth, getFontCacheSize, getParagraphCacheSize, getTextCacheSize, getTextWidthCacheGeneration, getTotalCacheSize, hashParagraphBlock, setCachedFontMetrics, setCachedParagraphMeasure, setCachedTextWidth, setFontCacheSize, setParagraphCacheSize, setTextCacheSize };
308
+ export { clearAllCaches, clearFontMetricsCache, clearParagraphMeasureCache, clearTextWidthCache, getCachedFontMetrics, getCachedParagraphMeasure, getCachedTextWidth, getFontCacheSize, getParagraphCacheSize, getTextCacheSize, getTextWidthCacheGeneration, getTotalCacheSize, hashParagraphBlock, labelMeasureCachesFontSet, setCachedFontMetrics, setCachedParagraphMeasure, setCachedTextWidth, setFontCacheSize, setParagraphCacheSize, setTextCacheSize, syncMeasureCachesToFontSet };
@@ -1,4 +1,4 @@
1
- import { WORKER_FONT_FINGERPRINT_TEXT, countCodePoints } from "./measureWorkerProtocol.js";
1
+ import { countCodePoints } from "./measureWorkerProtocol.js";
2
2
  import { TaggedError } from "better-result";
3
3
  //#region src/layout-engine/measure/font-metrics.worker.ts
4
4
  /**
@@ -36,16 +36,12 @@ function getCtx() {
36
36
  ctx = next;
37
37
  return ctx;
38
38
  }
39
- function isFontFingerprintMatch(context, expectedWidth) {
40
- const actualWidth = context.measureText(WORKER_FONT_FINGERPRINT_TEXT).width;
41
- const tolerance = Math.max(FONT_FINGERPRINT_EPSILON, expectedWidth * 1e-4);
42
- return Math.abs(actualWidth - expectedWidth) <= tolerance;
43
- }
44
39
  function measureEntry(entry) {
45
40
  const context = getCtx();
46
41
  context.font = entry.font;
47
42
  context.fontKerning = entry.fontKerning;
48
- if (!isFontFingerprintMatch(context, entry.fontFingerprintWidth)) return null;
43
+ const actualFingerprintWidth = context.measureText(entry.fontFingerprintText).width;
44
+ if (Math.abs(actualFingerprintWidth - entry.fontFingerprintWidth) > FONT_FINGERPRINT_EPSILON) return null;
49
45
  let width = context.measureText(entry.text).width;
50
46
  const codePoints = countCodePoints(entry.text);
51
47
  if (entry.letterSpacing !== 0 && codePoints > 1) width += entry.letterSpacing * (codePoints - 1);
@@ -1,11 +1,11 @@
1
1
  import { getHorizontalScaleFactor } from "../../utils/horizontalScale.js";
2
2
  import { SCRIPT_CLASS, hasComplexScript, hasEastAsiaSlotText, scriptClassOf, segmentByScript } from "../../utils/scriptSegments.js";
3
- import { getCachedFontMetrics, getCachedTextWidth, getTextWidthCacheGeneration, setCachedFontMetrics, setCachedTextWidth } from "./cache.js";
3
+ import { getCachedFontMetrics, getCachedTextWidth, setCachedFontMetrics, setCachedTextWidth } from "./cache.js";
4
4
  import { applyComplexScriptFormatting, hasComplexScriptFormatting } from "./complexScriptFormatting.js";
5
5
  import { buildFontString, getResolvedData, ptToPx } from "./measureHelpers.js";
6
6
  import { setMeasureProvider } from "./measureProvider.js";
7
7
  import { canPrefetchMeasurement, prefetchMeasurement } from "./measureWorker.js";
8
- import { WORKER_FONT_FINGERPRINT_TEXT, countCodePoints } from "./measureWorkerProtocol.js";
8
+ import { countCodePoints } from "./measureWorkerProtocol.js";
9
9
  import { SMALL_CAPS_SCALE, smallCapsMask, smallCapsSegments } from "./smallCapsCasing.js";
10
10
  import { getFontKerningMode } from "./textMeasurementPolicy.js";
11
11
  import { panic } from "better-result";
@@ -31,7 +31,6 @@ const DEFAULT_LINE_HEIGHT_MULTIPLIER = 1;
31
31
  const DEFAULT_ASCENT_RATIO = .8;
32
32
  const DEFAULT_DESCENT_RATIO = .2;
33
33
  let canvasContext = null;
34
- const workerFontFingerprintCache = /* @__PURE__ */ new Map();
35
34
  /**
36
35
  * Get or create a canvas 2D context for text measurement
37
36
  */
@@ -50,19 +49,6 @@ function getCanvasContext() {
50
49
  function resetCanvasContext() {
51
50
  canvasContext = null;
52
51
  }
53
- function getWorkerFontFingerprintWidth(ctx, font, fontCacheKey, fontKerning) {
54
- const generation = getTextWidthCacheGeneration();
55
- const cached = workerFontFingerprintCache.get(fontCacheKey);
56
- if (cached?.generation === generation) return cached.width;
57
- ctx.font = font;
58
- ctx.fontKerning = fontKerning;
59
- const width = ctx.measureText(WORKER_FONT_FINGERPRINT_TEXT).width;
60
- workerFontFingerprintCache.set(fontCacheKey, {
61
- generation,
62
- width
63
- });
64
- return width;
65
- }
66
52
  /**
67
53
  * Get typography metrics for a given font size and family
68
54
  *
@@ -149,7 +135,8 @@ function canvasMeasureTextWidth(text, sourceStyle) {
149
135
  if (cached !== void 0) return cached;
150
136
  ctx.font = font;
151
137
  ctx.fontKerning = fontKerning;
152
- let width = ctx.measureText(measuredText).width;
138
+ const metrics = ctx.measureText(measuredText);
139
+ let width = metrics.width;
153
140
  if (letterSpacing) {
154
141
  const codePoints = countCodePoints(measuredText);
155
142
  if (codePoints > 1) width += letterSpacing * (codePoints - 1);
@@ -157,17 +144,18 @@ function canvasMeasureTextWidth(text, sourceStyle) {
157
144
  const scaledWidth = width * horizontalScale;
158
145
  setCachedTextWidth(measuredText, fontCacheKey, letterSpacing, scaledWidth);
159
146
  if (!canPrefetchMeasurement()) return scaledWidth;
160
- const fontFingerprintWidth = getWorkerFontFingerprintWidth(ctx, font, fontCacheKey, fontKerning);
147
+ const fontFingerprintText = measuredText;
148
+ const fontFingerprintWidth = metrics.width;
161
149
  prefetchMeasurement({
162
150
  text: measuredText,
163
151
  font,
164
152
  letterSpacing,
165
153
  horizontalScale,
166
154
  fontCacheKey,
155
+ fontFingerprintText,
167
156
  fontFingerprintWidth,
168
157
  fontKerning
169
158
  });
170
- prefetchBinarySearchProbes(measuredText, font, fontCacheKey, fontFingerprintWidth, letterSpacing, horizontalScale, fontKerning);
171
159
  return scaledWidth;
172
160
  }
173
161
  /**
@@ -262,34 +250,6 @@ function measureSmallCapsWidth(measuredText, style) {
262
250
  return width * horizontalScale;
263
251
  }
264
252
  /**
265
- * Speculatively enqueue the slice lengths that a subsequent
266
- * `findMaxFittingLength` binary search is likely to probe. We pick the
267
- * geometric series (full, half, quarter, eighth) which covers the
268
- * majority of probe points the binary search uses, without flooding
269
- * the worker for runs that will never trigger a line break.
270
- *
271
- * The worker is racing the main thread here: if the main thread asks
272
- * for slice(0, n/2) before the worker has answered, the cache miss
273
- * pays the main-thread cost as usual. When the worker wins, that probe
274
- * lands on a hit.
275
- */
276
- function prefetchBinarySearchProbes(text, font, fontCacheKey, fontFingerprintWidth, letterSpacing, horizontalScale, fontKerning) {
277
- if (text.length < 4) return;
278
- for (let denom = 2; denom <= 8; denom *= 2) {
279
- const len = Math.floor(text.length / denom);
280
- if (len < 2) break;
281
- prefetchMeasurement({
282
- text: text.slice(0, len),
283
- font,
284
- letterSpacing,
285
- horizontalScale,
286
- fontCacheKey,
287
- fontFingerprintWidth,
288
- fontKerning
289
- });
290
- }
291
- }
292
- /**
293
253
  * Measure text and return full metrics
294
254
  */
295
255
  function canvasMeasureText(text, style) {
@@ -34,6 +34,11 @@ type ResolvedFontCache = {
34
34
  * Get the resolved font data for a font family, with caching.
35
35
  */
36
36
  declare function getResolvedData(fontFamily: string, alternateFontFamily?: string): ResolvedFontCache;
37
+ /**
38
+ * Whether a face of `family` (a `FontFace.family`, possibly quoted) can change
39
+ * a width this page has measured.
40
+ */
41
+ declare function isLayoutFontFamily(family: string): boolean;
37
42
  /**
38
43
  * Clear the resolved-font-family cache. `resolveFontFamily`'s output for a
39
44
  * given key can change even when the raw font names don't — e.g. when the
@@ -100,4 +105,4 @@ declare function halfPtToPx(halfPt: number): number;
100
105
  */
101
106
  declare function pxToHalfPt(px: number): number;
102
107
  //#endregion
103
- export { DEFAULT_FONT_FAMILY, DEFAULT_FONT_SIZE, buildFontString, buildRunFontStyle, clearFontResolvedCache, docxScriptFontSize, findCharacterAtX, getResolvedData, getXForCharacter, halfPtToPx, ptToPx, pxToHalfPt, pxToPt, pxToTwips, twipsToPx };
108
+ export { DEFAULT_FONT_FAMILY, DEFAULT_FONT_SIZE, buildFontString, buildRunFontStyle, clearFontResolvedCache, docxScriptFontSize, findCharacterAtX, getResolvedData, getXForCharacter, halfPtToPx, isLayoutFontFamily, ptToPx, pxToHalfPt, pxToPt, pxToTwips, twipsToPx };
@@ -1,4 +1,4 @@
1
- import { resolveFontFamily } from "../../utils/fontResolver.js";
1
+ import { parseFontFamilyList, resolveFontFamily } from "../../utils/fontResolver.js";
2
2
  import "../../utils/fontWeights.js";
3
3
  import { normalizeHorizontalScalePercent } from "../../utils/horizontalScale.js";
4
4
  import { eastAsiaHintApplies } from "../../utils/scriptSegments.js";
@@ -93,10 +93,30 @@ function getResolvedData(fontFamily, alternateFontFamily) {
93
93
  singleLineRatio: resolved.singleLineRatio
94
94
  };
95
95
  fontResolvedCache.set(cacheKey, cached);
96
+ for (const family of parseFontFamilyList(resolved.cssFallback)) layoutFontFamilies.add(normalizeFontFamilyName(family));
96
97
  }
97
98
  return cached;
98
99
  }
99
100
  /**
101
+ * Every family a measured font stack has named on this page, normalized.
102
+ *
103
+ * Recorded where measurement resolves its stacks, so it is exactly the set of
104
+ * families whose faces can change a measured width: a face of any other family
105
+ * loading (the host's UI font, say) cannot. Never cleared, because a family
106
+ * stays relevant for as long as a cached or committed measurement may hold it,
107
+ * and the set is bounded by the families the page's documents name.
108
+ */
109
+ const layoutFontFamilies = /* @__PURE__ */ new Set();
110
+ /** CSS family names match ASCII case-insensitively, quotes aside. */
111
+ const normalizeFontFamilyName = (family) => family.trim().replace(/^(["'])(.*)\1$/u, "$2").toLowerCase();
112
+ /**
113
+ * Whether a face of `family` (a `FontFace.family`, possibly quoted) can change
114
+ * a width this page has measured.
115
+ */
116
+ function isLayoutFontFamily(family) {
117
+ return layoutFontFamilies.has(normalizeFontFamilyName(family));
118
+ }
119
+ /**
100
120
  * Get the CSS fallback string for a font family, with caching.
101
121
  */
102
122
  function getResolvedFallback(fontFamily, alternateFontFamily) {
@@ -207,4 +227,4 @@ function pxToHalfPt(px) {
207
227
  return pxToPt(px) * 2;
208
228
  }
209
229
  //#endregion
210
- export { DEFAULT_FONT_FAMILY, DEFAULT_FONT_SIZE, buildFontString, buildRunFontStyle, clearFontResolvedCache, docxScriptFontSize, findCharacterAtX, getResolvedData, getXForCharacter, halfPtToPx, ptToPx, pxToHalfPt, pxToPt, pxToTwips, twipsToPx };
230
+ export { DEFAULT_FONT_FAMILY, DEFAULT_FONT_SIZE, buildFontString, buildRunFontStyle, clearFontResolvedCache, docxScriptFontSize, findCharacterAtX, getResolvedData, getXForCharacter, halfPtToPx, isLayoutFontFamily, ptToPx, pxToHalfPt, pxToPt, pxToTwips, twipsToPx };
@@ -15,7 +15,7 @@ import { applyDocumentGrid, calculateEmptyParagraphMetrics, calculateTypographyM
15
15
  import { getListMarkerInlineWidth } from "./listMarkerWidth.js";
16
16
  import { DEFAULT_FONT_FAMILY, buildRunFontStyle, ptToPx } from "./measureHelpers.js";
17
17
  import { getFontMetrics, measureRun, measureTextWidth } from "./measureProvider.js";
18
- import { WIDTH_TOLERANCE, fieldMeasureText, isEmptyTextRun, isFieldRun, isImageRun, isLineBreakRun, isMathRun, isTabRun, isTextRun, runToFontStyle } from "./paragraphMeasureShared.js";
18
+ import { WIDTH_TOLERANCE, canonicalLineWidth, fieldMeasureText, isEmptyTextRun, isFieldRun, isImageRun, isLineBreakRun, isMathRun, isTabRun, isTextRun, runToFontStyle } from "./paragraphMeasureShared.js";
19
19
  import { canClampTabToRightEdge, hasFollowingTabOnLine, hasPriorTabOnLine, measureDecimalPrefixWidthAfterTab, measureInlineWidthAfterTab } from "./paragraphTabs.js";
20
20
  import { calculateTabWidth, pixelsToTwips } from "./tabCalculator.js";
21
21
  //#region src/layout-engine/measure/measureParagraph.ts
@@ -215,7 +215,7 @@ function measureParagraph(block, maxWidth, options) {
215
215
  fromChar: currentLine.fromChar,
216
216
  toRun: currentLine.toRun,
217
217
  toChar: currentLine.toChar,
218
- width: Math.max(0, currentLine.width - currentLine.trailingWhitespaceWidth),
218
+ width: canonicalLineWidth(currentLine.width - currentLine.trailingWhitespaceWidth),
219
219
  ...finalTypography,
220
220
  ...currentLine.justificationPaint !== void 0 ? { justificationPaint: currentLine.justificationPaint } : {},
221
221
  ...currentLine.discretionaryHyphen ? { discretionaryHyphen: currentLine.discretionaryHyphen } : {},
@@ -118,9 +118,8 @@ function ensureProxy() {
118
118
  }
119
119
  /**
120
120
  * How long to wait before flushing the queue, in milliseconds. Short
121
- * enough to keep the worker warm and ahead of the binary-search probes,
122
- * long enough to amortise `postMessage` overhead across a typical
123
- * paragraph's worth of probes.
121
+ * enough to process measured entries promptly, long enough to amortise
122
+ * `postMessage` overhead across a typical paragraph's runs.
124
123
  */
125
124
  const FLUSH_INTERVAL_MS = 10;
126
125
  /**
@@ -14,22 +14,21 @@ import { FontKerningMode } from "./textMeasurementPolicy.js";
14
14
  * `fontCacheKey` is the main-thread cache identity. It intentionally
15
15
  * differs from `font` when scale metadata is appended.
16
16
  *
17
- * `fontFingerprintWidth` is the main-thread width for
18
- * `WORKER_FONT_FINGERPRINT_TEXT` in the same `font`. The worker checks
19
- * the same sentinel before measuring and skips entries whose font
20
- * metrics do not match, which prevents worker fallback fonts from
21
- * poisoning the main-thread cache.
17
+ * `fontFingerprintText` is text already measured on the main thread in
18
+ * this font. The worker checks its unscaled width against
19
+ * `fontFingerprintWidth` before caching a result. This covers the actual
20
+ * glyphs and font subsets used by the request, including non-Latin text.
22
21
  */
23
22
  type MeasureRequestEntry = {
24
23
  text: string;
25
24
  font: string;
26
25
  fontCacheKey: string;
26
+ fontFingerprintText: string;
27
27
  fontFingerprintWidth: number;
28
28
  letterSpacing: number;
29
29
  horizontalScale: number;
30
30
  fontKerning: FontKerningMode;
31
31
  };
32
- declare const WORKER_FONT_FINGERPRINT_TEXT = "HAMBURGEFONTS ivwqy 0123456789";
33
32
  /**
34
33
  * Count whole code points (not UTF-16 units) so letter spacing is applied once
35
34
  * per rendered glyph — an astral character is one glyph spanning two units.
@@ -73,4 +72,4 @@ type MeasureWorkerResponse = {
73
72
  error: string;
74
73
  };
75
74
  //#endregion
76
- export { MeasureRequestEntry, MeasureResponseEntry, MeasureWorkerRequest, MeasureWorkerResponse, WORKER_FONT_FINGERPRINT_TEXT, countCodePoints };
75
+ export { MeasureRequestEntry, MeasureResponseEntry, MeasureWorkerRequest, MeasureWorkerResponse, countCodePoints };
@@ -1,5 +1,4 @@
1
1
  //#region src/layout-engine/measure/measureWorkerProtocol.ts
2
- const WORKER_FONT_FINGERPRINT_TEXT = "HAMBURGEFONTS ivwqy 0123456789";
3
2
  /**
4
3
  * Count whole code points (not UTF-16 units) so letter spacing is applied once
5
4
  * per rendered glyph — an astral character is one glyph spanning two units.
@@ -17,4 +16,4 @@ function countCodePoints(text) {
17
16
  return count;
18
17
  }
19
18
  //#endregion
20
- export { WORKER_FONT_FINGERPRINT_TEXT, countCodePoints };
19
+ export { countCodePoints };
@@ -5,6 +5,17 @@ import { FloatingLineSegmentZone } from "./floatingZones.js";
5
5
  declare const DEFAULT_FONT_SIZE = 11;
6
6
  declare const DEFAULT_LINE_HEIGHT_MULTIPLIER = 1;
7
7
  declare const WIDTH_TOLERANCE = 0.5;
8
+ /**
9
+ * The width a finished line reports. A line's width is a floating-point sum
10
+ * of per-token measurements, and the same text can reach it through different
11
+ * token groupings, e.g. a run split where a hidden revision sat measures
12
+ * "confirm" + "ation" where the resolved text measures "confirmation". Those
13
+ * sums agree only up to the last few bits, so the result snaps to a
14
+ * binary-exact 1/1024 px grid (under 0.0005 px, far below a device pixel):
15
+ * the same text yields the same width whichever grouping summed it, and the
16
+ * alignment offsets derived from it agree too.
17
+ */
18
+ declare const canonicalLineWidth: (width: number) => number;
8
19
  /**
9
20
  * Typography metrics for a line
10
21
  */
@@ -106,4 +117,4 @@ declare function isEmptyTextRun(run: TextRun): boolean;
106
117
  declare function isBlockLayoutImageRun(run: ImageRun): boolean;
107
118
  declare function isSpaceOrTab(char: string | undefined): boolean;
108
119
  //#endregion
109
- export { DEFAULT_FONT_SIZE, DEFAULT_LINE_HEIGHT_MULTIPLIER, LineState, LineTypography, WIDTH_TOLERANCE, fieldMeasureText, isBlockLayoutImageRun, isEmptyTextRun, isFieldRun, isImageRun, isLineBreakRun, isMathRun, isSpaceOrTab, isTabRun, isTextRun, runToFontStyle };
120
+ export { DEFAULT_FONT_SIZE, DEFAULT_LINE_HEIGHT_MULTIPLIER, LineState, LineTypography, WIDTH_TOLERANCE, canonicalLineWidth, fieldMeasureText, isBlockLayoutImageRun, isEmptyTextRun, isFieldRun, isImageRun, isLineBreakRun, isMathRun, isSpaceOrTab, isTabRun, isTextRun, runToFontStyle };
@@ -4,6 +4,19 @@ import { DEFAULT_FONT_FAMILY, buildRunFontStyle } from "./measureHelpers.js";
4
4
  const DEFAULT_FONT_SIZE = 11;
5
5
  const DEFAULT_LINE_HEIGHT_MULTIPLIER = 1;
6
6
  const WIDTH_TOLERANCE = .5;
7
+ /** Grid a finished line's width snaps to: 1/1024 px, exact in binary floating point. */
8
+ const LINE_WIDTH_GRID = 1024;
9
+ /**
10
+ * The width a finished line reports. A line's width is a floating-point sum
11
+ * of per-token measurements, and the same text can reach it through different
12
+ * token groupings, e.g. a run split where a hidden revision sat measures
13
+ * "confirm" + "ation" where the resolved text measures "confirmation". Those
14
+ * sums agree only up to the last few bits, so the result snaps to a
15
+ * binary-exact 1/1024 px grid (under 0.0005 px, far below a device pixel):
16
+ * the same text yields the same width whichever grouping summed it, and the
17
+ * alignment offsets derived from it agree too.
18
+ */
19
+ const canonicalLineWidth = (width) => Math.round(Math.max(0, width) * LINE_WIDTH_GRID) / LINE_WIDTH_GRID;
7
20
  /**
8
21
  * Extract FontStyle from a run that carries RunFormatting (text, tab, or
9
22
  * field). All three share the same formatting shape, so they measure the
@@ -79,4 +92,4 @@ function isSpaceOrTab(char) {
79
92
  return char === " " || char === " ";
80
93
  }
81
94
  //#endregion
82
- export { DEFAULT_FONT_SIZE, DEFAULT_LINE_HEIGHT_MULTIPLIER, WIDTH_TOLERANCE, fieldMeasureText, isBlockLayoutImageRun, isEmptyTextRun, isFieldRun, isImageRun, isLineBreakRun, isMathRun, isSpaceOrTab, isTabRun, isTextRun, runToFontStyle };
95
+ export { DEFAULT_FONT_SIZE, DEFAULT_LINE_HEIGHT_MULTIPLIER, WIDTH_TOLERANCE, canonicalLineWidth, fieldMeasureText, isBlockLayoutImageRun, isEmptyTextRun, isFieldRun, isImageRun, isLineBreakRun, isMathRun, isSpaceOrTab, isTabRun, isTextRun, runToFontStyle };
@@ -585,6 +585,12 @@ type ParagraphBlock = {
585
585
  * the innermost group and draws boundary chrome per outer→inner level.
586
586
  */
587
587
  sdtGroups?: SdtGroup[];
588
+ /**
589
+ * Set by a review view that lays out resolved text (Simple Markup) on a
590
+ * paragraph whose authored text carries a revision the view resolved: the
591
+ * painter marks it with the change bar its runs no longer show.
592
+ */
593
+ reviewIndicator?: "change-bar";
588
594
  };
589
595
  /**
590
596
  * Cell border specification for rendering.
@@ -1326,6 +1326,7 @@ function collectContentFingerprint(block, parts) {
1326
1326
  if (block.kind === "paragraph") {
1327
1327
  if (block.attrs?.styleId) parts.push(`p:st:${block.attrs.styleId}`);
1328
1328
  if (block.attrs?.alignment) parts.push(`p:al:${block.attrs.alignment}`);
1329
+ if (block.reviewIndicator) parts.push(`p:ri:${block.reviewIndicator}`);
1329
1330
  for (let index = 0; index < block.runs.length; index++) {
1330
1331
  const run = block.runs[index];
1331
1332
  if (!run) continue;
@@ -1500,7 +1500,7 @@ function bordersFormGroup(a, b) {
1500
1500
  if (!a || !b) return false;
1501
1501
  return bordersEqual(a.top, b.top) && bordersEqual(a.bottom, b.bottom) && bordersEqual(a.left, b.left) && bordersEqual(a.right, b.right) && bordersEqual(a.between, b.between);
1502
1502
  }
1503
- const paragraphHasTrackedChanges = (block) => block.attrs?.listMarkerRevision !== void 0 || block.runs.some((run) => run.kind !== "lineBreak" && (run.isInsertion === true || run.isDeletion === true));
1503
+ const paragraphHasTrackedChanges = (block) => block.reviewIndicator === "change-bar" || block.attrs?.listMarkerRevision !== void 0 || block.runs.some((run) => run.kind !== "lineBreak" && (run.isInsertion === true || run.isDeletion === true));
1504
1504
  /**
1505
1505
  * Render a paragraph fragment
1506
1506
  *