@stll/folio-core 0.35.1 → 0.37.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 (236) hide show
  1. package/README.md +59 -1
  2. package/dist/ai-edits/apply.js +878 -377
  3. package/dist/ai-edits/block-identity.d.ts +4 -1
  4. package/dist/ai-edits/block-identity.js +4 -1
  5. package/dist/ai-edits/blockRange.js +14 -14
  6. package/dist/ai-edits/clean-text.d.ts +40 -1
  7. package/dist/ai-edits/clean-text.js +52 -2
  8. package/dist/ai-edits/headless.d.ts +3 -1
  9. package/dist/ai-edits/headless.js +141 -73
  10. package/dist/ai-edits/index.d.ts +3 -3
  11. package/dist/ai-edits/index.js +2 -2
  12. package/dist/ai-edits/read.js +38 -20
  13. package/dist/ai-edits/snapshot.d.ts +14 -6
  14. package/dist/ai-edits/snapshot.js +105 -20
  15. package/dist/ai-edits/table-cell-mutations.js +1 -1
  16. package/dist/ai-edits/table-row-column-mutations.js +7 -0
  17. package/dist/ai-edits/table-template.d.ts +11 -1
  18. package/dist/ai-edits/table-template.js +49 -17
  19. package/dist/ai-edits/types.d.ts +62 -61
  20. package/dist/ai-edits/word-diff.d.ts +18 -3
  21. package/dist/ai-edits/word-diff.js +556 -67
  22. package/dist/ai-suggestions/conflict.js +1 -4
  23. package/dist/ai-suggestions/text-positions.d.ts +8 -0
  24. package/dist/ai-suggestions/text-positions.js +27 -5
  25. package/dist/compare/__fixtures__/body-sequence.js +3 -4
  26. package/dist/compare/column-alignment.d.ts +13 -13
  27. package/dist/compare/column-alignment.js +78 -39
  28. package/dist/compare/compare.d.ts +4 -3
  29. package/dist/compare/compare.js +48 -21
  30. package/dist/compare/content-alignment.d.ts +95 -0
  31. package/dist/compare/content-alignment.js +1450 -0
  32. package/dist/compare/content-types.d.ts +100 -0
  33. package/dist/compare/content-types.js +0 -0
  34. package/dist/compare/content.d.ts +209 -0
  35. package/dist/compare/content.js +885 -0
  36. package/dist/compare/formatting.d.ts +5 -5
  37. package/dist/compare/formatting.js +6 -4
  38. package/dist/compare/plan.d.ts +6 -1
  39. package/dist/compare/plan.js +171 -566
  40. package/dist/compare/scenario.d.ts +2 -2
  41. package/dist/compare/types.d.ts +3 -3
  42. package/dist/compare/verification.d.ts +8 -9
  43. package/dist/compare/verification.js +72 -50
  44. package/dist/compat/eigenpal.d.ts +5 -3
  45. package/dist/compat/eigenpal.js +3 -2
  46. package/dist/controller/headerFooterEditorManager.js +18 -10
  47. package/dist/controller/hiddenEditorApi.js +1 -1
  48. package/dist/controller/hiddenEditorManager.d.ts +7 -2
  49. package/dist/controller/hiddenEditorManager.js +15 -6
  50. package/dist/controller/layoutPipeline.js +5 -3
  51. package/dist/controller/noteEditorManager.js +12 -7
  52. package/dist/display-list/build/headerFooterPrimitives.js +1 -0
  53. package/dist/display-list/build/storyPrimitives.d.ts +5 -2
  54. package/dist/display-list/build/storyPrimitives.js +60 -3
  55. package/dist/display-list/build/tablePrimitives.js +30 -0
  56. package/dist/display-list/primitives.d.ts +1 -1
  57. package/dist/document-operations.d.ts +8 -4
  58. package/dist/document-operations.js +104 -12
  59. package/dist/docx/blockContentParser.js +6 -27
  60. package/dist/docx/commentParser.js +2 -4
  61. package/dist/docx/commentRangeIntegrity.js +2 -4
  62. package/dist/docx/documentClone.d.ts +2 -0
  63. package/dist/docx/documentClone.js +2 -0
  64. package/dist/docx/ensureParaIds.js +9 -4
  65. package/dist/docx/headerFooterParser.js +2 -4
  66. package/dist/docx/normalizeBaseDirection.js +5 -7
  67. package/dist/docx/numberingParser.d.ts +3 -1
  68. package/dist/docx/numberingParser.js +4 -1
  69. package/dist/docx/paragraphParser.js +34 -35
  70. package/dist/docx/paragraphPropertySource.d.ts +49 -0
  71. package/dist/docx/paragraphPropertySource.js +113 -0
  72. package/dist/docx/paragraphTraversal.js +30 -34
  73. package/dist/docx/rezip.d.ts +0 -8
  74. package/dist/docx/rezip.js +41 -16
  75. package/dist/docx/runConsolidator.js +2 -4
  76. package/dist/docx/runParser.js +6 -17
  77. package/dist/docx/sectionParser.js +1 -15
  78. package/dist/docx/serializer/paragraphSerializer.js +289 -30
  79. package/dist/docx/serializer/runSerializer.js +6 -12
  80. package/dist/docx/serializer/sectionPropertiesSerializer.js +2 -10
  81. package/dist/docx/serializer/tableSerializer.js +4 -23
  82. package/dist/docx/serializer/trackedChangeAttributes.d.ts +11 -0
  83. package/dist/docx/serializer/trackedChangeAttributes.js +31 -0
  84. package/dist/docx/server/build.d.ts +1 -1
  85. package/dist/docx/server/createBilingualDocument.js +8 -10
  86. package/dist/docx/server/evaluateDocxXmlPatchProposal.js +22 -13
  87. package/dist/docx/server/validateDocxConformance.js +17 -13
  88. package/dist/docx/tableParser.js +1 -37
  89. package/dist/docx/trackedChangeInfo.d.ts +11 -0
  90. package/dist/docx/trackedChangeInfo.js +38 -0
  91. package/dist/docx/verbatimCapture.d.ts +20 -9
  92. package/dist/docx/verbatimCapture.js +208 -8
  93. package/dist/docx/xmlParser.d.ts +3 -1
  94. package/dist/docx/xmlParser.js +6 -1
  95. package/dist/docx/xmlSafety.d.ts +1 -1
  96. package/dist/docx/xmlSafety.js +157 -0
  97. package/dist/headless-layout.js +5 -4
  98. package/dist/index.d.ts +5 -3
  99. package/dist/index.js +3 -2
  100. package/dist/internal/headlessRevisionResolution.d.ts +23 -0
  101. package/dist/internal/headlessRevisionResolution.js +155 -0
  102. package/dist/internal/headlessRevisionResolutionGuard.d.ts +12 -0
  103. package/dist/internal/headlessRevisionResolutionGuard.js +28 -0
  104. package/dist/internal/pageBreakRunDescendantIndex.d.ts +9 -0
  105. package/dist/internal/pageBreakRunDescendantIndex.js +27 -0
  106. package/dist/internal/pageBreakRunPartition.d.ts +26 -0
  107. package/dist/internal/pageBreakRunPartition.js +35 -0
  108. package/dist/internal/pageBreakRunSourceDescendantIndex.d.ts +15 -0
  109. package/dist/internal/pageBreakRunSourceDescendantIndex.js +126 -0
  110. package/dist/internal/sectionEndpointResolution.d.ts +32 -0
  111. package/dist/internal/sectionEndpointResolution.js +38 -0
  112. package/dist/layout-bridge/convert/footnoteLayout.js +1 -0
  113. package/dist/layout-bridge/convert/headerFooterLayout.d.ts +16 -4
  114. package/dist/layout-bridge/convert/headerFooterLayout.js +52 -9
  115. package/dist/layout-bridge/convert/toFlowBlocks.d.ts +4 -0
  116. package/dist/layout-bridge/convert/toFlowBlocks.js +391 -82
  117. package/dist/layout-bridge/dom/clickToPositionDom.d.ts +8 -1
  118. package/dist/layout-bridge/dom/clickToPositionDom.js +114 -40
  119. package/dist/layout-bridge/dom/textStreamDom.d.ts +24 -0
  120. package/dist/layout-bridge/dom/textStreamDom.js +75 -0
  121. package/dist/layout-bridge/headerFooterLayout.js +16 -30
  122. package/dist/layout-engine/index.js +12 -3
  123. package/dist/layout-engine/measure/tableFragmentBorderGeometry.d.ts +17 -0
  124. package/dist/layout-engine/measure/tableFragmentBorderGeometry.js +24 -0
  125. package/dist/layout-engine/renderedBreakReconciliation.js +1 -1
  126. package/dist/layout-engine/types.d.ts +7 -0
  127. package/dist/layout-painter/imageLayout.d.ts +1 -1
  128. package/dist/layout-painter/renderTable.js +20 -0
  129. package/dist/markdown/renderBlock.js +7 -10
  130. package/dist/model.d.ts +1 -1
  131. package/dist/paged-layout/rangeProjection.js +6 -9
  132. package/dist/paged-layout/transactionDirtyRange.d.ts +3 -1
  133. package/dist/paged-layout/transactionDirtyRange.js +23 -1
  134. package/dist/prosemirror/attrs/index.d.ts +7 -3
  135. package/dist/prosemirror/attrs/index.js +128 -7
  136. package/dist/prosemirror/bookmarkBoundaryIntegrity.d.ts +9 -0
  137. package/dist/prosemirror/bookmarkBoundaryIntegrity.js +22 -0
  138. package/dist/prosemirror/commands/comments.d.ts +10 -1
  139. package/dist/prosemirror/commands/comments.js +551 -87
  140. package/dist/prosemirror/commands/formatPainter.d.ts +45 -10
  141. package/dist/prosemirror/commands/formatPainter.js +319 -63
  142. package/dist/prosemirror/commands/index.d.ts +2 -2
  143. package/dist/prosemirror/commands/pageBreak.d.ts +5 -2
  144. package/dist/prosemirror/commands/pageBreak.js +18 -36
  145. package/dist/prosemirror/commands/propertyChangeScope.d.ts +27 -3
  146. package/dist/prosemirror/commands/propertyChangeScope.js +85 -14
  147. package/dist/prosemirror/conversion/fromProseDoc.d.ts +8 -5
  148. package/dist/prosemirror/conversion/fromProseDoc.js +935 -223
  149. package/dist/prosemirror/conversion/runShadingMark.js +2 -2
  150. package/dist/prosemirror/conversion/toProseDoc.d.ts +26 -1
  151. package/dist/prosemirror/conversion/toProseDoc.js +439 -291
  152. package/dist/prosemirror/extensions/StarterKit.js +4 -0
  153. package/dist/prosemirror/extensions/core/ParagraphExtension.js +54 -6
  154. package/dist/prosemirror/extensions/features/AutoBidiDetectionExtension.js +7 -1
  155. package/dist/prosemirror/extensions/features/ListExtension.js +95 -123
  156. package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.js +19 -6
  157. package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.d.ts +27 -1
  158. package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.js +134 -30
  159. package/dist/prosemirror/extensions/features/pasteCleanup.js +9 -15
  160. package/dist/prosemirror/extensions/marks/BoldExtension.js +4 -3
  161. package/dist/prosemirror/extensions/marks/CharacterStyleExtension.d.ts +4 -7
  162. package/dist/prosemirror/extensions/marks/CharacterStyleExtension.js +5 -11
  163. package/dist/prosemirror/extensions/marks/FontSizeExtension.js +3 -3
  164. package/dist/prosemirror/extensions/marks/ItalicExtension.js +4 -3
  165. package/dist/prosemirror/extensions/marks/PageBreakRunOwnerExtension.d.ts +13 -0
  166. package/dist/prosemirror/extensions/marks/PageBreakRunOwnerExtension.js +39 -0
  167. package/dist/prosemirror/extensions/marks/RunFormattingOverrideExtension.d.ts +7 -1
  168. package/dist/prosemirror/extensions/marks/RunFormattingOverrideExtension.js +67 -21
  169. package/dist/prosemirror/extensions/marks/TrackedChangeExtensions.js +2 -0
  170. package/dist/prosemirror/extensions/marks/markUtils.d.ts +8 -1
  171. package/dist/prosemirror/extensions/marks/markUtils.js +88 -2
  172. package/dist/prosemirror/extensions/nodes/BookmarkBoundaryExtension.js +44 -3
  173. package/dist/prosemirror/extensions/nodes/FieldExtension.js +1 -1
  174. package/dist/prosemirror/extensions/nodes/HardBreakExtension.js +15 -4
  175. package/dist/prosemirror/extensions/nodes/PageBreakExtension.d.ts +6 -0
  176. package/dist/prosemirror/extensions/nodes/PageBreakExtension.js +6 -0
  177. package/dist/prosemirror/extensions/nodes/PageBreakRunExtension.d.ts +6 -0
  178. package/dist/prosemirror/extensions/nodes/PageBreakRunExtension.js +36 -0
  179. package/dist/prosemirror/findReplaceSelection.js +8 -3
  180. package/dist/prosemirror/index.d.ts +3 -3
  181. package/dist/prosemirror/listMarker.d.ts +26 -1
  182. package/dist/prosemirror/listMarker.js +108 -14
  183. package/dist/prosemirror/pageBreakRunProjection.d.ts +28 -0
  184. package/dist/prosemirror/pageBreakRunProjection.js +47 -0
  185. package/dist/prosemirror/paraText.js +6 -0
  186. package/dist/prosemirror/paragraphAlignment.d.ts +12 -0
  187. package/dist/prosemirror/paragraphAlignment.js +13 -0
  188. package/dist/prosemirror/paragraphSpacing.d.ts +29 -0
  189. package/dist/prosemirror/paragraphSpacing.js +125 -0
  190. package/dist/prosemirror/plugins/documentNumbering.d.ts +8 -0
  191. package/dist/prosemirror/plugins/documentNumbering.js +18 -0
  192. package/dist/prosemirror/plugins/pmTextScan.d.ts +3 -2
  193. package/dist/prosemirror/plugins/pmTextScan.js +14 -4
  194. package/dist/prosemirror/plugins/suggestionMode.js +9 -11
  195. package/dist/prosemirror/rebaseParagraphRunFormatting.d.ts +16 -0
  196. package/dist/prosemirror/rebaseParagraphRunFormatting.js +61 -0
  197. package/dist/prosemirror/runFormattingInlineCarriers.d.ts +64 -0
  198. package/dist/prosemirror/runFormattingInlineCarriers.js +121 -0
  199. package/dist/prosemirror/runFormattingProvenance.d.ts +12 -0
  200. package/dist/prosemirror/runFormattingProvenance.js +48 -0
  201. package/dist/prosemirror/runFormattingReconciliation.d.ts +25 -0
  202. package/dist/prosemirror/runFormattingReconciliation.js +54 -0
  203. package/dist/prosemirror/runPropertyChangeResolution.d.ts +18 -0
  204. package/dist/prosemirror/runPropertyChangeResolution.js +18 -0
  205. package/dist/prosemirror/runStyleFormatting.d.ts +50 -0
  206. package/dist/prosemirror/runStyleFormatting.js +105 -0
  207. package/dist/prosemirror/schema/index.d.ts +3 -3
  208. package/dist/prosemirror/schema/marks.d.ts +84 -9
  209. package/dist/prosemirror/schema/marks.js +73 -1
  210. package/dist/prosemirror/schema/nodes.d.ts +30 -6
  211. package/dist/prosemirror/styles/resolvedStyleAttrs.d.ts +14 -2
  212. package/dist/prosemirror/styles/resolvedStyleAttrs.js +45 -23
  213. package/dist/prosemirror/styles/styleResolver.d.ts +10 -13
  214. package/dist/prosemirror/styles/styleResolver.js +3 -3
  215. package/dist/prosemirror/styles/styleToggleCascade.d.ts +8 -1
  216. package/dist/prosemirror/styles/styleToggleCascade.js +24 -1
  217. package/dist/prosemirror/tableGridMutation.d.ts +20 -0
  218. package/dist/prosemirror/tableGridMutation.js +30 -0
  219. package/dist/prosemirror/trackedRunInlineAtoms.d.ts +31 -0
  220. package/dist/prosemirror/trackedRunInlineAtoms.js +39 -0
  221. package/dist/prosemirror/utils/visualLineNavigation.js +27 -31
  222. package/dist/prosemirror/validation.js +23 -4
  223. package/dist/redline.js +4 -1
  224. package/dist/render-dom/HeaderFooterSelectionOverlay.js +20 -20
  225. package/dist/render-dom/RenderedDomContext.js +17 -34
  226. package/dist/server.d.ts +4 -4
  227. package/dist/server.js +2 -2
  228. package/dist/style-engine/styleEngine.d.ts +1 -1
  229. package/dist/utils/clipboard.js +1 -1
  230. package/dist/utils/findReplace.js +38 -21
  231. package/dist/utils/mergeDocumentContent.js +3 -3
  232. package/dist/utils/replaceText.js +2 -1
  233. package/dist/version-comparison.d.ts +38 -44
  234. package/dist/version-comparison.js +270 -399
  235. package/dist/watermark/index.js +2 -4
  236. package/package.json +8 -2
@@ -1,26 +1,35 @@
1
1
  import { numPrEqual } from "../../docx/numberingParser.js";
2
+ import { copyParagraphPropertySource, getParagraphPropertySource, getParagraphPropertySourceCandidate, getParagraphPropertySourceTransferId, linkParagraphPropertySourceCandidate, recreateProseNodeWithParagraphPropertySource } from "../../docx/paragraphPropertySource.js";
3
+ import { visitDocxParagraphs } from "../../docx/paragraphTraversal.js";
2
4
  import { ShapeOutlineStyleSchema, narrowEnum } from "../../docx/parserEnums.js";
5
+ import { DATE_UTC_ATTRIBUTE } from "../../docx/trackedChangeInfo.js";
6
+ import { createStyleEngine } from "../../style-engine/styleEngine.js";
3
7
  import { OUTLINE_STYLE_CSS_ALIASES, normalizeShapeTextAnchor } from "../../types/documentEnumValues.js";
4
8
  import { canonicalJson } from "../../utils/canonicalJson.js";
5
9
  import { normalizeHorizontalScalePercent } from "../../utils/horizontalScale.js";
10
+ import { mergeTextFormatting } from "../../utils/textFormattingMerge.js";
6
11
  import { pixelsToEmu } from "../../utils/units.js";
7
- import { expectBlockSdtAttrs, expectCharacterSpacingMarkAttrs, expectCharacterStyleMarkAttrs, expectCommentMarkAttrs, expectEmphasisMarkAttrs, expectFieldAttrs, expectFontFamilyMarkAttrs, expectFontSizeMarkAttrs, expectFootnoteRefMarkAttrs, expectHardBreakAttrs, expectHighlightMarkAttrs, expectHyperlinkMarkAttrs, expectImageAttrs, expectLanguageMarkAttrs, expectMathAttrs, expectParagraphAttrs, expectRunFormattingOverrideMarkAttrs, expectRunPropertyChangeMarkAttrs, expectRunShadingMarkAttrs, expectSdtAttrs, expectShapeAttrs, expectStrikeMarkAttrs, expectSymbolAttrs, expectTabAttrs, expectTableAttrs, expectTableCellAttrs, expectTableRowAttrs, expectTextBoxAttrs, expectTextColorMarkAttrs, expectTextEffectMarkAttrs, expectTrackedChangeMarkAttrs, expectUnderlineMarkAttrs } from "../attrs/index.js";
12
+ import { expectBlockSdtAttrs, expectCharacterSpacingMarkAttrs, expectCharacterStyleMarkAttrs, expectCommentMarkAttrs, expectEmphasisMarkAttrs, expectFieldAttrs, expectFontFamilyMarkAttrs, expectFontSizeMarkAttrs, expectFootnoteRefMarkAttrs, expectHardBreakAttrs, expectHighlightMarkAttrs, expectHyperlinkMarkAttrs, expectImageAttrs, expectLanguageMarkAttrs, expectMathAttrs, expectPageBreakRunAttrs, expectPageBreakRunOwnerMarkAttrs, expectParagraphAttrs, expectRunFormattingOverrideMarkAttrs, expectRunPropertyChangeMarkAttrs, expectRunShadingMarkAttrs, expectSdtAttrs, expectShapeAttrs, expectStrikeMarkAttrs, expectSymbolAttrs, expectTabAttrs, expectTableAttrs, expectTableCellAttrs, expectTableRowAttrs, expectTextBoxAttrs, expectTextColorMarkAttrs, expectTextEffectMarkAttrs, expectTrackedChangeMarkAttrs, expectUnderlineMarkAttrs } from "../attrs/index.js";
8
13
  import { autospacingMatchesBase, hasAutospacingBaseSide } from "../autospacingBase.js";
9
14
  import { expectBookmarkBoundaryAttrs } from "../bookmarkBoundaryAttrs.js";
10
- import { applyRunFormattingOverrideAttrs } from "../extensions/marks/RunFormattingOverrideExtension.js";
15
+ import { paragraphRejectAttrPatch, paragraphRejectOriginalFormatting, removeParagraphPropertyChanges } from "../commands/propertyChangeScope.js";
16
+ import { applyRunFormattingOverrideAttrs, buildRunFormattingOverrideAttrs } from "../extensions/marks/RunFormattingOverrideExtension.js";
11
17
  import { resolveNumberedRefFields } from "../numberedRefFields.js";
18
+ import { directParagraphAlignment } from "../paragraphAlignment.js";
12
19
  import { directionToBidi } from "../paragraphDirection.js";
20
+ import { directParagraphSpacing } from "../paragraphSpacing.js";
13
21
  import { RUN_FORMATTING_MARK_NAMES } from "../runFormattingMarkNames.js";
22
+ import { authoredRunFormattingFromAttrs, hasAuthoredRunFormattingProvenance } from "../runFormattingProvenance.js";
23
+ import { paragraphFormattingForRun, paragraphRunStyleContext, resolveEffectiveRunStyleFormatting, suppressParagraphMarkFormatting } from "../runStyleFormatting.js";
14
24
  import { parseShapeGeometryAdjustments } from "../shapeGeometryAdjustments.js";
15
- import { cascadeStyleTextFormatting } from "../styles/styleToggleCascade.js";
16
25
  import { expectTextBoxAnchorAttrs } from "../textBoxAnchorAttrs.js";
17
26
  import { assertValidProseMirrorDocument } from "../validation.js";
18
- import { runShadingAttrsToShading } from "./runShadingMark.js";
27
+ import { runShadingAttrsToShading, shadingToRunShadingAttrs } from "./runShadingMark.js";
19
28
  import { decodeSdtListItems, sdtPropertiesFromAttrs, sdtPropertiesMatchAttrs } from "./sdtAttrs.js";
20
29
  import { textFormattingToMarks } from "./toProseDoc.js";
21
30
  import { panic } from "better-result";
22
- import { DRAWING_RAW_XML_MODES } from "@stll/docx-core/model";
23
31
  import { Fragment } from "prosemirror-model";
32
+ import { DRAWING_RAW_XML_MODES } from "@stll/docx-core/model";
24
33
  //#region src/prosemirror/conversion/fromProseDoc.ts
25
34
  /**
26
35
  * ProseMirror to Document Conversion
@@ -76,12 +85,68 @@ function textBoxWrapFromAttrs(attrs) {
76
85
  if (attrs.distRight !== void 0) wrap.distR = pixelsToEmu(attrs.distRight);
77
86
  return wrap;
78
87
  }
79
- /**
80
- * Convert a ProseMirror document to our Document type
81
- */
88
+ const assignUniqueParagraph = (paragraphs, paraId, paragraph) => {
89
+ const existing = paragraphs.get(paraId);
90
+ if (!paragraphs.has(paraId) || existing === paragraph) {
91
+ paragraphs.set(paraId, paragraph);
92
+ return;
93
+ }
94
+ paragraphs.set(paraId, null);
95
+ };
96
+ const uniqueParagraphsById = (content, includeTransferIds = false) => {
97
+ const paragraphs = /* @__PURE__ */ new Map();
98
+ visitDocxParagraphs({ documentBody: { content } }, (paragraph) => {
99
+ const { paraId } = paragraph;
100
+ if (paraId) assignUniqueParagraph(paragraphs, paraId, paragraph);
101
+ const transferId = includeTransferIds ? getParagraphPropertySourceTransferId(paragraph) : void 0;
102
+ if (transferId) assignUniqueParagraph(paragraphs, transferId, paragraph);
103
+ });
104
+ return paragraphs;
105
+ };
106
+ const restoreParagraphPropertySources = (content, baseContent, linkedTargets, linkedSources) => {
107
+ const baseParagraphs = uniqueParagraphsById(baseContent, true);
108
+ for (const [paraId, paragraph] of uniqueParagraphsById(content)) {
109
+ const baseParagraph = baseParagraphs.get(paraId);
110
+ if (!paragraph || !baseParagraph || linkedTargets.has(paragraph) || linkedSources.has(baseParagraph) || !getParagraphPropertySource(baseParagraph)) continue;
111
+ copyParagraphPropertySource(paragraph, baseParagraph);
112
+ const baseFormatting = baseParagraph.formatting;
113
+ if (!baseFormatting?.numPr || !baseFormatting.numPrFromStyle || !numPrEqual(baseFormatting.numPr, baseFormatting.numPrFromStyle)) continue;
114
+ const { numPr, numPrFromStyle, ...authoredFormatting } = baseFormatting;
115
+ if (canonicalJson(paragraph.formatting ?? {}) !== canonicalJson(authoredFormatting)) continue;
116
+ paragraph.formatting = {
117
+ ...paragraph.formatting,
118
+ numPr,
119
+ numPrFromStyle
120
+ };
121
+ }
122
+ };
123
+ const restoreLinkedParagraphPropertySources = (content) => {
124
+ const targetsBySource = /* @__PURE__ */ new Map();
125
+ const linkedTargets = /* @__PURE__ */ new Set();
126
+ visitDocxParagraphs({ documentBody: { content } }, (paragraph) => {
127
+ const source = getParagraphPropertySourceCandidate(paragraph);
128
+ if (!source) return;
129
+ linkedTargets.add(paragraph);
130
+ const targets = targetsBySource.get(source);
131
+ if (targets) targets.push(paragraph);
132
+ else targetsBySource.set(source, [paragraph]);
133
+ });
134
+ for (const [source, targets] of targetsBySource) if (targets.length === 1) {
135
+ const target = targets.at(0);
136
+ if (target) copyParagraphPropertySource(target, source);
137
+ }
138
+ return {
139
+ targets: linkedTargets,
140
+ sources: new Set(targetsBySource.keys())
141
+ };
142
+ };
143
+ /** Convert a ProseMirror document to the document model. */
82
144
  function fromProseDoc(pmDoc, baseDocument) {
83
145
  assertValidProseMirrorDocument(pmDoc, "Cannot convert invalid ProseMirror document to DOCX model");
84
- const documentBody = { content: extractBlocks(pmDoc) };
146
+ const blocks = extractBlocks(pmDoc, "resolve", baseDocument?.package.styles ? createStyleEngine(baseDocument.package.styles) : null);
147
+ const linkedSources = restoreLinkedParagraphPropertySources(blocks);
148
+ if (baseDocument) restoreParagraphPropertySources(blocks, baseDocument.package.document.content, linkedSources.targets, linkedSources.sources);
149
+ const documentBody = { content: blocks };
85
150
  if (baseDocument?.package.document.finalSectionProperties) documentBody.finalSectionProperties = baseDocument.package.document.finalSectionProperties;
86
151
  if (baseDocument?.package.document.sections) documentBody.sections = baseDocument.package.document.sections;
87
152
  if (baseDocument?.package.document.comments) documentBody.comments = baseDocument.package.document.comments;
@@ -105,15 +170,40 @@ const hasSuggestedInsertion = (marks) => marks.some((mark) => mark.type.name ===
105
170
  * Returns the input array unchanged when there is nothing to strip so callers
106
171
  * can skip rebuilding the node.
107
172
  */
108
- function stripSuggestedInlineMarks(marks) {
173
+ function stripSuggestedInlineMarks(marks, { baseParagraphFormatting, inheritedFormatting, paragraphMarkFormatting, paragraphMarkPrecedesStyle, styleResolver }) {
109
174
  const hasSuggestedDeletion = marks.some((mark) => mark.type.name === "deletion" && isSuggestedMark(mark));
110
175
  const suggestedRunPropertyChange = marks.find((mark) => mark.type.name === "runPropertyChange" && isSuggestedMark(mark));
111
176
  if (!hasSuggestedDeletion && !suggestedRunPropertyChange) return marks;
112
177
  let next = marks.filter((mark) => !((mark.type.name === "deletion" || mark.type.name === "runPropertyChange") && isSuggestedMark(mark)));
113
178
  if (suggestedRunPropertyChange) {
114
179
  const previousFormatting = expectRunPropertyChangeMarkAttrs(suggestedRunPropertyChange).changes.at(0)?.previousFormatting;
180
+ const characterStyleMark = marks.find(({ type }) => type.name === "characterStyle");
181
+ const characterStyleAttrs = characterStyleMark ? expectCharacterStyleMarkAttrs(characterStyleMark) : void 0;
182
+ const preservedCharacterStyleAttrs = previousFormatting?.styleId !== void 0 && characterStyleAttrs?.styleId === previousFormatting.styleId ? characterStyleAttrs : void 0;
183
+ const paragraphFormatting = paragraphFormattingForRun({
184
+ marks,
185
+ context: {
186
+ baseParagraphFormatting,
187
+ paragraphFormatting: inheritedFormatting,
188
+ paragraphMarkFormatting,
189
+ paragraphMarkPrecedesStyle
190
+ },
191
+ ...previousFormatting !== void 0 ? { directFormatting: previousFormatting } : {}
192
+ });
193
+ const effectivePreviousFormatting = mergeTextFormatting(preservedCharacterStyleAttrs ? resolveEffectiveRunStyleFormatting({
194
+ marks,
195
+ paragraphFormatting,
196
+ styleResolver
197
+ }) : paragraphFormatting, previousFormatting);
115
198
  next = next.filter((mark) => !RUN_FORMATTING_MARK_NAMES.has(mark.type.name));
116
- for (const restored of textFormattingToMarks(previousFormatting)) next = restored.addToSet(next);
199
+ for (const restored of textFormattingToMarks(effectivePreviousFormatting, {
200
+ overrideFormatting: previousFormatting,
201
+ directFormatting: previousFormatting
202
+ })) next = restored.addToSet(next);
203
+ if (previousFormatting?.styleId) {
204
+ const characterStyle = suggestedRunPropertyChange.type.schema.marks["characterStyle"];
205
+ if (characterStyle) next = characterStyle.create(preservedCharacterStyleAttrs ?? { styleId: previousFormatting.styleId }).addToSet(next);
206
+ }
117
207
  }
118
208
  return next;
119
209
  }
@@ -131,6 +221,22 @@ function stripSuggestedInlineMarks(marks) {
131
221
  */
132
222
  function stripSuggestedNodeAttrs(node) {
133
223
  const name = node.type.name;
224
+ if (name === "paragraph") {
225
+ const propertyChanges = expectParagraphAttrs(node)._propertyChanges;
226
+ if (!Array.isArray(propertyChanges)) return null;
227
+ if (!propertyChanges.some(({ info }) => info.provenance === "suggested")) return null;
228
+ const removal = removeParagraphPropertyChanges(propertyChanges, ({ info }) => info.provenance === "suggested");
229
+ if (removal.type === "unchanged") return null;
230
+ const nextAttrs = {
231
+ ...node.attrs,
232
+ _propertyChanges: removal.remaining.length > 0 ? removal.remaining : null
233
+ };
234
+ if (removal.type === "restore-previous") {
235
+ Object.assign(nextAttrs, paragraphRejectAttrPatch(removal.previousFormatting));
236
+ nextAttrs["_originalFormatting"] = paragraphRejectOriginalFormatting(removal.previousFormatting, nextAttrs["_originalFormatting"]);
237
+ }
238
+ return nextAttrs;
239
+ }
134
240
  if (name === "tableRow") {
135
241
  const rowAttrs = expectTableRowAttrs(node);
136
242
  if (rowAttrs.trDel?.provenance === "suggested") return {
@@ -171,18 +277,32 @@ function isSuggestedInsertedNode(node) {
171
277
  * Surviving block nodes are rebuilt with their suggested delete/merge markers
172
278
  * cleared and their children stripped.
173
279
  */
174
- function mapSuggestionStrippedNode(node) {
280
+ function mapSuggestionStrippedNode(node, formattingContext = {
281
+ baseParagraphFormatting: void 0,
282
+ inheritedFormatting: void 0,
283
+ paragraphMarkFormatting: void 0,
284
+ paragraphMarkPrecedesStyle: false,
285
+ styleResolver: null
286
+ }) {
175
287
  if (node.isInline) {
176
288
  if (hasSuggestedInsertion(node.marks)) return null;
177
- const marks = stripSuggestedInlineMarks(node.marks);
289
+ const marks = stripSuggestedInlineMarks(node.marks, formattingContext);
178
290
  return marks === node.marks ? node : node.mark(marks);
179
291
  }
180
292
  if (isSuggestedInsertedNode(node)) return null;
181
293
  const nextAttrs = stripSuggestedNodeAttrs(node);
182
294
  const children = [];
183
295
  let changed = nextAttrs !== null;
296
+ const paragraphStyleContext = node.type.name === "paragraph" ? paragraphRunStyleContext(node, formattingContext.styleResolver) : void 0;
297
+ const childFormattingContext = paragraphStyleContext ? {
298
+ baseParagraphFormatting: paragraphStyleContext.baseParagraphFormatting,
299
+ inheritedFormatting: paragraphStyleContext.paragraphFormatting,
300
+ paragraphMarkFormatting: paragraphStyleContext.paragraphMarkFormatting,
301
+ paragraphMarkPrecedesStyle: paragraphStyleContext.paragraphMarkPrecedesStyle,
302
+ styleResolver: formattingContext.styleResolver
303
+ } : formattingContext;
184
304
  node.forEach((child) => {
185
- const mapped = mapSuggestionStrippedNode(child);
305
+ const mapped = mapSuggestionStrippedNode(child, childFormattingContext);
186
306
  if (mapped === null) {
187
307
  changed = true;
188
308
  return;
@@ -192,15 +312,24 @@ function mapSuggestionStrippedNode(node) {
192
312
  });
193
313
  if (!changed) return node;
194
314
  const content = Fragment.fromArray(children);
195
- return nextAttrs === null ? node.copy(content) : node.type.create(nextAttrs, content, node.marks);
315
+ return recreateProseNodeWithParagraphPropertySource(node, {
316
+ ...nextAttrs === null ? {} : { attrs: nextAttrs },
317
+ content
318
+ });
196
319
  }
197
320
  /**
198
321
  * Strip suggested (AI-proposed) tracked changes from a document so it
199
322
  * serializes as though the suggestion never happened. See the call site in
200
323
  * {@link extractBlocks} for why this is the sole serialization boundary.
201
324
  */
202
- function stripSuggestedProvenance(doc) {
203
- return mapSuggestionStrippedNode(doc) ?? doc;
325
+ function stripSuggestedProvenance(doc, styleResolver) {
326
+ return mapSuggestionStrippedNode(doc, {
327
+ baseParagraphFormatting: void 0,
328
+ inheritedFormatting: void 0,
329
+ paragraphMarkFormatting: void 0,
330
+ paragraphMarkPrecedesStyle: false,
331
+ styleResolver
332
+ }) ?? doc;
204
333
  }
205
334
  function materializeNumberedRefValues(doc) {
206
335
  const results = resolveNumberedRefFields(doc);
@@ -208,10 +337,10 @@ function materializeNumberedRefValues(doc) {
208
337
  const visit = (node) => {
209
338
  if (node.type.name === "field" || node.type.name === "structuredField") {
210
339
  const displayText = results.get(node);
211
- if (displayText !== void 0) return node.type.create({
340
+ if (displayText !== void 0) return recreateProseNodeWithParagraphPropertySource(node, { attrs: {
212
341
  ...node.attrs,
213
342
  displayText
214
- }, node.content, node.marks);
343
+ } });
215
344
  return node;
216
345
  }
217
346
  if (node.childCount === 0) return node;
@@ -222,12 +351,12 @@ function materializeNumberedRefValues(doc) {
222
351
  children.push(mappedChild);
223
352
  changed ||= mappedChild !== child;
224
353
  });
225
- return changed ? node.copy(Fragment.fromArray(children)) : node;
354
+ return changed ? recreateProseNodeWithParagraphPropertySource(node, { content: Fragment.fromArray(children) }) : node;
226
355
  };
227
356
  return visit(doc);
228
357
  }
229
- function extractBlocks(inputDoc, refResolution = "resolve") {
230
- const strippedDoc = stripSuggestedProvenance(inputDoc);
358
+ function extractBlocks(inputDoc, refResolution = "resolve", styleResolver = null) {
359
+ const strippedDoc = stripSuggestedProvenance(inputDoc, styleResolver);
231
360
  const pmDoc = refResolution === "resolve" ? materializeNumberedRefValues(strippedDoc) : strippedDoc;
232
361
  const blocks = [];
233
362
  const textBoxAnchorMarkers = /* @__PURE__ */ new Map();
@@ -252,25 +381,26 @@ function extractBlocks(inputDoc, refResolution = "resolve") {
252
381
  return;
253
382
  }
254
383
  if (node.type.name === "paragraph") {
255
- const paragraph = convertPMParagraph(node, documentCounts, textBoxAnchorMarkers);
384
+ const paragraph = convertPMParagraph(node, documentCounts, textBoxAnchorMarkers, styleResolver);
256
385
  prependPageBreaks(paragraph, pendingPageBreaks);
257
386
  pendingPageBreaks = 0;
258
387
  blocks.push(paragraph);
259
388
  previousStandaloneTextBox = null;
260
389
  } else if (node.type.name === "table") {
261
390
  if (pendingPageBreaks > 0 && !appendPendingPageBreaksToPreviousParagraph()) flushPendingPageBreaks();
262
- blocks.push(convertPMTable(node, documentCounts));
391
+ blocks.push(convertPMTable(node, documentCounts, styleResolver));
263
392
  previousStandaloneTextBox = null;
264
393
  } else if (node.type.name === "textBox") {
265
394
  previousStandaloneTextBox = appendTextBoxBlock(blocks, node, {
266
395
  pendingPageBreaks,
267
396
  previousStandaloneTextBox,
268
- textBoxAnchorMarkers
397
+ textBoxAnchorMarkers,
398
+ styleResolver
269
399
  });
270
400
  pendingPageBreaks = 0;
271
401
  } else if (node.type.name === "blockSdt") {
272
402
  if (pendingPageBreaks > 0 && !appendPendingPageBreaksToPreviousParagraph()) flushPendingPageBreaks();
273
- blocks.push(convertPMBlockSdt(node));
403
+ blocks.push(convertPMBlockSdt(node, styleResolver));
274
404
  previousStandaloneTextBox = null;
275
405
  }
276
406
  });
@@ -278,7 +408,7 @@ function extractBlocks(inputDoc, refResolution = "resolve") {
278
408
  removeUnresolvedTextBoxAnchors(blocks, textBoxAnchorMarkers);
279
409
  return blocks;
280
410
  }
281
- function convertPMBlockSdt(node) {
411
+ function convertPMBlockSdt(node, styleResolver) {
282
412
  const attrs = expectBlockSdtAttrs(node);
283
413
  const properties = { sdtType: attrs.sdtType };
284
414
  if (attrs.alias) properties.alias = attrs.alias;
@@ -296,7 +426,7 @@ function convertPMBlockSdt(node) {
296
426
  if (attrs.rawEndPropertiesXml) properties.rawEndPropertiesXml = attrs.rawEndPropertiesXml;
297
427
  if (attrs.rawSdtChildrenBeforeContent) properties.rawSdtChildrenBeforeContent = attrs.rawSdtChildrenBeforeContent;
298
428
  if (attrs.rawSdtChildrenAfterContent) properties.rawSdtChildrenAfterContent = attrs.rawSdtChildrenAfterContent;
299
- const extracted = extractBlocks(node.type.schema.node("doc", null, node.content), "inherit");
429
+ const extracted = extractBlocks(node.type.schema.node("doc", null, node.content), "inherit", styleResolver);
300
430
  return {
301
431
  type: "blockSdt",
302
432
  properties,
@@ -316,7 +446,7 @@ function isStillSyntheticFiller(blocks) {
316
446
  }
317
447
  function appendTextBoxBlock(blocks, node, options) {
318
448
  const attrs = expectTextBoxAttrs(node);
319
- const paragraph = convertPMTextBox(node);
449
+ const paragraph = convertPMTextBox(node, options.styleResolver);
320
450
  const previousBlock = blocks.at(-1);
321
451
  if (attrs._docxPlacement === "inlineWithPrevious" && previousBlock?.type === "paragraph") {
322
452
  appendPageBreaks(previousBlock, options.pendingPageBreaks);
@@ -456,6 +586,7 @@ function listRenderingFromAttrs(attrs) {
456
586
  if (!(attrs.listMarker != null || attrs.listIsBullet || attrs.listNumFmt != null)) return;
457
587
  return {
458
588
  marker: attrs.listMarker ?? "",
589
+ ...attrs.listMarkerTemplate != null && { markerTemplate: attrs.listMarkerTemplate },
459
590
  level: attrs.numPr?.ilvl ?? 0,
460
591
  numId,
461
592
  isBullet: attrs.listIsBullet ?? false,
@@ -506,9 +637,16 @@ function appendPageBreaks(paragraph, count) {
506
637
  /**
507
638
  * Convert a ProseMirror paragraph node to our Paragraph type
508
639
  */
509
- function convertPMParagraph(node, documentCounts, textBoxAnchorMarkers) {
640
+ function convertPMParagraph(node, documentCounts, textBoxAnchorMarkers, styleResolver = null) {
510
641
  const attrs = expectParagraphAttrs(node);
511
- let content = extractParagraphContent(node, documentCounts, attrs._emptyHyperlinks ?? void 0, textBoxAnchorMarkers, attrs.renderedPageBreakBefore === true);
642
+ const paragraphStyleContext = paragraphRunStyleContext(node, styleResolver);
643
+ let content = extractParagraphContent(node, documentCounts, attrs._emptyHyperlinks ?? void 0, textBoxAnchorMarkers, attrs.renderedPageBreakBefore === true, {
644
+ baseParagraphFormatting: paragraphStyleContext.baseParagraphFormatting,
645
+ inheritedFormatting: paragraphStyleContext.paragraphFormatting,
646
+ paragraphMarkFormatting: paragraphStyleContext.paragraphMarkFormatting,
647
+ paragraphMarkPrecedesStyle: paragraphStyleContext.paragraphMarkPrecedesStyle,
648
+ styleResolver
649
+ });
512
650
  const bookmarks = attrs.bookmarks;
513
651
  if (bookmarks && bookmarks.length > 0) {
514
652
  const starts = bookmarks.map((b) => ({
@@ -541,12 +679,20 @@ function convertPMParagraph(node, documentCounts, textBoxAnchorMarkers) {
541
679
  else if (attrs.sectionBreakType) paragraph.sectionProperties = { sectionStart: attrs.sectionBreakType };
542
680
  if (attrs._propertyChanges && attrs._propertyChanges.length > 0) paragraph.propertyChanges = attrs._propertyChanges.map(propertyChangeFromAttrs);
543
681
  if (attrs.pPrMark) paragraph.pPrMark = attrs.pPrMark;
682
+ linkParagraphPropertySourceCandidate(paragraph, node);
544
683
  return paragraph;
545
684
  }
546
685
  const propertyChangeFromAttrs = (change) => {
547
- const { previousFormatting, currentFormatting, ...info } = change;
548
- if (previousFormatting === void 0) return currentFormatting === void 0 ? info : {
549
- ...info,
686
+ const { previousFormatting, currentFormatting, info, ...changeInfo } = change;
687
+ const serializedInfo = { ...info };
688
+ Reflect.deleteProperty(serializedInfo, "provenance");
689
+ Reflect.deleteProperty(serializedInfo, "suggestionId");
690
+ const normalizedChangeInfo = {
691
+ ...changeInfo,
692
+ info: serializedInfo
693
+ };
694
+ if (previousFormatting === void 0) return currentFormatting === void 0 ? normalizedChangeInfo : {
695
+ ...normalizedChangeInfo,
550
696
  currentFormatting
551
697
  };
552
698
  const { numPr, ...previousWithoutNumPr } = previousFormatting;
@@ -555,7 +701,7 @@ const propertyChangeFromAttrs = (change) => {
555
701
  numPr
556
702
  };
557
703
  return {
558
- ...info,
704
+ ...normalizedChangeInfo,
559
705
  previousFormatting: normalizedPrevious,
560
706
  ...currentFormatting !== void 0 && { currentFormatting }
561
707
  };
@@ -576,6 +722,8 @@ function assignBooleanToggle(result, attrs, orig, key) {
576
722
  else result[key] = value;
577
723
  }
578
724
  function paragraphAttrsToFormatting(attrs) {
725
+ const directAlignment = directParagraphAlignment(attrs);
726
+ const directSpacing = directParagraphSpacing(attrs);
579
727
  const spaceBefore = Reflect.get(attrs, "spaceBefore");
580
728
  const spaceAfter = Reflect.get(attrs, "spaceAfter");
581
729
  const beforeHasAutospacingBase = hasAutospacingBaseSide(attrs._autospacingBase, "before");
@@ -584,9 +732,12 @@ function paragraphAttrsToFormatting(attrs) {
584
732
  const afterOriginalAutospacing = attrs._originalFormatting?.afterAutospacing === true;
585
733
  const beforeAutospacingEdited = beforeHasAutospacingBase ? !autospacingMatchesBase(attrs._autospacingBase, "before", spaceBefore) : beforeOriginalAutospacing && attrs._autospacingBase == null;
586
734
  const afterAutospacingEdited = afterHasAutospacingBase ? !autospacingMatchesBase(attrs._autospacingBase, "after", spaceAfter) : afterOriginalAutospacing && attrs._autospacingBase == null;
587
- const shouldSerializeSpaceBefore = typeof spaceBefore === "number" && (!beforeHasAutospacingBase || beforeAutospacingEdited);
588
- const shouldSerializeSpaceAfter = typeof spaceAfter === "number" && (!afterHasAutospacingBase || afterAutospacingEdited);
589
- const hasDirectLineSpacing = attrs.lineSpacingExplicit === true;
735
+ const beforeIsInherited = attrs.spacingFromDocDefaults?.before === true || attrs.spacingFromImplicitDefaultStyle?.before === true;
736
+ const afterIsInherited = attrs.spacingFromDocDefaults?.after === true || attrs.spacingFromImplicitDefaultStyle?.after === true;
737
+ const shouldSerializeSpaceBefore = typeof spaceBefore === "number" && (attrs.spacingExplicit?.before === true || beforeAutospacingEdited || !beforeIsInherited && !beforeHasAutospacingBase);
738
+ const shouldSerializeSpaceAfter = typeof spaceAfter === "number" && (attrs.spacingExplicit?.after === true || afterAutospacingEdited || !afterIsInherited && !afterHasAutospacingBase);
739
+ const hasDirectLineSpacing = directSpacing?.lineSpacing !== void 0;
740
+ const hasDirectLineSpacingRule = directSpacing?.lineSpacingRule !== void 0;
590
741
  if (attrs._originalFormatting) {
591
742
  const orig = attrs._originalFormatting;
592
743
  const result = { ...orig };
@@ -600,17 +751,18 @@ function paragraphAttrsToFormatting(attrs) {
600
751
  if (typeof spaceAfter === "number") result.spaceAfter = spaceAfter;
601
752
  else delete result.spaceAfter;
602
753
  }
603
- if (attrs.spacingExplicit?.before && typeof spaceBefore === "number") result.spaceBefore = spaceBefore;
604
- if (attrs.spacingExplicit?.after && typeof spaceAfter === "number") result.spaceAfter = spaceAfter;
605
- const originalHasDirectLineSpacing = orig.lineSpacing !== void 0 || orig.lineSpacingRule !== void 0;
606
- if (hasDirectLineSpacing || originalHasDirectLineSpacing) {
607
- if (typeof attrs.lineSpacing === "number") result.lineSpacing = attrs.lineSpacing;
608
- else Reflect.deleteProperty(result, "lineSpacing");
609
- if (attrs.lineSpacingRule) result.lineSpacingRule = attrs.lineSpacingRule;
610
- else Reflect.deleteProperty(result, "lineSpacingRule");
611
- }
612
- if (attrs.alignment !== (orig.alignment ?? void 0)) if (attrs.alignment) result.alignment = attrs.alignment;
613
- else delete result.alignment;
754
+ if (orig.spaceBefore !== void 0 || attrs.spacingExplicit?.before) if (typeof spaceBefore === "number") result.spaceBefore = spaceBefore;
755
+ else Reflect.deleteProperty(result, "spaceBefore");
756
+ if (orig.spaceAfter !== void 0 || attrs.spacingExplicit?.after) if (typeof spaceAfter === "number") result.spaceAfter = spaceAfter;
757
+ else Reflect.deleteProperty(result, "spaceAfter");
758
+ const originalHasDirectLineSpacing = orig.lineSpacing !== void 0;
759
+ if (hasDirectLineSpacing || originalHasDirectLineSpacing) if (typeof attrs.lineSpacing === "number") result.lineSpacing = attrs.lineSpacing;
760
+ else Reflect.deleteProperty(result, "lineSpacing");
761
+ const originalHasDirectLineSpacingRule = orig.lineSpacingRule !== void 0;
762
+ if (hasDirectLineSpacingRule || originalHasDirectLineSpacingRule) if (attrs.lineSpacingRule) result.lineSpacingRule = attrs.lineSpacingRule;
763
+ else Reflect.deleteProperty(result, "lineSpacingRule");
764
+ if (directAlignment === void 0) Reflect.deleteProperty(result, "alignment");
765
+ else result.alignment = directAlignment;
614
766
  if (isStyleSourcedNumPr(attrs)) {
615
767
  delete result.numPr;
616
768
  delete result.numPrFromStyle;
@@ -636,15 +788,15 @@ function paragraphAttrsToFormatting(attrs) {
636
788
  }
637
789
  const outlineLevel = Reflect.get(attrs, "outlineLevel");
638
790
  const bidi = directionToBidi(attrs.direction);
639
- if (!(attrs.alignment || shouldSerializeSpaceBefore || shouldSerializeSpaceAfter || beforeAutospacingEdited || afterAutospacingEdited || hasDirectLineSpacing || attrs.snapToGrid != null || attrs.indentLeft || attrs.indentRight || attrs.indentFirstLine || attrs.numPr || attrs.styleId || attrs.borders || attrs.shading || attrs.tabs || typeof outlineLevel === "number" || attrs.contextualSpacing || attrs.spacingExplicit || bidi != null || attrs.pageBreakBefore != null || attrs.widowControl != null || attrs.kinsoku != null || attrs.overflowPunctuation != null || attrs.suppressAutoHyphens != null)) return;
791
+ if (!(directAlignment !== void 0 || shouldSerializeSpaceBefore || shouldSerializeSpaceAfter || beforeAutospacingEdited || afterAutospacingEdited || hasDirectLineSpacing || hasDirectLineSpacingRule || attrs.snapToGrid != null || attrs.indentLeft || attrs.indentRight || attrs.indentFirstLine || attrs.numPr || attrs.styleId || attrs.borders || attrs.shading || attrs.tabs || typeof outlineLevel === "number" || attrs.contextualSpacing || attrs.spacingExplicit || bidi != null || attrs.pageBreakBefore != null || attrs.widowControl != null || attrs.kinsoku != null || attrs.overflowPunctuation != null || attrs.suppressAutoHyphens != null)) return;
640
792
  const f = {};
641
- if (attrs.alignment) f.alignment = attrs.alignment;
793
+ if (directAlignment !== void 0) f.alignment = directAlignment;
642
794
  if (shouldSerializeSpaceBefore) f.spaceBefore = spaceBefore;
643
795
  if (beforeAutospacingEdited) f.beforeAutospacing = false;
644
796
  if (shouldSerializeSpaceAfter) f.spaceAfter = spaceAfter;
645
797
  if (afterAutospacingEdited) f.afterAutospacing = false;
646
798
  if (hasDirectLineSpacing && typeof attrs.lineSpacing === "number") f.lineSpacing = attrs.lineSpacing;
647
- if (hasDirectLineSpacing && attrs.lineSpacingRule) f.lineSpacingRule = attrs.lineSpacingRule;
799
+ if (hasDirectLineSpacingRule && attrs.lineSpacingRule) f.lineSpacingRule = attrs.lineSpacingRule;
648
800
  if (attrs.snapToGrid != null) f.snapToGrid = attrs.snapToGrid;
649
801
  if (attrs.spacingExplicit) f.spacingExplicit = attrs.spacingExplicit;
650
802
  if (attrs.indentLeft) f.indentLeft = attrs.indentLeft;
@@ -691,7 +843,14 @@ function createTrackedRunWrapper(type, info, child) {
691
843
  }
692
844
  function extractParagraphContent(paragraph, _documentCounts, emptyHyperlinks, textBoxAnchorMarkers, skipLeadingRenderedPageBreak = false, inheritedFormattingOverride) {
693
845
  const content = [];
694
- const inheritedFormatting = inheritedFormattingOverride ?? (paragraph.type.name === "paragraph" ? expectParagraphAttrs(paragraph).defaultTextFormatting ?? void 0 : void 0);
846
+ const paragraphStyleContext = paragraph.type.name === "paragraph" ? paragraphRunStyleContext(paragraph) : void 0;
847
+ const formattingContext = inheritedFormattingOverride ?? {
848
+ baseParagraphFormatting: paragraphStyleContext?.baseParagraphFormatting,
849
+ inheritedFormatting: paragraphStyleContext?.paragraphFormatting,
850
+ paragraphMarkFormatting: paragraphStyleContext?.paragraphMarkFormatting,
851
+ paragraphMarkPrecedesStyle: paragraphStyleContext?.paragraphMarkPrecedesStyle ?? false,
852
+ styleResolver: null
853
+ };
695
854
  const sortedEmptyHyperlinks = (emptyHyperlinks ?? []).map((attrs, order) => ({
696
855
  attrs,
697
856
  order
@@ -703,6 +862,7 @@ function extractParagraphContent(paragraph, _documentCounts, emptyHyperlinks, te
703
862
  let currentHyperlink = null;
704
863
  let currentHyperlinkKey = null;
705
864
  let currentTrackedChange;
865
+ const sourceRunOwners = /* @__PURE__ */ new WeakMap();
706
866
  const openedComments = /* @__PURE__ */ new Set();
707
867
  const commentLastOffset = /* @__PURE__ */ new Map();
708
868
  paragraph.forEach((node, offset) => {
@@ -720,6 +880,24 @@ function extractParagraphContent(paragraph, _documentCounts, emptyHyperlinks, te
720
880
  currentHyperlinkKey = null;
721
881
  }
722
882
  };
883
+ const appendDirectRun = (node, run, coalescePlainText = false) => {
884
+ const marksKey = getMarksKey(node.marks);
885
+ const ownerId = pageBreakRunOwnerId(node);
886
+ const currentOwnerId = currentRun ? sourceRunOwners.get(currentRun) : void 0;
887
+ const currentRunIsPlainText = currentRun?.content.every((runContent) => runContent.type === "text");
888
+ const joinsOwnedSourceRun = ownerId !== void 0 && ownerId === currentOwnerId && currentRun !== null && runsShareProperties(currentRun, run);
889
+ const joinsOrdinaryText = coalescePlainText && ownerId === void 0 && currentOwnerId === void 0 && currentRunIsPlainText === true && currentMarksKey === marksKey;
890
+ if (currentRun && (joinsOwnedSourceRun || joinsOrdinaryText)) {
891
+ if (joinsOrdinaryText) {
892
+ for (const runContent of run.content) if (runContent.type === "text") appendTextToRun(currentRun, runContent.text);
893
+ } else currentRun.content.push(...run.content);
894
+ return;
895
+ }
896
+ if (currentRun) content.push(currentRun);
897
+ currentRun = run;
898
+ currentMarksKey = marksKey;
899
+ rememberSourceRunOwner(run, node, sourceRunOwners);
900
+ };
723
901
  const syncCommentRanges = (node, offset) => {
724
902
  const nodeCommentIds = getCommentMarkIds(node.marks);
725
903
  const toClose = [];
@@ -794,6 +972,10 @@ function extractParagraphContent(paragraph, _documentCounts, emptyHyperlinks, te
794
972
  id: changeAttrs.revisionId,
795
973
  author: changeAttrs.author || "Unknown",
796
974
  ...changeAttrs.date ? { date: changeAttrs.date } : {},
975
+ ...changeAttrs.utcDate ? { utcDate: {
976
+ attribute: DATE_UTC_ATTRIBUTE,
977
+ value: changeAttrs.utcDate
978
+ } } : {},
797
979
  ...changeAttrs.initials ? { initials: changeAttrs.initials } : {}
798
980
  };
799
981
  if (insertionMark) content.push({
@@ -819,6 +1001,10 @@ function extractParagraphContent(paragraph, _documentCounts, emptyHyperlinks, te
819
1001
  author: changeAttrs.author || "Unknown"
820
1002
  };
821
1003
  if (changeAttrs.date) info.date = changeAttrs.date;
1004
+ if (changeAttrs.utcDate) info.utcDate = {
1005
+ attribute: DATE_UTC_ATTRIBUTE,
1006
+ value: changeAttrs.utcDate
1007
+ };
822
1008
  if (changeAttrs.initials) info.initials = changeAttrs.initials;
823
1009
  let type;
824
1010
  if (insertionMark) type = changeAttrs.moveKind === "moveTo" ? "moveTo" : "insertion";
@@ -841,18 +1027,19 @@ function extractParagraphContent(paragraph, _documentCounts, emptyHyperlinks, te
841
1027
  if (currentTrackedChange.type !== "hyperlink") panic("A tracked hyperlink lost its serialization parent");
842
1028
  if (node.type.name === "bookmarkBoundary") {
843
1029
  addNodeToHyperlink({
1030
+ ...formattingContext,
844
1031
  hyperlink: currentTrackedChange.hyperlink,
845
- inheritedFormatting,
846
- node
1032
+ node,
1033
+ sourceRunOwners
847
1034
  });
848
1035
  return;
849
1036
  }
850
1037
  const run = createTrackedChangeRun({
851
- inheritedFormatting,
1038
+ ...formattingContext,
852
1039
  marks: otherMarks,
853
1040
  node
854
1041
  });
855
- if (run) currentTrackedChange.hyperlink.children.push(run);
1042
+ if (run) appendRunToHyperlink(currentTrackedChange.hyperlink, run, node, sourceRunOwners);
856
1043
  return;
857
1044
  }
858
1045
  if (!currentTrackedChange || currentTrackedChange.type !== "direct" || currentTrackedChange.key !== trackedChangeKey) {
@@ -881,22 +1068,32 @@ function extractParagraphContent(paragraph, _documentCounts, emptyHyperlinks, te
881
1068
  }
882
1069
  if (node.type.name === "field" || node.type.name === "structuredField") {
883
1070
  currentTrackedChange.wrapper.content.push(createFieldFromNode(node, {
1071
+ ...formattingContext,
884
1072
  marks: otherMarks,
885
1073
  textBoxAnchorMarkers
886
1074
  }));
887
1075
  return;
888
1076
  }
889
1077
  const run = createTrackedChangeRun({
890
- inheritedFormatting,
1078
+ ...formattingContext,
891
1079
  marks: otherMarks,
892
1080
  node
893
1081
  });
894
- if (run) currentTrackedChange.wrapper.content.push(run);
1082
+ if (run) appendRunToTrackedWrapper(currentTrackedChange.wrapper, run, node, sourceRunOwners);
1083
+ return;
1084
+ }
1085
+ const ownedRun = linkMark || pageBreakRunOwnerId(node) === void 0 ? null : createTrackedChangeRun({
1086
+ ...formattingContext,
1087
+ marks: node.marks,
1088
+ node
1089
+ });
1090
+ if (ownedRun) {
1091
+ appendDirectRun(node, ownedRun, node.isText);
895
1092
  return;
896
1093
  }
897
1094
  if (noteRefMark && !linkMark) {
898
1095
  flushCurrentInline();
899
- content.push(createNoteReferenceRun(noteRefMark, node.marks));
1096
+ content.push(createNoteReferenceRun(noteRefMark, node.marks, formattingContext));
900
1097
  return;
901
1098
  }
902
1099
  if (linkMark) {
@@ -907,9 +1104,10 @@ function extractParagraphContent(paragraph, _documentCounts, emptyHyperlinks, te
907
1104
  currentHyperlinkKey = linkKey;
908
1105
  }
909
1106
  addNodeToHyperlink({
1107
+ ...formattingContext,
910
1108
  hyperlink: currentHyperlink,
911
- inheritedFormatting,
912
- node
1109
+ node,
1110
+ sourceRunOwners
913
1111
  });
914
1112
  return;
915
1113
  }
@@ -928,24 +1126,24 @@ function extractParagraphContent(paragraph, _documentCounts, emptyHyperlinks, te
928
1126
  type: "bookmarkEnd",
929
1127
  id: attrs.id
930
1128
  });
931
- } else if (node.isText) {
932
- const marksKey = getMarksKey(node.marks);
933
- if (currentRun && currentMarksKey === marksKey) appendTextToRun(currentRun, node.text || "");
934
- else {
935
- if (currentRun) content.push(currentRun);
936
- currentRun = createRunFromText({
937
- inheritedFormatting,
938
- marks: node.marks,
939
- text: node.text || ""
940
- });
941
- currentMarksKey = marksKey;
942
- }
1129
+ } else if (node.isText) appendDirectRun(node, createRunFromText({
1130
+ ...formattingContext,
1131
+ marks: node.marks,
1132
+ text: node.text || ""
1133
+ }), true);
1134
+ else if (node.type.name === "pageBreakRun") {
1135
+ const { clear } = expectPageBreakRunAttrs(node);
1136
+ appendDirectRun(node, createPageBreakCarrierRun({
1137
+ ...formattingContext,
1138
+ clear,
1139
+ marks: node.marks
1140
+ }));
943
1141
  } else if (node.type.name === "symbol") {
944
1142
  flushCurrentInline();
945
- content.push(createSymbolRun(node, node.marks));
1143
+ content.push(createSymbolRun(node, node.marks, formattingContext));
946
1144
  } else if (node.type.name === "hardBreak") {
947
1145
  flushCurrentInline();
948
- content.push(createBreakRun(readHardBreakType(node)));
1146
+ content.push(createBreakRun(expectHardBreakAttrs(node), node.marks, formattingContext));
949
1147
  } else if (node.type.name === "image") {
950
1148
  flushCurrentInline();
951
1149
  content.push(createImageRun(node));
@@ -954,19 +1152,20 @@ function extractParagraphContent(paragraph, _documentCounts, emptyHyperlinks, te
954
1152
  content.push(createShapeRun(node));
955
1153
  } else if (node.type.name === "tab") {
956
1154
  flushCurrentInline();
957
- content.push(createTabRun(node));
1155
+ content.push(createTabRun(node, node.marks, formattingContext));
958
1156
  } else if (node.type.name === "renderedPageBreak") {
959
1157
  flushCurrentInline();
960
1158
  content.push(createRenderedPageBreakRun());
961
1159
  } else if (node.type.name === "field" || node.type.name === "structuredField") {
962
1160
  flushCurrentInline();
963
1161
  content.push(createFieldFromNode(node, {
1162
+ ...formattingContext,
964
1163
  marks: node.marks,
965
1164
  textBoxAnchorMarkers
966
1165
  }));
967
1166
  } else if (node.type.name === "sdt") {
968
1167
  flushCurrentInline();
969
- content.push(createInlineSdtFromNode(node, textBoxAnchorMarkers, inheritedFormatting));
1168
+ content.push(createInlineSdtFromNode(node, textBoxAnchorMarkers, formattingContext));
970
1169
  } else if (node.type.name === "math") {
971
1170
  flushCurrentInline();
972
1171
  content.push(createMathFromNode(node));
@@ -1002,12 +1201,20 @@ function extractParagraphContent(paragraph, _documentCounts, emptyHyperlinks, te
1002
1201
  });
1003
1202
  return content;
1004
1203
  }
1005
- function createTrackedChangeRun({ inheritedFormatting, marks, node }) {
1204
+ function createTrackedChangeRun({ baseParagraphFormatting, inheritedFormatting, marks, node, paragraphMarkFormatting, paragraphMarkPrecedesStyle, styleResolver }) {
1205
+ const formattingContext = {
1206
+ baseParagraphFormatting,
1207
+ inheritedFormatting,
1208
+ paragraphMarkFormatting,
1209
+ paragraphMarkPrecedesStyle,
1210
+ styleResolver
1211
+ };
1006
1212
  const noteRefMark = marks.find((mark) => mark.type.name === "footnoteRef");
1007
- if (noteRefMark) return createNoteReferenceRun(noteRefMark, marks);
1008
- if (node.isText) {
1009
- const formatting = marksToTextFormatting(marks, { inheritedFormatting });
1010
- const run = {
1213
+ let run = null;
1214
+ if (noteRefMark) run = createNoteReferenceRun(noteRefMark, marks, formattingContext);
1215
+ else if (node.isText) {
1216
+ const formatting = marksToTextFormatting(marks, formattingContext);
1217
+ run = {
1011
1218
  type: "run",
1012
1219
  content: node.text ? [{
1013
1220
  type: "text",
@@ -1016,15 +1223,26 @@ function createTrackedChangeRun({ inheritedFormatting, marks, node }) {
1016
1223
  ...Object.keys(formatting).length > 0 ? { formatting } : {}
1017
1224
  };
1018
1225
  restoreRunPropertyChanges(run, marks);
1019
- return run;
1020
- }
1021
- if (node.type.name === "symbol") return createSymbolRun(node, marks);
1022
- if (node.type.name === "hardBreak") return createBreakRun(readHardBreakType(node));
1023
- if (node.type.name === "image") return createImageRun(node);
1024
- if (node.type.name === "shape") return createShapeRun(node);
1025
- if (node.type.name === "tab") return createTabRun(node);
1026
- if (node.type.name === "renderedPageBreak") return createRenderedPageBreakRun();
1027
- return null;
1226
+ } else if (node.type.name === "symbol") run = createSymbolRun(node, marks, formattingContext);
1227
+ else if (node.type.name === "hardBreak") run = createBreakRun(expectHardBreakAttrs(node), marks, formattingContext);
1228
+ else if (node.type.name === "pageBreakRun") {
1229
+ const { clear } = expectPageBreakRunAttrs(node);
1230
+ run = createPageBreakCarrierRun({
1231
+ ...formattingContext,
1232
+ clear,
1233
+ marks
1234
+ });
1235
+ } else if (node.type.name === "image") run = createImageRun(node);
1236
+ else if (node.type.name === "shape") run = createShapeRun(node);
1237
+ else if (node.type.name === "tab") run = createTabRun(node, marks, formattingContext);
1238
+ else if (node.type.name === "renderedPageBreak") run = createRenderedPageBreakRun();
1239
+ if (!run || pageBreakRunOwnerId(node) === void 0) return run;
1240
+ if (node.type.name === "image" || node.type.name === "shape" || node.type.name === "renderedPageBreak") {
1241
+ const formatting = getRunFormattingFromMarks(marks, formattingContext);
1242
+ if (formatting) run.formatting = formatting;
1243
+ restoreRunPropertyChanges(run, marks);
1244
+ }
1245
+ return run;
1028
1246
  }
1029
1247
  function createEmptyHyperlink(attrs) {
1030
1248
  const hyperlink = {
@@ -1111,7 +1329,7 @@ function createHyperlink(linkMark) {
1111
1329
  if (attrs.rId) hyperlink.rId = attrs.rId;
1112
1330
  return hyperlink;
1113
1331
  }
1114
- function addNodeToHyperlink({ hyperlink, inheritedFormatting, node }) {
1332
+ function addNodeToHyperlink({ baseParagraphFormatting, hyperlink, inheritedFormatting, node, paragraphMarkFormatting, paragraphMarkPrecedesStyle, sourceRunOwners, styleResolver }) {
1115
1333
  if (node.type.name === "bookmarkBoundary") {
1116
1334
  const attrs = expectBookmarkBoundaryAttrs(node);
1117
1335
  if (attrs.type === "start") hyperlink.children.push({
@@ -1127,31 +1345,84 @@ function addNodeToHyperlink({ hyperlink, inheritedFormatting, node }) {
1127
1345
  });
1128
1346
  return;
1129
1347
  }
1348
+ const formattingContext = {
1349
+ baseParagraphFormatting,
1350
+ inheritedFormatting,
1351
+ paragraphMarkFormatting,
1352
+ paragraphMarkPrecedesStyle,
1353
+ styleResolver
1354
+ };
1355
+ const nonLinkMarks = node.marks.filter((mark) => mark.type.name !== "hyperlink");
1356
+ const ownedRun = pageBreakRunOwnerId(node) === void 0 ? null : createTrackedChangeRun({
1357
+ ...formattingContext,
1358
+ marks: nonLinkMarks,
1359
+ node
1360
+ });
1361
+ if (ownedRun) {
1362
+ appendRunToHyperlink(hyperlink, ownedRun, node, sourceRunOwners);
1363
+ return;
1364
+ }
1130
1365
  const noteRefMark = node.marks.find((m) => m.type.name === "footnoteRef");
1131
1366
  if (noteRefMark) {
1132
- hyperlink.children.push(createNoteReferenceRun(noteRefMark, node.marks));
1367
+ hyperlink.children.push(createNoteReferenceRun(noteRefMark, node.marks, {
1368
+ baseParagraphFormatting,
1369
+ inheritedFormatting,
1370
+ paragraphMarkFormatting,
1371
+ paragraphMarkPrecedesStyle,
1372
+ styleResolver
1373
+ }));
1133
1374
  return;
1134
1375
  }
1135
- const nonLinkMarks = node.marks.filter((m) => m.type.name !== "hyperlink");
1136
1376
  if (node.isText && node.text) {
1137
1377
  const run = createRunFromText({
1378
+ baseParagraphFormatting,
1138
1379
  inheritedFormatting,
1139
1380
  marks: nonLinkMarks,
1381
+ paragraphMarkFormatting,
1382
+ paragraphMarkPrecedesStyle,
1383
+ styleResolver,
1140
1384
  text: node.text
1141
1385
  });
1142
1386
  hyperlink.children.push(run);
1143
1387
  return;
1144
1388
  }
1145
1389
  if (node.type.name === "symbol") {
1146
- hyperlink.children.push(createSymbolRun(node, nonLinkMarks));
1390
+ hyperlink.children.push(createSymbolRun(node, nonLinkMarks, {
1391
+ baseParagraphFormatting,
1392
+ inheritedFormatting,
1393
+ paragraphMarkFormatting,
1394
+ paragraphMarkPrecedesStyle,
1395
+ styleResolver
1396
+ }));
1147
1397
  return;
1148
1398
  }
1149
1399
  if (node.type.name === "hardBreak") {
1150
- hyperlink.children.push(createBreakRun(readHardBreakType(node), nonLinkMarks));
1400
+ hyperlink.children.push(createBreakRun(expectHardBreakAttrs(node), nonLinkMarks, {
1401
+ baseParagraphFormatting,
1402
+ inheritedFormatting,
1403
+ paragraphMarkFormatting,
1404
+ paragraphMarkPrecedesStyle,
1405
+ styleResolver
1406
+ }));
1407
+ return;
1408
+ }
1409
+ if (node.type.name === "pageBreakRun") {
1410
+ const { clear } = expectPageBreakRunAttrs(node);
1411
+ hyperlink.children.push(createPageBreakCarrierRun({
1412
+ ...formattingContext,
1413
+ clear,
1414
+ marks: nonLinkMarks
1415
+ }));
1151
1416
  return;
1152
1417
  }
1153
1418
  if (node.type.name === "tab") {
1154
- hyperlink.children.push(createTabRun(node, nonLinkMarks));
1419
+ hyperlink.children.push(createTabRun(node, nonLinkMarks, {
1420
+ baseParagraphFormatting,
1421
+ inheritedFormatting,
1422
+ paragraphMarkFormatting,
1423
+ paragraphMarkPrecedesStyle,
1424
+ styleResolver
1425
+ }));
1155
1426
  return;
1156
1427
  }
1157
1428
  if (node.type.name === "renderedPageBreak") {
@@ -1169,7 +1440,7 @@ function getNoteReferenceVertAlign(noteAttrs, marks) {
1169
1440
  if (marks.some((mark) => mark.type.name === "superscript")) return "superscript";
1170
1441
  if (noteAttrs.vertAlign === "baseline" || noteAttrs.vertAlign === "superscript") return noteAttrs.vertAlign;
1171
1442
  }
1172
- function createNoteReferenceRun(noteRefMark, marks) {
1443
+ function createNoteReferenceRun(noteRefMark, marks, formattingContext) {
1173
1444
  const noteAttrs = expectFootnoteRefMarkAttrs(noteRefMark);
1174
1445
  const run = {
1175
1446
  type: "run",
@@ -1178,12 +1449,24 @@ function createNoteReferenceRun(noteRefMark, marks) {
1178
1449
  id: typeof noteAttrs.id === "string" ? Number.parseInt(noteAttrs.id, 10) || 0 : noteAttrs.id
1179
1450
  }]
1180
1451
  };
1452
+ const formatting = getAtomRunFormattingFromMarks(marks, formattingContext);
1181
1453
  const vertAlign = getNoteReferenceVertAlign(noteAttrs, marks);
1182
- if (vertAlign) run.formatting = { vertAlign };
1454
+ if (formatting) run.formatting = formatting;
1455
+ if (vertAlign && formatting?.vertAlign === void 0 && formatting?.styleId === void 0) run.formatting = {
1456
+ ...formatting,
1457
+ vertAlign
1458
+ };
1459
+ restoreRunPropertyChanges(run, marks);
1183
1460
  return run;
1184
1461
  }
1185
- function createRunFromText({ inheritedFormatting, marks, text }) {
1186
- const formatting = getRunFormattingFromMarks(marks, { inheritedFormatting });
1462
+ function createRunFromText({ baseParagraphFormatting, inheritedFormatting, marks, paragraphMarkFormatting, paragraphMarkPrecedesStyle, styleResolver, text }) {
1463
+ const formatting = getRunFormattingFromMarks(marks, {
1464
+ baseParagraphFormatting,
1465
+ inheritedFormatting,
1466
+ paragraphMarkFormatting,
1467
+ paragraphMarkPrecedesStyle,
1468
+ styleResolver
1469
+ });
1187
1470
  const run = {
1188
1471
  type: "run",
1189
1472
  content: [{
@@ -1195,7 +1478,7 @@ function createRunFromText({ inheritedFormatting, marks, text }) {
1195
1478
  restoreRunPropertyChanges(run, marks);
1196
1479
  return run;
1197
1480
  }
1198
- function createSymbolRun(node, marks) {
1481
+ function createSymbolRun(node, marks, formattingContext) {
1199
1482
  const { font, char } = expectSymbolAttrs(node);
1200
1483
  const run = {
1201
1484
  type: "run",
@@ -1205,7 +1488,7 @@ function createSymbolRun(node, marks) {
1205
1488
  char
1206
1489
  }]
1207
1490
  };
1208
- const formatting = getRunFormattingFromMarks(marks);
1491
+ const formatting = getAtomRunFormattingFromMarks(marks, formattingContext);
1209
1492
  if (formatting) run.formatting = formatting;
1210
1493
  restoreRunPropertyChanges(run, marks);
1211
1494
  return run;
@@ -1218,10 +1501,14 @@ function restoreRunPropertyChanges(run, marks) {
1218
1501
  run.propertyChanges = [...changes];
1219
1502
  }
1220
1503
  function getRunFormattingFromMarks(marks, options) {
1221
- if (!marks || marks.length === 0) return;
1504
+ if (!marks || marks.length === 0 && !options) return;
1222
1505
  const formatting = marksToTextFormatting(marks, options);
1223
1506
  return Object.keys(formatting).length > 0 ? formatting : void 0;
1224
1507
  }
1508
+ function getAtomRunFormattingFromMarks(marks, options) {
1509
+ if (!marks?.some(({ type }) => RUN_FORMATTING_MARK_NAMES.has(type.name))) return;
1510
+ return getRunFormattingFromMarks(marks, options);
1511
+ }
1225
1512
  /**
1226
1513
  * Append text to an existing run
1227
1514
  */
@@ -1233,19 +1520,81 @@ function appendTextToRun(run, text) {
1233
1520
  text
1234
1521
  });
1235
1522
  }
1523
+ function runsShareProperties(left, right) {
1524
+ return canonicalJson({
1525
+ formatting: left.formatting,
1526
+ propertyChanges: left.propertyChanges
1527
+ }) === canonicalJson({
1528
+ formatting: right.formatting,
1529
+ propertyChanges: right.propertyChanges
1530
+ });
1531
+ }
1532
+ function pageBreakRunOwnerId(node) {
1533
+ const mark = node.marks.find(({ type }) => type.name === "pageBreakRunOwner");
1534
+ return mark ? expectPageBreakRunOwnerMarkAttrs(mark).id : void 0;
1535
+ }
1536
+ function canJoinOwnedRuns(previous, run, node, sourceRunOwners) {
1537
+ if (!previous || !runsShareProperties(previous, run)) return false;
1538
+ const ownerId = pageBreakRunOwnerId(node);
1539
+ return ownerId !== void 0 && sourceRunOwners.get(previous) === ownerId;
1540
+ }
1541
+ function rememberSourceRunOwner(run, node, sourceRunOwners) {
1542
+ const ownerId = pageBreakRunOwnerId(node);
1543
+ if (ownerId !== void 0) sourceRunOwners.set(run, ownerId);
1544
+ }
1545
+ function appendRunToTrackedWrapper(wrapper, run, node, sourceRunOwners) {
1546
+ const previous = wrapper.content.at(-1);
1547
+ if (previous?.type === "run" && canJoinOwnedRuns(previous, run, node, sourceRunOwners)) {
1548
+ previous.content.push(...run.content);
1549
+ return;
1550
+ }
1551
+ wrapper.content.push(run);
1552
+ rememberSourceRunOwner(run, node, sourceRunOwners);
1553
+ }
1554
+ function appendRunToHyperlink(hyperlink, run, node, sourceRunOwners) {
1555
+ const previous = hyperlink.children.at(-1);
1556
+ if (previous?.type === "run" && canJoinOwnedRuns(previous, run, node, sourceRunOwners)) {
1557
+ previous.content.push(...run.content);
1558
+ return;
1559
+ }
1560
+ hyperlink.children.push(run);
1561
+ rememberSourceRunOwner(run, node, sourceRunOwners);
1562
+ }
1563
+ function createPageBreakCarrierRun({ baseParagraphFormatting, clear, inheritedFormatting, marks, paragraphMarkFormatting, paragraphMarkPrecedesStyle, styleResolver }) {
1564
+ const run = {
1565
+ type: "run",
1566
+ content: [{
1567
+ type: "break",
1568
+ breakType: "page",
1569
+ ...clear !== void 0 ? { clear } : {}
1570
+ }]
1571
+ };
1572
+ const formatting = getAtomRunFormattingFromMarks(marks, {
1573
+ baseParagraphFormatting,
1574
+ inheritedFormatting,
1575
+ paragraphMarkFormatting,
1576
+ paragraphMarkPrecedesStyle,
1577
+ styleResolver
1578
+ });
1579
+ if (formatting) run.formatting = formatting;
1580
+ if (marks) restoreRunPropertyChanges(run, marks);
1581
+ return run;
1582
+ }
1236
1583
  /**
1237
1584
  * Create a Run containing a line break
1238
1585
  */
1239
- function createBreakRun(breakType = "textWrapping", marks) {
1586
+ function createBreakRun(attrs, marks, formattingContext) {
1240
1587
  const run = {
1241
1588
  type: "run",
1242
1589
  content: [{
1243
1590
  type: "break",
1244
- breakType
1591
+ ...attrs.breakType !== void 0 ? { breakType: attrs.breakType } : {},
1592
+ ...attrs.clear !== void 0 ? { clear: attrs.clear } : {}
1245
1593
  }]
1246
1594
  };
1247
- const formatting = getRunFormattingFromMarks(marks);
1595
+ const formatting = getAtomRunFormattingFromMarks(marks, formattingContext);
1248
1596
  if (formatting) run.formatting = formatting;
1597
+ if (marks) restoreRunPropertyChanges(run, marks);
1249
1598
  return run;
1250
1599
  }
1251
1600
  function createRenderedPageBreakRun() {
@@ -1254,13 +1603,10 @@ function createRenderedPageBreakRun() {
1254
1603
  content: [{ type: "renderedPageBreak" }]
1255
1604
  };
1256
1605
  }
1257
- function readHardBreakType(node) {
1258
- return expectHardBreakAttrs(node).breakType ?? "textWrapping";
1259
- }
1260
1606
  /**
1261
1607
  * Create a Run containing a tab
1262
1608
  */
1263
- function createTabRun(node, marks) {
1609
+ function createTabRun(node, marks, formattingContext) {
1264
1610
  const { positional } = expectTabAttrs(node);
1265
1611
  const run = {
1266
1612
  type: "run",
@@ -1269,15 +1615,32 @@ function createTabRun(node, marks) {
1269
1615
  ...positional ? { positional } : {}
1270
1616
  }]
1271
1617
  };
1272
- const formatting = getRunFormattingFromMarks(marks);
1618
+ const formatting = getAtomRunFormattingFromMarks(marks, formattingContext);
1273
1619
  if (formatting) run.formatting = formatting;
1620
+ if (marks) restoreRunPropertyChanges(run, marks);
1274
1621
  return run;
1275
1622
  }
1276
- function createFieldFromNode(node, { marks, textBoxAnchorMarkers }) {
1623
+ function createFieldFromNode(node, { baseParagraphFormatting, inheritedFormatting, marks, paragraphMarkFormatting, paragraphMarkPrecedesStyle, styleResolver, textBoxAnchorMarkers }) {
1277
1624
  const attrs = expectFieldAttrs(node);
1278
- const formatting = marks && marks.length > 0 ? marksToTextFormatting(marks) : void 0;
1625
+ const formatting = marks && marks.length > 0 ? marksToTextFormatting(marks, {
1626
+ baseParagraphFormatting,
1627
+ inheritedFormatting,
1628
+ paragraphMarkFormatting,
1629
+ paragraphMarkPrecedesStyle,
1630
+ styleResolver
1631
+ }) : void 0;
1632
+ const extractedContent = extractParagraphContent(node, void 0, void 0, textBoxAnchorMarkers, false, {
1633
+ baseParagraphFormatting,
1634
+ inheritedFormatting,
1635
+ paragraphMarkFormatting,
1636
+ paragraphMarkPrecedesStyle: paragraphMarkPrecedesStyle ?? false,
1637
+ styleResolver: styleResolver ?? null
1638
+ }).filter((content) => content.type === "run" || content.type === "hyperlink");
1639
+ const hasExplicitPageBreak = extractedContent.some((content) => {
1640
+ return (content.type === "run" ? [content] : content.children).some((run) => run.type === "run" && run.content.some((runContent) => runContent.type === "break" && runContent.breakType === "page"));
1641
+ });
1279
1642
  let displayText = attrs.displayText ?? "";
1280
- if (!displayText) switch (attrs.fieldType) {
1643
+ if (!displayText && !hasExplicitPageBreak) switch (attrs.fieldType) {
1281
1644
  case "PAGE":
1282
1645
  displayText = "1";
1283
1646
  break;
@@ -1296,7 +1659,7 @@ function createFieldFromNode(node, { marks, textBoxAnchorMarkers }) {
1296
1659
  }],
1297
1660
  ...formatting && Object.keys(formatting).length > 0 ? { formatting } : {}
1298
1661
  };
1299
- const extractedContent = extractParagraphContent(node, void 0, void 0, textBoxAnchorMarkers).filter((content) => content.type === "run" || content.type === "hyperlink");
1662
+ if (marks && node.type.name === "field") restoreRunPropertyChanges(displayRun, marks);
1300
1663
  const fieldContent = extractedContent.length > 0 ? synchronizeFieldDisplayText(extractedContent, displayText, displayRun) : [];
1301
1664
  if (attrs.fieldKind === "complex") {
1302
1665
  const complex = {
@@ -1369,11 +1732,11 @@ function createMathFromNode(node) {
1369
1732
  /**
1370
1733
  * Create an InlineSdt from a PM sdt node
1371
1734
  */
1372
- function createInlineSdtFromNode(node, textBoxAnchorMarkers, inheritedFormatting) {
1735
+ function createInlineSdtFromNode(node, textBoxAnchorMarkers, formattingContext) {
1373
1736
  return {
1374
1737
  type: "inlineSdt",
1375
1738
  properties: sdtPropertiesFromAttrs(expectSdtAttrs(node)),
1376
- content: extractParagraphContent(node, void 0, void 0, textBoxAnchorMarkers, false, inheritedFormatting).filter((c) => c.type === "run" || c.type === "hyperlink" || c.type === "simpleField" || c.type === "complexField" || c.type === "inlineSdt" || c.type === "insertion" || c.type === "deletion" || c.type === "moveFrom" || c.type === "moveTo" || c.type === "mathEquation")
1739
+ content: extractParagraphContent(node, void 0, void 0, textBoxAnchorMarkers, false, formattingContext).filter((c) => c.type === "run" || c.type === "hyperlink" || c.type === "simpleField" || c.type === "complexField" || c.type === "inlineSdt" || c.type === "insertion" || c.type === "deletion" || c.type === "moveFrom" || c.type === "moveTo" || c.type === "mathEquation")
1377
1740
  };
1378
1741
  }
1379
1742
  /**
@@ -1521,20 +1884,380 @@ function createShapeRun(node) {
1521
1884
  }]
1522
1885
  };
1523
1886
  }
1887
+ const RUN_FORMATTING_VISUAL_GROUPS = {
1888
+ bold: "bold",
1889
+ boldCs: null,
1890
+ italic: "italic",
1891
+ italicCs: null,
1892
+ underline: "underline",
1893
+ strike: "strike",
1894
+ doubleStrike: "strike",
1895
+ vertAlign: "vertAlign",
1896
+ smallCaps: "smallCaps",
1897
+ allCaps: "allCaps",
1898
+ hidden: "hidden",
1899
+ color: "color",
1900
+ highlight: "highlight",
1901
+ shading: "shading",
1902
+ fontSize: "fontSize",
1903
+ fontSizeCs: null,
1904
+ fontFamily: "fontFamily",
1905
+ language: "language",
1906
+ spacing: "characterSpacing",
1907
+ position: "characterSpacing",
1908
+ scale: "characterSpacing",
1909
+ kerning: "characterSpacing",
1910
+ effect: "effect",
1911
+ emphasisMark: "emphasisMark",
1912
+ emboss: "emboss",
1913
+ imprint: "imprint",
1914
+ outline: "outline",
1915
+ shadow: "shadow",
1916
+ rtl: "rtl",
1917
+ cs: null,
1918
+ styleId: null
1919
+ };
1920
+ const RUN_FORMATTING_FAST_PATH_DISPOSITION = {
1921
+ bold: "visual",
1922
+ boldCs: "structural",
1923
+ italic: "visual",
1924
+ italicCs: "structural",
1925
+ underline: "visual",
1926
+ strike: "visual",
1927
+ doubleStrike: "visual",
1928
+ vertAlign: "visual",
1929
+ smallCaps: "visual",
1930
+ allCaps: "visual",
1931
+ hidden: "visual",
1932
+ color: "visual",
1933
+ highlight: "visual",
1934
+ shading: "visual",
1935
+ fontSize: "visual",
1936
+ fontSizeCs: "structural",
1937
+ fontFamily: "visual",
1938
+ language: "visual",
1939
+ spacing: "visual",
1940
+ position: "visual",
1941
+ scale: "visual",
1942
+ kerning: "visual",
1943
+ effect: "visual",
1944
+ emphasisMark: "visual",
1945
+ emboss: "visual",
1946
+ imprint: "visual",
1947
+ outline: "visual",
1948
+ shadow: "visual",
1949
+ rtl: "visual",
1950
+ cs: "structural",
1951
+ styleId: "character-style"
1952
+ };
1953
+ const hasOnlyCarrierlessVisualFormatting = (formatting) => {
1954
+ for (const property of Object.keys(formatting)) if (RUN_FORMATTING_FAST_PATH_DISPOSITION[property] !== "visual") return false;
1955
+ return true;
1956
+ };
1957
+ const visibleUnderline = (formatting) => {
1958
+ const underline = formatting?.underline;
1959
+ return underline?.style === "none" ? void 0 : underline;
1960
+ };
1961
+ const visibleStrike = (formatting) => {
1962
+ if (formatting?.doubleStrike === true) return "double";
1963
+ return formatting?.strike === true ? "single" : void 0;
1964
+ };
1965
+ const visibleColor = (formatting) => formatting?.color?.auto === true ? void 0 : formatting?.color;
1966
+ const visibleValue = (value) => value === "none" ? void 0 : value;
1967
+ /**
1968
+ * Compare the exact presentation encoded by PM run marks without allocating the
1969
+ * intermediate maps used by reconciliation. Non-visual authored state is
1970
+ * deliberately absent here: the carrierless fast path below excludes every
1971
+ * structural carrier before calling this predicate.
1972
+ */
1973
+ const sameVisualFormatting = (left, right) => {
1974
+ if (left?.bold === true !== (right?.bold === true) || left?.italic === true !== (right?.italic === true) || !sameFormattingValue(visibleUnderline(left), visibleUnderline(right)) || visibleStrike(left) !== visibleStrike(right) || !sameFormattingValue(visibleColor(left), visibleColor(right)) || visibleValue(left?.highlight) !== visibleValue(right?.highlight) || (left?.fontSize || void 0) !== (right?.fontSize || void 0) || !sameFormattingValue(left?.fontFamily, right?.fontFamily) || !sameFormattingValue(left?.language, right?.language) || (left?.vertAlign === "superscript" || left?.vertAlign === "subscript" ? left.vertAlign : void 0) !== (right?.vertAlign === "superscript" || right?.vertAlign === "subscript" ? right.vertAlign : void 0) || left?.allCaps === true !== (right?.allCaps === true) || left?.smallCaps === true !== (right?.smallCaps === true) || left?.hidden === true !== (right?.hidden === true) || left?.emboss === true !== (right?.emboss === true) || left?.imprint === true !== (right?.imprint === true) || left?.shadow === true !== (right?.shadow === true) || left?.outline === true !== (right?.outline === true) || left?.rtl === true !== (right?.rtl === true) || (typeof left?.spacing === "number" ? left.spacing : null) !== (typeof right?.spacing === "number" ? right.spacing : null) || (typeof left?.position === "number" ? left.position : null) !== (typeof right?.position === "number" ? right.position : null) || (normalizeHorizontalScalePercent(left?.scale) ?? null) !== (normalizeHorizontalScalePercent(right?.scale) ?? null) || (typeof left?.kerning === "number" ? left.kerning : null) !== (typeof right?.kerning === "number" ? right.kerning : null) || visibleValue(left?.effect) !== visibleValue(right?.effect) || visibleValue(left?.emphasisMark) !== visibleValue(right?.emphasisMark)) return false;
1975
+ return sameFormattingValue(shadingToRunShadingAttrs(left?.shading), shadingToRunShadingAttrs(right?.shading));
1976
+ };
1977
+ const visualFormattingGroups = (formatting) => {
1978
+ const groups = /* @__PURE__ */ new Map();
1979
+ if (!formatting) return groups;
1980
+ if (formatting.bold) groups.set("bold", true);
1981
+ if (formatting.italic) groups.set("italic", true);
1982
+ if (formatting.underline && formatting.underline.style !== "none") groups.set("underline", {
1983
+ style: formatting.underline.style || "single",
1984
+ ...formatting.underline.color ? { color: formatting.underline.color } : {}
1985
+ });
1986
+ if (formatting.strike || formatting.doubleStrike) groups.set("strike", formatting.doubleStrike ? "double" : "single");
1987
+ if (formatting.color && !formatting.color.auto) {
1988
+ const { rgb, themeColor, themeTint, themeShade } = formatting.color;
1989
+ groups.set("color", {
1990
+ ...rgb ? { rgb } : {},
1991
+ ...themeColor ? { themeColor } : {},
1992
+ ...themeTint ? { themeTint } : {},
1993
+ ...themeShade ? { themeShade } : {}
1994
+ });
1995
+ }
1996
+ if (formatting.highlight && formatting.highlight !== "none") groups.set("highlight", formatting.highlight);
1997
+ const shadingAttrs = shadingToRunShadingAttrs(formatting.shading);
1998
+ if (shadingAttrs) groups.set("shading", runShadingAttrsToShading(shadingAttrs));
1999
+ if (formatting.fontSize) groups.set("fontSize", formatting.fontSize);
2000
+ if (formatting.fontFamily) {
2001
+ const { ascii, hAnsi, eastAsia, cs, hint, asciiTheme, hAnsiTheme, eastAsiaTheme, csTheme } = formatting.fontFamily;
2002
+ groups.set("fontFamily", {
2003
+ ...ascii ? { ascii } : {},
2004
+ ...hAnsi ? { hAnsi } : {},
2005
+ ...eastAsia ? { eastAsia } : {},
2006
+ ...cs ? { cs } : {},
2007
+ ...hint ? { hint } : {},
2008
+ ...asciiTheme ? { asciiTheme } : {},
2009
+ ...hAnsiTheme ? { hAnsiTheme } : {},
2010
+ ...eastAsiaTheme ? { eastAsiaTheme } : {},
2011
+ ...csTheme ? { csTheme } : {}
2012
+ });
2013
+ }
2014
+ if (formatting.language) {
2015
+ const { val, eastAsia, bidi } = formatting.language;
2016
+ groups.set("language", {
2017
+ ...val ? { val } : {},
2018
+ ...eastAsia ? { eastAsia } : {},
2019
+ ...bidi ? { bidi } : {}
2020
+ });
2021
+ }
2022
+ if (formatting.vertAlign === "superscript" || formatting.vertAlign === "subscript") groups.set("vertAlign", formatting.vertAlign);
2023
+ for (const [property, group] of [
2024
+ ["allCaps", "allCaps"],
2025
+ ["smallCaps", "smallCaps"],
2026
+ ["hidden", "hidden"],
2027
+ ["emboss", "emboss"],
2028
+ ["imprint", "imprint"],
2029
+ ["shadow", "shadow"],
2030
+ ["outline", "outline"],
2031
+ ["rtl", "rtl"]
2032
+ ]) if (formatting[property]) groups.set(group, true);
2033
+ const spacing = typeof formatting.spacing === "number" ? formatting.spacing : null;
2034
+ const position = typeof formatting.position === "number" ? formatting.position : null;
2035
+ const scale = normalizeHorizontalScalePercent(formatting.scale) ?? null;
2036
+ const kerning = typeof formatting.kerning === "number" ? formatting.kerning : null;
2037
+ if (spacing !== null || position !== null || scale !== null || kerning !== null) groups.set("characterSpacing", {
2038
+ spacing,
2039
+ position,
2040
+ scale,
2041
+ kerning
2042
+ });
2043
+ if (formatting.effect && formatting.effect !== "none") groups.set("effect", formatting.effect);
2044
+ if (formatting.emphasisMark && formatting.emphasisMark !== "none") groups.set("emphasisMark", formatting.emphasisMark);
2045
+ return groups;
2046
+ };
2047
+ const expectedRunFormattingOverrideAttrs = (authoredFormatting) => {
2048
+ const attrs = buildRunFormattingOverrideAttrs(authoredFormatting, {
2049
+ type: "authored-baseline",
2050
+ formatting: authoredFormatting
2051
+ });
2052
+ const hasDirectFormatting = Object.keys(authoredFormatting).some((property) => property !== "styleId");
2053
+ if (!attrs && !hasDirectFormatting) return;
2054
+ const expected = { ...attrs };
2055
+ const directFontProperties = [
2056
+ "color",
2057
+ "fontFamily",
2058
+ "fontSize"
2059
+ ].filter((property) => authoredFormatting[property] !== void 0);
2060
+ if (directFontProperties.length > 0) expected.directFontProperties = directFontProperties;
2061
+ const complexScriptPropertyAbsences = [
2062
+ ["bold", "boldCs"],
2063
+ ["italic", "italicCs"],
2064
+ ["fontSize", "fontSizeCs"]
2065
+ ].filter(([ordinary, complex]) => authoredFormatting[ordinary] !== void 0 && authoredFormatting[complex] === void 0).map(([, complex]) => complex);
2066
+ if (complexScriptPropertyAbsences.length > 0) expected.complexScriptPropertyAbsences = complexScriptPropertyAbsences;
2067
+ return Object.keys(expected).length > 0 ? expected : void 0;
2068
+ };
2069
+ const changedVisualFormattingGroups = (observedFormatting, expectedFormatting) => {
2070
+ const actual = visualFormattingGroups(observedFormatting);
2071
+ const expected = visualFormattingGroups(expectedFormatting);
2072
+ const changed = /* @__PURE__ */ new Set();
2073
+ for (const group of /* @__PURE__ */ new Set([...actual.keys(), ...expected.keys()])) {
2074
+ const actualValue = actual.get(group);
2075
+ const expectedValue = expected.get(group);
2076
+ if (!sameFormattingValue(actualValue, expectedValue)) changed.add(group);
2077
+ }
2078
+ return changed;
2079
+ };
2080
+ const VISUAL_BOOLEAN_FORMATTING_PROPERTIES = /* @__PURE__ */ new Set([
2081
+ "allCaps",
2082
+ "bold",
2083
+ "doubleStrike",
2084
+ "emboss",
2085
+ "hidden",
2086
+ "imprint",
2087
+ "italic",
2088
+ "outline",
2089
+ "rtl",
2090
+ "shadow",
2091
+ "smallCaps",
2092
+ "strike"
2093
+ ]);
2094
+ const fontFamilyDifference = (actual, inherited) => {
2095
+ const difference = {};
2096
+ for (const property of [
2097
+ "ascii",
2098
+ "hAnsi",
2099
+ "eastAsia",
2100
+ "cs",
2101
+ "hint",
2102
+ "asciiTheme",
2103
+ "hAnsiTheme",
2104
+ "eastAsiaTheme",
2105
+ "csTheme"
2106
+ ]) {
2107
+ const value = actual[property];
2108
+ if (value !== void 0 && value !== inherited?.[property]) Reflect.set(difference, property, value);
2109
+ }
2110
+ return Object.keys(difference).length > 0 ? difference : void 0;
2111
+ };
2112
+ const DIRECT_OVERRIDE_FORMATTING_PROPERTIES = [
2113
+ "allCaps",
2114
+ "bold",
2115
+ "boldCs",
2116
+ "cs",
2117
+ "doubleStrike",
2118
+ "emboss",
2119
+ "fontSizeCs",
2120
+ "hidden",
2121
+ "imprint",
2122
+ "italic",
2123
+ "italicCs",
2124
+ "outline",
2125
+ "rtl",
2126
+ "shadow",
2127
+ "smallCaps",
2128
+ "strike",
2129
+ "underline"
2130
+ ];
2131
+ const POSITIVE_OVERRIDE_PROPERTIES_REPRESENTED_BY_VISUAL_MARKS = /* @__PURE__ */ new Set([
2132
+ "allCaps",
2133
+ "emboss",
2134
+ "hidden",
2135
+ "imprint",
2136
+ "outline",
2137
+ "rtl",
2138
+ "shadow",
2139
+ "smallCaps",
2140
+ "strike"
2141
+ ]);
2142
+ const setFormattingFromOverrideSignal = (formatting, property, value) => {
2143
+ Reflect.deleteProperty(formatting, property);
2144
+ if (value === void 0) return;
2145
+ if (property === "underline") {
2146
+ formatting.underline = { style: "none" };
2147
+ return;
2148
+ }
2149
+ Reflect.set(formatting, property, value);
2150
+ };
2151
+ const sameFormattingValue = (left, right) => {
2152
+ if (left === right) return true;
2153
+ if (typeof left !== "object" || left === null || typeof right !== "object" || right === null) return false;
2154
+ if (Array.isArray(left) || Array.isArray(right)) {
2155
+ if (!Array.isArray(left) || !Array.isArray(right) || left.length !== right.length) return false;
2156
+ return left.every((value, index) => sameFormattingValue(value, right[index]));
2157
+ }
2158
+ const leftKeys = Object.keys(left);
2159
+ const rightKeys = Object.keys(right);
2160
+ if (leftKeys.length !== rightKeys.length) return false;
2161
+ return leftKeys.every((key) => Object.prototype.hasOwnProperty.call(right, key) && sameFormattingValue(Reflect.get(left, key), Reflect.get(right, key)));
2162
+ };
2163
+ const reconcileOverrideSignals = (formatting, current, expected, inheritedFormatting, observedFormatting) => {
2164
+ for (const property of DIRECT_OVERRIDE_FORMATTING_PROPERTIES) {
2165
+ if (sameFormattingValue(current?.[property], expected?.[property])) continue;
2166
+ if (current?.[property] === void 0 && expected?.[property] === true && POSITIVE_OVERRIDE_PROPERTIES_REPRESENTED_BY_VISUAL_MARKS.has(property)) continue;
2167
+ if (current && hasAuthoredRunFormattingProvenance(current) && expected?.[property] === void 0 && sameFormattingValue(current[property], inheritedFormatting?.[property])) continue;
2168
+ setFormattingFromOverrideSignal(formatting, property, current?.[property]);
2169
+ }
2170
+ for (const property of [
2171
+ "color",
2172
+ "fontFamily",
2173
+ "fontSize"
2174
+ ]) {
2175
+ const currentIsDirect = current?.directFontProperties?.includes(property) === true;
2176
+ if (currentIsDirect === (expected?.directFontProperties?.includes(property) === true)) continue;
2177
+ if (!currentIsDirect) {
2178
+ Reflect.deleteProperty(formatting, property);
2179
+ continue;
2180
+ }
2181
+ const observed = observedFormatting[property];
2182
+ if (observed !== void 0) Reflect.set(formatting, property, observed);
2183
+ }
2184
+ for (const property of [
2185
+ "boldCs",
2186
+ "italicCs",
2187
+ "fontSizeCs"
2188
+ ]) {
2189
+ const currentIsAbsent = current?.complexScriptPropertyAbsences?.includes(property) === true;
2190
+ if (currentIsAbsent !== (expected?.complexScriptPropertyAbsences?.includes(property) === true) && currentIsAbsent) Reflect.deleteProperty(formatting, property);
2191
+ }
2192
+ };
2193
+ /**
2194
+ * Reconcile source-authored provenance with the current visual mark set at the
2195
+ * one save boundary shared by editor commands, raw transactions and compare.
2196
+ * Unchanged groups keep exact source state (including equal direct values and
2197
+ * otherwise invisible sentinels); changed groups derive the smallest direct
2198
+ * override needed relative to the current style cascade.
2199
+ */
2200
+ const reconcileAuthoredFormatting = ({ authoredFormatting, carrierlessContext, currentOverrideAttrs, inheritedFormatting, observedFormatting }) => {
2201
+ const hasAuthoredFormatting = Object.keys(authoredFormatting).length > 0;
2202
+ if (carrierlessContext === "ordinary" && currentOverrideAttrs === void 0 && !hasAuthoredFormatting && hasOnlyCarrierlessVisualFormatting(observedFormatting)) {
2203
+ if (sameVisualFormatting(observedFormatting, inheritedFormatting)) return authoredFormatting;
2204
+ if (observedFormatting.fontFamily === void 0 && sameVisualFormatting(inheritedFormatting, void 0)) return observedFormatting;
2205
+ }
2206
+ const expectedFormatting = hasAuthoredFormatting ? mergeTextFormatting(inheritedFormatting, authoredFormatting) : inheritedFormatting;
2207
+ const changedGroups = changedVisualFormattingGroups(observedFormatting, expectedFormatting);
2208
+ const reconciled = { ...authoredFormatting };
2209
+ for (const property of Object.keys(RUN_FORMATTING_VISUAL_GROUPS)) {
2210
+ const group = RUN_FORMATTING_VISUAL_GROUPS[property];
2211
+ if (group === null || !changedGroups.has(group)) continue;
2212
+ Reflect.deleteProperty(reconciled, property);
2213
+ if (VISUAL_BOOLEAN_FORMATTING_PROPERTIES.has(property)) {
2214
+ const observed = observedFormatting[property] === true;
2215
+ if (observed !== (inheritedFormatting?.[property] === true)) Reflect.set(reconciled, property, observed);
2216
+ continue;
2217
+ }
2218
+ const observed = observedFormatting[property];
2219
+ if (observed === void 0) continue;
2220
+ if (property === "fontFamily") {
2221
+ const difference = fontFamilyDifference(observed, inheritedFormatting?.fontFamily);
2222
+ if (difference) reconciled.fontFamily = difference;
2223
+ continue;
2224
+ }
2225
+ if (!sameFormattingValue(observed, inheritedFormatting?.[property])) Reflect.set(reconciled, property, observed);
2226
+ }
2227
+ if (currentOverrideAttrs !== void 0) reconcileOverrideSignals(reconciled, currentOverrideAttrs, expectedRunFormattingOverrideAttrs(authoredFormatting), inheritedFormatting, observedFormatting);
2228
+ return reconciled;
2229
+ };
2230
+ const formattingAuthorshipCost = (formatting) => {
2231
+ let cost = 0;
2232
+ const visit = (value) => {
2233
+ if (value === void 0) return;
2234
+ if (value === null || typeof value !== "object") {
2235
+ cost++;
2236
+ return;
2237
+ }
2238
+ const entries = Object.entries(value);
2239
+ if (entries.length === 0) {
2240
+ cost++;
2241
+ return;
2242
+ }
2243
+ for (const [, nested] of entries) visit(nested);
2244
+ };
2245
+ for (const [property, value] of Object.entries(formatting)) if (property !== "styleId") visit(value);
2246
+ return cost;
2247
+ };
1524
2248
  function marksToTextFormatting(marks, options) {
1525
2249
  const formatting = {};
1526
2250
  let directOverrideFormatting;
1527
2251
  let directFontProperties;
1528
- let characterStyleRPr;
2252
+ let characterStyleId;
1529
2253
  let runFormattingOverrideMark;
2254
+ let currentOverrideAttrs;
1530
2255
  for (const mark of marks) switch (mark.type.name) {
1531
2256
  case "bold":
1532
2257
  formatting.bold = true;
1533
- formatting.boldCs = true;
1534
2258
  break;
1535
2259
  case "italic":
1536
2260
  formatting.italic = true;
1537
- formatting.italicCs = true;
1538
2261
  break;
1539
2262
  case "underline": {
1540
2263
  const attrs = expectUnderlineMarkAttrs(mark);
@@ -1563,12 +2286,9 @@ function marksToTextFormatting(marks, options) {
1563
2286
  case "runShading":
1564
2287
  formatting.shading = runShadingAttrsToShading(expectRunShadingMarkAttrs(mark));
1565
2288
  break;
1566
- case "fontSize": {
1567
- const attrs = expectFontSizeMarkAttrs(mark);
1568
- formatting.fontSize = attrs.size;
1569
- formatting.fontSizeCs = attrs.size;
2289
+ case "fontSize":
2290
+ formatting.fontSize = expectFontSizeMarkAttrs(mark).size;
1570
2291
  break;
1571
- }
1572
2292
  case "fontFamily": {
1573
2293
  const attrs = expectFontFamilyMarkAttrs(mark);
1574
2294
  const ff = {};
@@ -1576,8 +2296,7 @@ function marksToTextFormatting(marks, options) {
1576
2296
  if (attrs.hAnsi) ff.hAnsi = attrs.hAnsi;
1577
2297
  if (attrs.eastAsia) ff.eastAsia = attrs.eastAsia;
1578
2298
  if (attrs.hint) ff.hint = attrs.hint;
1579
- const csVal = attrs.cs || attrs.ascii;
1580
- if (csVal) ff.cs = csVal;
2299
+ if (attrs.cs) ff.cs = attrs.cs;
1581
2300
  if (attrs.asciiTheme) ff.asciiTheme = attrs.asciiTheme;
1582
2301
  if (attrs.hAnsiTheme) ff.hAnsiTheme = attrs.hAnsiTheme;
1583
2302
  if (attrs.eastAsiaTheme) ff.eastAsiaTheme = attrs.eastAsiaTheme;
@@ -1645,100 +2364,77 @@ function marksToTextFormatting(marks, options) {
1645
2364
  case "characterStyle": {
1646
2365
  const attrs = expectCharacterStyleMarkAttrs(mark);
1647
2366
  formatting.styleId = attrs.styleId;
1648
- characterStyleRPr = attrs._styleRPr;
2367
+ characterStyleId = attrs.styleId;
1649
2368
  break;
1650
2369
  }
1651
2370
  default: break;
1652
2371
  }
2372
+ let authoredFormatting = {};
1653
2373
  if (runFormattingOverrideMark) {
1654
2374
  const overrideAttrs = expectRunFormattingOverrideMarkAttrs(runFormattingOverrideMark);
2375
+ currentOverrideAttrs = overrideAttrs;
1655
2376
  directFontProperties = overrideAttrs.directFontProperties;
1656
- applyRunFormattingOverrideAttrs(formatting, overrideAttrs);
1657
2377
  directOverrideFormatting = {};
1658
2378
  applyRunFormattingOverrideAttrs(directOverrideFormatting, overrideAttrs);
1659
2379
  for (const property of directFontProperties ?? []) {
1660
2380
  const value = formatting[property];
1661
2381
  if (value !== void 0) Reflect.set(directOverrideFormatting, property, value);
1662
2382
  }
2383
+ authoredFormatting = authoredRunFormattingFromAttrs(overrideAttrs) ?? directOverrideFormatting;
1663
2384
  }
1664
- if (characterStyleRPr) return subtractCharacterStyleFormatting({
1665
- directOverrideFormatting,
1666
- formatting,
1667
- inheritedFormatting: options?.inheritedFormatting,
1668
- styleRPr: characterStyleRPr
1669
- });
1670
- for (const property of [
1671
- "fontFamily",
1672
- "fontSize",
1673
- "color"
1674
- ]) {
1675
- if (directFontProperties?.includes(property)) continue;
1676
- const value = formatting[property];
1677
- const inheritedValue = options?.inheritedFormatting?.[property];
1678
- const matchesInherited = property === "fontFamily" ? sameFontFamily(formatting.fontFamily, options?.inheritedFormatting?.fontFamily) : JSON.stringify(value) === JSON.stringify(inheritedValue);
1679
- if (inheritedValue !== void 0 && matchesInherited) Reflect.deleteProperty(formatting, property);
1680
- }
1681
- return formatting;
1682
- }
1683
- const sameFontFamily = (left, right) => [
1684
- "ascii",
1685
- "hAnsi",
1686
- "eastAsia",
1687
- "hint",
1688
- "asciiTheme",
1689
- "hAnsiTheme",
1690
- "eastAsiaTheme",
1691
- "csTheme"
1692
- ].every((property) => left?.[property] === right?.[property]) && (left?.cs ?? left?.ascii) === (right?.cs ?? right?.ascii);
1693
- /**
1694
- * Negatable boolean run-property keys whose serializer emits an explicit
1695
- * `w:val="0"` override when the value is `false` (see `serializeTextFormatting`
1696
- * in `runSerializer.ts`). Each entry pairs a base key with the complex-script
1697
- * mirror that `marksToTextFormatting` sets alongside it (the bold/italic marks
1698
- * set `*Cs` too), so a negative override disables both. Keys without a complex
1699
- * mirror use `null`.
1700
- */
1701
- const NEGATABLE_STYLE_KEYS = [
1702
- ["bold", "boldCs"],
1703
- ["italic", "italicCs"],
1704
- ["strike", null],
1705
- ["doubleStrike", null],
1706
- ["allCaps", null],
1707
- ["smallCaps", null],
1708
- ["hidden", null],
1709
- ["emboss", null],
1710
- ["imprint", null],
1711
- ["shadow", null],
1712
- ["outline", null],
1713
- ["rtl", null]
1714
- ];
1715
- function subtractCharacterStyleFormatting({ directOverrideFormatting, formatting, inheritedFormatting, styleRPr }) {
1716
- const result = {};
1717
- const effectiveStyleFormatting = cascadeStyleTextFormatting([{
1718
- formatting: inheritedFormatting,
1719
- type: "direct"
1720
- }, {
1721
- formatting: styleRPr,
1722
- type: "style"
1723
- }]).formatting;
1724
- for (const key of Object.keys(formatting)) {
1725
- const value = formatting[key];
1726
- if (value === void 0) continue;
1727
- if (directOverrideFormatting?.[key] !== void 0) {
1728
- result[key] = value;
1729
- continue;
1730
- }
1731
- const styleValue = key === "styleId" ? void 0 : effectiveStyleFormatting?.[key];
1732
- if ((key === "boldCs" || key === "italicCs") && styleValue === false && value === true) continue;
1733
- if (styleValue !== void 0 && JSON.stringify(value) === JSON.stringify(styleValue)) continue;
1734
- result[key] = value;
2385
+ if (characterStyleId !== void 0 && !options?.styleResolver) {
2386
+ const conservativeFormatting = mergeTextFormatting(formatting, directOverrideFormatting) ?? {};
2387
+ for (const property of currentOverrideAttrs?.complexScriptPropertyAbsences ?? []) Reflect.deleteProperty(conservativeFormatting, property);
2388
+ return {
2389
+ ...conservativeFormatting,
2390
+ styleId: characterStyleId
2391
+ };
1735
2392
  }
1736
- for (const [key, csKey] of NEGATABLE_STYLE_KEYS) {
1737
- if (effectiveStyleFormatting?.[key] !== true || formatting[key] !== void 0) continue;
1738
- result[key] = false;
1739
- if (csKey !== null) result[csKey] = false;
2393
+ const inheritedFormatting = resolveEffectiveRunStyleFormatting({
2394
+ marks,
2395
+ paragraphFormatting: paragraphFormattingForRun({
2396
+ context: {
2397
+ baseParagraphFormatting: options?.baseParagraphFormatting,
2398
+ paragraphFormatting: options?.inheritedFormatting,
2399
+ paragraphMarkFormatting: options?.paragraphMarkFormatting,
2400
+ paragraphMarkPrecedesStyle: options?.paragraphMarkPrecedesStyle ?? false
2401
+ },
2402
+ directFormatting: authoredFormatting,
2403
+ marks
2404
+ }),
2405
+ ...options?.styleResolver !== void 0 ? { styleResolver: options.styleResolver } : {}
2406
+ });
2407
+ let reconciled = reconcileAuthoredFormatting({
2408
+ authoredFormatting,
2409
+ carrierlessContext: options?.paragraphMarkFormatting === void 0 ? "ordinary" : "paragraph-mark",
2410
+ currentOverrideAttrs,
2411
+ inheritedFormatting,
2412
+ observedFormatting: formatting
2413
+ });
2414
+ if (runFormattingOverrideMark === void 0 && characterStyleId === void 0 && options?.paragraphMarkFormatting !== void 0) {
2415
+ const suppressedInheritedFormatting = resolveEffectiveRunStyleFormatting({
2416
+ marks,
2417
+ paragraphFormatting: suppressParagraphMarkFormatting({
2418
+ baseFormatting: options.baseParagraphFormatting,
2419
+ directFormatting: authoredFormatting,
2420
+ paragraphMarkFormatting: options.paragraphMarkFormatting,
2421
+ paragraphMarkPrecedesStyle: options.paragraphMarkPrecedesStyle ?? false
2422
+ }),
2423
+ ...options.styleResolver !== void 0 ? { styleResolver: options.styleResolver } : {}
2424
+ });
2425
+ const suppressed = reconcileAuthoredFormatting({
2426
+ authoredFormatting,
2427
+ carrierlessContext: "paragraph-mark",
2428
+ currentOverrideAttrs,
2429
+ inheritedFormatting: suppressedInheritedFormatting,
2430
+ observedFormatting: formatting
2431
+ });
2432
+ if (formattingAuthorshipCost(suppressed) < formattingAuthorshipCost(reconciled)) reconciled = suppressed;
1740
2433
  }
1741
- return result;
2434
+ return {
2435
+ ...reconciled,
2436
+ ...characterStyleId !== void 0 ? { styleId: characterStyleId } : {}
2437
+ };
1742
2438
  }
1743
2439
  /**
1744
2440
  * Convert a ProseMirror table node to our Table type
@@ -1760,9 +2456,9 @@ function inferTableBorders(rows) {
1760
2456
  }
1761
2457
  }
1762
2458
  }
1763
- function convertPMTable(node, documentCounts) {
2459
+ function convertPMTable(node, documentCounts, styleResolver = null) {
1764
2460
  const attrs = expectTableAttrs(node);
1765
- const rows = convertPMTableRows(node, documentCounts);
2461
+ const rows = convertPMTableRows(node, documentCounts, styleResolver);
1766
2462
  const formatting = tableAttrsToFormatting(attrs) || void 0;
1767
2463
  if (!formatting?.borders) {
1768
2464
  const inferredBorders = inferTableBorders(rows);
@@ -1795,11 +2491,11 @@ function convertPMTable(node, documentCounts) {
1795
2491
  function restoreTablePropertyChanges(table, attrs) {
1796
2492
  if (Array.isArray(attrs.tblPrChange) && attrs.tblPrChange.length > 0) table.propertyChanges = [...attrs.tblPrChange];
1797
2493
  }
1798
- function convertPMTableRows(node, documentCounts) {
2494
+ function convertPMTableRows(node, documentCounts, styleResolver = null) {
1799
2495
  const rows = [];
1800
2496
  const activeVerticalMerges = /* @__PURE__ */ new Map();
1801
2497
  node.forEach((rowNode) => {
1802
- if (rowNode.type.name === "tableRow") rows.push(convertPMTableRow(rowNode, documentCounts, activeVerticalMerges));
2498
+ if (rowNode.type.name === "tableRow") rows.push(convertPMTableRow(rowNode, documentCounts, activeVerticalMerges, styleResolver));
1803
2499
  });
1804
2500
  return rows;
1805
2501
  }
@@ -1838,7 +2534,7 @@ function buildCellMarginsFromAttrs(m) {
1838
2534
  * inherited value becomes a direct override that outranks the style it came
1839
2535
  * from on reload. The resolved companion is what tells the two apart.
1840
2536
  */
1841
- const sameResolvedValue = (live, resolved) => resolved !== void 0 && resolved !== null && canonicalJson(live) === canonicalJson(resolved);
2537
+ const sameResolvedValue = (live, resolved) => resolved !== void 0 && resolved !== null && sameFormattingValue(live, resolved);
1842
2538
  function tableAttrsToFormatting(attrs) {
1843
2539
  if (attrs._originalFormatting) {
1844
2540
  const orig = attrs._originalFormatting;
@@ -1887,7 +2583,7 @@ function tableAttrsToFormatting(attrs) {
1887
2583
  /**
1888
2584
  * Convert a ProseMirror table row node to our TableRow type
1889
2585
  */
1890
- function convertPMTableRow(node, documentCounts, activeVerticalMerges) {
2586
+ function convertPMTableRow(node, documentCounts, activeVerticalMerges, styleResolver = null) {
1891
2587
  const attrs = expectTableRowAttrs(node);
1892
2588
  const cells = [];
1893
2589
  let gridColumn = 0;
@@ -1908,7 +2604,7 @@ function convertPMTableRow(node, documentCounts, activeVerticalMerges) {
1908
2604
  if (cellNode.type.name === "tableCell" || cellNode.type.name === "tableHeader") {
1909
2605
  const cellAttrs = expectTableCellAttrs(cellNode);
1910
2606
  const colspan = Math.max(cellAttrs.colspan, 1);
1911
- cells.push(convertPMTableCell(cellNode, documentCounts));
2607
+ cells.push(convertPMTableCell(cellNode, documentCounts, styleResolver));
1912
2608
  if (cellAttrs.rowspan > 1) {
1913
2609
  const continuationCells = cellAttrs._docxVMergeContinuationCells;
1914
2610
  activeVerticalMerges?.set(gridColumn, {
@@ -1934,6 +2630,10 @@ function convertPMTableRow(node, documentCounts, activeVerticalMerges) {
1934
2630
  id: attrs.trIns.revisionId,
1935
2631
  author: attrs.trIns.author,
1936
2632
  ...attrs.trIns.date != null && { date: attrs.trIns.date },
2633
+ ...attrs.trIns.utcDate != null && { utcDate: {
2634
+ attribute: "w16du:dateUtc",
2635
+ value: attrs.trIns.utcDate
2636
+ } },
1937
2637
  ...attrs.trIns.initials != null && { initials: attrs.trIns.initials }
1938
2638
  }
1939
2639
  };
@@ -1943,6 +2643,10 @@ function convertPMTableRow(node, documentCounts, activeVerticalMerges) {
1943
2643
  id: attrs.trDel.revisionId,
1944
2644
  author: attrs.trDel.author,
1945
2645
  ...attrs.trDel.date != null && { date: attrs.trDel.date },
2646
+ ...attrs.trDel.utcDate != null && { utcDate: {
2647
+ attribute: "w16du:dateUtc",
2648
+ value: attrs.trDel.utcDate
2649
+ } },
1946
2650
  ...attrs.trDel.initials != null && { initials: attrs.trDel.initials }
1947
2651
  }
1948
2652
  };
@@ -1994,22 +2698,23 @@ function tableRowAttrsToFormatting(attrs) {
1994
2698
  /**
1995
2699
  * Convert a ProseMirror table cell node to our TableCell type
1996
2700
  */
1997
- function convertPMTableCell(node, documentCounts) {
2701
+ function convertPMTableCell(node, documentCounts, styleResolver = null) {
1998
2702
  const attrs = expectTableCellAttrs(node);
1999
2703
  const content = [];
2000
2704
  const textBoxAnchorMarkers = /* @__PURE__ */ new Map();
2001
2705
  let previousStandaloneTextBox = null;
2002
2706
  node.forEach((contentNode) => {
2003
2707
  if (contentNode.type.name === "paragraph") {
2004
- content.push(convertPMParagraph(contentNode, documentCounts, textBoxAnchorMarkers));
2708
+ content.push(convertPMParagraph(contentNode, documentCounts, textBoxAnchorMarkers, styleResolver));
2005
2709
  previousStandaloneTextBox = null;
2006
2710
  } else if (contentNode.type.name === "table") {
2007
- content.push(convertPMTable(contentNode, documentCounts));
2711
+ content.push(convertPMTable(contentNode, documentCounts, styleResolver));
2008
2712
  previousStandaloneTextBox = null;
2009
2713
  } else if (contentNode.type.name === "textBox") previousStandaloneTextBox = appendTextBoxBlock(content, contentNode, {
2010
2714
  pendingPageBreaks: 0,
2011
2715
  previousStandaloneTextBox,
2012
- textBoxAnchorMarkers
2716
+ textBoxAnchorMarkers,
2717
+ styleResolver
2013
2718
  });
2014
2719
  });
2015
2720
  removeUnresolvedTextBoxAnchors(content, textBoxAnchorMarkers);
@@ -2025,6 +2730,10 @@ function convertPMTableCell(node, documentCounts) {
2025
2730
  id: attrs.cellMarker.info.revisionId,
2026
2731
  author: attrs.cellMarker.info.author,
2027
2732
  ...attrs.cellMarker.info.date != null && { date: attrs.cellMarker.info.date },
2733
+ ...attrs.cellMarker.info.utcDate != null && { utcDate: {
2734
+ attribute: "w16du:dateUtc",
2735
+ value: attrs.cellMarker.info.utcDate
2736
+ } },
2028
2737
  ...attrs.cellMarker.info.initials != null && { initials: attrs.cellMarker.info.initials }
2029
2738
  };
2030
2739
  if (attrs.cellMarker.kind === "merge") cell.structuralChange = {
@@ -2086,13 +2795,13 @@ function tableCellAttrsToFormatting(attrs) {
2086
2795
  * Convert a ProseMirror textBox node back to a Paragraph wrapping a ShapeContent run.
2087
2796
  * The text box content becomes a Shape with textBody.
2088
2797
  */
2089
- function convertPMTextBox(node) {
2798
+ function convertPMTextBox(node, styleResolver = null) {
2090
2799
  const attrs = expectTextBoxAttrs(node);
2091
2800
  const verticalAlign = normalizeShapeTextAnchor(attrs.verticalAlign);
2092
2801
  const childBlocks = [];
2093
2802
  node.forEach((child) => {
2094
- if (child.type.name === "paragraph") childBlocks.push(convertPMParagraph(child));
2095
- else if (child.type.name === "table") childBlocks.push(convertPMTable(child));
2803
+ if (child.type.name === "paragraph") childBlocks.push(convertPMParagraph(child, void 0, void 0, styleResolver));
2804
+ else if (child.type.name === "table") childBlocks.push(convertPMTable(child, void 0, styleResolver));
2096
2805
  });
2097
2806
  const shape = {
2098
2807
  type: "shape",
@@ -2188,8 +2897,11 @@ function updateDocumentContent(originalDocument, pmDoc) {
2188
2897
  * Used for converting edited header/footer PM content back to the document
2189
2898
  * model.
2190
2899
  */
2191
- function proseDocToBlocks(pmDoc) {
2192
- return extractBlocks(pmDoc);
2900
+ function proseDocToBlocks(pmDoc, baseContent, styles) {
2901
+ const blocks = extractBlocks(pmDoc, "resolve", styles ? createStyleEngine(styles) : null);
2902
+ const linkedSources = restoreLinkedParagraphPropertySources(blocks);
2903
+ if (baseContent) restoreParagraphPropertySources(blocks, baseContent, linkedSources.targets, linkedSources.sources);
2904
+ return blocks;
2193
2905
  }
2194
2906
  //#endregion
2195
2907
  export { fromProseDoc, marksToTextFormatting, proseDocToBlocks, standaloneTableCellFromProseMirror, tableAttrsToFormatting, tableCellAttrsToFormatting, tableRowAttrsToFormatting, updateDocumentContent };