@stll/folio-core 0.52.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 (307) 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/plan.js +10 -5
  47. package/dist/compare/scenario.js +14 -3
  48. package/dist/compare/section-boundary-properties.js +1 -1
  49. package/dist/compare/types.d.ts +4 -2
  50. package/dist/compare/types.js +2 -1
  51. package/dist/compare/verification.d.ts +1 -1
  52. package/dist/compare/verification.js +15 -3
  53. package/dist/controller/committedLayoutDiff.d.ts +25 -0
  54. package/dist/controller/committedLayoutDiff.js +71 -0
  55. package/dist/controller/contentControlWidgetController.d.ts +1 -1
  56. package/dist/controller/folioEditor.d.ts +1 -1
  57. package/dist/controller/fontReadiness.d.ts +70 -3
  58. package/dist/controller/fontReadiness.js +100 -10
  59. package/dist/controller/headerFooterEditorManager.js +6 -1
  60. package/dist/controller/layoutPipeline.d.ts +12 -10
  61. package/dist/controller/layoutPipeline.js +62 -9
  62. package/dist/controller/layoutRunOptions.d.ts +24 -0
  63. package/dist/controller/layoutRunOptions.js +17 -0
  64. package/dist/controller/layoutScheduler.d.ts +19 -14
  65. package/dist/controller/layoutScheduler.js +15 -12
  66. package/dist/controller/layoutSession.d.ts +26 -2
  67. package/dist/controller/layoutSession.js +1 -1
  68. package/dist/controller/noteEditorManager.js +8 -3
  69. package/dist/document-operations.d.ts +11 -2
  70. package/dist/document-operations.js +230 -21
  71. package/dist/docx/altChunk.d.ts +8 -0
  72. package/dist/docx/altChunk.js +17 -0
  73. package/dist/docx/attributeRemainder.d.ts +1 -1
  74. package/dist/docx/blockContentParser.d.ts +64 -1
  75. package/dist/docx/blockContentParser.js +17 -4
  76. package/dist/docx/blockCustomXmlShell.d.ts +7 -0
  77. package/dist/docx/blockCustomXmlShell.js +14 -0
  78. package/dist/docx/blockPlainText.js +7 -0
  79. package/dist/docx/commentAnchorIndex.js +1 -1
  80. package/dist/docx/commentRangeIntegrity.js +8 -3
  81. package/dist/docx/commentReferenceNormalization.js +1 -1
  82. package/dist/docx/commentReplyMarkers.js +20 -1
  83. package/dist/docx/compatibility.d.ts +1 -1
  84. package/dist/docx/compatibility.js +34 -13
  85. package/dist/docx/containerChildren.gen.d.ts +1 -1
  86. package/dist/docx/containerChildren.gen.js +1 -0
  87. package/dist/docx/documentParser.js +12 -12
  88. package/dist/docx/drawingIdNormalization.d.ts +3 -1
  89. package/dist/docx/drawingIdNormalization.js +6 -1
  90. package/dist/docx/ensureParaIds.js +119 -97
  91. package/dist/docx/footnoteParser.js +8 -4
  92. package/dist/docx/headerFooterParser.js +3 -3
  93. package/dist/docx/headerFooterReferenceNormalization.d.ts +20 -1
  94. package/dist/docx/headerFooterReferenceNormalization.js +52 -27
  95. package/dist/docx/hyperlinkParser.d.ts +1 -1
  96. package/dist/docx/index.d.ts +1 -1
  97. package/dist/docx/listNumberingInstances.d.ts +59 -0
  98. package/dist/docx/listNumberingInstances.js +249 -0
  99. package/dist/docx/normalizeBaseDirection.js +2 -1
  100. package/dist/docx/opaqueCarrier.d.ts +7 -0
  101. package/dist/docx/opaqueCarrier.js +38 -0
  102. package/dist/docx/packageParts.js +4 -1
  103. package/dist/docx/paragraphParser.js +91 -24
  104. package/dist/docx/paragraphPropertySource.d.ts +4 -2
  105. package/dist/docx/paragraphPropertySource.js +7 -1
  106. package/dist/docx/paragraphTraversal.js +1 -0
  107. package/dist/docx/parseWarningMessage.js +4 -1
  108. package/dist/docx/parser.js +173 -20
  109. package/dist/docx/rezip.js +27 -5
  110. package/dist/docx/sdtProperties.js +1 -1
  111. package/dist/docx/sdtPropertiesPatch.js +3 -0
  112. package/dist/docx/selectiveSave.js +16 -9
  113. package/dist/docx/selectiveXmlPatch.js +106 -37
  114. package/dist/docx/serializer/blockCustomXmlSerializer.d.ts +5 -0
  115. package/dist/docx/serializer/blockCustomXmlSerializer.js +4 -0
  116. package/dist/docx/serializer/documentSerializer.js +2 -0
  117. package/dist/docx/serializer/headerFooterSerializer.js +2 -0
  118. package/dist/docx/serializer/noteSerializer.js +3 -1
  119. package/dist/docx/serializer/paragraphSerializer.js +33 -9
  120. package/dist/docx/serializer/tableSerializer.js +25 -38
  121. package/dist/docx/server/createBilingualDocument.js +3 -3
  122. package/dist/docx/tableParser.d.ts +157 -1
  123. package/dist/docx/tableParser.js +89 -10
  124. package/dist/docx/textBoxParser.js +1 -1
  125. package/dist/docx/unzip.d.ts +2 -1
  126. package/dist/docx/unzip.js +1 -1
  127. package/dist/docx/wordprocessingPrefixes.d.ts +78 -0
  128. package/dist/docx/wordprocessingPrefixes.js +286 -0
  129. package/dist/i18n/messages/catalogs.gen.d.ts +136 -0
  130. package/dist/i18n/messages/catalogs.gen.js +153 -17
  131. package/dist/i18n/messages/messages.gen.d.ts +8 -0
  132. package/dist/internal/compare/inline-presentation.d.ts +2 -1
  133. package/dist/internal/compare/inline-presentation.js +11 -10
  134. package/dist/internal/headlessRevisionResolutionGuard.d.ts +2 -8
  135. package/dist/internal/headlessRevisionResolutionGuard.js +2 -11
  136. package/dist/internal/indexedPositionMap.d.ts +11 -0
  137. package/dist/internal/indexedPositionMap.js +42 -0
  138. package/dist/internal/pageBreakRunSourceDescendantIndex.js +2 -1
  139. package/dist/internal/revisionResolutionEdits.d.ts +13 -0
  140. package/dist/internal/revisionResolutionEdits.js +19 -0
  141. package/dist/internal/revisionResolutionInline.d.ts +24 -0
  142. package/dist/internal/{headlessRevisionResolution.js → revisionResolutionInline.js} +61 -43
  143. package/dist/internal/revisionResolutionStep.d.ts +34 -0
  144. package/dist/internal/revisionResolutionStep.js +282 -0
  145. package/dist/internal/revisionResolutionTracking.d.ts +11 -0
  146. package/dist/internal/revisionResolutionTracking.js +124 -0
  147. package/dist/internal/wholeStoryRevisionResolution.d.ts +56 -0
  148. package/dist/internal/wholeStoryRevisionResolution.js +530 -0
  149. package/dist/layout-bridge/convert/markupViewFlow.d.ts +20 -0
  150. package/dist/layout-bridge/convert/markupViewFlow.js +123 -0
  151. package/dist/layout-bridge/convert/tableConversion.js +1 -1
  152. package/dist/layout-bridge/convert/toFlowBlocks.js +10 -1
  153. package/dist/layout-engine/layoutInstrumentation.d.ts +9 -1
  154. package/dist/layout-engine/layoutInstrumentation.js +4 -1
  155. package/dist/layout-engine/measure/cache.d.ts +18 -1
  156. package/dist/layout-engine/measure/cache.js +31 -1
  157. package/dist/layout-engine/measure/font-metrics.worker.js +3 -7
  158. package/dist/layout-engine/measure/measureContainer.js +7 -47
  159. package/dist/layout-engine/measure/measureHelpers.d.ts +6 -1
  160. package/dist/layout-engine/measure/measureHelpers.js +22 -2
  161. package/dist/layout-engine/measure/measureWorker.js +2 -3
  162. package/dist/layout-engine/measure/measureWorkerProtocol.d.ts +6 -7
  163. package/dist/layout-engine/measure/measureWorkerProtocol.js +1 -2
  164. package/dist/layout-engine/types.d.ts +6 -0
  165. package/dist/layout-painter/renderPage.js +1 -0
  166. package/dist/layout-painter/renderParagraph.js +1 -1
  167. package/dist/managers/ContextMenuManager.js +5 -2
  168. package/dist/managers/types.d.ts +3 -0
  169. package/dist/markdown/fromMarkdown.js +2 -1
  170. package/dist/markdown/internals.d.ts +11 -1
  171. package/dist/markdown/internals.js +24 -3
  172. package/dist/markdown/renderBlock.js +39 -9
  173. package/dist/markdown/renderParagraph.d.ts +13 -1
  174. package/dist/markdown/renderParagraph.js +85 -38
  175. package/dist/markdown/renderRuns.js +3 -10
  176. package/dist/markdown/renderTable.js +24 -12
  177. package/dist/markdown/trailers.js +2 -2
  178. package/dist/markdown/types.d.ts +29 -7
  179. package/dist/paged-layout/incrementalMeasure.d.ts +1 -2
  180. package/dist/paged-layout/incrementalMeasure.js +1 -9
  181. package/dist/paged-layout/transactionDirtyRange.d.ts +1 -3
  182. package/dist/paged-layout/transactionDirtyRange.js +29 -41
  183. package/dist/panel-layout.d.ts +83 -0
  184. package/dist/panel-layout.js +96 -0
  185. package/dist/prosemirror/anchoredTextBoxes.d.ts +37 -0
  186. package/dist/prosemirror/anchoredTextBoxes.js +156 -0
  187. package/dist/prosemirror/attrs/index.d.ts +6 -2
  188. package/dist/prosemirror/attrs/index.js +172 -1
  189. package/dist/prosemirror/commands/comments.d.ts +7 -8
  190. package/dist/prosemirror/commands/comments.js +241 -207
  191. package/dist/prosemirror/commands/contentControls.d.ts +1 -1
  192. package/dist/prosemirror/commands/formatPainter.d.ts +1 -1
  193. package/dist/prosemirror/commands/formatting.d.ts +1 -1
  194. package/dist/prosemirror/commands/index.d.ts +2 -2
  195. package/dist/prosemirror/commands/index.js +2 -2
  196. package/dist/prosemirror/commands/paragraph.d.ts +7 -1
  197. package/dist/prosemirror/commands/paragraph.js +9 -1
  198. package/dist/prosemirror/commands/paragraphBookmarkJoin.d.ts +13 -0
  199. package/dist/prosemirror/commands/paragraphBookmarkJoin.js +22 -0
  200. package/dist/prosemirror/commands/pastePlainText.d.ts +1 -1
  201. package/dist/prosemirror/commands/resolveAllTableChanges.d.ts +40 -0
  202. package/dist/prosemirror/commands/resolveAllTableChanges.js +615 -0
  203. package/dist/prosemirror/commands/resolveNodePropertyChangeAttrs.d.ts +15 -0
  204. package/dist/prosemirror/commands/resolveNodePropertyChangeAttrs.js +46 -0
  205. package/dist/prosemirror/commands/resolveParagraphProperties.d.ts +16 -0
  206. package/dist/prosemirror/commands/resolveParagraphProperties.js +59 -0
  207. package/dist/prosemirror/commands/sectionBreak.js +2 -1
  208. package/dist/prosemirror/commands/tableCellMergeResolution.d.ts +8 -2
  209. package/dist/prosemirror/commands/tableCellMergeResolution.js +1 -1
  210. package/dist/prosemirror/contentControlRevisions.d.ts +1 -1
  211. package/dist/prosemirror/conversion/fromProseDoc.js +181 -31
  212. package/dist/prosemirror/conversion/toProseDoc.js +39 -4
  213. package/dist/prosemirror/emptyFieldResultRuns.d.ts +18 -0
  214. package/dist/prosemirror/emptyFieldResultRuns.js +33 -0
  215. package/dist/prosemirror/extensions/ExtensionManager.d.ts +1 -1
  216. package/dist/prosemirror/extensions/ExtensionManager.js +3 -1
  217. package/dist/prosemirror/extensions/StarterKit.js +3 -1
  218. package/dist/prosemirror/extensions/core/DocExtension.js +1 -1
  219. package/dist/prosemirror/extensions/core/ParagraphExtension.js +12 -0
  220. package/dist/prosemirror/extensions/features/BaseKeymapExtension.js +3 -0
  221. package/dist/prosemirror/extensions/features/ListExtension.js +161 -123
  222. package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.d.ts +19 -2
  223. package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.js +33 -20
  224. package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.d.ts +31 -2
  225. package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.js +270 -99
  226. package/dist/prosemirror/extensions/features/PasteCleanupExtension.js +3 -2
  227. package/dist/prosemirror/extensions/features/pasteCleanup.js +2 -1
  228. package/dist/prosemirror/extensions/features/pastedHtmlLists.d.ts +12 -0
  229. package/dist/prosemirror/extensions/features/pastedHtmlLists.js +126 -0
  230. package/dist/prosemirror/extensions/marks/FootnoteRefExtension.js +21 -5
  231. package/dist/prosemirror/extensions/marks/RunIdentityExtension.d.ts +21 -18
  232. package/dist/prosemirror/extensions/marks/RunIdentityExtension.js +37 -17
  233. package/dist/prosemirror/extensions/marks/markUtils.d.ts +7 -2
  234. package/dist/prosemirror/extensions/marks/markUtils.js +8 -2
  235. package/dist/prosemirror/extensions/marks/noteReferenceDeletion.d.ts +10 -0
  236. package/dist/prosemirror/extensions/marks/noteReferenceDeletion.js +35 -0
  237. package/dist/prosemirror/extensions/nodes/BlockCustomXmlExtension.d.ts +6 -0
  238. package/dist/prosemirror/extensions/nodes/BlockCustomXmlExtension.js +52 -0
  239. package/dist/prosemirror/extensions/nodes/FieldExtension.d.ts +3 -3
  240. package/dist/prosemirror/extensions/nodes/FieldExtension.js +50 -15
  241. package/dist/prosemirror/extensions/nodes/PreservedBlockExtension.js +4 -1
  242. package/dist/prosemirror/extensions/nodes/TableExtension.d.ts +1 -1
  243. package/dist/prosemirror/extensions/nodes/TableExtension.js +19 -18
  244. package/dist/prosemirror/extensions/types.d.ts +4 -1
  245. package/dist/prosemirror/findReplaceSelection.js +1 -1
  246. package/dist/prosemirror/index.d.ts +3 -2
  247. package/dist/prosemirror/index.js +3 -2
  248. package/dist/prosemirror/indexedNodeLookup.d.ts +17 -0
  249. package/dist/prosemirror/indexedNodeLookup.js +103 -0
  250. package/dist/prosemirror/listAutoformatMarkers.d.ts +19 -0
  251. package/dist/prosemirror/listAutoformatMarkers.js +98 -0
  252. package/dist/prosemirror/listInstanceReferences.d.ts +12 -0
  253. package/dist/prosemirror/listInstanceReferences.js +72 -0
  254. package/dist/prosemirror/listLabels.d.ts +24 -0
  255. package/dist/prosemirror/listLabels.js +111 -0
  256. package/dist/prosemirror/listNumbering.d.ts +110 -0
  257. package/dist/prosemirror/listNumbering.js +345 -0
  258. package/dist/prosemirror/listRenderingAttrs.d.ts +11 -2
  259. package/dist/prosemirror/listRenderingAttrs.js +8 -1
  260. package/dist/prosemirror/markupViewProjection.d.ts +95 -0
  261. package/dist/prosemirror/markupViewProjection.js +83 -0
  262. package/dist/prosemirror/numberingAttr.d.ts +9 -1
  263. package/dist/prosemirror/numberingAttr.js +9 -1
  264. package/dist/prosemirror/outlineLevelAttr.js +1 -1
  265. package/dist/prosemirror/paragraphIndentation.d.ts +10 -1
  266. package/dist/prosemirror/paragraphIndentation.js +29 -7
  267. package/dist/prosemirror/paragraphMarkJoin.d.ts +19 -0
  268. package/dist/prosemirror/paragraphMarkJoin.js +24 -0
  269. package/dist/prosemirror/plugins/createDocScanPlugin.d.ts +1 -1
  270. package/dist/prosemirror/plugins/documentNumbering.d.ts +27 -1
  271. package/dist/prosemirror/plugins/documentNumbering.js +97 -11
  272. package/dist/prosemirror/plugins/documentStyles.d.ts +10 -1
  273. package/dist/prosemirror/plugins/documentStyles.js +14 -1
  274. package/dist/prosemirror/plugins/suggestionMode.d.ts +16 -2
  275. package/dist/prosemirror/plugins/suggestionMode.js +116 -52
  276. package/dist/prosemirror/plugins/templateDirectives.d.ts +1 -1
  277. package/dist/prosemirror/plugins/transactionInvariants.d.ts +32 -0
  278. package/dist/prosemirror/plugins/transactionInvariants.js +86 -0
  279. package/dist/prosemirror/positionSweep.d.ts +24 -0
  280. package/dist/prosemirror/positionSweep.js +222 -0
  281. package/dist/prosemirror/rebaseParagraphRunFormatting.d.ts +1 -1
  282. package/dist/prosemirror/rejoinRunCarriers.d.ts +1 -1
  283. package/dist/prosemirror/replacedAnnotations.d.ts +33 -1
  284. package/dist/prosemirror/replacedAnnotations.js +170 -1
  285. package/dist/prosemirror/runFormattingInlineCarriers.d.ts +1 -1
  286. package/dist/prosemirror/schema/index.d.ts +2 -2
  287. package/dist/prosemirror/schema/index.js +3 -0
  288. package/dist/prosemirror/schema/nodes.d.ts +42 -11
  289. package/dist/prosemirror/sectionMarkEdits.d.ts +20 -0
  290. package/dist/prosemirror/sectionMarkEdits.js +59 -0
  291. package/dist/prosemirror/storyListNumbering.d.ts +17 -0
  292. package/dist/prosemirror/storyListNumbering.js +102 -0
  293. package/dist/prosemirror/tableGridMutation.d.ts +48 -2
  294. package/dist/prosemirror/tableGridMutation.js +106 -1
  295. package/dist/prosemirror/validation.js +5 -1
  296. package/dist/redline.js +93 -9
  297. package/dist/render-dom/BodySelectionOverlay.d.ts +4 -1
  298. package/dist/render-dom/BodySelectionOverlay.js +3 -2
  299. package/dist/utils/findReplace.js +2 -2
  300. package/dist/utils/mergeDocumentContent.js +1 -1
  301. package/dist/utils/noteReferenceLabels.d.ts +36 -0
  302. package/dist/utils/noteReferenceLabels.js +32 -0
  303. package/dist/utils/replaceText.js +1 -1
  304. package/dist/version-comparison.d.ts +1 -0
  305. package/dist/version-comparison.js +1 -0
  306. package/package.json +3 -2
  307. package/dist/internal/headlessRevisionResolution.d.ts +0 -23
@@ -0,0 +1,249 @@
1
+ import { NUMBER_FORMATS } from "@stll/docx-core/model";
2
+ //#region src/docx/listNumberingInstances.ts
3
+ /**
4
+ * Numbering instances the editor defines itself.
5
+ *
6
+ * A list command in a document with no list of the requested kind has nothing
7
+ * to reference: the package may have no numbering part at all. The command
8
+ * then defines one, an `w:abstractNum` built from {@link defaultListLevels}
9
+ * plus the `w:num` naming it, as a word processor does when a list is
10
+ * started in a document without lists.
11
+ *
12
+ * The definition lives in two places without being stored twice. While the
13
+ * document is edited, the paragraphs that reference the instance carry the
14
+ * rendering it resolved to (`listAbstractNumId`, `listNumFmt`,
15
+ * `listMarkerTemplate`, `listStartOverride`, …), and those attrs travel with
16
+ * the paragraph through undo, collaboration and every save path.
17
+ * {@link completeListNumbering} turns them back into the definition wherever
18
+ * the package's own numbering has no entry for the id. Because a minted
19
+ * definition is the template plus level-0 facts that the rendering states, the
20
+ * definition it rebuilds is the one the command minted.
21
+ */
22
+ /** The two kinds of list a command can create. */
23
+ const LIST_KINDS = ["bullet", "numbered"];
24
+ const INDENT_STEP_TWIPS = 720;
25
+ const HANGING_TWIPS = 360;
26
+ const ROMAN_HANGING_TWIPS = 180;
27
+ const LEVEL_COUNT = 9;
28
+ const levelIndent = (ilvl, hanging) => ({
29
+ indentLeft: INDENT_STEP_TWIPS * (ilvl + 1),
30
+ indentFirstLine: -hanging,
31
+ hangingIndent: true
32
+ });
33
+ /** The customary numbered-list cycle: `1.`, `a.`, `i.`, then again one level deeper. */
34
+ const NUMBERED_CYCLE = [
35
+ {
36
+ numFmt: "decimal",
37
+ lvlJc: "left",
38
+ hanging: HANGING_TWIPS
39
+ },
40
+ {
41
+ numFmt: "lowerLetter",
42
+ lvlJc: "left",
43
+ hanging: HANGING_TWIPS
44
+ },
45
+ {
46
+ numFmt: "lowerRoman",
47
+ lvlJc: "right",
48
+ hanging: ROMAN_HANGING_TWIPS
49
+ }
50
+ ];
51
+ /** The customary bullet cycle: a round bullet, an open circle, a square. */
52
+ const BULLET_CYCLE = [
53
+ {
54
+ text: "•",
55
+ font: null
56
+ },
57
+ {
58
+ text: "o",
59
+ font: "Courier New"
60
+ },
61
+ {
62
+ text: "▪",
63
+ font: null
64
+ }
65
+ ];
66
+ const cycleEntry = (cycle, ilvl) => cycle.at(ilvl % cycle.length) ?? cycle[0];
67
+ const numberedLevel = (ilvl) => {
68
+ const { numFmt, lvlJc, hanging } = cycleEntry(NUMBERED_CYCLE, ilvl);
69
+ return {
70
+ ilvl,
71
+ start: 1,
72
+ numFmt,
73
+ lvlText: `%${ilvl + 1}.`,
74
+ lvlJc,
75
+ pPr: levelIndent(ilvl, hanging)
76
+ };
77
+ };
78
+ const bulletLevel = (ilvl) => {
79
+ const { text, font } = cycleEntry(BULLET_CYCLE, ilvl);
80
+ return {
81
+ ilvl,
82
+ start: 1,
83
+ numFmt: "bullet",
84
+ lvlText: text,
85
+ lvlJc: "left",
86
+ pPr: levelIndent(ilvl, HANGING_TWIPS),
87
+ ...font === null ? {} : { rPr: { fontFamily: {
88
+ ascii: font,
89
+ hAnsi: font
90
+ } } }
91
+ };
92
+ };
93
+ /** The nine levels a list of `kind` is minted with. */
94
+ const defaultListLevels = (kind) => Array.from({ length: LEVEL_COUNT }, (_, ilvl) => kind === "bullet" ? bulletLevel(ilvl) : numberedLevel(ilvl));
95
+ const mintAbstractNumbering = ({ abstractNumId, kind, format }) => {
96
+ const levels = defaultListLevels(kind);
97
+ const first = levels[0];
98
+ if (first && kind === "numbered" && format) levels[0] = {
99
+ ...first,
100
+ numFmt: format.numFmt,
101
+ lvlText: format.lvlText
102
+ };
103
+ return {
104
+ abstractNumId,
105
+ multiLevelType: "hybridMultilevel",
106
+ levels
107
+ };
108
+ };
109
+ /** The template counts from one, so only another first value needs an override. */
110
+ const levelZeroStart = (start) => start === void 0 || start === 1 ? void 0 : [{
111
+ ilvl: 0,
112
+ startOverride: start
113
+ }];
114
+ const EMPTY_DEFINITIONS = {
115
+ abstractNums: [],
116
+ nums: []
117
+ };
118
+ const nextId = (ids, floor) => {
119
+ let next = floor;
120
+ for (const id of ids) next = Math.max(next, id + 1);
121
+ return next;
122
+ };
123
+ /** A fresh `w:numId` for `definitions`; zero is reserved for "no numbering". */
124
+ const nextNumId = (definitions) => nextId((definitions?.nums ?? []).map(({ numId }) => numId), 1);
125
+ /** A fresh `w:abstractNumId` for `definitions`. */
126
+ const nextAbstractNumId = (definitions) => nextId((definitions?.abstractNums ?? []).map(({ abstractNumId }) => abstractNumId), 0);
127
+ /**
128
+ * Define a new list: a new `w:abstractNum` of the requested kind and the
129
+ * `w:num` naming it. `definitions` must already hold every instance the
130
+ * document references (see {@link completeListNumbering}), so the new ids
131
+ * collide with none of them.
132
+ */
133
+ const mintListInstance = (definitions, { kind, format, start }) => {
134
+ const current = definitions ?? EMPTY_DEFINITIONS;
135
+ const numId = nextNumId(current);
136
+ const abstractNumId = nextAbstractNumId(current);
137
+ const levelOverrides = levelZeroStart(start);
138
+ const instance = {
139
+ numId,
140
+ abstractNumId,
141
+ ...levelOverrides ? { levelOverrides } : {}
142
+ };
143
+ return {
144
+ numId,
145
+ definitions: {
146
+ ...current,
147
+ abstractNums: [...current.abstractNums, mintAbstractNumbering({
148
+ abstractNumId,
149
+ kind,
150
+ format
151
+ })],
152
+ nums: [...current.nums, instance]
153
+ }
154
+ };
155
+ };
156
+ /**
157
+ * A new `w:num` over an existing `w:abstractNum`, with a `w:startOverride` at
158
+ * `ilvl`: *Restart Numbering* and *Set Numbering Value*. The override is what
159
+ * makes a consumer count the instance on its own rather than continue the
160
+ * other instances of the same definition.
161
+ */
162
+ const restartListInstance = (definitions, { abstractNumId, ilvl, start }) => {
163
+ const current = definitions ?? EMPTY_DEFINITIONS;
164
+ const numId = nextNumId(current);
165
+ const instance = {
166
+ numId,
167
+ abstractNumId,
168
+ levelOverrides: [{
169
+ ilvl,
170
+ startOverride: start
171
+ }]
172
+ };
173
+ return {
174
+ numId,
175
+ definitions: {
176
+ ...current,
177
+ nums: [...current.nums, instance]
178
+ }
179
+ };
180
+ };
181
+ const NUMBER_FORMAT_SET = new Set(NUMBER_FORMATS);
182
+ const isNumberFormat = (format) => format !== void 0 && NUMBER_FORMAT_SET.has(format);
183
+ const levelZeroFormat = (references) => {
184
+ const first = references.find(({ ilvl }) => ilvl === 0)?.rendering;
185
+ const numFmt = first?.numFmt ?? references.find(({ rendering }) => rendering.levelNumFmts?.[0])?.rendering.levelNumFmts?.[0];
186
+ if (!isNumberFormat(numFmt)) return;
187
+ return {
188
+ numFmt,
189
+ lvlText: first?.markerTemplate ?? "%1."
190
+ };
191
+ };
192
+ const startOverridesOf = (references) => {
193
+ const byLevel = /* @__PURE__ */ new Map();
194
+ for (const { ilvl, rendering } of references) if (rendering.startOverride !== void 0 && !byLevel.has(ilvl)) byLevel.set(ilvl, rendering.startOverride);
195
+ return [...byLevel.entries()].toSorted(([left], [right]) => left - right).map(([ilvl, startOverride]) => ({
196
+ ilvl,
197
+ startOverride
198
+ }));
199
+ };
200
+ /**
201
+ * Define every instance `references` name that `definitions` does not.
202
+ *
203
+ * A reference the editor resolved carries its rendering, and a rendering is
204
+ * what a minted instance leaves behind; a reference without one (a dangling
205
+ * id read from a file) has no rendering and so is never defined here. Returns
206
+ * `definitions` itself when nothing is missing.
207
+ */
208
+ const completeListNumbering = (definitions, references) => {
209
+ const definedNums = new Set((definitions?.nums ?? []).map(({ numId }) => numId));
210
+ const missing = /* @__PURE__ */ new Map();
211
+ for (const reference of references) {
212
+ if (definedNums.has(reference.numId)) continue;
213
+ const group = missing.get(reference.numId);
214
+ if (group) group.push(reference);
215
+ else missing.set(reference.numId, [reference]);
216
+ }
217
+ if (missing.size === 0) return definitions;
218
+ const current = definitions ?? EMPTY_DEFINITIONS;
219
+ const abstractIds = new Set(current.abstractNums.map(({ abstractNumId }) => abstractNumId));
220
+ const statedAbstractIds = [...missing.values()].flatMap((group) => group.flatMap(({ rendering }) => rendering.abstractNumId === void 0 ? [] : [rendering.abstractNumId]));
221
+ let freeAbstractId = nextId([...abstractIds, ...statedAbstractIds], 0);
222
+ const abstractNums = [];
223
+ const nums = [];
224
+ for (const [numId, group] of missing) {
225
+ const abstractNumId = group.find(({ rendering }) => rendering.abstractNumId !== void 0)?.rendering.abstractNumId ?? freeAbstractId++;
226
+ if (!abstractIds.has(abstractNumId)) {
227
+ abstractIds.add(abstractNumId);
228
+ const kind = group.some(({ rendering }) => rendering.isBullet) ? "bullet" : "numbered";
229
+ abstractNums.push(mintAbstractNumbering({
230
+ abstractNumId,
231
+ kind,
232
+ format: levelZeroFormat(group)
233
+ }));
234
+ }
235
+ const levelOverrides = startOverridesOf(group);
236
+ nums.push({
237
+ numId,
238
+ abstractNumId,
239
+ ...levelOverrides.length > 0 ? { levelOverrides } : {}
240
+ });
241
+ }
242
+ return {
243
+ ...current,
244
+ abstractNums: [...current.abstractNums, ...abstractNums],
245
+ nums: [...current.nums, ...nums]
246
+ };
247
+ };
248
+ //#endregion
249
+ export { LIST_KINDS, completeListNumbering, mintListInstance, restartListInstance };
@@ -52,7 +52,8 @@ const normalizeCellBlock = (block, styles) => {
52
52
  switch (block.type) {
53
53
  case "paragraph": return normalizeParagraph(block, styles);
54
54
  case "table": return normalizeTable(block, styles);
55
- case "blockSdt": return {
55
+ case "blockSdt":
56
+ case "blockCustomXml": return {
56
57
  ...block,
57
58
  content: block.content.map((child) => normalizeCellBlock(child, styles))
58
59
  };
@@ -0,0 +1,7 @@
1
+ //#region src/docx/opaqueCarrier.d.ts
2
+ declare const OPAQUE_REVISION_CARRIER_READER_DIAGNOSTIC = "[Unsupported block-level tracked-change content]";
3
+ declare const opaqueRevisionCarrierName: (xml: string) => string | undefined;
4
+ declare const countOpaqueRevisionWrappers: (xml: string) => number;
5
+ declare const isOpaqueNestedRowMarkup: (xml: string) => boolean;
6
+ //#endregion
7
+ export { OPAQUE_REVISION_CARRIER_READER_DIAGNOSTIC, countOpaqueRevisionWrappers, isOpaqueNestedRowMarkup, opaqueRevisionCarrierName };
@@ -0,0 +1,38 @@
1
+ import { OOXML_NAMESPACE_SCOPE, WORDPROCESSINGML_NAMESPACE_URIS, getChildElements, getLocalName, parseXml } from "./xmlParser.js";
2
+ //#region src/docx/opaqueCarrier.ts
3
+ const OPAQUE_REVISION_CARRIER_READER_DIAGNOSTIC = "[Unsupported block-level tracked-change content]";
4
+ const REVISION_WRAPPERS = /* @__PURE__ */ new Set([
5
+ "ins",
6
+ "del",
7
+ "moveFrom",
8
+ "moveTo"
9
+ ]);
10
+ const opaqueRevisionCarrierName = (xml) => {
11
+ const visit = (element) => {
12
+ const localName = getLocalName(element.name);
13
+ if (WORDPROCESSINGML_NAMESPACE_URIS.has(element.namespaceUri ?? "") && REVISION_WRAPPERS.has(localName)) return `w:${localName}`;
14
+ for (const child of getChildElements(element)) {
15
+ const match = visit(child);
16
+ if (match !== void 0) return match;
17
+ }
18
+ };
19
+ for (const root of getChildElements(parseXml(xml, OOXML_NAMESPACE_SCOPE))) {
20
+ const match = visit(root);
21
+ if (match !== void 0) return match;
22
+ }
23
+ };
24
+ const countOpaqueRevisionWrappers = (xml) => {
25
+ const count = (element) => {
26
+ const localName = getLocalName(element.name);
27
+ let total = WORDPROCESSINGML_NAMESPACE_URIS.has(element.namespaceUri ?? "") && REVISION_WRAPPERS.has(localName) ? 1 : 0;
28
+ for (const child of getChildElements(element)) total += count(child);
29
+ return total;
30
+ };
31
+ return getChildElements(parseXml(xml, OOXML_NAMESPACE_SCOPE)).reduce((total, element) => total + count(element), 0);
32
+ };
33
+ const isOpaqueNestedRowMarkup = (xml) => {
34
+ const element = getChildElements(parseXml(xml, OOXML_NAMESPACE_SCOPE)).at(0);
35
+ return element !== void 0 && getLocalName(element.name) === "tr" && WORDPROCESSINGML_NAMESPACE_URIS.has(element.namespaceUri ?? "");
36
+ };
37
+ //#endregion
38
+ export { OPAQUE_REVISION_CARRIER_READER_DIAGNOSTIC, countOpaqueRevisionWrappers, isOpaqueNestedRowMarkup, opaqueRevisionCarrierName };
@@ -58,7 +58,10 @@ const isPresent = (present, partPath) => present.has(normalizePartPath(partPath)
58
58
  const relationshipTarget = (element, relsPath) => {
59
59
  if (TARGET_MODE_ATTRIBUTE.exec(element)?.groups?.["value"] === "External") return null;
60
60
  const target = TARGET_ATTRIBUTE.exec(element)?.groups?.["value"];
61
- return target === void 0 ? null : resolveRelativePath(relsPath, target);
61
+ if (target === void 0) return null;
62
+ const fragment = target.indexOf("#");
63
+ if (fragment === 0) return owningPartPath(relsPath) ?? "";
64
+ return resolveRelativePath(relsPath, fragment > 0 ? target.slice(0, fragment) : target);
62
65
  };
63
66
  /**
64
67
  * Every `.rels` part with its text. Read one at a time rather than through
@@ -578,8 +578,8 @@ const hasRunPayload = ({ run, runElement, rels, media }) => {
578
578
  * the assembled field, and one that reaches the editor's inline converter on
579
579
  * its own is dropped. So a `w:fldChar` whose field this paragraph never closed,
580
580
  * or one with no `begin` before it, loses the editor round trip — and the
581
- * model holds nothing of its `w:ffData` either, so the save loses a legacy form
582
- * field's name, macros, help text and checkbox state as well.
581
+ * orphan field has no owning `ComplexField` to hold its `w:ffData`, so dropping
582
+ * this run would also lose its name, macros, help text and checkbox state.
583
583
  *
584
584
  * `preservedXml` is the run's own capture member: the editor carries it as an
585
585
  * opaque atom and the serializer replays the source bytes, `w:ffData` included.
@@ -610,9 +610,11 @@ const LEGACY_FORM_CHECKBOX_GLYPHS = {
610
610
  unchecked: "☐"
611
611
  };
612
612
  const LEGACY_FORM_CHECKBOX_INSTRUCTION = "FORMCHECKBOX";
613
- function getLegacyFormCheckboxDisplay(runElement) {
614
- const fieldChar = findChild(runElement, "w", "fldChar");
615
- const fieldData = fieldChar ? findChild(fieldChar, "w", "ffData") : null;
613
+ const beginFieldCharOf = (runElement) => findChildrenByNamespaceUri(runElement, WORDPROCESSINGML_NAMESPACE_URIS, "fldChar").find((fieldChar) => {
614
+ const charType = getAttribute(fieldChar, "w", "fldCharType");
615
+ return charType !== "separate" && charType !== "end";
616
+ });
617
+ function getLegacyFormCheckboxDisplay(fieldData) {
616
618
  const checkBox = fieldData ? findChild(fieldData, "w", "checkBox") : null;
617
619
  if (!checkBox) return;
618
620
  const checked = findChild(checkBox, "w", "checked");
@@ -676,6 +678,30 @@ const FIELD_INLINE_WRAPPER_HANDLERS = {
676
678
  pPr: CAPTURE
677
679
  };
678
680
  /**
681
+ * Whether the walk is currently inside some open field's code region — its
682
+ * own `begin` has been read but not yet its `separate` — at any nesting
683
+ * depth. `codeDepthStack` tracks every open field regardless of whether it
684
+ * assembles into a `ComplexField`, so this answers the question for content,
685
+ * such as a `w:fldSimple`, that a `ComplexField`'s own code/result split
686
+ * cannot carry.
687
+ */
688
+ const isHiddenByOpenFieldCode = (scan) => scan.codeDepthStack.some((pastSeparator) => !pastSeparator);
689
+ /**
690
+ * A run captured for a position this field's `fieldResult` (or `fieldCode`)
691
+ * must hold — the source ordering a save has to reproduce puts it there —
692
+ * whose actual content sits inside a deeper, still-open field's own
693
+ * instruction region and so must show nothing. Every non-`w:rPr` child is
694
+ * captured through `preserveRunChild`, the same verbatim-with-no-text capture
695
+ * an unrecognised run child already gets, rather than kept as the `text`/
696
+ * `instrText` the parse produced — a `w:t` this walk read as authored result
697
+ * text is exactly what must not read back out of `fieldResult`.
698
+ */
699
+ const hiddenRunCaptureOf = (runElement, formatting) => ({
700
+ type: "run",
701
+ content: getChildElements(runElement).filter((child) => getLocalName(child.name) !== "rPr").map((child) => preserveRunChild(child)),
702
+ ...formatting && Object.keys(formatting).length > 0 ? { formatting } : {}
703
+ });
704
+ /**
679
705
  * The container children a complex field's result may hold and still be
680
706
  * assembled into a `ComplexField`: its runs and the zero-width markers read
681
707
  * beside them. Any other child is inline content (a hyperlink, a simple field,
@@ -713,25 +739,31 @@ const isWordprocessingChild = (child) => {
713
739
  };
714
740
  /**
715
741
  * The `w:r` children whose `begin` opens a complex field that this container's
716
- * walk closes.
742
+ * walk closes as its own top-level `ComplexField`.
717
743
  *
718
744
  * A field is assembled from the runs between its `begin` and its `end`, so it
719
745
  * exists only when both are runs of this container with nothing between them
720
746
  * that a `ComplexField` cannot hold. A TOC opened here and closed in a later
721
- * paragraph, a field whose result holds a `w:hyperlink` (a TOC's `\h` entries),
722
- * and an outer field whose result holds a nested field are none of these; their
723
- * runs are ordinary content, read in source order alongside the siblings
724
- * between them. Mirrors the `w:r` handler run by run: a run with a `begin`
725
- * opens a field, and a run with an `end` closes the one open.
747
+ * paragraph, and a field whose result holds a `w:hyperlink` (a TOC's `\h`
748
+ * entries), are neither of those; their runs are ordinary content, read in
749
+ * source order alongside the siblings between them.
750
+ *
751
+ * A `begin`/`end` pair that closes while another `begin` is still open is
752
+ * nested inside that other field's code or result — its own runs stay with
753
+ * the outer field's, carried in `fieldCode`/`fieldResult` rather than
754
+ * assembled into a `ComplexField` of their own, which is why only the
755
+ * outermost pair of a nested run adds its `begin` here. Tracked with a stack
756
+ * rather than one slot so a field nested inside a field nested inside a field
757
+ * closes each level against the right opener instead of the most recent one.
726
758
  */
727
759
  const assembledFieldBeginsOf = (container) => {
728
760
  const assembled = /* @__PURE__ */ new Set();
729
- let open;
761
+ const open = [];
730
762
  for (const child of getChildElements(container)) {
731
763
  const wordprocessing = isWordprocessingChild(child);
732
764
  const localName = getLocalName(child.name);
733
765
  if (!wordprocessing || localName !== "r") {
734
- if (!wordprocessing || !FIELD_TRANSPARENT_CHILDREN.has(localName)) open = void 0;
766
+ if (!wordprocessing || !FIELD_TRANSPARENT_CHILDREN.has(localName)) open.length = 0;
735
767
  continue;
736
768
  }
737
769
  let hasBegin = false;
@@ -742,10 +774,10 @@ const assembledFieldBeginsOf = (container) => {
742
774
  if (charType === "end") hasEnd = true;
743
775
  else if (charType !== "separate") hasBegin = true;
744
776
  }
745
- if (hasBegin) open = child;
746
- if (hasEnd && open !== void 0) {
747
- assembled.add(open);
748
- open = void 0;
777
+ if (hasBegin) open.push(child);
778
+ if (hasEnd && open.length > 0) {
779
+ const closed = open.pop();
780
+ if (closed !== void 0 && open.length === 0) assembled.add(closed);
749
781
  }
750
782
  }
751
783
  return assembled;
@@ -774,7 +806,8 @@ const PARAGRAPH_CONTENT_HANDLERS = {
774
806
  const commentReferenceId = getCommentReferenceId(runElement);
775
807
  let hasFieldBegin = false;
776
808
  let beginFieldState = {};
777
- const beginFallbackDisplay = getLegacyFormCheckboxDisplay(runElement);
809
+ const beginFieldData = findWordprocessingChild(beginFieldCharOf(runElement), "ffData");
810
+ const beginFallbackDisplay = getLegacyFormCheckboxDisplay(beginFieldData);
778
811
  let hasFieldSeparate = false;
779
812
  let hasFieldEnd = false;
780
813
  let endOriginalValue;
@@ -788,6 +821,8 @@ const PARAGRAPH_CONTENT_HANDLERS = {
788
821
  if (content.originalValue !== void 0) endOriginalValue = content.originalValue;
789
822
  }
790
823
  else if (content.type === "instrText") instrText += content.text;
824
+ if (hasFieldBegin) scan.codeDepthStack.push(false);
825
+ if (hasFieldSeparate && scan.codeDepthStack.length > 0) scan.codeDepthStack[scan.codeDepthStack.length - 1] = true;
791
826
  if (hasFieldBegin) {
792
827
  scan.assembledFieldBegins ??= assembledFieldBeginsOf(scan.container);
793
828
  if (!scan.assembledFieldBegins.has(child)) hasFieldBegin = false;
@@ -804,9 +839,13 @@ const PARAGRAPH_CONTENT_HANDLERS = {
804
839
  scan.complexFieldResultRuns = [];
805
840
  scan.complexFieldOpenRuns = [];
806
841
  scan.complexFieldState = beginFieldState;
842
+ scan.complexFieldDataXml = beginFieldData ? captureVerbatimXml(beginFieldData) : void 0;
807
843
  scan.complexFieldFallbackDisplay = beginFallbackDisplay;
808
844
  scan.complexFieldFormatting = run.formatting;
845
+ scan.complexFieldBaseDepth = scan.codeDepthStack.length;
809
846
  }
847
+ const isNestedField = scan.codeDepthStack.length > scan.complexFieldBaseDepth;
848
+ if (hasFieldEnd && scan.codeDepthStack.length > 0) scan.codeDepthStack.pop();
810
849
  if (scan.inComplexField) {
811
850
  scan.complexFieldOpenRuns.push(withOrphanFieldCharsPreserved(run, runElement));
812
851
  if (instrText) scan.complexFieldInstr += instrText;
@@ -815,6 +854,10 @@ const PARAGRAPH_CONTENT_HANDLERS = {
815
854
  const fieldCodeContent = [];
816
855
  for (const content of run.content) {
817
856
  if (content.type === "fieldChar") {
857
+ if (isNestedField) {
858
+ if (inFieldCodeRegion) fieldCodeContent.push(content);
859
+ continue;
860
+ }
818
861
  inFieldCodeRegion = content.charType === "begin";
819
862
  continue;
820
863
  }
@@ -824,11 +867,11 @@ const PARAGRAPH_CONTENT_HANDLERS = {
824
867
  ...run,
825
868
  content: fieldCodeContent
826
869
  });
827
- if (hasFieldSeparate) scan.afterSeparator = true;
870
+ if (hasFieldSeparate && !isNestedField) scan.afterSeparator = true;
828
871
  if (scan.afterSeparator && !hasFieldEnd) {
829
- if (!hasFieldSeparate) scan.complexFieldResultRuns.push(run);
872
+ if (!hasFieldSeparate) scan.complexFieldResultRuns.push(isHiddenByOpenFieldCode(scan) ? hiddenRunCaptureOf(runElement, run.formatting) : run);
830
873
  }
831
- if (hasFieldEnd) {
874
+ if (hasFieldEnd && !isNestedField) {
832
875
  let resultRuns = scan.complexFieldResultRuns;
833
876
  let resultIsFallback = false;
834
877
  if (resultRuns.length === 0 && scan.complexFieldFallbackDisplay !== void 0 && isLegacyFormCheckboxInstruction(scan.complexFieldInstr)) {
@@ -850,6 +893,7 @@ const PARAGRAPH_CONTENT_HANDLERS = {
850
893
  fieldResult: resultRuns,
851
894
  ...scan.complexFieldState
852
895
  };
896
+ if (scan.complexFieldDataXml !== void 0) complexField.formFieldDataXml = scan.complexFieldDataXml;
853
897
  if (resultIsFallback) complexField.fieldResultIsFallback = true;
854
898
  if (scan.complexFieldFormatting) complexField.formatting = scan.complexFieldFormatting;
855
899
  contents.push(complexField);
@@ -865,6 +909,17 @@ const PARAGRAPH_CONTENT_HANDLERS = {
865
909
  type: "commentReference",
866
910
  id: commentReferenceId
867
911
  });
912
+ } else if (isHiddenByOpenFieldCode(scan)) {
913
+ if (hasRunPayload({
914
+ run,
915
+ runElement,
916
+ rels,
917
+ media
918
+ })) contents.push({
919
+ type: "preservedInline",
920
+ xml: captureVerbatimXml(runElement),
921
+ text: ""
922
+ });
868
923
  } else if (hasRunPayload({
869
924
  run,
870
925
  runElement,
@@ -881,8 +936,17 @@ const PARAGRAPH_CONTENT_HANDLERS = {
881
936
  bookmarkEnd: (child, { contents }) => {
882
937
  contents.push(parseBookmarkEnd(child));
883
938
  },
884
- fldSimple: (child, { contents, styles, theme, rels, media, previews, inScopeXmlns }) => {
885
- contents.push(parseSimpleField(child, styles, theme, rels, media, inScopeXmlns, previews));
939
+ fldSimple: (child, { contents, styles, theme, rels, media, previews, inScopeXmlns, trackedContext, scan }) => {
940
+ const fieldElement = trackedContext === "deletion" ? normalizeDeletionContentElement(child) : child;
941
+ if (isHiddenByOpenFieldCode(scan)) {
942
+ contents.push({
943
+ type: "preservedInline",
944
+ xml: captureVerbatimXml(fieldElement),
945
+ text: ""
946
+ });
947
+ return;
948
+ }
949
+ contents.push(parseSimpleField(fieldElement, styles, theme, rels, media, inScopeXmlns, previews));
886
950
  },
887
951
  pPr: PARAGRAPH_PROPERTIES_OWNER,
888
952
  customXml: paragraphInlineWrapper("customXml"),
@@ -1005,10 +1069,13 @@ function parseParagraphContents(paraElement, styles, theme, _numbering, rels, me
1005
1069
  complexFieldOpenRuns: [],
1006
1070
  afterSeparator: false,
1007
1071
  complexFieldState: {},
1072
+ complexFieldDataXml: void 0,
1008
1073
  complexFieldFallbackDisplay: void 0,
1009
1074
  complexFieldFormatting: void 0,
1010
1075
  container: paraElement,
1011
- assembledFieldBegins: void 0
1076
+ assembledFieldBegins: void 0,
1077
+ codeDepthStack: [],
1078
+ complexFieldBaseDepth: 0
1012
1079
  };
1013
1080
  const preserved = dispatchChildrenWithContext({
1014
1081
  element: paraElement,
@@ -1,7 +1,7 @@
1
1
  import { document_d_exports } from "../types/document.js";
2
2
  import { ModeledParagraphFormattingEmission } from "../internal/paragraphFormattingSerialization.js";
3
- import { Transaction } from "prosemirror-state";
4
3
  import { Fragment, Mark, Node, NodeType } from "prosemirror-model";
4
+ import { Transaction } from "prosemirror-state";
5
5
  //#region src/docx/paragraphPropertySource.d.ts
6
6
  declare const paragraphPropertySourceEmissionFingerprint: unique symbol;
7
7
  type ParagraphPropertySource = Readonly<{
@@ -97,6 +97,8 @@ type JoinProseParagraphsWithRightPropertySourceOptions = {
97
97
  };
98
98
  /** Join adjacent paragraphs when revision semantics deliberately select the right owner. */
99
99
  declare const joinProseParagraphsWithRightPropertySource: ({ attrs, pos, transaction }: JoinProseParagraphsWithRightPropertySourceOptions) => Transaction;
100
+ /** Record the property owners deliberately selected by a batch of paragraph joins. */
101
+ declare const markParagraphPropertySourceTransfers: (transaction: Transaction, transfers: readonly ParagraphPropertySourceTransfer[]) => void;
100
102
  declare const getExplicitParagraphPropertySourceTransfers: (transaction: Transaction) => readonly ParagraphPropertySourceTransfer[];
101
103
  type RecreateProseNodeOptions = {
102
104
  attrs?: Node["attrs"];
@@ -134,4 +136,4 @@ declare const linkParagraphPropertySourceCandidate: (target: document_d_exports.
134
136
  declare const getParagraphPropertySourceCandidate: (paragraph: document_d_exports.Paragraph) => document_d_exports.Paragraph | undefined;
135
137
  declare const getParagraphPropertySourceTransferId: (paragraph: document_d_exports.Paragraph) => string | undefined;
136
138
  //#endregion
137
- export { DecodedTableCellParagraphSourcePayload, PARAGRAPH_PROPERTY_SOURCE_VALIDATION_CODES, PROSE_PARAGRAPH_SOURCE_CONTRACT_ATTR, PROSE_PARAGRAPH_SOURCE_TOKEN_ATTR, ParagraphPropertySourceValidationCode, ParagraphPropertySourceValidationError, TABLE_CELL_PARAGRAPH_SOURCE_BINDING_ATTR, TABLE_CELL_PARAGRAPH_SOURCE_PAYLOAD_ERROR_CLASSIFICATIONS, TableCellParagraphPropertySourceBinding, TableCellParagraphSourcePayloadErrorClassification, assignDocumentParagraphPropertySourceContract, assignParagraphPropertySource, cloneDocumentWithParagraphPropertySources, cloneParagraphWithPropertySource, cloneParagraphWithoutPropertySource, cloneTableCellsWithParagraphPropertyCaptures, copyDocumentParagraphPropertySourceContract, copyDocumentParagraphPropertySources, copyParagraphPropertyCapture, copyParagraphPropertySource, createProseParagraphWithPropertySource, decodeTableCellParagraphSourcePayload, getDocumentParagraphPropertySourceContract, getExplicitParagraphPropertySourceTransfers, getParagraphPropertySource, getParagraphPropertySourceCandidate, getParagraphPropertySourceToken, getParagraphPropertySourceTransferId, getProseDocumentParagraphPropertySourceContract, getProseParagraphPropertySourceToken, isParagraphPropertySourceToken, joinProseParagraphsWithRightPropertySource, linkParagraphPropertySourceCandidate, linkProseParagraphPropertySource, paragraphPropertySourceBelongsToDocument, paragraphPropertySourceMatchesEmission, paragraphPropertySourceTokenMatchesContract, proseParagraphAttrsWithoutPropertySource, recreateProseNodeWithDetachedParagraphPropertySource, recreateProseNodeWithParagraphPropertySource, restoreTableCellsWithParagraphPropertySources, setProseParagraphMarkupWithPropertySource, transferProseParagraphPropertySource, transportTableCellsWithParagraphPropertySources, visitDocumentStoryParagraphs, visitTableCellParagraphPropertySourceBindings };
139
+ export { DecodedTableCellParagraphSourcePayload, PARAGRAPH_PROPERTY_SOURCE_VALIDATION_CODES, PROSE_PARAGRAPH_SOURCE_CONTRACT_ATTR, PROSE_PARAGRAPH_SOURCE_TOKEN_ATTR, ParagraphPropertySourceValidationCode, ParagraphPropertySourceValidationError, TABLE_CELL_PARAGRAPH_SOURCE_BINDING_ATTR, TABLE_CELL_PARAGRAPH_SOURCE_PAYLOAD_ERROR_CLASSIFICATIONS, TableCellParagraphPropertySourceBinding, TableCellParagraphSourcePayloadErrorClassification, assignDocumentParagraphPropertySourceContract, assignParagraphPropertySource, cloneDocumentWithParagraphPropertySources, cloneParagraphWithPropertySource, cloneParagraphWithoutPropertySource, cloneTableCellsWithParagraphPropertyCaptures, copyDocumentParagraphPropertySourceContract, copyDocumentParagraphPropertySources, copyParagraphPropertyCapture, copyParagraphPropertySource, createProseParagraphWithPropertySource, decodeTableCellParagraphSourcePayload, getDocumentParagraphPropertySourceContract, getExplicitParagraphPropertySourceTransfers, getParagraphPropertySource, getParagraphPropertySourceCandidate, getParagraphPropertySourceToken, getParagraphPropertySourceTransferId, getProseDocumentParagraphPropertySourceContract, getProseParagraphPropertySourceToken, isParagraphPropertySourceToken, joinProseParagraphsWithRightPropertySource, linkParagraphPropertySourceCandidate, linkProseParagraphPropertySource, markParagraphPropertySourceTransfers, paragraphPropertySourceBelongsToDocument, paragraphPropertySourceMatchesEmission, paragraphPropertySourceTokenMatchesContract, proseParagraphAttrsWithoutPropertySource, recreateProseNodeWithDetachedParagraphPropertySource, recreateProseNodeWithParagraphPropertySource, restoreTableCellsWithParagraphPropertySources, setProseParagraphMarkupWithPropertySource, transferProseParagraphPropertySource, transportTableCellsWithParagraphPropertySources, visitDocumentStoryParagraphs, visitTableCellParagraphPropertySourceBindings };
@@ -261,6 +261,7 @@ const invalidTableCellParagraphSourcePayload = (classification, path) => {
261
261
  };
262
262
  const tableCellBlockTraversalByType = {
263
263
  blockSdt: "blockSdt",
264
+ blockCustomXml: "blockSdt",
264
265
  bookmarkEnd: "leaf",
265
266
  bookmarkStart: "leaf",
266
267
  paragraph: "paragraph",
@@ -634,6 +635,11 @@ const joinProseParagraphsWithRightPropertySource = ({ attrs, pos, transaction })
634
635
  }]);
635
636
  return transaction;
636
637
  };
638
+ /** Record the property owners deliberately selected by a batch of paragraph joins. */
639
+ const markParagraphPropertySourceTransfers = (transaction, transfers) => {
640
+ if (transfers.length === 0) return;
641
+ transaction.setMeta(paragraphPropertySourceTransfersKey, [...transaction.getMeta(paragraphPropertySourceTransfersKey) ?? [], ...transfers]);
642
+ };
637
643
  const getExplicitParagraphPropertySourceTransfers = (transaction) => transaction.getMeta(paragraphPropertySourceTransfersKey) ?? [];
638
644
  /** Carry a parser-linked paragraph owner across an immutable PM node rebuild. */
639
645
  const copyProseParagraphPropertySource = (target, source) => {
@@ -703,4 +709,4 @@ const linkParagraphPropertySourceCandidate = (target, source) => {
703
709
  const getParagraphPropertySourceCandidate = (paragraph) => paragraphPropertySourceCandidates.get(paragraph);
704
710
  const getParagraphPropertySourceTransferId = (paragraph) => paragraphPropertySourceTransferIds.get(paragraph);
705
711
  //#endregion
706
- export { PARAGRAPH_PROPERTY_SOURCE_VALIDATION_CODES, PROSE_PARAGRAPH_SOURCE_CONTRACT_ATTR, PROSE_PARAGRAPH_SOURCE_TOKEN_ATTR, ParagraphPropertySourceValidationError, TABLE_CELL_PARAGRAPH_SOURCE_BINDING_ATTR, TABLE_CELL_PARAGRAPH_SOURCE_PAYLOAD_ERROR_CLASSIFICATIONS, assignDocumentParagraphPropertySourceContract, assignParagraphPropertySource, cloneDocumentWithParagraphPropertySources, cloneParagraphWithPropertySource, cloneParagraphWithoutPropertySource, cloneTableCellsWithParagraphPropertyCaptures, copyDocumentParagraphPropertySourceContract, copyDocumentParagraphPropertySources, copyParagraphPropertyCapture, copyParagraphPropertySource, createProseParagraphWithPropertySource, decodeTableCellParagraphSourcePayload, getDocumentParagraphPropertySourceContract, getExplicitParagraphPropertySourceTransfers, getParagraphPropertySource, getParagraphPropertySourceCandidate, getParagraphPropertySourceToken, getParagraphPropertySourceTransferId, getProseDocumentParagraphPropertySourceContract, getProseParagraphPropertySourceToken, isParagraphPropertySourceToken, joinProseParagraphsWithRightPropertySource, linkParagraphPropertySourceCandidate, linkProseParagraphPropertySource, paragraphPropertySourceBelongsToDocument, paragraphPropertySourceMatchesEmission, paragraphPropertySourceTokenMatchesContract, proseParagraphAttrsWithoutPropertySource, recreateProseNodeWithDetachedParagraphPropertySource, recreateProseNodeWithParagraphPropertySource, restoreTableCellsWithParagraphPropertySources, setProseParagraphMarkupWithPropertySource, transferProseParagraphPropertySource, transportTableCellsWithParagraphPropertySources, visitDocumentStoryParagraphs, visitTableCellParagraphPropertySourceBindings };
712
+ export { PARAGRAPH_PROPERTY_SOURCE_VALIDATION_CODES, PROSE_PARAGRAPH_SOURCE_CONTRACT_ATTR, PROSE_PARAGRAPH_SOURCE_TOKEN_ATTR, ParagraphPropertySourceValidationError, TABLE_CELL_PARAGRAPH_SOURCE_BINDING_ATTR, TABLE_CELL_PARAGRAPH_SOURCE_PAYLOAD_ERROR_CLASSIFICATIONS, assignDocumentParagraphPropertySourceContract, assignParagraphPropertySource, cloneDocumentWithParagraphPropertySources, cloneParagraphWithPropertySource, cloneParagraphWithoutPropertySource, cloneTableCellsWithParagraphPropertyCaptures, copyDocumentParagraphPropertySourceContract, copyDocumentParagraphPropertySources, copyParagraphPropertyCapture, copyParagraphPropertySource, createProseParagraphWithPropertySource, decodeTableCellParagraphSourcePayload, getDocumentParagraphPropertySourceContract, getExplicitParagraphPropertySourceTransfers, getParagraphPropertySource, getParagraphPropertySourceCandidate, getParagraphPropertySourceToken, getParagraphPropertySourceTransferId, getProseDocumentParagraphPropertySourceContract, getProseParagraphPropertySourceToken, isParagraphPropertySourceToken, joinProseParagraphsWithRightPropertySource, linkParagraphPropertySourceCandidate, linkProseParagraphPropertySource, markParagraphPropertySourceTransfers, paragraphPropertySourceBelongsToDocument, paragraphPropertySourceMatchesEmission, paragraphPropertySourceTokenMatchesContract, proseParagraphAttrsWithoutPropertySource, recreateProseNodeWithDetachedParagraphPropertySource, recreateProseNodeWithParagraphPropertySource, restoreTableCellsWithParagraphPropertySources, setProseParagraphMarkupWithPropertySource, transferProseParagraphPropertySource, transportTableCellsWithParagraphPropertySources, visitDocumentStoryParagraphs, visitTableCellParagraphPropertySourceBindings };
@@ -126,6 +126,7 @@ const visitBlockTreeRecords = (blocks, visit) => {
126
126
  }
127
127
  break;
128
128
  case "blockSdt":
129
+ case "blockCustomXml":
129
130
  visitBlocks(block.content);
130
131
  break;
131
132
  case "preservedBlock":
@@ -40,7 +40,10 @@ const PARSE_WARNING_MESSAGES = {
40
40
  [PARSE_WARNING_CODES.outlineDashOutsideEnum]: (warning) => `Kept outline dash${quoted(warning.value)} verbatim${where(warning)}; ST_PresetLineDashVal does not declare it.`,
41
41
  [PARSE_WARNING_CODES.styleSetDuplicateStyleId]: (warning) => `Dropped a style repeating the id${quoted(warning.value)} another style in the set already defines.`,
42
42
  [PARSE_WARNING_CODES.styleSetInitialStyleMissing]: (warning) => `The style set names initial paragraph style${quoted(warning.value)}, which it does not contain; used the set's default instead${where(warning)}.`,
43
- [PARSE_WARNING_CODES.pageBreakProjectionApproximated]: (warning) => `${warning.detail ?? "An explicit page break is laid out approximately"}${where(warning)}.`
43
+ [PARSE_WARNING_CODES.pageBreakProjectionApproximated]: (warning) => `${warning.detail ?? "An explicit page break is laid out approximately"}${where(warning)}.`,
44
+ [PARSE_WARNING_CODES.altChunkUnsupported]: (warning) => `Preserved ${plural(warning.count, "w:altChunk")}; Folio cannot import its external content. Readers show a diagnostic marker.`,
45
+ [PARSE_WARNING_CODES.revisionCarrierOpaque]: (warning) => `Preserved ${plural(warning.count, "block-level tracked-change wrapper")}; Folio cannot interpret its block content, so that content is unavailable to readers or edits.`,
46
+ [PARSE_WARNING_CODES.nestedRowOpaque]: (warning) => `Preserved ${plural(warning.count, "nested table row")} as opaque markup; readers show a diagnostic marker for its content.`
44
47
  };
45
48
  const formatParseWarning = (warning) => PARSE_WARNING_MESSAGES[warning.code](warning);
46
49
  const formatParseWarnings = (warnings) => warnings.map(formatParseWarning);