@stll/folio-core 0.51.0 → 0.53.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 (316) 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 +1519 -105
  4. package/dist/ai-edits/batch-claims.d.ts +130 -0
  5. package/dist/ai-edits/batch-claims.js +244 -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 +71 -7
  14. package/dist/ai-edits/headless.js +381 -41
  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 +1 -1
  26. package/dist/ai-edits/read.js +56 -43
  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/snapshot.d.ts +36 -3
  30. package/dist/ai-edits/snapshot.js +177 -23
  31. package/dist/ai-edits/table-cell-mutations.d.ts +1 -1
  32. package/dist/ai-edits/table-cell-mutations.js +4 -1
  33. package/dist/ai-edits/table-geometry.d.ts +1 -1
  34. package/dist/ai-edits/table-row-column-mutations.d.ts +38 -16
  35. package/dist/ai-edits/table-row-column-mutations.js +61 -26
  36. package/dist/ai-edits/types.d.ts +155 -16
  37. package/dist/compare/compare.d.ts +1 -1
  38. package/dist/compare/compare.js +65 -16
  39. package/dist/compare/content-alignment.js +13 -2
  40. package/dist/compare/content-types.d.ts +7 -0
  41. package/dist/compare/content.d.ts +4 -1
  42. package/dist/compare/content.js +6 -1
  43. package/dist/compare/formatting.js +2 -1
  44. package/dist/compare/inline-atoms.d.ts +21 -4
  45. package/dist/compare/inline-atoms.js +138 -16
  46. package/dist/compare/inline-provenance.js +18 -22
  47. package/dist/compare/plan.js +10 -5
  48. package/dist/compare/scenario.js +14 -3
  49. package/dist/compare/section-boundary-properties.js +14 -1
  50. package/dist/compare/types.d.ts +4 -2
  51. package/dist/compare/types.js +2 -1
  52. package/dist/compare/verification.d.ts +1 -1
  53. package/dist/compare/verification.js +15 -3
  54. package/dist/controller/committedLayoutDiff.d.ts +25 -0
  55. package/dist/controller/committedLayoutDiff.js +71 -0
  56. package/dist/controller/contentControlWidgetController.d.ts +1 -1
  57. package/dist/controller/folioEditor.d.ts +1 -1
  58. package/dist/controller/fontReadiness.d.ts +70 -3
  59. package/dist/controller/fontReadiness.js +100 -10
  60. package/dist/controller/headerFooterEditorManager.js +6 -1
  61. package/dist/controller/layoutPipeline.d.ts +12 -10
  62. package/dist/controller/layoutPipeline.js +62 -9
  63. package/dist/controller/layoutRunOptions.d.ts +24 -0
  64. package/dist/controller/layoutRunOptions.js +17 -0
  65. package/dist/controller/layoutScheduler.d.ts +19 -14
  66. package/dist/controller/layoutScheduler.js +15 -12
  67. package/dist/controller/layoutSession.d.ts +26 -2
  68. package/dist/controller/layoutSession.js +1 -1
  69. package/dist/controller/noteEditorManager.js +8 -3
  70. package/dist/document-operations.d.ts +11 -2
  71. package/dist/document-operations.js +230 -21
  72. package/dist/docx/altChunk.d.ts +8 -0
  73. package/dist/docx/altChunk.js +17 -0
  74. package/dist/docx/attributeRemainder.d.ts +1 -1
  75. package/dist/docx/blockContentParser.d.ts +64 -1
  76. package/dist/docx/blockContentParser.js +17 -4
  77. package/dist/docx/blockCustomXmlShell.d.ts +7 -0
  78. package/dist/docx/blockCustomXmlShell.js +14 -0
  79. package/dist/docx/blockPlainText.js +7 -0
  80. package/dist/docx/commentAnchorIndex.js +1 -1
  81. package/dist/docx/commentRangeIntegrity.js +8 -3
  82. package/dist/docx/commentReferenceNormalization.js +1 -1
  83. package/dist/docx/commentReplyMarkers.js +20 -1
  84. package/dist/docx/compatibility.d.ts +1 -1
  85. package/dist/docx/compatibility.js +34 -13
  86. package/dist/docx/containerChildren.gen.d.ts +1 -1
  87. package/dist/docx/containerChildren.gen.js +1 -0
  88. package/dist/docx/documentParser.js +12 -12
  89. package/dist/docx/drawingIdNormalization.d.ts +3 -1
  90. package/dist/docx/drawingIdNormalization.js +6 -1
  91. package/dist/docx/ensureParaIds.js +119 -97
  92. package/dist/docx/footnoteParser.js +8 -4
  93. package/dist/docx/headerFooterParser.js +3 -3
  94. package/dist/docx/headerFooterReferenceNormalization.d.ts +20 -1
  95. package/dist/docx/headerFooterReferenceNormalization.js +52 -27
  96. package/dist/docx/hyperlinkParser.d.ts +1 -1
  97. package/dist/docx/index.d.ts +1 -1
  98. package/dist/docx/listNumberingInstances.d.ts +59 -0
  99. package/dist/docx/listNumberingInstances.js +249 -0
  100. package/dist/docx/normalizeBaseDirection.js +2 -1
  101. package/dist/docx/opaqueCarrier.d.ts +7 -0
  102. package/dist/docx/opaqueCarrier.js +38 -0
  103. package/dist/docx/packageParts.js +4 -1
  104. package/dist/docx/paragraphParser.js +91 -24
  105. package/dist/docx/paragraphPropertySource.d.ts +4 -2
  106. package/dist/docx/paragraphPropertySource.js +7 -1
  107. package/dist/docx/paragraphTraversal.js +1 -0
  108. package/dist/docx/parseWarningMessage.js +4 -1
  109. package/dist/docx/parser.js +173 -20
  110. package/dist/docx/rezip.js +27 -5
  111. package/dist/docx/sdtProperties.js +1 -1
  112. package/dist/docx/sdtPropertiesPatch.js +3 -0
  113. package/dist/docx/selectiveSave.js +16 -9
  114. package/dist/docx/selectiveXmlPatch.js +106 -37
  115. package/dist/docx/serializer/blockCustomXmlSerializer.d.ts +5 -0
  116. package/dist/docx/serializer/blockCustomXmlSerializer.js +4 -0
  117. package/dist/docx/serializer/documentSerializer.js +2 -0
  118. package/dist/docx/serializer/headerFooterSerializer.js +2 -0
  119. package/dist/docx/serializer/noteSerializer.js +3 -1
  120. package/dist/docx/serializer/paragraphSerializer.js +33 -9
  121. package/dist/docx/serializer/tableSerializer.js +25 -38
  122. package/dist/docx/server/createBilingualDocument.js +3 -3
  123. package/dist/docx/tableParser.d.ts +157 -1
  124. package/dist/docx/tableParser.js +89 -10
  125. package/dist/docx/textBoxParser.js +1 -1
  126. package/dist/docx/unzip.d.ts +2 -1
  127. package/dist/docx/unzip.js +1 -1
  128. package/dist/docx/wordprocessingPrefixes.d.ts +78 -0
  129. package/dist/docx/wordprocessingPrefixes.js +286 -0
  130. package/dist/generated/text_shaper.js +26 -0
  131. package/dist/generated/text_shaper_bg.wasm +0 -0
  132. package/dist/i18n/messages/catalogs.gen.d.ts +136 -0
  133. package/dist/i18n/messages/catalogs.gen.js +153 -17
  134. package/dist/i18n/messages/messages.gen.d.ts +8 -0
  135. package/dist/internal/compare/inline-presentation.d.ts +2 -1
  136. package/dist/internal/compare/inline-presentation.js +11 -10
  137. package/dist/internal/headlessRevisionResolutionGuard.d.ts +2 -8
  138. package/dist/internal/headlessRevisionResolutionGuard.js +2 -11
  139. package/dist/internal/indexedPositionMap.d.ts +11 -0
  140. package/dist/internal/indexedPositionMap.js +42 -0
  141. package/dist/internal/pageBreakRunSourceDescendantIndex.js +2 -1
  142. package/dist/internal/revisionResolutionEdits.d.ts +13 -0
  143. package/dist/internal/revisionResolutionEdits.js +19 -0
  144. package/dist/internal/revisionResolutionInline.d.ts +24 -0
  145. package/dist/internal/{headlessRevisionResolution.js → revisionResolutionInline.js} +61 -43
  146. package/dist/internal/revisionResolutionStep.d.ts +34 -0
  147. package/dist/internal/revisionResolutionStep.js +282 -0
  148. package/dist/internal/revisionResolutionTracking.d.ts +11 -0
  149. package/dist/internal/revisionResolutionTracking.js +124 -0
  150. package/dist/internal/wholeStoryRevisionResolution.d.ts +56 -0
  151. package/dist/internal/wholeStoryRevisionResolution.js +530 -0
  152. package/dist/layout-bridge/convert/markupViewFlow.d.ts +20 -0
  153. package/dist/layout-bridge/convert/markupViewFlow.js +123 -0
  154. package/dist/layout-bridge/convert/tableConversion.js +1 -1
  155. package/dist/layout-bridge/convert/toFlowBlocks.js +10 -1
  156. package/dist/layout-engine/layoutInstrumentation.d.ts +9 -1
  157. package/dist/layout-engine/layoutInstrumentation.js +4 -1
  158. package/dist/layout-engine/measure/cache.d.ts +18 -1
  159. package/dist/layout-engine/measure/cache.js +31 -1
  160. package/dist/layout-engine/measure/font-metrics.worker.js +3 -7
  161. package/dist/layout-engine/measure/measureContainer.js +7 -47
  162. package/dist/layout-engine/measure/measureHelpers.d.ts +6 -1
  163. package/dist/layout-engine/measure/measureHelpers.js +22 -2
  164. package/dist/layout-engine/measure/measureWorker.js +2 -3
  165. package/dist/layout-engine/measure/measureWorkerProtocol.d.ts +6 -7
  166. package/dist/layout-engine/measure/measureWorkerProtocol.js +1 -2
  167. package/dist/layout-engine/types.d.ts +6 -0
  168. package/dist/layout-painter/renderPage.js +1 -0
  169. package/dist/layout-painter/renderParagraph.js +1 -1
  170. package/dist/managers/ContextMenuManager.js +5 -2
  171. package/dist/managers/types.d.ts +3 -0
  172. package/dist/markdown/fromMarkdown.js +2 -1
  173. package/dist/markdown/internals.d.ts +11 -1
  174. package/dist/markdown/internals.js +24 -3
  175. package/dist/markdown/renderBlock.js +39 -9
  176. package/dist/markdown/renderParagraph.d.ts +13 -1
  177. package/dist/markdown/renderParagraph.js +85 -38
  178. package/dist/markdown/renderRuns.js +3 -10
  179. package/dist/markdown/renderTable.js +24 -12
  180. package/dist/markdown/trailers.js +2 -2
  181. package/dist/markdown/types.d.ts +29 -7
  182. package/dist/paged-layout/incrementalMeasure.d.ts +1 -2
  183. package/dist/paged-layout/incrementalMeasure.js +1 -9
  184. package/dist/paged-layout/transactionDirtyRange.d.ts +1 -3
  185. package/dist/paged-layout/transactionDirtyRange.js +29 -41
  186. package/dist/panel-layout.d.ts +83 -0
  187. package/dist/panel-layout.js +96 -0
  188. package/dist/prosemirror/anchoredTextBoxes.d.ts +37 -0
  189. package/dist/prosemirror/anchoredTextBoxes.js +156 -0
  190. package/dist/prosemirror/attrs/index.d.ts +6 -2
  191. package/dist/prosemirror/attrs/index.js +172 -1
  192. package/dist/prosemirror/commands/comments.d.ts +7 -8
  193. package/dist/prosemirror/commands/comments.js +241 -207
  194. package/dist/prosemirror/commands/contentControls.d.ts +1 -1
  195. package/dist/prosemirror/commands/formatPainter.d.ts +1 -1
  196. package/dist/prosemirror/commands/formatting.d.ts +1 -1
  197. package/dist/prosemirror/commands/index.d.ts +2 -2
  198. package/dist/prosemirror/commands/index.js +2 -2
  199. package/dist/prosemirror/commands/paragraph.d.ts +7 -1
  200. package/dist/prosemirror/commands/paragraph.js +9 -1
  201. package/dist/prosemirror/commands/paragraphBookmarkJoin.d.ts +13 -0
  202. package/dist/prosemirror/commands/paragraphBookmarkJoin.js +22 -0
  203. package/dist/prosemirror/commands/pastePlainText.d.ts +1 -1
  204. package/dist/prosemirror/commands/resolveAllTableChanges.d.ts +40 -0
  205. package/dist/prosemirror/commands/resolveAllTableChanges.js +615 -0
  206. package/dist/prosemirror/commands/resolveNodePropertyChangeAttrs.d.ts +15 -0
  207. package/dist/prosemirror/commands/resolveNodePropertyChangeAttrs.js +46 -0
  208. package/dist/prosemirror/commands/resolveParagraphProperties.d.ts +16 -0
  209. package/dist/prosemirror/commands/resolveParagraphProperties.js +59 -0
  210. package/dist/prosemirror/commands/sectionBreak.js +2 -1
  211. package/dist/prosemirror/commands/tableCellMergeResolution.d.ts +8 -2
  212. package/dist/prosemirror/commands/tableCellMergeResolution.js +1 -1
  213. package/dist/prosemirror/contentControlRevisions.d.ts +1 -1
  214. package/dist/prosemirror/conversion/fromProseDoc.js +181 -31
  215. package/dist/prosemirror/conversion/toProseDoc.js +39 -4
  216. package/dist/prosemirror/emptyFieldResultRuns.d.ts +18 -0
  217. package/dist/prosemirror/emptyFieldResultRuns.js +33 -0
  218. package/dist/prosemirror/extensions/ExtensionManager.d.ts +1 -1
  219. package/dist/prosemirror/extensions/ExtensionManager.js +3 -1
  220. package/dist/prosemirror/extensions/StarterKit.js +3 -1
  221. package/dist/prosemirror/extensions/core/DocExtension.js +1 -1
  222. package/dist/prosemirror/extensions/core/ParagraphExtension.js +12 -0
  223. package/dist/prosemirror/extensions/features/BaseKeymapExtension.js +3 -0
  224. package/dist/prosemirror/extensions/features/ListExtension.js +161 -123
  225. package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.d.ts +19 -2
  226. package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.js +33 -20
  227. package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.d.ts +31 -2
  228. package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.js +270 -99
  229. package/dist/prosemirror/extensions/features/PasteCleanupExtension.js +3 -2
  230. package/dist/prosemirror/extensions/features/pasteCleanup.js +2 -1
  231. package/dist/prosemirror/extensions/features/pastedHtmlLists.d.ts +12 -0
  232. package/dist/prosemirror/extensions/features/pastedHtmlLists.js +126 -0
  233. package/dist/prosemirror/extensions/marks/FootnoteRefExtension.js +21 -5
  234. package/dist/prosemirror/extensions/marks/RunIdentityExtension.d.ts +21 -18
  235. package/dist/prosemirror/extensions/marks/RunIdentityExtension.js +37 -17
  236. package/dist/prosemirror/extensions/marks/markUtils.d.ts +7 -2
  237. package/dist/prosemirror/extensions/marks/markUtils.js +8 -2
  238. package/dist/prosemirror/extensions/marks/noteReferenceDeletion.d.ts +10 -0
  239. package/dist/prosemirror/extensions/marks/noteReferenceDeletion.js +35 -0
  240. package/dist/prosemirror/extensions/nodes/BlockCustomXmlExtension.d.ts +6 -0
  241. package/dist/prosemirror/extensions/nodes/BlockCustomXmlExtension.js +52 -0
  242. package/dist/prosemirror/extensions/nodes/FieldExtension.d.ts +3 -3
  243. package/dist/prosemirror/extensions/nodes/FieldExtension.js +50 -15
  244. package/dist/prosemirror/extensions/nodes/PreservedBlockExtension.js +4 -1
  245. package/dist/prosemirror/extensions/nodes/TableExtension.d.ts +1 -1
  246. package/dist/prosemirror/extensions/nodes/TableExtension.js +19 -18
  247. package/dist/prosemirror/extensions/types.d.ts +4 -1
  248. package/dist/prosemirror/findReplaceSelection.js +1 -1
  249. package/dist/prosemirror/index.d.ts +3 -2
  250. package/dist/prosemirror/index.js +3 -2
  251. package/dist/prosemirror/indexedNodeLookup.d.ts +17 -0
  252. package/dist/prosemirror/indexedNodeLookup.js +103 -0
  253. package/dist/prosemirror/listAutoformatMarkers.d.ts +19 -0
  254. package/dist/prosemirror/listAutoformatMarkers.js +98 -0
  255. package/dist/prosemirror/listInstanceReferences.d.ts +12 -0
  256. package/dist/prosemirror/listInstanceReferences.js +72 -0
  257. package/dist/prosemirror/listLabels.d.ts +24 -0
  258. package/dist/prosemirror/listLabels.js +111 -0
  259. package/dist/prosemirror/listNumbering.d.ts +110 -0
  260. package/dist/prosemirror/listNumbering.js +345 -0
  261. package/dist/prosemirror/listRenderingAttrs.d.ts +11 -2
  262. package/dist/prosemirror/listRenderingAttrs.js +8 -1
  263. package/dist/prosemirror/markupViewProjection.d.ts +95 -0
  264. package/dist/prosemirror/markupViewProjection.js +83 -0
  265. package/dist/prosemirror/numberingAttr.d.ts +9 -1
  266. package/dist/prosemirror/numberingAttr.js +9 -1
  267. package/dist/prosemirror/outlineLevelAttr.js +1 -1
  268. package/dist/prosemirror/paragraphIndentation.d.ts +10 -1
  269. package/dist/prosemirror/paragraphIndentation.js +29 -7
  270. package/dist/prosemirror/paragraphMarkJoin.d.ts +19 -0
  271. package/dist/prosemirror/paragraphMarkJoin.js +24 -0
  272. package/dist/prosemirror/plugins/createDocScanPlugin.d.ts +1 -1
  273. package/dist/prosemirror/plugins/documentNumbering.d.ts +27 -1
  274. package/dist/prosemirror/plugins/documentNumbering.js +97 -11
  275. package/dist/prosemirror/plugins/documentStyles.d.ts +10 -1
  276. package/dist/prosemirror/plugins/documentStyles.js +14 -1
  277. package/dist/prosemirror/plugins/suggestionMode.d.ts +16 -2
  278. package/dist/prosemirror/plugins/suggestionMode.js +116 -52
  279. package/dist/prosemirror/plugins/templateDirectives.d.ts +1 -1
  280. package/dist/prosemirror/plugins/transactionInvariants.d.ts +32 -0
  281. package/dist/prosemirror/plugins/transactionInvariants.js +86 -0
  282. package/dist/prosemirror/positionSweep.d.ts +24 -0
  283. package/dist/prosemirror/positionSweep.js +222 -0
  284. package/dist/prosemirror/rebaseParagraphRunFormatting.d.ts +1 -1
  285. package/dist/prosemirror/rejoinRunCarriers.d.ts +1 -1
  286. package/dist/prosemirror/replacedAnnotations.d.ts +33 -1
  287. package/dist/prosemirror/replacedAnnotations.js +170 -1
  288. package/dist/prosemirror/runFormattingInlineCarriers.d.ts +1 -1
  289. package/dist/prosemirror/runStyleFormatting.d.ts +7 -1
  290. package/dist/prosemirror/runStyleFormatting.js +13 -7
  291. package/dist/prosemirror/schema/index.d.ts +2 -2
  292. package/dist/prosemirror/schema/index.js +3 -0
  293. package/dist/prosemirror/schema/nodes.d.ts +42 -11
  294. package/dist/prosemirror/sectionMarkEdits.d.ts +20 -0
  295. package/dist/prosemirror/sectionMarkEdits.js +59 -0
  296. package/dist/prosemirror/storyListNumbering.d.ts +17 -0
  297. package/dist/prosemirror/storyListNumbering.js +102 -0
  298. package/dist/prosemirror/tableGridMutation.d.ts +48 -2
  299. package/dist/prosemirror/tableGridMutation.js +106 -1
  300. package/dist/prosemirror/validation.js +5 -1
  301. package/dist/redline.js +93 -9
  302. package/dist/render-dom/BodySelectionOverlay.d.ts +4 -1
  303. package/dist/render-dom/BodySelectionOverlay.js +3 -2
  304. package/dist/shaping/shaper.d.ts +47 -4
  305. package/dist/shaping/shaper.js +46 -15
  306. package/dist/text-shaping.d.ts +4 -0
  307. package/dist/text-shaping.js +4 -0
  308. package/dist/utils/findReplace.js +2 -2
  309. package/dist/utils/mergeDocumentContent.js +1 -1
  310. package/dist/utils/noteReferenceLabels.d.ts +36 -0
  311. package/dist/utils/noteReferenceLabels.js +32 -0
  312. package/dist/utils/replaceText.js +1 -1
  313. package/dist/version-comparison.d.ts +1 -0
  314. package/dist/version-comparison.js +1 -0
  315. package/package.json +8 -2
  316. package/dist/internal/headlessRevisionResolution.d.ts +0 -23
package/dist/redline.js CHANGED
@@ -1,4 +1,4 @@
1
- import { FolioDocxReviewer, isFolioResolvedReviewedView } from "./ai-edits/headless.js";
1
+ import { FolioDocxReviewer, getFolioDocxComparisonAccess, isFolioResolvedReviewedView } from "./ai-edits/headless.js";
2
2
  import { createFolioAITextRangeHandle, trailingBodyBlockId } from "./ai-edits/snapshot.js";
3
3
  import { createScopedWordDiffOptions } from "./ai-edits/word-diff.js";
4
4
  import { FolioContentInlinePresentationProjectionError } from "./compare/content.js";
@@ -77,6 +77,7 @@ const buildRedlineOperations = ({ baseSnapshot, revisedBlocks, nextOperationId }
77
77
  const operations = [];
78
78
  const trailingAdditions = [];
79
79
  const lastBaseBlockId = trailingBodyBlockId(baseSnapshot);
80
+ const baseBlocksById = new Map(baseSnapshot.blocks.map((block) => [block.id, block]));
80
81
  events.forEach((event, eventIndex) => {
81
82
  if (event.type === "pair") {
82
83
  if (event.baseBlock.text !== event.revisedBlock.text) operations.push({
@@ -102,10 +103,7 @@ const buildRedlineOperations = ({ baseSnapshot, revisedBlocks, nextOperationId }
102
103
  }
103
104
  const anchorId = anchorIds[eventIndex] ?? null;
104
105
  if (anchorId === null) {
105
- trailingAdditions.push({
106
- text: event.block.text,
107
- ...event.block.styleId !== void 0 && { styleId: event.block.styleId }
108
- });
106
+ trailingAdditions.push(event.block);
109
107
  return;
110
108
  }
111
109
  operations.push({
@@ -113,7 +111,7 @@ const buildRedlineOperations = ({ baseSnapshot, revisedBlocks, nextOperationId }
113
111
  type: "insertBeforeBlock",
114
112
  blockId: anchorId,
115
113
  text: event.block.text,
116
- ...event.block.styleId !== void 0 && { styleId: event.block.styleId }
114
+ ...insertedParagraphProperties(event.block, baseBlocksById.get(anchorId))
117
115
  });
118
116
  });
119
117
  for (const addition of trailingAdditions) operations.push({
@@ -121,10 +119,85 @@ const buildRedlineOperations = ({ baseSnapshot, revisedBlocks, nextOperationId }
121
119
  type: "insertAfterBlock",
122
120
  blockId: lastBaseBlockId ?? "redline-unanchored",
123
121
  text: addition.text,
124
- ...addition.styleId !== void 0 && { styleId: addition.styleId }
122
+ ...insertedParagraphProperties(addition, lastBaseBlockId === null ? void 0 : baseBlocksById.get(lastBaseBlockId))
125
123
  });
126
124
  return operations;
127
125
  };
126
+ /**
127
+ * The revised value, or `null` to clear one the anchor would pass on, or
128
+ * `undefined` when neither has one: an explicit `null` costs a restyle pass.
129
+ */
130
+ const statedOrCleared = (revised, anchor) => revised ?? (anchor === void 0 ? void 0 : null);
131
+ /**
132
+ * The paragraph properties an inserted block states. An insertion that says
133
+ * nothing takes the properties of its anchor, which is whichever base block
134
+ * happens to follow it, so whatever the anchor states and the revised block
135
+ * does not is cleared: a list item keeps its numbering, and a plain paragraph
136
+ * beside a list item stays plain.
137
+ */
138
+ const insertedParagraphProperties = (block, anchor) => {
139
+ const properties = {};
140
+ const styleId = statedOrCleared(block.styleId, anchor?.styleId);
141
+ if (styleId !== void 0) properties.styleId = styleId;
142
+ const alignment = statedOrCleared(block.directAlignment, anchor?.directAlignment);
143
+ if (alignment !== void 0) properties.alignment = alignment;
144
+ const spacing = statedOrCleared(block.directSpacing, anchor?.directSpacing);
145
+ if (spacing !== void 0) properties.spacing = spacing;
146
+ const indentation = statedOrCleared(block.directIndentation, anchor?.directIndentation);
147
+ if (indentation !== void 0) properties.indentation = indentation;
148
+ if (block.listReference !== void 0 || anchor?.listReference !== void 0 || anchor?.listLevel !== void 0) {
149
+ properties.numbering = block.listReference ?? null;
150
+ properties.listLevel = block.listLevel ?? null;
151
+ } else if (block.listLevel !== void 0) properties.listLevel = block.listLevel;
152
+ return properties;
153
+ };
154
+ const insertedNumbering = (operation) => {
155
+ if (operation.type !== "insertBeforeBlock" && operation.type !== "insertAfterBlock") return null;
156
+ const numbering = operation.numbering;
157
+ return numbering && !("start" in numbering) ? numbering : null;
158
+ };
159
+ /** The `w:numId`s whose `w:num` and abstract definition both exist. */
160
+ const definedNumIds = (numbering) => {
161
+ const abstractIds = new Set(numbering?.abstractNums.map((entry) => entry.abstractNumId));
162
+ return new Set((numbering?.nums ?? []).filter((entry) => abstractIds.has(entry.abstractNumId)).map((entry) => entry.numId));
163
+ };
164
+ /**
165
+ * Rebind every inserted list item to numbering the redline package defines.
166
+ * The redline is the base package, where the revised version's `w:numId` may
167
+ * name nothing, or another list: the referenced definitions are copied in,
168
+ * under a fresh id wherever the base uses that one for different numbering.
169
+ * A reference the revised package cannot resolve shows no number there
170
+ * either, and is inserted without one.
171
+ */
172
+ const bindInsertedNumbering = (baseReviewer, revisedReviewer, operationsByStory) => {
173
+ const baseAccess = getFolioDocxComparisonAccess(baseReviewer);
174
+ const revisedNumbering = getFolioDocxComparisonAccess(revisedReviewer).numberingDefinitions();
175
+ const resolvable = definedNumIds(revisedNumbering);
176
+ const references = operationsByStory.flatMap((operations) => operations.flatMap((operation) => {
177
+ const numbering = insertedNumbering(operation);
178
+ return numbering && resolvable.has(numbering.numId) ? [numbering] : [];
179
+ }));
180
+ const remapped = baseAccess.planTargetNumberingReferences(revisedNumbering, references) ?? panic("Resolvable revised numbering references could not be planned");
181
+ baseAccess.stageTargetNumbering(revisedNumbering, references, remapped);
182
+ const defined = definedNumIds(baseAccess.numberingDefinitions());
183
+ return operationsByStory.map((operations) => operations.map((operation) => {
184
+ const numbering = insertedNumbering(operation);
185
+ if (numbering === null) return operation;
186
+ const numId = remapped.get(numbering.numId) ?? numbering.numId;
187
+ if (!resolvable.has(numbering.numId) || !defined.has(numId)) return {
188
+ ...operation,
189
+ numbering: null,
190
+ listLevel: null
191
+ };
192
+ return {
193
+ ...operation,
194
+ numbering: {
195
+ numId,
196
+ level: numbering.level
197
+ }
198
+ };
199
+ }));
200
+ };
128
201
  const resolveInputView = (value, option) => {
129
202
  if (value === void 0) return "final";
130
203
  if (!isFolioResolvedReviewedView(value)) throw new InvalidGenerateRedlineDocxOptionsError({
@@ -155,6 +228,7 @@ const generateRedlineDocx = async (base, revised, options = {}) => {
155
228
  if (operationSequence >= 1e4) throw new GenerateRedlineDocxOperationLimitError({ message: "The document comparison exceeds the generated operation limit." });
156
229
  return `redline-${++operationSequence}`;
157
230
  };
231
+ const plannedStories = [];
158
232
  for (const pair of pairFolioDocumentStories(baseStories, revisedStories)) {
159
233
  if (!pair.baseStory) {
160
234
  unprocessedStories.push({
@@ -182,15 +256,25 @@ const generateRedlineDocx = async (base, revised, options = {}) => {
182
256
  nextOperationId
183
257
  });
184
258
  if (operations.length === 0) continue;
185
- const result = baseReviewer.applyDocumentOperationsToStory({
259
+ plannedStories.push({
186
260
  story: pair.baseStory,
187
261
  snapshot: baseSnapshot,
262
+ operations
263
+ });
264
+ }
265
+ const boundOperations = bindInsertedNumbering(baseReviewer, revisedReviewer, plannedStories.map(({ operations }) => operations));
266
+ for (const [index, { story, snapshot }] of plannedStories.entries()) {
267
+ const operations = boundOperations[index] ?? panic("A planned story lost its operations");
268
+ const result = baseReviewer.applyDocumentOperationsToStory({
269
+ story,
270
+ snapshot,
188
271
  batch: {
189
272
  version: 1,
190
273
  mode: "tracked-changes",
191
274
  operations
192
275
  },
193
- wordDiff
276
+ wordDiff,
277
+ undefinedStyles: "keep"
194
278
  });
195
279
  applied.push(...result.applied);
196
280
  skipped.push(...result.skipped);
@@ -1,3 +1,4 @@
1
+ import { DisplayMode } from "../managers/EditorModeManager.js";
1
2
  import { EditorState } from "prosemirror-state";
2
3
  //#region src/render-dom/BodySelectionOverlay.d.ts
3
4
  type BodySelectionOverlayResult = {
@@ -10,6 +11,8 @@ type BodySelectionOverlayResult = {
10
11
  type SyncBodySelectionOverlayOptions = {
11
12
  pagesContainer: HTMLElement;
12
13
  state: EditorState;
14
+ /** The review view the pages were laid out for; a caret in text it hides paints at its edge. */
15
+ markupView: DisplayMode;
13
16
  zoom: number;
14
17
  zIndex?: number;
15
18
  caretColor?: string;
@@ -17,7 +20,7 @@ type SyncBodySelectionOverlayOptions = {
17
20
  };
18
21
  declare class BodySelectionOverlay {
19
22
  clear(pagesContainer: HTMLElement): void;
20
- sync({ pagesContainer, state, zoom, zIndex, caretColor, selectionColor }: SyncBodySelectionOverlayOptions): BodySelectionOverlayResult;
23
+ sync({ pagesContainer, state, markupView, zoom, zIndex, caretColor, selectionColor }: SyncBodySelectionOverlayOptions): BodySelectionOverlayResult;
21
24
  }
22
25
  //#endregion
23
26
  export { BodySelectionOverlay, BodySelectionOverlayResult, SyncBodySelectionOverlayOptions };
@@ -2,6 +2,7 @@ import { applyCellSelectionHighlight } from "../layout-bridge/cellSelectionHighl
2
2
  import { getCaretPositionFromDom, getSelectionRectsFromDom } from "../layout-bridge/dom/clickToPositionDom.js";
3
3
  import { findBodyPmAnchor } from "../layout-bridge/dom/findBodyPmSpans.js";
4
4
  import { findImageElement } from "../layout-painter/imageLayout.js";
5
+ import { projectMarkupView, visibleCaretPosition } from "../prosemirror/markupViewProjection.js";
5
6
  import { NodeSelection } from "prosemirror-state";
6
7
  //#region src/render-dom/BodySelectionOverlay.ts
7
8
  /**
@@ -23,7 +24,7 @@ var BodySelectionOverlay = class {
23
24
  clear(pagesContainer) {
24
25
  for (const element of pagesContainer.querySelectorAll(OWNED_OVERLAY_SELECTOR)) element.remove();
25
26
  }
26
- sync({ pagesContainer, state, zoom, zIndex = 10, caretColor = "var(--doc-caret, #000)", selectionColor = "var(--doc-selection, rgba(66, 133, 244, 0.3))" }) {
27
+ sync({ pagesContainer, state, markupView, zoom, zIndex = 10, caretColor = "var(--doc-caret, #000)", selectionColor = "var(--doc-selection, rgba(66, 133, 244, 0.3))" }) {
27
28
  this.clear(pagesContainer);
28
29
  applyCellSelectionHighlight(pagesContainer, state);
29
30
  const { selection } = state;
@@ -37,7 +38,7 @@ var BodySelectionOverlay = class {
37
38
  };
38
39
  }
39
40
  if (selection.empty) {
40
- const caret = getCaretPositionFromDom(pagesContainer, selection.from, pagesContainer.getBoundingClientRect());
41
+ const caret = getCaretPositionFromDom(pagesContainer, visibleCaretPosition(projectMarkupView(state, markupView), selection.from), pagesContainer.getBoundingClientRect());
41
42
  if (!caret) return { type: "text" };
42
43
  const element = pagesContainer.ownerDocument.createElement("div");
43
44
  element.className = CARET_CLASS;
@@ -14,6 +14,9 @@
14
14
  * the Unicode data that engine needs, and a document in Latin, Cyrillic or
15
15
  * Greek needs none of it: `getShaper` is called only once a run in a shaping
16
16
  * script is about to be measured or painted, and never before.
17
+ *
18
+ * The same artifact resolves the bidirectional algorithm, because splitting a
19
+ * line into runs that each read one way is what shaping needs first.
17
20
  */
18
21
  /** Which way a run advances. Resolved by the producer, never guessed here. */
19
22
  declare const SHAPING_DIRECTION: {
@@ -57,22 +60,62 @@ type ShapedRun = {
57
60
  /** Design units per em, so a caller scales without re-reading the face. */
58
61
  readonly unitsPerEm: number;
59
62
  };
63
+ /** The paragraph direction of a line whose bidirectional levels are resolved. */
64
+ declare const BIDI_DIRECTION: {
65
+ readonly leftToRight: "ltr";
66
+ readonly rightToLeft: "rtl";
67
+ /** Rules P2 and P3: the first strong character outside an isolate decides. */
68
+ readonly auto: "auto";
69
+ };
70
+ type BidiDirection = (typeof BIDI_DIRECTION)[keyof typeof BIDI_DIRECTION];
71
+ type ResolveBidiRequest = {
72
+ /** One paragraph laid out as one line; a paragraph separator does not split it. */
73
+ readonly text: string;
74
+ readonly direction: BidiDirection;
75
+ };
76
+ /**
77
+ * One line after the Unicode Bidirectional Algorithm (UAX #9), rules P2
78
+ * through L2. Indices count code points, not UTF-16 units.
79
+ */
80
+ type BidiLine = {
81
+ /** 0 when the paragraph reads left to right, 1 when right to left. */
82
+ readonly paragraphLevel: number;
83
+ /**
84
+ * Embedding level per code point, after rule L1; odd levels read right to
85
+ * left. Characters rule X9 removes (explicit formatting characters such as
86
+ * isolates) carry a level but draw nothing.
87
+ */
88
+ readonly levels: readonly number[];
89
+ /** Code-point indices in visual order, left to right (rule L2). */
90
+ readonly visualOrder: readonly number[];
91
+ };
60
92
  type Shaper = {
61
93
  readonly shapeRun: (request: ShapeRunRequest) => ShapedRun;
94
+ readonly resolveBidi: (request: ResolveBidiRequest) => BidiLine;
62
95
  };
63
96
  declare const ShaperError_base: import("better-result").TaggedErrorClass<"ShaperError">;
64
97
  declare class ShaperError extends ShaperError_base<{
65
98
  message: string;
66
99
  cause?: unknown;
67
100
  }> {}
101
+ /**
102
+ * Where the artifact comes from when the caller already holds it: a runtime
103
+ * that cannot fetch its own package files (a single-file executable, an
104
+ * embedded asset) hands over the WebAssembly bytes instead.
105
+ */
106
+ type ShaperSource = {
107
+ readonly wasm: Uint8Array | ArrayBuffer;
108
+ };
68
109
  /**
69
110
  * Loads the shaper, once, and hands back the single implementation both the
70
111
  * measurer and the PDF backend use.
71
112
  *
72
- * Calling this is what fetches the artifact, so a caller asks for it only after
73
- * establishing that some run actually needs shaping.
113
+ * Calling this without a source is what fetches the artifact, so a caller asks
114
+ * for it only after establishing that some run actually needs shaping. With a
115
+ * source, the bytes given are instantiated and nothing is fetched. Either way
116
+ * the first successful load is the one every later call shares.
74
117
  */
75
- declare const getShaper: () => Promise<Shaper>;
118
+ declare const getShaper: (source?: ShaperSource) => Promise<Shaper>;
76
119
  /**
77
120
  * Whether the artifact has been loaded in this process.
78
121
  *
@@ -89,4 +132,4 @@ declare const shaperLoaded: () => boolean;
89
132
  */
90
133
  declare const resolvedShaper: () => Shaper | null;
91
134
  //#endregion
92
- export { SHAPING_DIRECTION, ShapeRunRequest, ShapedGlyph, ShapedRun, Shaper, ShaperError, ShapingDirection, getShaper, resolvedShaper, shaperLoaded };
135
+ export { BIDI_DIRECTION, BidiDirection, BidiLine, ResolveBidiRequest, SHAPING_DIRECTION, ShapeRunRequest, ShapedGlyph, ShapedRun, Shaper, ShaperError, ShaperSource, ShapingDirection, getShaper, resolvedShaper, shaperLoaded };
@@ -1,4 +1,4 @@
1
- import __wbg_init, { shapeRun } from "../generated/text_shaper.js";
1
+ import __wbg_init, { resolveBidi, shapeRun } from "../generated/text_shaper.js";
2
2
  import { TaggedError } from "better-result";
3
3
  //#region src/shaping/shaper.ts
4
4
  /**
@@ -16,12 +16,22 @@ import { TaggedError } from "better-result";
16
16
  * the Unicode data that engine needs, and a document in Latin, Cyrillic or
17
17
  * Greek needs none of it: `getShaper` is called only once a run in a shaping
18
18
  * script is about to be measured or painted, and never before.
19
+ *
20
+ * The same artifact resolves the bidirectional algorithm, because splitting a
21
+ * line into runs that each read one way is what shaping needs first.
19
22
  */
20
23
  /** Which way a run advances. Resolved by the producer, never guessed here. */
21
24
  const SHAPING_DIRECTION = {
22
25
  leftToRight: "ltr",
23
26
  rightToLeft: "rtl"
24
27
  };
28
+ /** The paragraph direction of a line whose bidirectional levels are resolved. */
29
+ const BIDI_DIRECTION = {
30
+ leftToRight: "ltr",
31
+ rightToLeft: "rtl",
32
+ /** Rules P2 and P3: the first strong character outside an isolate decides. */
33
+ auto: "auto"
34
+ };
25
35
  var ShaperError = class extends TaggedError("ShaperError") {};
26
36
  /**
27
37
  * The flat buffer the WebAssembly entry returns:
@@ -51,26 +61,47 @@ const decode = (buffer) => {
51
61
  unitsPerEm
52
62
  };
53
63
  };
54
- const shaper = { shapeRun: ({ font, faceIndex = 0, text, direction, script = "", language = "", featuresOn = [], featuresOff = [] }) => {
55
- try {
56
- return decode(shapeRun(font, faceIndex, text, direction === SHAPING_DIRECTION.rightToLeft, script, language, [...featuresOn], [...featuresOff]));
57
- } catch (cause) {
58
- throw new ShaperError({
59
- message: "Could not shape a run of text",
60
- cause
61
- });
64
+ /** `[paragraphLevel, count, level * count, visualIndex * count]`. */
65
+ const decodeBidi = (buffer) => {
66
+ const count = buffer[1] ?? 0;
67
+ const levelsAt = HEADER_FIELDS;
68
+ const orderAt = HEADER_FIELDS + count;
69
+ return {
70
+ paragraphLevel: buffer[0] ?? 0,
71
+ levels: Array.from(buffer.subarray(levelsAt, orderAt)),
72
+ visualOrder: Array.from(buffer.subarray(orderAt, orderAt + count))
73
+ };
74
+ };
75
+ const RIGHT_TO_LEFT_BY_BIDI_DIRECTION = {
76
+ ltr: false,
77
+ rtl: true,
78
+ auto: void 0
79
+ };
80
+ const shaper = {
81
+ resolveBidi: ({ text, direction }) => decodeBidi(resolveBidi(text, RIGHT_TO_LEFT_BY_BIDI_DIRECTION[direction])),
82
+ shapeRun: ({ font, faceIndex = 0, text, direction, script = "", language = "", featuresOn = [], featuresOff = [] }) => {
83
+ try {
84
+ return decode(shapeRun(font, faceIndex, text, direction === SHAPING_DIRECTION.rightToLeft, script, language, [...featuresOn], [...featuresOff]));
85
+ } catch (cause) {
86
+ throw new ShaperError({
87
+ message: "Could not shape a run of text",
88
+ cause
89
+ });
90
+ }
62
91
  }
63
- } };
92
+ };
64
93
  let loading;
65
94
  /**
66
95
  * Loads the shaper, once, and hands back the single implementation both the
67
96
  * measurer and the PDF backend use.
68
97
  *
69
- * Calling this is what fetches the artifact, so a caller asks for it only after
70
- * establishing that some run actually needs shaping.
98
+ * Calling this without a source is what fetches the artifact, so a caller asks
99
+ * for it only after establishing that some run actually needs shaping. With a
100
+ * source, the bytes given are instantiated and nothing is fetched. Either way
101
+ * the first successful load is the one every later call shares.
71
102
  */
72
- const getShaper = () => {
73
- loading ??= __wbg_init().then(() => {
103
+ const getShaper = (source) => {
104
+ loading ??= __wbg_init(source === void 0 ? void 0 : { module_or_path: source.wasm }).then(() => {
74
105
  resolved = shaper;
75
106
  return shaper;
76
107
  }).catch((cause) => {
@@ -99,4 +130,4 @@ let resolved = null;
99
130
  */
100
131
  const resolvedShaper = () => resolved;
101
132
  //#endregion
102
- export { SHAPING_DIRECTION, ShaperError, getShaper, resolvedShaper, shaperLoaded };
133
+ export { BIDI_DIRECTION, SHAPING_DIRECTION, ShaperError, getShaper, resolvedShaper, shaperLoaded };
@@ -0,0 +1,4 @@
1
+ import { BIDI_DIRECTION, BidiLine, ResolveBidiRequest, SHAPING_DIRECTION, ShapeRunRequest, ShapedRun, Shaper, ShaperSource, getShaper } from "./shaping/shaper.js";
2
+ import { SfntFont, parseSfnt } from "./fonts/sfnt/parse.js";
3
+ import { TrueTypeSubset, subsetTrueType } from "./fonts/sfnt/subset.js";
4
+ export { BIDI_DIRECTION, type BidiLine, type ResolveBidiRequest, SHAPING_DIRECTION, type SfntFont, type ShapeRunRequest, type ShapedRun, type Shaper, type ShaperSource, type TrueTypeSubset, getShaper, parseSfnt, subsetTrueType };
@@ -0,0 +1,4 @@
1
+ import { parseSfnt } from "./fonts/sfnt/parse.js";
2
+ import { subsetTrueType } from "./fonts/sfnt/subset.js";
3
+ import { BIDI_DIRECTION, SHAPING_DIRECTION, getShaper } from "./shaping/shaper.js";
4
+ export { BIDI_DIRECTION, SHAPING_DIRECTION, getShaper, parseSfnt, subsetTrueType };
@@ -66,7 +66,7 @@ const forEachParagraph = (blocks, visit) => {
66
66
  walkTable(block);
67
67
  continue;
68
68
  }
69
- if (isBlockSdt(block)) walkBlocks(block.content);
69
+ if (isBlockContainer(block)) walkBlocks(block.content);
70
70
  }
71
71
  };
72
72
  const walkTable = (table) => {
@@ -172,6 +172,6 @@ const isParagraph = (value) => isRecord(value) && value["type"] === "paragraph"
172
172
  const isTable = (value) => isRecord(value) && value["type"] === "table" && Array.isArray(value["rows"]);
173
173
  const isTableRow = (value) => isRecord(value) && Array.isArray(value["cells"]);
174
174
  const isTableCell = (value) => isRecord(value) && Array.isArray(value["content"]);
175
- const isBlockSdt = (value) => isRecord(value) && value["type"] === "blockSdt" && Array.isArray(value["content"]);
175
+ const isBlockContainer = (value) => isRecord(value) && (value["type"] === "blockSdt" || value["type"] === "blockCustomXml") && Array.isArray(value["content"]);
176
176
  //#endregion
177
177
  export { createDefaultFindOptions, createSearchPattern, escapeRegexString, findAllMatches, findInDocument, findInParagraph };
@@ -86,7 +86,7 @@ function mergeDocumentContent(target, source) {
86
86
  function remapBlock(block, numIdRemap, abstractNumIdRemap) {
87
87
  if (block.type === "paragraph") return remapParagraph(block, numIdRemap, abstractNumIdRemap);
88
88
  if (block.type === "table") return remapTable(block, numIdRemap, abstractNumIdRemap);
89
- if (block.type === "blockSdt" && Array.isArray(block.content)) return {
89
+ if ((block.type === "blockSdt" || block.type === "blockCustomXml") && Array.isArray(block.content)) return {
90
90
  ...block,
91
91
  content: block.content.map((child) => remapBlock(child, numIdRemap, abstractNumIdRemap))
92
92
  };
@@ -0,0 +1,36 @@
1
+ //#region src/utils/noteReferenceLabels.d.ts
2
+ /**
3
+ * How a reader shows a footnote or endnote reference.
4
+ *
5
+ * A reference's `w:id` is a package key, not something a reader sees: the
6
+ * rendered document numbers notes by the order they are first referenced
7
+ * (1, 2, 3 …), whatever ids the package gave them. Every reader that puts a reference in a line of
8
+ * text — the Markdown export, `getContent()`, the AI snapshot and the agent
9
+ * tools built on it — numbers through {@link createNoteReferenceNumbering}, so
10
+ * the same reference reads as the same marker everywhere.
11
+ *
12
+ * Footnotes and endnotes are numbered in separate sequences; an
13
+ * endnote's token carries an `e` so the two sequences never collide
14
+ * (`[^1]` is footnote 1, `[^e1]` is endnote 1).
15
+ */
16
+ type NoteReferenceKind = "footnote" | "endnote";
17
+ /** The bare token: `1` for footnote 1, `e1` for endnote 1. */
18
+ declare const noteReferenceToken: (kind: NoteReferenceKind, displayNumber: number) => string;
19
+ /** The marker a text reader shows in the line: `[^1]`, `[^e1]`. */
20
+ declare const noteReferenceMarker: (kind: NoteReferenceKind, displayNumber: number) => string;
21
+ type NoteReferenceNumber = {
22
+ displayNumber: number;
23
+ /** Whether this is the note's first reference in reading order. */
24
+ first: boolean;
25
+ };
26
+ type NoteReferenceNumbering = {
27
+ /** Number one reference, in reading order. */
28
+ next: (kind: NoteReferenceKind, noteId: string | number) => NoteReferenceNumber;
29
+ };
30
+ /**
31
+ * A reading-order numbering: each note takes the next number of its kind the
32
+ * first time it is referenced, and a repeated reference reuses it.
33
+ */
34
+ declare const createNoteReferenceNumbering: () => NoteReferenceNumbering;
35
+ //#endregion
36
+ export { NoteReferenceKind, NoteReferenceNumber, NoteReferenceNumbering, createNoteReferenceNumbering, noteReferenceMarker, noteReferenceToken };
@@ -0,0 +1,32 @@
1
+ //#region src/utils/noteReferenceLabels.ts
2
+ /** The bare token: `1` for footnote 1, `e1` for endnote 1. */
3
+ const noteReferenceToken = (kind, displayNumber) => kind === "endnote" ? `e${displayNumber}` : String(displayNumber);
4
+ /** The marker a text reader shows in the line: `[^1]`, `[^e1]`. */
5
+ const noteReferenceMarker = (kind, displayNumber) => `[^${noteReferenceToken(kind, displayNumber)}]`;
6
+ /**
7
+ * A reading-order numbering: each note takes the next number of its kind the
8
+ * first time it is referenced, and a repeated reference reuses it.
9
+ */
10
+ const createNoteReferenceNumbering = () => {
11
+ const numbers = /* @__PURE__ */ new Map();
12
+ const counts = {
13
+ footnote: 0,
14
+ endnote: 0
15
+ };
16
+ return { next: (kind, noteId) => {
17
+ const key = `${kind}:${String(noteId)}`;
18
+ const existing = numbers.get(key);
19
+ if (existing !== void 0) return {
20
+ displayNumber: existing,
21
+ first: false
22
+ };
23
+ counts[kind] += 1;
24
+ numbers.set(key, counts[kind]);
25
+ return {
26
+ displayNumber: counts[kind],
27
+ first: true
28
+ };
29
+ } };
30
+ };
31
+ //#endregion
32
+ export { createNoteReferenceNumbering, noteReferenceMarker, noteReferenceToken };
@@ -49,7 +49,7 @@ function getParagraphByIndex(body, paragraphIndex) {
49
49
  }
50
50
  continue;
51
51
  }
52
- if (block.type !== "blockSdt") continue;
52
+ if (block.type !== "blockSdt" && block.type !== "blockCustomXml") continue;
53
53
  const found = walkBlocks(block.content);
54
54
  if (found !== null) return found;
55
55
  }
@@ -46,6 +46,7 @@ declare const INLINE_FORMAT_PROPERTIES: {
46
46
  declare const PARAGRAPH_FORMAT_PROPERTIES: {
47
47
  readonly indentation: true;
48
48
  readonly styleId: true;
49
+ readonly outlineLevel: true;
49
50
  readonly listLevel: true;
50
51
  readonly listReference: true;
51
52
  readonly alignment: true;
@@ -88,6 +88,7 @@ const INLINE_FORMAT_PROPERTIES = {
88
88
  const PARAGRAPH_FORMAT_PROPERTIES = {
89
89
  indentation: true,
90
90
  styleId: true,
91
+ outlineLevel: true,
91
92
  listLevel: true,
92
93
  listReference: true,
93
94
  alignment: true,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stll/folio-core",
3
- "version": "0.51.0",
3
+ "version": "0.53.0",
4
4
  "description": "Headless, framework-neutral core of folio: the OOXML (.docx) parser, document model, ProseMirror integration, and page-layout engine. No React.",
5
5
  "keywords": [
6
6
  "document-model",
@@ -106,6 +106,11 @@
106
106
  "types": "./dist/docx/documentClone.d.ts",
107
107
  "import": "./dist/docx/documentClone.js"
108
108
  },
109
+ "./text-shaping": {
110
+ "types": "./dist/text-shaping.d.ts",
111
+ "import": "./dist/text-shaping.js"
112
+ },
113
+ "./text-shaping/wasm": "./dist/generated/text_shaper_bg.wasm",
109
114
  "./docx/paragraphPropertySource": null,
110
115
  "./internal/*": null,
111
116
  "./*": {
@@ -122,13 +127,14 @@
122
127
  "pack:dry-run": "bun pm pack --dry-run",
123
128
  "typecheck": "bun ../../scripts/tsc-native.ts --noEmit -p tsconfig.build.json",
124
129
  "test": "bun test src scripts",
130
+ "test:conformance:full": "FOLIO_CONFORMANCE=full bun test src/__tests__/editorCommandConformance.test.ts",
125
131
  "wasm:check": "bun ../../scripts/build-shaper-wasm.ts --check",
126
132
  "wasm:generate": "bun ../../scripts/build-shaper-wasm.ts --write",
127
133
  "test:property": "bun test $(grep -rlF 'fc.assert' src --include='*.test.ts')",
128
134
  "perf": "bun scripts/profile-editor.ts"
129
135
  },
130
136
  "dependencies": {
131
- "@stll/docx-core": "^0.28.0",
137
+ "@stll/docx-core": "^0.28.1",
132
138
  "@stll/docx-utils": "^0.1.0",
133
139
  "@stll/template-conditions": ">=0.4.0 <1.0.0",
134
140
  "better-result": "3.0.1",
@@ -1,23 +0,0 @@
1
- import { RunStyleResolver } from "../prosemirror/runStyleFormatting.js";
2
- import { Transaction } from "prosemirror-state";
3
- import { MarkType } from "prosemirror-model";
4
- //#region src/internal/headlessRevisionResolution.d.ts
5
- type HeadlessRevisionResolutionMode = "accept" | "reject";
6
- type HeadlessRange = {
7
- from: number;
8
- to: number;
9
- };
10
- type HeadlessInlineChangeTracking = {
11
- ranges: readonly HeadlessRange[];
12
- mappingFrom: number;
13
- };
14
- type AppendHeadlessInlineResolutionOptions = {
15
- tr: Transaction;
16
- mode: HeadlessRevisionResolutionMode;
17
- keepType: MarkType | undefined;
18
- removeType: MarkType | undefined;
19
- styleResolver: RunStyleResolver | null;
20
- };
21
- declare const appendHeadlessInlineResolution: ({ tr, mode, keepType, removeType, styleResolver }: AppendHeadlessInlineResolutionOptions) => HeadlessInlineChangeTracking | null;
22
- //#endregion
23
- export { HeadlessInlineChangeTracking, HeadlessRevisionResolutionMode, appendHeadlessInlineResolution };