@stll/folio-core 0.54.2 → 0.56.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 (267) hide show
  1. package/dist/ai-edits/apply.js +185 -33
  2. package/dist/ai-edits/headless.js +3 -2
  3. package/dist/ai-edits/types.d.ts +7 -1
  4. package/dist/compare/compare.js +1 -0
  5. package/dist/compare/content-types.d.ts +3 -15
  6. package/dist/compare/reproducible-package.d.ts +0 -17
  7. package/dist/compare/reproducible-package.js +12 -18
  8. package/dist/controller/canonicalClipboard.d.ts +23 -0
  9. package/dist/controller/canonicalClipboard.js +476 -0
  10. package/dist/controller/canonicalClipboardResources.d.ts +21 -0
  11. package/dist/controller/canonicalClipboardResources.js +382 -0
  12. package/dist/controller/canonicalComposition.d.ts +53 -0
  13. package/dist/controller/canonicalComposition.js +296 -0
  14. package/dist/controller/canonicalInlineProjection.d.ts +113 -0
  15. package/dist/controller/canonicalInlineProjection.js +393 -0
  16. package/dist/controller/canonicalInput.d.ts +54 -0
  17. package/dist/controller/canonicalInput.js +377 -0
  18. package/dist/controller/canonicalInputTimer.d.ts +7 -0
  19. package/dist/controller/canonicalInputTimer.js +11 -0
  20. package/dist/controller/canonicalOperations.d.ts +22 -0
  21. package/dist/controller/canonicalOperations.js +85 -0
  22. package/dist/controller/canonicalPublicOperations.d.ts +48 -0
  23. package/dist/controller/canonicalPublicOperations.js +556 -0
  24. package/dist/controller/canonicalReview.d.ts +12 -0
  25. package/dist/controller/canonicalReview.js +19 -0
  26. package/dist/controller/canonicalSession.d.ts +167 -0
  27. package/dist/controller/canonicalSession.js +1186 -0
  28. package/dist/controller/canonicalStoryEditor.d.ts +36 -0
  29. package/dist/controller/canonicalStoryEditor.js +87 -0
  30. package/dist/controller/canonicalStructure.d.ts +16 -0
  31. package/dist/controller/canonicalStructure.js +322 -0
  32. package/dist/controller/canonicalTocSelection.d.ts +11 -0
  33. package/dist/controller/canonicalTocSelection.js +43 -0
  34. package/dist/controller/folioEditor.d.ts +3 -10
  35. package/dist/controller/folioEditor.js +14 -4
  36. package/dist/controller/headerFooterEditorManager.d.ts +5 -0
  37. package/dist/controller/headerFooterEditorManager.js +72 -3
  38. package/dist/controller/hiddenEditorApi.d.ts +45 -0
  39. package/dist/controller/hiddenEditorApi.js +29 -8
  40. package/dist/controller/hiddenEditorManager.d.ts +13 -2
  41. package/dist/controller/hiddenEditorManager.js +639 -31
  42. package/dist/controller/layoutPipeline.d.ts +1 -1
  43. package/dist/controller/layoutPipeline.js +2 -0
  44. package/dist/controller/noteEditorManager.d.ts +5 -0
  45. package/dist/controller/noteEditorManager.js +114 -15
  46. package/dist/document-operations.d.ts +8 -1
  47. package/dist/document-operations.js +6 -4
  48. package/dist/docx/attributeRemainder.js +1 -0
  49. package/dist/docx/blockPlainText.d.ts +1 -1
  50. package/dist/docx/blockPlainText.js +11 -3
  51. package/dist/docx/canonicalResourceSave.d.ts +16 -0
  52. package/dist/docx/canonicalResourceSave.js +27 -0
  53. package/dist/docx/canonicalSave.d.ts +29 -0
  54. package/dist/docx/canonicalSave.js +101 -0
  55. package/dist/docx/canonicalSessionInput.d.ts +11 -0
  56. package/dist/docx/canonicalSessionInput.js +27 -0
  57. package/dist/docx/canonicalStoryRepack.d.ts +10 -0
  58. package/dist/docx/canonicalStoryRepack.js +74 -0
  59. package/dist/docx/contentTypeRegistry.d.ts +8 -0
  60. package/dist/docx/contentTypeRegistry.js +64 -0
  61. package/dist/docx/documentParser.d.ts +1 -13
  62. package/dist/docx/documentParser.js +1 -47
  63. package/dist/docx/ensureParaIds.d.ts +7 -1
  64. package/dist/docx/ensureParaIds.js +173 -215
  65. package/dist/docx/foldedListNumberFields.d.ts +85 -0
  66. package/dist/docx/foldedListNumberFields.js +267 -0
  67. package/dist/docx/footnoteParser.d.ts +1 -11
  68. package/dist/docx/footnoteParser.js +1 -16
  69. package/dist/docx/headerFooterParser.d.ts +1 -9
  70. package/dist/docx/headerFooterParser.js +1 -12
  71. package/dist/docx/headerFooterVerbatim.d.ts +39 -1
  72. package/dist/docx/headerFooterVerbatim.js +173 -2
  73. package/dist/docx/imageParser.d.ts +13 -1
  74. package/dist/docx/imageParser.js +20 -11
  75. package/dist/docx/metadataPrivacy.js +6 -1
  76. package/dist/docx/noteIds.d.ts +5 -0
  77. package/dist/docx/noteIds.js +6 -2
  78. package/dist/docx/noteReferenceMark.d.ts +3 -1
  79. package/dist/docx/noteReferenceMark.js +15 -14
  80. package/dist/docx/numberingParser.d.ts +3 -1
  81. package/dist/docx/numberingParser.js +17 -3
  82. package/dist/docx/packageParts.d.ts +3 -1
  83. package/dist/docx/packageParts.js +74 -19
  84. package/dist/docx/paragraphMarkPropertyPresence.d.ts +9 -0
  85. package/dist/docx/paragraphMarkPropertyPresence.js +21 -0
  86. package/dist/docx/paragraphParser.js +101 -53
  87. package/dist/docx/paragraphPropertySource.d.ts +15 -1
  88. package/dist/docx/paragraphPropertySource.js +77 -22
  89. package/dist/docx/parser.js +3 -1
  90. package/dist/docx/removeHeaderFooterParts.js +17 -6
  91. package/dist/docx/reviewHistoryNamespace.d.ts +4 -0
  92. package/dist/docx/reviewHistoryNamespace.js +4 -0
  93. package/dist/docx/reviewResolutionProvenance.d.ts +25 -0
  94. package/dist/docx/reviewResolutionProvenance.js +153 -0
  95. package/dist/docx/rezip.d.ts +54 -6
  96. package/dist/docx/rezip.js +835 -257
  97. package/dist/docx/runConsolidator.d.ts +2 -58
  98. package/dist/docx/runConsolidator.js +3 -175
  99. package/dist/docx/runParser.d.ts +2 -1
  100. package/dist/docx/runParser.js +156 -116
  101. package/dist/docx/saveDiagnostics.d.ts +22 -0
  102. package/dist/docx/saveDiagnostics.js +0 -0
  103. package/dist/docx/selectiveSave.d.ts +3 -1
  104. package/dist/docx/selectiveSave.js +36 -4
  105. package/dist/docx/selectiveXmlPatch.d.ts +16 -8
  106. package/dist/docx/selectiveXmlPatch.js +81 -7
  107. package/dist/docx/serializer/documentSerializer.d.ts +9 -2
  108. package/dist/docx/serializer/documentSerializer.js +29 -10
  109. package/dist/docx/serializer/headerFooterSerializer.d.ts +5 -1
  110. package/dist/docx/serializer/headerFooterSerializer.js +19 -11
  111. package/dist/docx/serializer/noteSerializer.d.ts +2 -2
  112. package/dist/docx/serializer/noteSerializer.js +24 -8
  113. package/dist/docx/serializer/paragraphSerializer.js +41 -4
  114. package/dist/docx/serializer/partNamespaces.js +2 -1
  115. package/dist/docx/serializer/runSerializer.js +3 -1
  116. package/dist/docx/server/applyDocxXmlPatchProposal.js +14 -9
  117. package/dist/docx/settingsHeaderFooterUpdate.d.ts +5 -0
  118. package/dist/docx/settingsHeaderFooterUpdate.js +90 -0
  119. package/dist/docx/settingsParser.d.ts +1 -2
  120. package/dist/docx/settingsParser.js +5 -6
  121. package/dist/docx/storyBlockReplay.d.ts +31 -0
  122. package/dist/docx/storyBlockReplay.js +471 -0
  123. package/dist/docx/storyPlainText.d.ts +20 -0
  124. package/dist/docx/storyPlainText.js +23 -0
  125. package/dist/docx/streamingXmlParser.d.ts +22 -1
  126. package/dist/docx/streamingXmlParser.js +49 -3
  127. package/dist/docx/structuralXmlPatch.js +18 -23
  128. package/dist/docx/styleParser.d.ts +5 -1
  129. package/dist/docx/styleParser.js +1 -1
  130. package/dist/docx/tableParser.d.ts +1 -8
  131. package/dist/docx/tableParser.js +1 -28
  132. package/dist/docx/textBoxParser.d.ts +1 -5
  133. package/dist/docx/textBoxParser.js +1 -20
  134. package/dist/docx/unzip.js +6 -1
  135. package/dist/docx/verbatimCapture.d.ts +3 -1
  136. package/dist/docx/verbatimCapture.js +49 -6
  137. package/dist/i18n/messages/ar.gen.d.ts +5 -0
  138. package/dist/i18n/messages/ar.gen.js +656 -0
  139. package/dist/i18n/messages/cs.gen.d.ts +5 -0
  140. package/dist/i18n/messages/cs.gen.js +656 -0
  141. package/dist/i18n/messages/de.gen.d.ts +5 -0
  142. package/dist/i18n/messages/de.gen.js +656 -0
  143. package/dist/i18n/messages/en.gen.d.ts +5 -0
  144. package/dist/i18n/messages/en.gen.js +656 -0
  145. package/dist/i18n/messages/es.gen.d.ts +5 -0
  146. package/dist/i18n/messages/es.gen.js +656 -0
  147. package/dist/i18n/messages/et.gen.d.ts +5 -0
  148. package/dist/i18n/messages/et.gen.js +656 -0
  149. package/dist/i18n/messages/fr.gen.d.ts +5 -0
  150. package/dist/i18n/messages/fr.gen.js +656 -0
  151. package/dist/i18n/messages/he.gen.d.ts +5 -0
  152. package/dist/i18n/messages/he.gen.js +656 -0
  153. package/dist/i18n/messages/hi.gen.d.ts +5 -0
  154. package/dist/i18n/messages/hi.gen.js +656 -0
  155. package/dist/i18n/messages/hu.gen.d.ts +5 -0
  156. package/dist/i18n/messages/hu.gen.js +656 -0
  157. package/dist/i18n/messages/locales.d.ts +5 -0
  158. package/dist/i18n/messages/locales.js +22 -0
  159. package/dist/i18n/messages/lt.gen.d.ts +5 -0
  160. package/dist/i18n/messages/lt.gen.js +656 -0
  161. package/dist/i18n/messages/lv.gen.d.ts +5 -0
  162. package/dist/i18n/messages/lv.gen.js +656 -0
  163. package/dist/i18n/messages/pl.gen.d.ts +5 -0
  164. package/dist/i18n/messages/pl.gen.js +656 -0
  165. package/dist/i18n/messages/pt-BR.gen.d.ts +5 -0
  166. package/dist/i18n/messages/pt-BR.gen.js +656 -0
  167. package/dist/i18n/messages/sk.gen.d.ts +5 -0
  168. package/dist/i18n/messages/sk.gen.js +656 -0
  169. package/dist/i18n/messages/tr.gen.d.ts +5 -0
  170. package/dist/i18n/messages/tr.gen.js +656 -0
  171. package/dist/i18n/messages/zh-CN.gen.d.ts +5 -0
  172. package/dist/i18n/messages/zh-CN.gen.js +656 -0
  173. package/dist/i18n/messages.d.ts +2 -3
  174. package/dist/i18n/messages.js +1 -19
  175. package/dist/internal/acceptedBlockProjection.d.ts +12 -0
  176. package/dist/internal/acceptedBlockProjection.js +45 -0
  177. package/dist/internal/noteMarkerAttrs.d.ts +8 -0
  178. package/dist/internal/noteMarkerAttrs.js +16 -0
  179. package/dist/internal/pageBreakRunSourceDescendantIndex.js +1 -0
  180. package/dist/internal/prosemirrorAttrBoundary.d.ts +21 -0
  181. package/dist/internal/prosemirrorAttrBoundary.js +50 -0
  182. package/dist/layout-bridge/convert/footnoteLayout.d.ts +1 -0
  183. package/dist/layout-bridge/convert/footnoteLayout.js +3 -3
  184. package/dist/layout-bridge/convert/headerFooterLayout.d.ts +1 -0
  185. package/dist/layout-bridge/convert/headerFooterLayout.js +1 -0
  186. package/dist/layout-bridge/convert/noteReferences.d.ts +1 -3
  187. package/dist/layout-bridge/convert/noteReferences.js +1 -6
  188. package/dist/layout-bridge/convert/paragraphRuns.js +2 -4
  189. package/dist/layout-bridge/convert/toFlowBlocks.d.ts +2 -2
  190. package/dist/layout-bridge/convert/toFlowBlocks.js +2 -2
  191. package/dist/managers/DocumentLoaderManager.d.ts +1 -0
  192. package/dist/managers/DocumentLoaderManager.js +9 -1
  193. package/dist/markdown/escape.d.ts +3 -1
  194. package/dist/markdown/escape.js +9 -2
  195. package/dist/markdown/renderBlock.js +20 -121
  196. package/dist/markdown/renderParagraph.js +13 -15
  197. package/dist/markdown/renderRuns.d.ts +7 -1
  198. package/dist/markdown/renderRuns.js +35 -15
  199. package/dist/markdown/renderTable.js +2 -0
  200. package/dist/markdown/types.d.ts +3 -9
  201. package/dist/prosemirror/attrs/index.d.ts +2 -12
  202. package/dist/prosemirror/attrs/index.js +22 -48
  203. package/dist/prosemirror/bookmarkBoundaryAttrs.d.ts +2 -1
  204. package/dist/prosemirror/canonicalCommands.d.ts +121 -0
  205. package/dist/prosemirror/canonicalCommands.js +35 -0
  206. package/dist/prosemirror/canonicalSelectionRange.d.ts +9 -0
  207. package/dist/prosemirror/canonicalSelectionRange.js +15 -0
  208. package/dist/prosemirror/clipboardIntent.d.ts +7 -0
  209. package/dist/prosemirror/clipboardIntent.js +9 -0
  210. package/dist/prosemirror/commands/pageBreak.js +15 -1
  211. package/dist/prosemirror/commands/pastePlainText.js +2 -1
  212. package/dist/prosemirror/commentReferenceAttrs.d.ts +2 -1
  213. package/dist/prosemirror/conversion/fromProseDoc.js +91 -19
  214. package/dist/prosemirror/conversion/hyphenTextCarriers.d.ts +8 -0
  215. package/dist/prosemirror/conversion/hyphenTextCarriers.js +8 -0
  216. package/dist/prosemirror/conversion/listRenderingDefinition.d.ts +6 -0
  217. package/dist/prosemirror/conversion/listRenderingDefinition.js +97 -0
  218. package/dist/prosemirror/conversion/toProseDoc.d.ts +11 -4
  219. package/dist/prosemirror/conversion/toProseDoc.js +55 -14
  220. package/dist/prosemirror/executeEditorCommand.d.ts +11 -0
  221. package/dist/prosemirror/executeEditorCommand.js +26 -0
  222. package/dist/prosemirror/extensions/StarterKit.js +2 -0
  223. package/dist/prosemirror/extensions/core/ParagraphExtension.js +88 -48
  224. package/dist/prosemirror/extensions/features/ListExtension.js +18 -5
  225. package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.d.ts +5 -2
  226. package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.js +13 -1
  227. package/dist/prosemirror/extensions/marks/HyperlinkExtension.js +56 -28
  228. package/dist/prosemirror/extensions/marks/TextColorExtension.js +3 -2
  229. package/dist/prosemirror/extensions/marks/TrackedChangeExtensions.js +2 -0
  230. package/dist/prosemirror/extensions/marks/markUtils.js +72 -8
  231. package/dist/prosemirror/extensions/nodes/NoteMarkerExtension.d.ts +6 -0
  232. package/dist/prosemirror/extensions/nodes/NoteMarkerExtension.js +36 -0
  233. package/dist/prosemirror/extensions/nodes/PreservedXmlExtension.js +4 -2
  234. package/dist/prosemirror/insertOperations.js +2 -1
  235. package/dist/prosemirror/listMarker.d.ts +1 -0
  236. package/dist/prosemirror/listMarker.js +16 -7
  237. package/dist/prosemirror/listNumbering.js +26 -5
  238. package/dist/prosemirror/listRenderingAttrs.d.ts +1 -0
  239. package/dist/prosemirror/listRenderingAttrs.js +3 -0
  240. package/dist/prosemirror/markupViewNotes.js +3 -2
  241. package/dist/prosemirror/moveRangeBoundaryAttrs.d.ts +2 -1
  242. package/dist/prosemirror/noteReferenceReview.js +5 -3
  243. package/dist/prosemirror/paragraphPropertyCarry.d.ts +7 -1
  244. package/dist/prosemirror/paragraphPropertyCarry.js +8 -3
  245. package/dist/prosemirror/plugins/suggestionMode.js +57 -7
  246. package/dist/prosemirror/rangeAnchorAttrs.d.ts +2 -1
  247. package/dist/prosemirror/runFormattingFromMarks.d.ts +4 -1
  248. package/dist/prosemirror/runFormattingFromMarks.js +15 -1
  249. package/dist/prosemirror/runFormattingInlineCarriers.d.ts +2 -1
  250. package/dist/prosemirror/runFormattingInlineCarriers.js +4 -1
  251. package/dist/prosemirror/schema/marks.d.ts +2 -0
  252. package/dist/prosemirror/schema/nodes.d.ts +10 -2
  253. package/dist/prosemirror/textBoxAnchorAttrs.d.ts +2 -1
  254. package/dist/prosemirror/textInput.js +5 -1
  255. package/dist/prosemirror/trackedRevisionPath.js +2 -1
  256. package/dist/prosemirror/trackedRunInlineAtoms.d.ts +1 -0
  257. package/dist/prosemirror/trackedRunInlineAtoms.js +1 -0
  258. package/dist/prosemirror/validation.js +4 -0
  259. package/dist/types/canonicalCapabilities.d.ts +215 -0
  260. package/dist/types/canonicalCapabilities.js +212 -0
  261. package/dist/types/canonicalSave.d.ts +11 -0
  262. package/dist/types/canonicalSave.js +0 -0
  263. package/dist/types/content.d.ts +2 -2
  264. package/dist/types/docxSerialization.d.ts +14 -0
  265. package/dist/types/docxSerialization.js +7 -0
  266. package/dist/utils/createDocument.js +2 -2
  267. package/package.json +16 -4
@@ -5,6 +5,7 @@ import { CAPTURE, dispatchChildrenWithContext, ownedElsewhere, transitionalNames
5
5
  import { resolveDefaultParagraphStyle } from "./defaultParagraphStyle.js";
6
6
  import { parseFieldType } from "./fieldParser.js";
7
7
  import { fieldStateOf, parseFieldState } from "./fieldState.js";
8
+ import { foldListNumberFields, isListNumberField, isListNumberGapMarker, isTabOnlyRun } from "./foldedListNumberFields.js";
8
9
  import { HYPERLINK_CHILD_HANDLERS, parseHyperlink as parseHyperlink$1, parseHyperlinkShell } from "./hyperlinkParser.js";
9
10
  import { isHyperlinkContent, isInlineSdtContent, isTrackedChangeWrapperChild } from "./inlineWrapperContent.js";
10
11
  import { inlineWrapperOf } from "./inlineWrapperParser.js";
@@ -13,10 +14,13 @@ import { counterFormatOf, markerAlignmentForLevel, markerFormattingFromLevel, nu
13
14
  import { mergeParagraphNumbering as mergeParagraphNumbering$1, paragraphNumberingReferenceId as paragraphNumberingReferenceId$1, resolveParagraphNumbering as resolveParagraphNumbering$1 } from "./numberingReference.js";
14
15
  import { paraIdAttribute, textIdAttribute } from "./paraIdAttribute.js";
15
16
  import { paraIdInRange } from "./paraIdRangeNormalization.js";
17
+ import { EMPTY_MARK_PROPERTIES_ATTRIBUTE, restoreEmptyMarkProperties } from "./paragraphMarkPropertyPresence.js";
16
18
  import { parseParagraphProperties } from "./paragraphProperties.js";
17
19
  import { assignParagraphPropertySource } from "./paragraphPropertySource.js";
18
20
  import { preserveInlineChild, preserveRunChild, preservedInlineCapture } from "./preservedRunContent.js";
19
21
  import { standalonePreviewLedger } from "./previewBudget.js";
22
+ import { FOLIO_REVIEW_HISTORY_NAMESPACE } from "./reviewHistoryNamespace.js";
23
+ import { ReviewResolutionProvenanceError, parseParagraphMarkResolutionJoin, parseResolutionJoins } from "./reviewResolutionProvenance.js";
20
24
  import { consolidateParagraphContent } from "./runConsolidator.js";
21
25
  import { parseRun } from "./runParser.js";
22
26
  import { runHoldsPayload } from "./runPayload.js";
@@ -31,15 +35,10 @@ import { WORDPROCESSINGML_NAMESPACE_URIS, cloneElement, findChild, findChildByNa
31
35
  import { panic } from "better-result";
32
36
  import { PARAGRAPH_MARK_CHANGE_KINDS, REVIEW_CARRIERS } from "@stll/docx-core/model";
33
37
  //#region src/docx/paragraphParser.ts
34
- const FOLIO_REVIEW_HISTORY_NAMESPACES = /* @__PURE__ */ new Set(["urn:stella:folio:review-history:1"]);
38
+ const FOLIO_REVIEW_HISTORY_NAMESPACES = /* @__PURE__ */ new Set([FOLIO_REVIEW_HISTORY_NAMESPACE]);
35
39
  /**
36
40
  * Extract plain text from a math element (recursive text content extraction)
37
41
  */
38
- function extractPlainText(runs) {
39
- let out = "";
40
- for (const run of runs) for (const c of run.content) if (c.type === "text") out += c.text;
41
- return out;
42
- }
43
42
  function extractMathText(el) {
44
43
  let text = "";
45
44
  if (el.type === "text" && typeof el.text === "string") return el.text;
@@ -200,17 +199,20 @@ function parseParagraphMarkChange(pPr) {
200
199
  const element = findChildByNamespaceUri(rPr, WORDPROCESSINGML_NAMESPACE_URIS, kind);
201
200
  if (element) return {
202
201
  kind,
203
- info: parseTrackedChangeInfo(element)
202
+ info: parseTrackedChangeInfo(element),
203
+ ...parseParagraphMarkResolutionJoin(element)
204
204
  };
205
205
  }
206
206
  }
207
- function pushTrackedChangeWrapper({ contents, type, info, content, preserveEmpty = false }) {
207
+ function pushTrackedChangeWrapper({ contents, type, info, resolutionJoins, content, preserveEmpty = false }) {
208
208
  if (content.length === 0 && !preserveEmpty) return;
209
+ const provenance = resolutionJoins === void 0 ? {} : { resolutionJoins };
209
210
  if (type === "insertion") {
210
211
  contents.push({
211
212
  type: "insertion",
212
213
  info,
213
- content: [...content]
214
+ content: [...content],
215
+ ...provenance
214
216
  });
215
217
  return;
216
218
  }
@@ -218,7 +220,8 @@ function pushTrackedChangeWrapper({ contents, type, info, content, preserveEmpty
218
220
  contents.push({
219
221
  type: "deletion",
220
222
  info,
221
- content: [...content]
223
+ content: [...content],
224
+ ...provenance
222
225
  });
223
226
  return;
224
227
  }
@@ -226,22 +229,30 @@ function pushTrackedChangeWrapper({ contents, type, info, content, preserveEmpty
226
229
  contents.push({
227
230
  type: "moveFrom",
228
231
  info,
229
- content: [...content]
232
+ content: [...content],
233
+ ...provenance
230
234
  });
231
235
  return;
232
236
  }
233
237
  contents.push({
234
238
  type: "moveTo",
235
239
  info,
236
- content: [...content]
240
+ content: [...content],
241
+ ...provenance
237
242
  });
238
243
  }
239
- function pushTrackedChangeSegments({ contents, type, info, parsedContent }) {
244
+ function pushTrackedChangeSegments({ contents, type, info, resolutionJoins, parsedContent }) {
245
+ if (resolutionJoins !== void 0 && parsedContent.some((item) => !isTrackedChangeWrapperChild(item))) throw new ReviewResolutionProvenanceError({
246
+ attribute: "resolutionJoins",
247
+ reason: "invalid",
248
+ message: "Tracked-resolution provenance cannot bind a fragmented imported wrapper."
249
+ });
240
250
  if (!parsedContent.some(isTrackedChangeWrapperChild)) {
241
251
  pushTrackedChangeWrapper({
242
252
  contents,
243
253
  type,
244
254
  info,
255
+ resolutionJoins,
245
256
  content: [],
246
257
  preserveEmpty: true
247
258
  });
@@ -258,6 +269,7 @@ function pushTrackedChangeSegments({ contents, type, info, parsedContent }) {
258
269
  contents,
259
270
  type,
260
271
  info,
272
+ resolutionJoins,
261
273
  content: segment
262
274
  });
263
275
  segment.length = 0;
@@ -267,6 +279,7 @@ function pushTrackedChangeSegments({ contents, type, info, parsedContent }) {
267
279
  contents,
268
280
  type,
269
281
  info,
282
+ resolutionJoins,
270
283
  content: segment
271
284
  });
272
285
  }
@@ -679,6 +692,34 @@ const FIELD_INLINE_WRAPPER_HANDLERS = {
679
692
  pPr: CAPTURE
680
693
  };
681
694
  /**
695
+ * The `w:r` elements a complex field, or a run holding one tab, was read
696
+ * from. A list paragraph draws its `LISTNUM` fields in the list marker and
697
+ * keeps their markup in the content as it was read; these are where that
698
+ * markup comes from.
699
+ */
700
+ const fieldSourceElements = /* @__PURE__ */ new WeakMap();
701
+ const tabRunSources = /* @__PURE__ */ new WeakMap();
702
+ /**
703
+ * Whether the content read so far ends in a list-number field whose markup is
704
+ * kept, with nothing but range markers after it: the next tab is its tab.
705
+ */
706
+ const followsListNumberField = (contents) => {
707
+ for (let index = contents.length - 1; index >= 0; index -= 1) {
708
+ const item = contents[index];
709
+ if (item === void 0 || isListNumberGapMarker(item)) continue;
710
+ return item.type === "complexField" && fieldSourceElements.has(item);
711
+ }
712
+ return false;
713
+ };
714
+ const sourceMarkupOf = (item) => {
715
+ if (item.type === "run") {
716
+ const element = tabRunSources.get(item);
717
+ return element ? captureVerbatimXml(element) : void 0;
718
+ }
719
+ const elements = fieldSourceElements.get(item);
720
+ return elements && elements.length > 0 ? elements.map((element) => captureVerbatimXml(element)).join("") : void 0;
721
+ };
722
+ /**
682
723
  * Whether the walk is currently inside some open field's code region — its
683
724
  * own `begin` has been read but not yet its `separate` — at any nesting
684
725
  * depth. `codeDepthStack` tracks every open field regardless of whether it
@@ -839,6 +880,7 @@ const PARAGRAPH_CONTENT_HANDLERS = {
839
880
  scan.complexFieldCodeRuns = [];
840
881
  scan.complexFieldResultRuns = [];
841
882
  scan.complexFieldOpenRuns = [];
883
+ scan.complexFieldSourceRuns = [];
842
884
  scan.complexFieldState = beginFieldState;
843
885
  scan.complexFieldDataXml = beginFieldData ? captureVerbatimXml(beginFieldData) : void 0;
844
886
  scan.complexFieldFallbackDisplay = beginFallbackDisplay;
@@ -849,6 +891,8 @@ const PARAGRAPH_CONTENT_HANDLERS = {
849
891
  if (hasFieldEnd && scan.codeDepthStack.length > 0) scan.codeDepthStack.pop();
850
892
  if (scan.inComplexField) {
851
893
  scan.complexFieldOpenRuns.push(withOrphanFieldCharsPreserved(run, runElement));
894
+ if (commentReferenceId !== null || trackedContext === "deletion") scan.complexFieldSourceRuns = null;
895
+ else scan.complexFieldSourceRuns?.push(runElement);
852
896
  if (instrText) scan.complexFieldInstr += instrText;
853
897
  if ((!scan.complexFieldFormatting || Object.keys(scan.complexFieldFormatting).length === 0) && run.formatting && Object.keys(run.formatting).length > 0) scan.complexFieldFormatting = run.formatting;
854
898
  let inFieldCodeRegion = !hasFieldBegin && !scan.afterSeparator;
@@ -897,6 +941,7 @@ const PARAGRAPH_CONTENT_HANDLERS = {
897
941
  if (scan.complexFieldDataXml !== void 0) complexField.formFieldDataXml = scan.complexFieldDataXml;
898
942
  if (resultIsFallback) complexField.fieldResultIsFallback = true;
899
943
  if (scan.complexFieldFormatting) complexField.formatting = scan.complexFieldFormatting;
944
+ if (scan.complexFieldSourceRuns !== null && isListNumberField(complexField)) fieldSourceElements.set(complexField, scan.complexFieldSourceRuns);
900
945
  contents.push(complexField);
901
946
  if (commentReferenceId !== null) contents.push({
902
947
  type: "commentReference",
@@ -926,7 +971,11 @@ const PARAGRAPH_CONTENT_HANDLERS = {
926
971
  runElement,
927
972
  rels,
928
973
  media
929
- })) contents.push(withOrphanFieldCharsPreserved(run, runElement));
974
+ })) {
975
+ const kept = withOrphanFieldCharsPreserved(run, runElement);
976
+ if (isTabOnlyRun(kept) && trackedContext !== "deletion" && followsListNumberField(contents)) tabRunSources.set(kept, runElement);
977
+ contents.push(kept);
978
+ }
930
979
  },
931
980
  hyperlink: (child, { contents, styles, theme, rels, media, previews, inScopeXmlns }) => {
932
981
  contents.push(...parseHyperlinkParagraphContents(child, rels, styles, theme, media, inScopeXmlns, previews));
@@ -983,35 +1032,47 @@ const PARAGRAPH_CONTENT_HANDLERS = {
983
1032
  }
984
1033
  },
985
1034
  ins: (child, { contents, styles, theme, rels, media, previews, inScopeXmlns }) => {
1035
+ const insInfo = parseTrackedChangeInfo(child);
1036
+ const insContent = parseParagraphContents(child, styles, theme, null, rels, media, previews, "default", inScopeXmlns);
986
1037
  pushTrackedChangeSegments({
987
1038
  contents,
988
1039
  type: "insertion",
989
- info: parseTrackedChangeInfo(child),
990
- parsedContent: parseParagraphContents(child, styles, theme, null, rels, media, previews, "default", inScopeXmlns)
1040
+ info: insInfo,
1041
+ resolutionJoins: parseResolutionJoins(child),
1042
+ parsedContent: insContent
991
1043
  });
992
1044
  },
993
1045
  del: (child, { contents, styles, theme, rels, media, previews, inScopeXmlns }) => {
1046
+ const delInfo = parseTrackedChangeInfo(child);
1047
+ const delContent = parseParagraphContents(child, styles, theme, null, rels, media, previews, "deletion", inScopeXmlns);
994
1048
  pushTrackedChangeSegments({
995
1049
  contents,
996
1050
  type: "deletion",
997
- info: parseTrackedChangeInfo(child),
998
- parsedContent: parseParagraphContents(child, styles, theme, null, rels, media, previews, "deletion", inScopeXmlns)
1051
+ info: delInfo,
1052
+ resolutionJoins: parseResolutionJoins(child),
1053
+ parsedContent: delContent
999
1054
  });
1000
1055
  },
1001
1056
  moveFrom: (child, { contents, styles, theme, rels, media, previews, inScopeXmlns }) => {
1057
+ const moveFromInfo = parseTrackedChangeInfo(child);
1058
+ const moveFromContent = parseParagraphContents(child, styles, theme, null, rels, media, previews, "deletion", inScopeXmlns);
1002
1059
  pushTrackedChangeSegments({
1003
1060
  contents,
1004
1061
  type: "moveFrom",
1005
- info: parseTrackedChangeInfo(child),
1006
- parsedContent: parseParagraphContents(child, styles, theme, null, rels, media, previews, "deletion", inScopeXmlns)
1062
+ info: moveFromInfo,
1063
+ resolutionJoins: parseResolutionJoins(child),
1064
+ parsedContent: moveFromContent
1007
1065
  });
1008
1066
  },
1009
1067
  moveTo: (child, { contents, styles, theme, rels, media, previews, inScopeXmlns }) => {
1068
+ const moveToInfo = parseTrackedChangeInfo(child);
1069
+ const moveToContent = parseParagraphContents(child, styles, theme, null, rels, media, previews, "default", inScopeXmlns);
1010
1070
  pushTrackedChangeSegments({
1011
1071
  contents,
1012
1072
  type: "moveTo",
1013
- info: parseTrackedChangeInfo(child),
1014
- parsedContent: parseParagraphContents(child, styles, theme, null, rels, media, previews, "default", inScopeXmlns)
1073
+ info: moveToInfo,
1074
+ resolutionJoins: parseResolutionJoins(child),
1075
+ parsedContent: moveToContent
1015
1076
  });
1016
1077
  },
1017
1078
  smartTag: paragraphInlineWrapper("smartTag"),
@@ -1068,6 +1129,7 @@ function parseParagraphContents(paraElement, styles, theme, _numbering, rels, me
1068
1129
  complexFieldCodeRuns: [],
1069
1130
  complexFieldResultRuns: [],
1070
1131
  complexFieldOpenRuns: [],
1132
+ complexFieldSourceRuns: null,
1071
1133
  afterSeparator: false,
1072
1134
  complexFieldState: {},
1073
1135
  complexFieldDataXml: void 0,
@@ -1116,7 +1178,8 @@ function getCommentReferenceId(runElement) {
1116
1178
  const PARAGRAPH_ATTRIBUTES = /* @__PURE__ */ new Set([
1117
1179
  "paraId",
1118
1180
  "textId",
1119
- "reviewCarrier"
1181
+ "reviewCarrier",
1182
+ EMPTY_MARK_PROPERTIES_ATTRIBUTE
1120
1183
  ]);
1121
1184
  /**
1122
1185
  * Parse a paragraph element (w:p)
@@ -1158,8 +1221,10 @@ function parseParagraph(node, styles, theme, numbering, rels = null, media = nul
1158
1221
  const sectPr = findChild(pPr, "w", "sectPr");
1159
1222
  if (sectPr) paragraph.sectionProperties = parseSectionProperties(sectPr);
1160
1223
  }
1224
+ restoreEmptyMarkProperties(paragraph, node);
1161
1225
  const rawContent = parseParagraphContents(node, styles, theme, numbering, rels, media, options?.previews ?? standalonePreviewLedger(), "default", options?.rootXmlns ?? {});
1162
- paragraph.content = options?.runConsolidation === "deferred" ? rawContent : consolidateParagraphContent(rawContent);
1226
+ const consolidated = (content) => options?.runConsolidation === "deferred" ? content : consolidateParagraphContent(content);
1227
+ paragraph.content = consolidated(rawContent);
1163
1228
  const paragraphFormatting = paragraph.formatting;
1164
1229
  const directNumPr = paragraphFormatting?.numPr;
1165
1230
  const styleNumPr = paragraphFormatting?.styleId && styles ? styles.get(paragraphFormatting.styleId)?.pPr?.numPr : void 0;
@@ -1206,41 +1271,23 @@ function parseParagraph(node, styles, theme, numbering, rels = null, media = nul
1206
1271
  if (markerAlignment !== void 0) listRendering.markerAlignment = markerAlignment;
1207
1272
  if (level.suffix) listRendering.markerSuffix = level.suffix;
1208
1273
  if (level.pPr?.tabs?.length) listRendering.levelTabs = level.pPr.tabs;
1209
- let implicitChildLevelAdvances = 0;
1210
- const foldedMarkerSuffix = [];
1211
- const filteredContent = [];
1212
- let dropNextTab = false;
1213
- const isMetadataContent = (content) => content.type === "bookmarkStart" || content.type === "bookmarkEnd" || content.type === "commentRangeStart" || content.type === "commentRangeEnd" || content.type === "commentReference";
1214
- for (const content of paragraph.content) {
1215
- if (dropNextTab && isMetadataContent(content)) {
1216
- filteredContent.push(content);
1217
- continue;
1218
- }
1219
- if (dropNextTab) {
1220
- dropNextTab = false;
1221
- if (content.type === "run" && content.content.length === 1 && content.content[0]?.type === "tab") continue;
1222
- }
1223
- if (content.type === "complexField") {
1224
- if (content.fieldType === "LISTNUM" || content.instruction.trim().toUpperCase().startsWith("LISTNUM")) {
1225
- implicitChildLevelAdvances += 1;
1226
- const cached = extractPlainText(content.fieldResult);
1227
- if (cached) foldedMarkerSuffix.push(cached);
1228
- dropNextTab = true;
1229
- continue;
1230
- }
1231
- }
1232
- filteredContent.push(content);
1233
- }
1234
- if (foldedMarkerSuffix.length > 0) {
1235
- paragraph.content = filteredContent;
1236
- listRendering.marker = `${listRendering.marker}\t${foldedMarkerSuffix.join(" ")}`;
1274
+ const fold = rawContent.some((item) => item.type === "complexField") ? foldListNumberFields(rawContent, sourceMarkupOf) : {
1275
+ content: rawContent,
1276
+ cached: [],
1277
+ fieldCount: 0
1278
+ };
1279
+ const markerShowsFields = !listRendering.isBullet && level.lvlText !== "" && !level.lvlText.includes(" ");
1280
+ if (fold.cached.length > 0 && markerShowsFields) {
1281
+ paragraph.content = consolidated(fold.content);
1282
+ listRendering.foldedMarkerSuffix = fold.cached.join(" ");
1283
+ listRendering.marker = `${listRendering.marker}\t${listRendering.foldedMarkerSuffix}`;
1237
1284
  const nextLevel = numbering.getLevel(numId, ilvl + 1);
1238
1285
  if (nextLevel?.pPr?.hangingIndent === true && nextLevel.pPr.indentFirstLine !== void 0) {
1239
1286
  const hangingTwips = -nextLevel.pPr.indentFirstLine;
1240
1287
  if (hangingTwips > 0) listRendering.markerSecondSlotOffsetTwips = hangingTwips;
1241
1288
  }
1242
1289
  }
1243
- if (implicitChildLevelAdvances > 0) listRendering.implicitChildLevelAdvances = implicitChildLevelAdvances;
1290
+ if (fold.fieldCount > 0) listRendering.implicitChildLevelAdvances = fold.fieldCount;
1244
1291
  paragraph.listRendering = listRendering;
1245
1292
  const styleInd = styleChainInd(paragraph.formatting?.styleId ?? (styles ? resolveDefaultParagraphStyle(styles.values())?.styleId : void 0), styles);
1246
1293
  const chainInd = numPrFromStyle ? styleInd : {
@@ -1304,6 +1351,7 @@ const getRunContentText = (content) => {
1304
1351
  case "fieldChar":
1305
1352
  case "footnoteRef":
1306
1353
  case "instrText":
1354
+ case "noteMarker":
1307
1355
  case "renderedPageBreak":
1308
1356
  case "shape":
1309
1357
  case "symbol": return "";
@@ -43,6 +43,20 @@ declare const getProseDocumentParagraphPropertySourceContract: (document: Node)
43
43
  declare const getProseParagraphPropertySourceToken: (paragraph: Node) => unknown;
44
44
  declare const copyDocumentParagraphPropertySourceContract: (target: document_d_exports.Document, source: document_d_exports.Document) => void;
45
45
  declare const getParagraphPropertySourceToken: (paragraph: document_d_exports.Paragraph) => string | undefined;
46
+ type ParagraphSourceIdentity = {
47
+ type: "durable";
48
+ token: string;
49
+ } | {
50
+ type: "capture-only";
51
+ } | {
52
+ type: "authored";
53
+ } | {
54
+ type: "missing-token";
55
+ } | {
56
+ type: "invalid";
57
+ };
58
+ /** Byte captures can follow derivations; only explicit copies carry durable tokens. */
59
+ declare const inspectParagraphSourceIdentity: (paragraph: document_d_exports.Paragraph, document: document_d_exports.Document) => ParagraphSourceIdentity;
46
60
  type ParagraphCloneOverrides = Omit<Partial<document_d_exports.Paragraph>, "type">;
47
61
  /** Clone a paragraph while deliberately retaining its parsed `w:pPr` owner. */
48
62
  declare const cloneParagraphWithPropertySource: (paragraph: document_d_exports.Paragraph, overrides: ParagraphCloneOverrides) => document_d_exports.Paragraph;
@@ -136,4 +150,4 @@ declare const linkParagraphPropertySourceCandidate: (target: document_d_exports.
136
150
  declare const getParagraphPropertySourceCandidate: (paragraph: document_d_exports.Paragraph) => document_d_exports.Paragraph | undefined;
137
151
  declare const getParagraphPropertySourceTransferId: (paragraph: document_d_exports.Paragraph) => string | undefined;
138
152
  //#endregion
139
- export { DecodedTableCellParagraphSourcePayload, PARAGRAPH_PROPERTY_SOURCE_VALIDATION_CODES, PROSE_PARAGRAPH_SOURCE_CONTRACT_ATTR, PROSE_PARAGRAPH_SOURCE_TOKEN_ATTR, ParagraphPropertySourceTransfer, 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 };
153
+ export { DecodedTableCellParagraphSourcePayload, PARAGRAPH_PROPERTY_SOURCE_VALIDATION_CODES, PROSE_PARAGRAPH_SOURCE_CONTRACT_ATTR, PROSE_PARAGRAPH_SOURCE_TOKEN_ATTR, ParagraphPropertySourceTransfer, 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, inspectParagraphSourceIdentity, isParagraphPropertySourceToken, joinProseParagraphsWithRightPropertySource, linkParagraphPropertySourceCandidate, linkProseParagraphPropertySource, markParagraphPropertySourceTransfers, paragraphPropertySourceBelongsToDocument, paragraphPropertySourceMatchesEmission, paragraphPropertySourceTokenMatchesContract, proseParagraphAttrsWithoutPropertySource, recreateProseNodeWithDetachedParagraphPropertySource, recreateProseNodeWithParagraphPropertySource, restoreTableCellsWithParagraphPropertySources, setProseParagraphMarkupWithPropertySource, transferProseParagraphPropertySource, transportTableCellsWithParagraphPropertySources, visitDocumentStoryParagraphs, visitTableCellParagraphPropertySourceBindings };
@@ -1,11 +1,28 @@
1
1
  import { modelParagraphFormattingEmission } from "../internal/paragraphFormattingSerialization.js";
2
2
  import { canonicalJson } from "../utils/canonicalJson.js";
3
+ import { copyHeaderFooterBaselineHandles, copyHeaderFooterPackageBaselines } from "./headerFooterVerbatim.js";
3
4
  import { visitDocxParagraphs } from "./paragraphTraversal.js";
4
5
  import { TaggedError, panic } from "better-result";
5
6
  import { PluginKey } from "prosemirror-state";
6
7
  //#region src/docx/paragraphPropertySource.ts
7
8
  const paragraphPropertySourceEmissionFingerprint = Symbol("paragraphPropertySourceEmissionFingerprint");
8
- const paragraphPropertySources = /* @__PURE__ */ new WeakMap();
9
+ const paragraphPropertyCapture = Symbol("paragraphPropertyCapture");
10
+ const paragraphPropertyCaptures = /* @__PURE__ */ new WeakMap();
11
+ const paragraphSourceRecordKinds = /* @__PURE__ */ new WeakMap();
12
+ const captureForParagraph = (paragraph) => {
13
+ const handle = Object.getOwnPropertyDescriptor(paragraph, paragraphPropertyCapture)?.value;
14
+ if (!Object.hasOwn(paragraph, paragraphPropertyCapture)) return paragraphPropertyCaptures.get(paragraph);
15
+ return typeof handle === "object" && handle !== null ? paragraphPropertyCaptures.get(handle) : void 0;
16
+ };
17
+ const attachParagraphCapture = (paragraph, capture) => {
18
+ const handle = Object.freeze({});
19
+ paragraphPropertyCaptures.set(handle, capture);
20
+ Object.defineProperty(paragraph, paragraphPropertyCapture, {
21
+ value: handle,
22
+ enumerable: true,
23
+ configurable: true
24
+ });
25
+ };
9
26
  const paragraphFormattingEmissionFingerprint = (emission) => canonicalJson(emission);
10
27
  const ownedParagraphPropertySource = (paragraph, xml) => {
11
28
  return Object.freeze({
@@ -13,7 +30,6 @@ const ownedParagraphPropertySource = (paragraph, xml) => {
13
30
  [paragraphPropertySourceEmissionFingerprint]: paragraphFormattingEmissionFingerprint(modelParagraphFormattingEmission(paragraph.formatting))
14
31
  });
15
32
  };
16
- const paragraphPropertySourceOwners = /* @__PURE__ */ new WeakMap();
17
33
  const proseParagraphSourceOwners = /* @__PURE__ */ new WeakMap();
18
34
  const paragraphPropertySourceCandidates = /* @__PURE__ */ new WeakMap();
19
35
  const paragraphPropertySourceTransferIds = /* @__PURE__ */ new WeakMap();
@@ -91,19 +107,23 @@ const visitDocumentStoryParagraphs = (content, visit) => {
91
107
  visitDocxParagraphs({ documentBody: { content } }, visit);
92
108
  };
93
109
  const assignParagraphPropertySource = (paragraph, xml) => {
94
- paragraphPropertySources.set(paragraph, ownedParagraphPropertySource(paragraph, xml));
95
- paragraphPropertySourceOwners.set(paragraph, paragraph);
110
+ attachParagraphCapture(paragraph, {
111
+ source: ownedParagraphPropertySource(paragraph, xml),
112
+ owner: paragraph
113
+ });
96
114
  };
97
- const getParagraphPropertySource = (paragraph) => paragraphPropertySources.get(paragraph);
115
+ const getParagraphPropertySource = (paragraph) => captureForParagraph(paragraph)?.source;
98
116
  const paragraphPropertySourceMatchesEmission = (source, emission) => source[paragraphPropertySourceEmissionFingerprint] === paragraphFormattingEmissionFingerprint(emission);
99
117
  /** Copy the captured `w:pPr` without claiming the source paragraph's durable identity. */
100
118
  const copyParagraphPropertyCapture = (target, source) => {
101
- const propertySource = paragraphPropertySources.get(source);
102
- if (propertySource) {
103
- const copiedSource = Object.freeze({ ...propertySource });
104
- paragraphPropertySources.set(target, copiedSource);
105
- paragraphPropertySourceOwners.set(target, paragraphPropertySourceOwners.get(source) ?? source);
106
- }
119
+ const capture = captureForParagraph(source);
120
+ if (capture) attachParagraphCapture(target, capture);
121
+ const kind = paragraphPropertySourceTokens.has(source) || paragraphSourceRecordKinds.get(source) === "durable" ? "durable" : "capture-only";
122
+ if (!paragraphSourceRecordKinds.has(target)) paragraphSourceRecordKinds.set(target, kind);
123
+ };
124
+ const copyParagraphCaptureForTransport = (target, source) => {
125
+ const capture = captureForParagraph(source);
126
+ if (capture) paragraphPropertyCaptures.set(target, capture);
107
127
  };
108
128
  const copyParagraphPropertySource = (target, source) => {
109
129
  copyParagraphPropertyCapture(target, source);
@@ -122,6 +142,7 @@ const assignDocumentParagraphPropertySourceContract = (document, sourceDigest) =
122
142
  visitDocumentStoryParagraphs(document.package.document.content, (paragraph) => {
123
143
  const token = tokenForOrdinal(contract, ordinal);
124
144
  paragraphPropertySourceTokens.set(paragraph, token);
145
+ paragraphSourceRecordKinds.set(paragraph, "durable");
125
146
  sources.set(token, paragraph);
126
147
  ordinal += 1;
127
148
  });
@@ -144,7 +165,7 @@ const copyDocumentParagraphPropertySources = (document) => {
144
165
  return sources ? new Map(sources) : void 0;
145
166
  };
146
167
  const paragraphPropertySourceBelongsToDocument = (paragraph, document) => {
147
- const owner = paragraphPropertySourceOwners.get(paragraph);
168
+ const owner = captureForParagraph(paragraph)?.owner;
148
169
  const binding = getDocumentParagraphPropertySourceBinding(document);
149
170
  return owner !== void 0 && binding !== void 0 && binding.sourceOwners.has(owner);
150
171
  };
@@ -158,6 +179,26 @@ const copyDocumentParagraphPropertySourceContract = (target, source) => {
158
179
  if (binding) setDocumentParagraphPropertySourceBinding(target, binding);
159
180
  };
160
181
  const getParagraphPropertySourceToken = (paragraph) => paragraphPropertySourceTokens.get(paragraph);
182
+ /** Byte captures can follow derivations; only explicit copies carry durable tokens. */
183
+ const inspectParagraphSourceIdentity = (paragraph, document) => {
184
+ const binding = getDocumentParagraphPropertySourceBinding(document);
185
+ if (!binding) return { type: "invalid" };
186
+ const capture = captureForParagraph(paragraph);
187
+ if (Object.hasOwn(paragraph, paragraphPropertyCapture) && !capture) return { type: "invalid" };
188
+ const token = getParagraphPropertySourceToken(paragraph);
189
+ if (token !== void 0) {
190
+ if (capture && !binding.sourceOwners.has(capture.owner)) return { type: "invalid" };
191
+ return {
192
+ type: "durable",
193
+ token
194
+ };
195
+ }
196
+ const kind = paragraphSourceRecordKinds.get(paragraph);
197
+ if (kind === "durable" || binding.sourceOwners.has(paragraph)) return { type: "missing-token" };
198
+ if (!capture) return { type: "authored" };
199
+ if (kind === "capture-only" || binding.sourceOwners.has(capture.owner)) return { type: "capture-only" };
200
+ return { type: "invalid" };
201
+ };
161
202
  /** Clone a paragraph while deliberately retaining its parsed `w:pPr` owner. */
162
203
  const cloneParagraphWithPropertySource = (paragraph, overrides) => {
163
204
  const cloned = {
@@ -168,10 +209,14 @@ const cloneParagraphWithPropertySource = (paragraph, overrides) => {
168
209
  return cloned;
169
210
  };
170
211
  /** Clone a paragraph whose formatting provenance is deliberately no longer applicable. */
171
- const cloneParagraphWithoutPropertySource = (paragraph, overrides) => ({
172
- ...paragraph,
173
- ...overrides
174
- });
212
+ const cloneParagraphWithoutPropertySource = (paragraph, overrides) => {
213
+ const cloned = {
214
+ ...paragraph,
215
+ ...overrides
216
+ };
217
+ Reflect.deleteProperty(cloned, paragraphPropertyCapture);
218
+ return cloned;
219
+ };
175
220
  const paragraphsIn = (document) => {
176
221
  const paragraphs = [];
177
222
  visitDocxParagraphs({
@@ -199,6 +244,8 @@ const cloneDocumentWithParagraphPropertySources = (document) => {
199
244
  copyParagraphPropertySource(target, source);
200
245
  }
201
246
  copyDocumentParagraphPropertySourceContract(cloned, document);
247
+ copyHeaderFooterBaselineHandles(cloned, document);
248
+ copyHeaderFooterPackageBaselines(cloned, document);
202
249
  return cloned;
203
250
  };
204
251
  const paragraphsInTableCells = (cells) => {
@@ -299,6 +346,7 @@ const tableCellRunContentTraversalByType = {
299
346
  footnoteRef: "leaf",
300
347
  instrText: "leaf",
301
348
  noBreakHyphen: "leaf",
349
+ noteMarker: "leaf",
302
350
  preservedXml: "leaf",
303
351
  renderedPageBreak: "leaf",
304
352
  shape: "shape",
@@ -549,7 +597,7 @@ const transportTableCellsWithParagraphPropertySources = (cells) => {
549
597
  for (const [index, source] of sources.entries()) {
550
598
  const target = targets.at(index);
551
599
  if (!target) panic("The cloned table cells lost a paragraph owner.");
552
- copyParagraphPropertyCapture(target, source);
600
+ copyParagraphCaptureForTransport(target, source);
553
601
  const inspection = inspectTableCellParagraphPropertySourceBinding(source);
554
602
  setTableCellParagraphPropertySourceBinding(target, tableCellParagraphPropertySourceBindingForTransport(source, inspection));
555
603
  }
@@ -568,8 +616,11 @@ const restoreTableCellsWithParagraphPropertySources = (payload) => {
568
616
  copyParagraphPropertyCapture(target, source);
569
617
  if (!Reflect.deleteProperty(target, "_docxParagraphSourceBinding")) panic("Cannot detach paragraph-property transport identity from a table cell.");
570
618
  switch (sourceEntry.binding.type) {
571
- case "authored": break;
619
+ case "authored":
620
+ paragraphSourceRecordKinds.set(target, "capture-only");
621
+ break;
572
622
  case "source":
623
+ paragraphSourceRecordKinds.set(target, "durable");
573
624
  paragraphPropertySourceTokens.set(target, sourceEntry.binding.token);
574
625
  break;
575
626
  default: return sourceEntry.binding;
@@ -593,13 +644,14 @@ const cloneTableCellsWithParagraphPropertyCaptures = (payload) => {
593
644
  for (const [index, sourceEntry] of sourceEntries.entries()) {
594
645
  const target = targets.at(index);
595
646
  if (!target) panic("The cloned table cells lost a paragraph owner.");
596
- copyParagraphPropertyCapture(target, sourceEntry.paragraph);
647
+ copyParagraphCaptureForTransport(target, sourceEntry.paragraph);
597
648
  setTableCellParagraphPropertySourceBinding(target, { type: "authored" });
598
649
  }
599
650
  return cloned;
600
651
  };
601
652
  const linkProseParagraphPropertySource = (proseParagraph, sourceParagraph) => {
602
- if (paragraphPropertySources.has(sourceParagraph)) proseParagraphSourceOwners.set(proseParagraph, paragraphPropertySourceOwners.get(sourceParagraph) ?? sourceParagraph);
653
+ const capture = captureForParagraph(sourceParagraph);
654
+ if (capture) proseParagraphSourceOwners.set(proseParagraph, capture.owner);
603
655
  };
604
656
  /** Create a parsed paragraph with both its same-process owner and durable body token. */
605
657
  const createProseParagraphWithPropertySource = (nodeType, sourceParagraph, options = {}) => {
@@ -704,11 +756,14 @@ const transferProseParagraphPropertySource = (target, source, paraId) => {
704
756
  };
705
757
  const linkParagraphPropertySourceCandidate = (target, source) => {
706
758
  const token = source.attrs[PROSE_PARAGRAPH_SOURCE_TOKEN_ATTR];
707
- if (typeof token === "string") paragraphPropertySourceTokens.set(target, token);
759
+ if (typeof token === "string") {
760
+ paragraphPropertySourceTokens.set(target, token);
761
+ paragraphSourceRecordKinds.set(target, "durable");
762
+ } else paragraphSourceRecordKinds.set(target, "capture-only");
708
763
  const sourceOwner = proseParagraphSourceOwners.get(source);
709
764
  if (sourceOwner) paragraphPropertySourceCandidates.set(target, sourceOwner);
710
765
  };
711
766
  const getParagraphPropertySourceCandidate = (paragraph) => paragraphPropertySourceCandidates.get(paragraph);
712
767
  const getParagraphPropertySourceTransferId = (paragraph) => paragraphPropertySourceTransferIds.get(paragraph);
713
768
  //#endregion
714
- 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 };
769
+ 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, inspectParagraphSourceIdentity, isParagraphPropertySourceToken, joinProseParagraphsWithRightPropertySource, linkParagraphPropertySourceCandidate, linkProseParagraphPropertySource, markParagraphPropertySourceTransfers, paragraphPropertySourceBelongsToDocument, paragraphPropertySourceMatchesEmission, paragraphPropertySourceTokenMatchesContract, proseParagraphAttrsWithoutPropertySource, recreateProseNodeWithDetachedParagraphPropertySource, recreateProseNodeWithParagraphPropertySource, restoreTableCellsWithParagraphPropertySources, setProseParagraphMarkupWithPropertySource, transferProseParagraphPropertySource, transportTableCellsWithParagraphPropertySources, visitDocumentStoryParagraphs, visitTableCellParagraphPropertySourceBindings };
@@ -15,7 +15,7 @@ import { parseFontTable } from "./fontTableParser.js";
15
15
  import { parseEndnotes, parseFootnotes } from "./footnoteParser.js";
16
16
  import { parseFooter, parseHeader } from "./headerFooterParser.js";
17
17
  import { DANGLING_FOOTER_REFERENCE_WARNING, DANGLING_HEADER_REFERENCE_WARNING, assignHeaderFooterRoles, normalizeHeaderFooterReferences } from "./headerFooterReferenceNormalization.js";
18
- import { assignHeaderFooterVerbatimXml, canReplayHeaderFooterVerbatim, refreshHeaderFooterVerbatimFingerprint } from "./headerFooterVerbatim.js";
18
+ import { assignHeaderFooterVerbatimXml, canReplayHeaderFooterVerbatim, captureDocumentSourceBaseline, captureHeaderFooterPackageBaselines, refreshHeaderFooterVerbatimFingerprint } from "./headerFooterVerbatim.js";
19
19
  import { extractMetafileRaster, isMetafileMimeType } from "./metafileRaster.js";
20
20
  import { renderEmfSvg } from "./metafileSvg.js";
21
21
  import { DocxModelValidationError, formatDocumentModelIssues, validateFolioDocumentModel } from "./modelValidation.js";
@@ -473,6 +473,8 @@ async function parseDocxWithPreviewBudget(input, options, previewBudget) {
473
473
  document.warnings = formatParseWarnings(parseWarnings);
474
474
  }
475
475
  onProgress("Complete", 100);
476
+ captureHeaderFooterPackageBaselines(document);
477
+ if (raw.documentXml) captureDocumentSourceBaseline(document, raw.documentXml);
476
478
  return document;
477
479
  } catch (error) {
478
480
  if (error instanceof DocxEncryptionError) throw error;
@@ -4,6 +4,7 @@ import { captureVerbatimXml } from "./verbatimCapture.js";
4
4
  import { OFFICE_RELATIONSHIP_NAMESPACE_URIS, cloneElement, getAttribute, getLocalName, getNamespaceUri, parseXmlDocument } from "./xmlParser.js";
5
5
  import { panic } from "better-result";
6
6
  import { OOXML_NS } from "@stll/docx-utils";
7
+ import { writeZipPart } from "@stll/docx-core/zip";
7
8
  //#region src/docx/removeHeaderFooterParts.ts
8
9
  const DOCUMENT_RELS_PATH = "word/_rels/document.xml.rels";
9
10
  const officeRelationshipHasType = (type, kind) => [...OFFICE_RELATIONSHIP_NAMESPACE_URIS].some((namespace) => type === `${namespace}/${kind}`);
@@ -54,9 +55,14 @@ const removeResolvedHeaderFooterParts = async ({ document, zip, removedReference
54
55
  }
55
56
  }
56
57
  const compressionOptions = { level: compressionLevel };
57
- zip.file(DOCUMENT_RELS_PATH, withoutChildren(relsXml, (child) => getNamespaceUri(child) === OOXML_NS.pr && getLocalName(child.name) === "Relationship" && removedIds.has(getAttribute(child, null, "Id") ?? "")), {
58
- compression: "DEFLATE",
59
- compressionOptions
58
+ writeZipPart({
59
+ zip,
60
+ path: DOCUMENT_RELS_PATH,
61
+ data: withoutChildren(relsXml, (child) => getNamespaceUri(child) === OOXML_NS.pr && getLocalName(child.name) === "Relationship" && removedIds.has(getAttribute(child, null, "Id") ?? "")),
62
+ options: {
63
+ compression: "DEFLATE",
64
+ compressionOptions
65
+ }
60
66
  });
61
67
  if (document.package.relationships) {
62
68
  document.package.relationships = new Map(document.package.relationships);
@@ -78,9 +84,14 @@ const removeResolvedHeaderFooterParts = async ({ document, zip, removedReference
78
84
  const contentTypes = zip.file("[Content_Types].xml");
79
85
  if (!contentTypes) return panic("The package has no content types");
80
86
  const contentTypesXml = await contentTypes.async("text");
81
- zip.file("[Content_Types].xml", withoutChildren(contentTypesXml, (child) => getNamespaceUri(child) === OOXML_NS.ct && getLocalName(child.name) === "Override" && candidates.has((getAttribute(child, null, "PartName") ?? "").replace(/^\//u, ""))), {
82
- compression: "DEFLATE",
83
- compressionOptions
87
+ writeZipPart({
88
+ zip,
89
+ path: "[Content_Types].xml",
90
+ data: withoutChildren(contentTypesXml, (child) => getNamespaceUri(child) === OOXML_NS.ct && getLocalName(child.name) === "Override" && candidates.has((getAttribute(child, null, "PartName") ?? "").replace(/^\//u, ""))),
91
+ options: {
92
+ compression: "DEFLATE",
93
+ compressionOptions
94
+ }
84
95
  });
85
96
  };
86
97
  //#endregion
@@ -0,0 +1,4 @@
1
+ //#region src/docx/reviewHistoryNamespace.d.ts
2
+ declare const FOLIO_REVIEW_HISTORY_NAMESPACE = "urn:stella:folio:review-history:1";
3
+ //#endregion
4
+ export { FOLIO_REVIEW_HISTORY_NAMESPACE };