@stll/folio-core 0.42.0 → 0.44.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 (206) hide show
  1. package/dist/ai-edits/headless.js +6 -5
  2. package/dist/ai-edits/index.d.ts +2 -2
  3. package/dist/ai-edits/index.js +2 -2
  4. package/dist/ai-edits/snapshot.js +13 -9
  5. package/dist/compare/content-alignment.js +16 -1
  6. package/dist/compare/inline-atoms.js +1 -1
  7. package/dist/compare/style-resources.js +6 -0
  8. package/dist/compat/eigenpal.d.ts +2 -2
  9. package/dist/controller/layoutPipeline.d.ts +2 -1
  10. package/dist/controller/layoutPipeline.js +5 -2
  11. package/dist/controller/layoutSession.d.ts +2 -1
  12. package/dist/controller/layoutSession.js +1 -0
  13. package/dist/docx/appVersionNormalization.d.ts +0 -18
  14. package/dist/docx/blockContentParser.js +10 -1
  15. package/dist/docx/blockRangeMarkers.d.ts +36 -0
  16. package/dist/docx/blockRangeMarkers.js +59 -0
  17. package/dist/docx/bookmarkParser.d.ts +2 -20
  18. package/dist/docx/bookmarkParser.js +6 -30
  19. package/dist/docx/borderParser.d.ts +13 -0
  20. package/dist/docx/borderParser.js +71 -0
  21. package/dist/docx/builtInStyles.d.ts +165 -0
  22. package/dist/docx/builtInStyles.js +239 -0
  23. package/dist/docx/commentIdNormalization.d.ts +10 -0
  24. package/dist/docx/commentIdNormalization.js +33 -0
  25. package/dist/docx/commentParser.d.ts +2 -1
  26. package/dist/docx/commentParser.js +34 -7
  27. package/dist/docx/commentReferenceNormalization.d.ts +4 -1
  28. package/dist/docx/commentReferenceNormalization.js +23 -14
  29. package/dist/docx/danglingRelationshipReferences.d.ts +15 -0
  30. package/dist/docx/danglingRelationshipReferences.js +30 -0
  31. package/dist/docx/defaultParagraphStyle.d.ts +39 -0
  32. package/dist/docx/defaultParagraphStyle.js +54 -0
  33. package/dist/docx/documentParser.d.ts +2 -1
  34. package/dist/docx/documentParser.js +2 -2
  35. package/dist/docx/drawingUtils.d.ts +8 -1
  36. package/dist/docx/drawingUtils.js +12 -3
  37. package/dist/docx/fieldParser.js +3 -5
  38. package/dist/docx/footnoteParser.d.ts +3 -2
  39. package/dist/docx/footnoteParser.js +19 -2
  40. package/dist/docx/groupDrawingParser.js +1 -1
  41. package/dist/docx/headerFooterRefParser.d.ts +15 -3
  42. package/dist/docx/headerFooterRefParser.js +51 -14
  43. package/dist/docx/headerFooterReferenceNormalization.d.ts +4 -1
  44. package/dist/docx/headerFooterReferenceNormalization.js +5 -1
  45. package/dist/docx/hyperlinkParser.js +11 -15
  46. package/dist/docx/imageParser.d.ts +1 -1
  47. package/dist/docx/imageParser.js +22 -18
  48. package/dist/docx/imageRawXml.js +5 -5
  49. package/dist/docx/markupRangeMarker.d.ts +15 -0
  50. package/dist/docx/markupRangeMarker.js +44 -0
  51. package/dist/docx/noteReferenceStyles.d.ts +29 -0
  52. package/dist/docx/noteReferenceStyles.js +70 -0
  53. package/dist/docx/numberingParser.js +2 -1
  54. package/dist/docx/numberingReference.d.ts +21 -0
  55. package/dist/docx/numberingReference.js +21 -0
  56. package/dist/docx/numberingReferenceNormalization.d.ts +14 -2
  57. package/dist/docx/numberingReferenceNormalization.js +51 -9
  58. package/dist/docx/paraIdRangeNormalization.d.ts +0 -19
  59. package/dist/docx/paragraphParser.js +69 -101
  60. package/dist/docx/paragraphPropertySource.js +1 -0
  61. package/dist/docx/paragraphTraversal.d.ts +37 -1
  62. package/dist/docx/paragraphTraversal.js +84 -1
  63. package/dist/docx/parseContext.d.ts +37 -0
  64. package/dist/docx/parseContext.js +67 -0
  65. package/dist/docx/parseWarningMessage.d.ts +6 -0
  66. package/dist/docx/parseWarningMessage.js +44 -0
  67. package/dist/docx/parser.js +86 -24
  68. package/dist/docx/relsParser.d.ts +28 -11
  69. package/dist/docx/relsParser.js +26 -13
  70. package/dist/docx/revisionIdNormalization.js +81 -7
  71. package/dist/docx/rezip.js +85 -27
  72. package/dist/docx/runConsolidator.js +1 -2
  73. package/dist/docx/runParser.d.ts +8 -1
  74. package/dist/docx/runParser.js +30 -48
  75. package/dist/docx/sectionParser.d.ts +2 -1
  76. package/dist/docx/sectionParser.js +21 -65
  77. package/dist/docx/serializer/borderSerializer.d.ts +1 -2
  78. package/dist/docx/serializer/commentSerializer.js +22 -9
  79. package/dist/docx/serializer/documentSerializer.d.ts +1 -5
  80. package/dist/docx/serializer/documentSerializer.js +6 -16
  81. package/dist/docx/serializer/headerFooterSerializer.js +5 -0
  82. package/dist/docx/serializer/markupRangeAttributes.d.ts +8 -0
  83. package/dist/docx/serializer/markupRangeAttributes.js +24 -0
  84. package/dist/docx/serializer/noteSerializer.js +5 -0
  85. package/dist/docx/serializer/paragraphSerializer.d.ts +1 -5
  86. package/dist/docx/serializer/paragraphSerializer.js +29 -35
  87. package/dist/docx/serializer/runSerializer.js +13 -7
  88. package/dist/docx/serializer/tableSerializer.js +28 -13
  89. package/dist/docx/serializer/textFormattingSerializer.d.ts +2 -3
  90. package/dist/docx/server/build.js +8 -1
  91. package/dist/docx/server/createBilingualDocument.js +15 -22
  92. package/dist/docx/server/extractDocxText.js +3 -4
  93. package/dist/docx/shadingParser.d.ts +6 -0
  94. package/dist/docx/shadingParser.js +32 -0
  95. package/dist/docx/shapeParser.js +3 -3
  96. package/dist/docx/styleParser.js +15 -89
  97. package/dist/docx/styleReferenceResolution.d.ts +36 -0
  98. package/dist/docx/styleReferenceResolution.js +51 -0
  99. package/dist/docx/tableLook.d.ts +57 -0
  100. package/dist/docx/tableLook.js +63 -0
  101. package/dist/docx/tableParser.d.ts +7 -9
  102. package/dist/docx/tableParser.js +64 -110
  103. package/dist/docx/textBoxParser.js +4 -4
  104. package/dist/docx/trackedMoveRangeNormalization.d.ts +3 -1
  105. package/dist/docx/trackedMoveRangeNormalization.js +11 -21
  106. package/dist/docx/transitionalSpelling.d.ts +13 -2
  107. package/dist/docx/transitionalSpelling.js +23 -1
  108. package/dist/docx/verbatimCapture.js +4 -11
  109. package/dist/docx/vmlImageParser.js +2 -2
  110. package/dist/docx/watermarkParser.js +2 -2
  111. package/dist/docx/xmlParser.d.ts +22 -32
  112. package/dist/docx/xmlParser.js +36 -21
  113. package/dist/index.d.ts +2 -2
  114. package/dist/internal/pageBreakRunSourceDescendantIndex.d.ts +2 -0
  115. package/dist/internal/pageBreakRunSourceDescendantIndex.js +9 -6
  116. package/dist/internal/paragraphFormattingSerialization.d.ts +2 -3
  117. package/dist/internal/paragraphFormattingSerialization.js +26 -6
  118. package/dist/layout-bridge/convert/footnoteLayout.js +2 -7
  119. package/dist/layout-bridge/convert/templatePreviewFlow.d.ts +19 -11
  120. package/dist/layout-bridge/convert/templatePreviewFlow.js +103 -38
  121. package/dist/layout-bridge/convert/toFlowBlocks.js +12 -3
  122. package/dist/layout-engine/index.d.ts +2 -2
  123. package/dist/layout-engine/index.js +2 -2
  124. package/dist/layout-engine/measure/measureBlocks.js +1 -6
  125. package/dist/layout-engine/types.d.ts +8 -2
  126. package/dist/layout-engine/types.js +35 -2
  127. package/dist/markdown/index.js +1 -1
  128. package/dist/markdown/internals.d.ts +6 -1
  129. package/dist/markdown/internals.js +14 -1
  130. package/dist/markdown/renderBlock.js +35 -21
  131. package/dist/markdown/renderParagraph.js +14 -5
  132. package/dist/markdown/renderRuns.js +4 -3
  133. package/dist/markdown/renderTable.js +4 -3
  134. package/dist/markdown/trailers.js +41 -7
  135. package/dist/markdown/types.d.ts +3 -7
  136. package/dist/prosemirror/attrs/index.js +2 -5
  137. package/dist/prosemirror/bookmarkBoundaryAttrs.d.ts +11 -1
  138. package/dist/prosemirror/bookmarkBoundaryAttrs.js +18 -3
  139. package/dist/prosemirror/commands/index.d.ts +3 -3
  140. package/dist/prosemirror/commands/index.js +2 -2
  141. package/dist/prosemirror/commands/pageBreak.js +12 -1
  142. package/dist/prosemirror/commands/paragraph.d.ts +3 -3
  143. package/dist/prosemirror/commands/paragraph.js +2 -2
  144. package/dist/prosemirror/commentIdAllocator.js +2 -7
  145. package/dist/prosemirror/conversion/fromProseDoc.js +131 -41
  146. package/dist/prosemirror/conversion/toProseDoc.d.ts +1 -14
  147. package/dist/prosemirror/conversion/toProseDoc.js +402 -328
  148. package/dist/prosemirror/extensions/core/ParagraphExtension.d.ts +14 -1
  149. package/dist/prosemirror/extensions/core/ParagraphExtension.js +11 -6
  150. package/dist/prosemirror/extensions/features/EmptyParagraphFormatExtension.js +3 -3
  151. package/dist/prosemirror/extensions/features/ListExtension.js +42 -4
  152. package/dist/prosemirror/extensions/features/PasteCleanupExtension.d.ts +4 -1
  153. package/dist/prosemirror/extensions/features/PasteCleanupExtension.js +6 -2
  154. package/dist/prosemirror/extensions/features/pastedHeadingStyles.d.ts +7 -0
  155. package/dist/prosemirror/extensions/features/pastedHeadingStyles.js +74 -0
  156. package/dist/prosemirror/extensions/marks/markUtils.d.ts +11 -3
  157. package/dist/prosemirror/extensions/marks/markUtils.js +98 -19
  158. package/dist/prosemirror/extensions/nodes/BookmarkBoundaryExtension.js +7 -3
  159. package/dist/prosemirror/extensions/nodes/ImageExtension.js +2 -1
  160. package/dist/prosemirror/extensions/nodes/ShapeExtension.js +1 -0
  161. package/dist/prosemirror/extensions/nodes/TableExtension.js +15 -1
  162. package/dist/prosemirror/extensions/types.d.ts +2 -2
  163. package/dist/prosemirror/index.d.ts +3 -3
  164. package/dist/prosemirror/index.js +3 -3
  165. package/dist/prosemirror/insertOperations.d.ts +9 -2
  166. package/dist/prosemirror/insertOperations.js +9 -4
  167. package/dist/prosemirror/listMarker.js +2 -1
  168. package/dist/prosemirror/numberedRefFields.js +2 -1
  169. package/dist/prosemirror/pageBreakRunProjection.d.ts +11 -3
  170. package/dist/prosemirror/pageBreakRunProjection.js +16 -8
  171. package/dist/prosemirror/paragraphFormattingProvenance.d.ts +159 -0
  172. package/dist/prosemirror/paragraphFormattingProvenance.js +106 -0
  173. package/dist/prosemirror/plugins/documentStyles.d.ts +9 -1
  174. package/dist/prosemirror/plugins/documentStyles.js +11 -1
  175. package/dist/prosemirror/plugins/index.d.ts +2 -2
  176. package/dist/prosemirror/plugins/index.js +2 -2
  177. package/dist/prosemirror/plugins/revisionIds.d.ts +11 -2
  178. package/dist/prosemirror/plugins/revisionIds.js +21 -6
  179. package/dist/prosemirror/plugins/templatePreviewValues.d.ts +42 -1
  180. package/dist/prosemirror/plugins/templatePreviewValues.js +217 -14
  181. package/dist/prosemirror/runFormattingReconciliation.js +3 -2
  182. package/dist/prosemirror/runStyleFormatting.d.ts +1 -1
  183. package/dist/prosemirror/schema/nodes.d.ts +31 -0
  184. package/dist/prosemirror/styles/resolvedStyleAttrs.js +4 -1
  185. package/dist/prosemirror/styles/styleResolver.d.ts +9 -0
  186. package/dist/prosemirror/styles/styleResolver.js +15 -6
  187. package/dist/prosemirror/utils/visualLineNavigation.d.ts +22 -2
  188. package/dist/prosemirror/utils/visualLineNavigation.js +80 -63
  189. package/dist/style-engine/styleEngine.d.ts +4 -1
  190. package/dist/style-engine/styleEngine.js +3 -0
  191. package/dist/style-sets/extract.js +35 -11
  192. package/dist/style-sets/stellaStyle.js +46 -39
  193. package/dist/style-sets/styleSetNormalization.d.ts +19 -0
  194. package/dist/style-sets/styleSetNormalization.js +99 -0
  195. package/dist/types/content.d.ts +2 -2
  196. package/dist/utils/createDocument.js +145 -20
  197. package/dist/utils/headingCollector.d.ts +8 -5
  198. package/dist/utils/headingCollector.js +23 -25
  199. package/dist/utils/tableOfContentsStyle.js +9 -2
  200. package/package.json +3 -2
  201. package/dist/docx/textWhitespace.d.ts +0 -4
  202. package/dist/docx/textWhitespace.js +0 -4
  203. package/dist/layout-bridge/engine/tableWidthUtils.d.ts +0 -6
  204. package/dist/layout-bridge/engine/tableWidthUtils.js +0 -25
  205. package/dist/markdown/headings.d.ts +0 -13
  206. package/dist/markdown/headings.js +0 -20
@@ -1,5 +1,9 @@
1
1
  import { resolveColorValueToHex } from "../../docx/drawingUtils.js";
2
+ import { isNumberingReference } from "../../docx/numberingReference.js";
2
3
  import { PROSE_PARAGRAPH_SOURCE_CONTRACT_ATTR, createProseParagraphWithPropertySource, getDocumentParagraphPropertySourceContract, recreateProseNodeWithParagraphPropertySource, transportTableCellsWithParagraphPropertySources } from "../../docx/paragraphPropertySource.js";
4
+ import { isBaselineVertAlign } from "../../docx/runParser.js";
5
+ import { resolveTableLook } from "../../docx/tableLook.js";
6
+ import { isCellMergeContinuation } from "../../docx/tableParser.js";
3
7
  import { buildPageBreakRunSourceDescendantIndex } from "../../internal/pageBreakRunSourceDescendantIndex.js";
4
8
  import { createStyleEngine } from "../../style-engine/styleEngine.js";
5
9
  import { normalizeHorizontalScalePercent } from "../../utils/horizontalScale.js";
@@ -8,20 +12,19 @@ import { tableOfContentsStyleLevel } from "../../utils/tableOfContentsStyle.js";
8
12
  import { mergeTextFormatting } from "../../utils/textFormattingMerge.js";
9
13
  import { emuToPixels } from "../../utils/units.js";
10
14
  import { setAutospacingBaseValue } from "../autospacingBase.js";
11
- import { buildRunFormattingOverrideAttrs } from "../extensions/marks/RunFormattingOverrideExtension.js";
15
+ import { textFormattingToMarks } from "../extensions/marks/markUtils.js";
12
16
  import { listRenderingAttrPatch } from "../listRenderingAttrs.js";
13
17
  import { stampNumberedRefFieldBaselines } from "../numberedRefFields.js";
14
18
  import { pageBreakRunParagraphProjectionDispositionForFeatures } from "../pageBreakRunProjection.js";
15
19
  import { directionFromBidi } from "../paragraphDirection.js";
20
+ import { styleResolvedParagraphFormatting } from "../paragraphFormattingProvenance.js";
16
21
  import { lineSpacingProvenanceFromSpacing } from "../paragraphSpacing.js";
17
22
  import { getParagraphMarkSuppressionOverrides, hasDirectRunFormatting, resolveParagraphBodyRunFormatting, stripParagraphMarkFormattingForBodyRuns, stripParagraphMarkOnlyFormatting, suppressParagraphMarkFormatting } from "../runStyleFormatting.js";
18
23
  import { schema } from "../schema/index.js";
19
- import { COMPLEX_SCRIPT_RUN_PROPERTY_KEYS } from "../schema/marks.js";
20
24
  import { cascadeStyleTextFormatting } from "../styles/styleToggleCascade.js";
21
25
  import { canCarryTrackedRunMark, trackedRunInlineAtomDisposition } from "../trackedRunInlineAtoms.js";
22
26
  import { assertValidProseMirrorDocument } from "../validation.js";
23
27
  import { resolveEffectiveTableCellFormatting } from "./effectiveTableCellFormatting.js";
24
- import { shadingToRunShadingAttrs } from "./runShadingMark.js";
25
28
  import { sdtAttrsFromProperties } from "./sdtAttrs.js";
26
29
  import { TaggedError, panic } from "better-result";
27
30
  import { DRAWING_RAW_XML_MODES } from "@stll/docx-core/model";
@@ -76,25 +79,72 @@ const collectPairedBookmarkIds = (blocks) => {
76
79
  for (const content of run.content) if (content.type === "shape" && content.shape.textBody) visitBlocks(content.shape.textBody.content);
77
80
  };
78
81
  const visitHyperlink = (hyperlink) => {
79
- for (const child of hyperlink.children) if (child.type === "bookmarkStart") countBoundary(child.id, "start");
80
- else if (child.type === "bookmarkEnd") countBoundary(child.id, "end");
81
- else visitRun(child);
82
+ for (const child of hyperlink.children) switch (child.type) {
83
+ case "bookmarkStart":
84
+ countBoundary(child.id, "start");
85
+ break;
86
+ case "bookmarkEnd":
87
+ countBoundary(child.id, "end");
88
+ break;
89
+ case "run":
90
+ visitRun(child);
91
+ break;
92
+ default: panic(`Unsupported hyperlink child: ${JSON.stringify(child)}`);
93
+ }
82
94
  };
83
95
  const visitParagraphContent = (content) => {
84
- if (content.type === "bookmarkStart") countBoundary(content.id, "start");
85
- else if (content.type === "bookmarkEnd") countBoundary(content.id, "end");
86
- else if (content.type === "run") visitRun(content);
87
- else if (content.type === "hyperlink") visitHyperlink(content);
88
- else if (content.type === "simpleField") for (const child of content.content) if (child.type === "hyperlink") visitHyperlink(child);
89
- else visitRun(child);
90
- else if (content.type === "complexField") for (const run of [...content.fieldCode ?? [], ...content.fieldResult]) visitRun(run);
91
- else if (content.type === "inlineSdt") for (const child of content.content) visitParagraphContent(child);
92
- else if (content.type === "insertion" || content.type === "deletion" || content.type === "moveFrom" || content.type === "moveTo") for (const child of content.content) visitParagraphContent(child);
96
+ switch (content.type) {
97
+ case "bookmarkStart":
98
+ countBoundary(content.id, "start");
99
+ return;
100
+ case "bookmarkEnd":
101
+ countBoundary(content.id, "end");
102
+ return;
103
+ case "run":
104
+ visitRun(content);
105
+ return;
106
+ case "hyperlink":
107
+ visitHyperlink(content);
108
+ return;
109
+ case "simpleField":
110
+ for (const child of content.content) if (child.type === "hyperlink") visitHyperlink(child);
111
+ else visitRun(child);
112
+ return;
113
+ case "complexField":
114
+ for (const run of [...content.fieldCode ?? [], ...content.fieldResult]) visitRun(run);
115
+ return;
116
+ case "inlineSdt":
117
+ case "insertion":
118
+ case "deletion":
119
+ case "moveFrom":
120
+ case "moveTo":
121
+ case "bidiWrapper":
122
+ for (const child of content.content) visitParagraphContent(child);
123
+ return;
124
+ case "commentRangeStart":
125
+ case "commentRangeEnd":
126
+ case "commentReference":
127
+ case "moveFromRangeStart":
128
+ case "moveFromRangeEnd":
129
+ case "moveToRangeStart":
130
+ case "moveToRangeEnd":
131
+ case "mathEquation": return;
132
+ default: panic(`Unsupported paragraph content: ${JSON.stringify(content)}`);
133
+ }
93
134
  };
94
135
  const visitBlocks = (nestedBlocks) => {
95
- for (const block of nestedBlocks) if (block.type === "paragraph") for (const content of block.content) visitParagraphContent(content);
96
- else if (block.type === "table") for (const row of block.rows) for (const cell of row.cells) visitBlocks(cell.content);
97
- else visitBlocks(block.content);
136
+ for (const block of nestedBlocks) switch (block.type) {
137
+ case "paragraph":
138
+ for (const content of block.content) visitParagraphContent(content);
139
+ break;
140
+ case "table":
141
+ for (const row of block.rows) for (const cell of row.cells) visitBlocks(cell.content);
142
+ break;
143
+ case "blockSdt":
144
+ visitBlocks(block.content);
145
+ break;
146
+ default: panic(`Unsupported block content: ${JSON.stringify(block)}`);
147
+ }
98
148
  };
99
149
  visitBlocks(blocks);
100
150
  return new Set([...counts].flatMap(([id, count]) => count.starts === 1 && count.ends === 1 && count.firstStart !== void 0 && count.firstEnd !== void 0 && count.firstStart < count.firstEnd ? [id] : []));
@@ -120,12 +170,21 @@ function toProseDoc(document, options) {
120
170
  };
121
171
  const convertBodyBlocks = (blocks) => {
122
172
  const out = [];
123
- for (const block of blocks) if (block.type === "paragraph") out.push(...convertParagraphWithTextBoxes(block, styleResolver, {
124
- textBoxGroupId: nextTextBoxGroupId(),
125
- context: conversionContext
126
- }));
127
- else if (block.type === "table") out.push(convertTable(block, styleResolver, conversionContext));
128
- else out.push(convertBlockSdt(block, convertBodyBlocks));
173
+ for (const block of blocks) switch (block.type) {
174
+ case "paragraph":
175
+ out.push(...convertParagraphWithTextBoxes(block, styleResolver, {
176
+ textBoxGroupId: nextTextBoxGroupId(),
177
+ context: conversionContext
178
+ }));
179
+ break;
180
+ case "table":
181
+ out.push(convertTable(block, styleResolver, conversionContext));
182
+ break;
183
+ case "blockSdt":
184
+ out.push(convertBlockSdt(block, convertBodyBlocks));
185
+ break;
186
+ default: panic(`Unsupported block content: ${JSON.stringify(block)}`);
187
+ }
129
188
  return out;
130
189
  };
131
190
  nodes.push(...convertBodyBlocks(paragraphs));
@@ -264,58 +323,95 @@ function convertParagraph(paragraph, styleResolver, context, activeCommentIds, e
264
323
  const emitTrackedChange = (change, markType, moveKind) => {
265
324
  emitInlineNodes(convertTrackedChange(change, markType, nextHyperlinkInstanceIndex, nextPageBreakRunOwnerId, getInheritedRunFormatting, styleResolver, moveKind, textBoxAnchors));
266
325
  };
267
- for (const content of paragraph.content) if (content.type === "commentRangeStart") commentIds.add(content.id);
268
- else if (content.type === "commentRangeEnd") commentIds.delete(content.id);
269
- else if (content.type === "commentReference") anchorPointComment(inlineNodes, content.id);
270
- else if (content.type === "run") emitInlineNodes(convertRun(content, getInheritedRunFormatting(content.formatting), nextPageBreakRunOwnerId, styleResolver, textBoxAnchors));
271
- else if (content.type === "hyperlink") {
272
- const linkNodes = convertHyperlink(content, {
273
- getInheritedRunFormatting,
274
- styleResolver,
275
- hyperlinkIndex: nextHyperlinkInstanceIndex(),
276
- textBoxAnchors,
277
- nextPageBreakRunOwnerId
278
- });
279
- if (linkNodes.length === 0) {
280
- emptyHyperlinks ??= [];
281
- emptyHyperlinks.push({
282
- offset: inlineOffset,
283
- ...content.href !== void 0 ? { href: content.href } : {},
284
- ...content.anchor !== void 0 ? { anchor: content.anchor } : {},
285
- ...content.tooltip !== void 0 ? { tooltip: content.tooltip } : {},
286
- ...content.rId !== void 0 ? { rId: content.rId } : {}
326
+ for (const content of withoutBidiWrappers(paragraph.content)) switch (content.type) {
327
+ case "commentRangeStart":
328
+ commentIds.add(content.id);
329
+ break;
330
+ case "commentRangeEnd":
331
+ commentIds.delete(content.id);
332
+ break;
333
+ case "commentReference":
334
+ anchorPointComment(inlineNodes, content.id);
335
+ break;
336
+ case "run":
337
+ emitInlineNodes(convertRun(content, getInheritedRunFormatting(content.formatting), nextPageBreakRunOwnerId, styleResolver, textBoxAnchors));
338
+ break;
339
+ case "hyperlink": {
340
+ const linkNodes = convertHyperlink(content, {
341
+ getInheritedRunFormatting,
342
+ styleResolver,
343
+ hyperlinkIndex: nextHyperlinkInstanceIndex(),
344
+ textBoxAnchors,
345
+ nextPageBreakRunOwnerId
287
346
  });
288
- continue;
347
+ if (linkNodes.length === 0) {
348
+ emptyHyperlinks ??= [];
349
+ emptyHyperlinks.push({
350
+ offset: inlineOffset,
351
+ ...content.href !== void 0 ? { href: content.href } : {},
352
+ ...content.anchor !== void 0 ? { anchor: content.anchor } : {},
353
+ ...content.tooltip !== void 0 ? { tooltip: content.tooltip } : {},
354
+ ...content.rId !== void 0 ? { rId: content.rId } : {}
355
+ });
356
+ break;
357
+ }
358
+ emitInlineNodes(linkNodes);
359
+ break;
289
360
  }
290
- emitInlineNodes(linkNodes);
291
- } else if (content.type === "simpleField" || content.type === "complexField") emitInlineNode(convertField(content, {
292
- getInheritedRunFormatting,
293
- styleResolver,
294
- nextHyperlinkInstanceIndex,
295
- nextPageBreakRunOwnerId,
296
- textBoxAnchors
297
- }));
298
- else if (content.type === "inlineSdt") emitInlineNode(convertInlineSdt(content, nextHyperlinkInstanceIndex, nextPageBreakRunOwnerId, getInheritedRunFormatting, styleResolver, textBoxAnchors));
299
- else if (content.type === "insertion" || content.type === "moveTo") emitTrackedChange(content, "insertion", content.type === "moveTo" ? "moveTo" : null);
300
- else if (content.type === "deletion" || content.type === "moveFrom") emitTrackedChange(content, "deletion", content.type === "moveFrom" ? "moveFrom" : null);
301
- else if (content.type === "mathEquation") emitInlineNode(convertMathEquation(content));
302
- else if (content.type === "bookmarkStart" && pairedBookmarkIds.has(content.id)) emitInlineNode(schema.node("bookmarkBoundary", {
303
- type: "start",
304
- id: content.id,
305
- name: content.name,
306
- colFirst: content.colFirst,
307
- colLast: content.colLast
308
- }));
309
- else if (content.type === "bookmarkEnd" && pairedBookmarkIds.has(content.id)) emitInlineNode(schema.node("bookmarkBoundary", {
310
- type: "end",
311
- id: content.id
312
- }));
313
- else if (content.type === "bookmarkStart") {
314
- if (!bookmarksArr) bookmarksArr = [];
315
- bookmarksArr.push({
316
- id: content.id,
317
- name: content.name
318
- });
361
+ case "simpleField":
362
+ case "complexField":
363
+ emitInlineNode(convertField(content, {
364
+ getInheritedRunFormatting,
365
+ styleResolver,
366
+ nextHyperlinkInstanceIndex,
367
+ nextPageBreakRunOwnerId,
368
+ textBoxAnchors
369
+ }));
370
+ break;
371
+ case "inlineSdt":
372
+ emitInlineNode(convertInlineSdt(content, nextHyperlinkInstanceIndex, nextPageBreakRunOwnerId, getInheritedRunFormatting, styleResolver, textBoxAnchors));
373
+ break;
374
+ case "insertion":
375
+ case "moveTo":
376
+ emitTrackedChange(content, "insertion", content.type === "moveTo" ? "moveTo" : null);
377
+ break;
378
+ case "deletion":
379
+ case "moveFrom":
380
+ emitTrackedChange(content, "deletion", content.type === "moveFrom" ? "moveFrom" : null);
381
+ break;
382
+ case "mathEquation":
383
+ emitInlineNode(convertMathEquation(content));
384
+ break;
385
+ case "bookmarkStart":
386
+ if (pairedBookmarkIds.has(content.id)) {
387
+ emitInlineNode(schema.node("bookmarkBoundary", {
388
+ type: "start",
389
+ id: content.id,
390
+ name: content.name,
391
+ colFirst: content.colFirst,
392
+ colLast: content.colLast,
393
+ displacedByCustomXml: content.displacedByCustomXml
394
+ }));
395
+ break;
396
+ }
397
+ if (!bookmarksArr) bookmarksArr = [];
398
+ bookmarksArr.push({
399
+ id: content.id,
400
+ name: content.name
401
+ });
402
+ break;
403
+ case "bookmarkEnd":
404
+ if (pairedBookmarkIds.has(content.id)) emitInlineNode(schema.node("bookmarkBoundary", {
405
+ type: "end",
406
+ id: content.id,
407
+ displacedByCustomXml: content.displacedByCustomXml
408
+ }));
409
+ break;
410
+ case "moveFromRangeStart":
411
+ case "moveFromRangeEnd":
412
+ case "moveToRangeStart":
413
+ case "moveToRangeEnd": break;
414
+ default: panic(`Unsupported paragraph content: ${JSON.stringify(content)}`);
319
415
  }
320
416
  if (bookmarksArr) attrs.bookmarks = bookmarksArr;
321
417
  if (emptyHyperlinks) attrs._emptyHyperlinks = emptyHyperlinks;
@@ -386,11 +482,13 @@ function convertTrackedChange(change, markType, nextHyperlinkInstanceIndex, next
386
482
  id: item.id,
387
483
  name: item.name,
388
484
  colFirst: item.colFirst,
389
- colLast: item.colLast
485
+ colLast: item.colLast,
486
+ displacedByCustomXml: item.displacedByCustomXml
390
487
  }));
391
488
  else if (item.type === "bookmarkEnd") nodes.push(schema.node("bookmarkBoundary", {
392
489
  type: "end",
393
- id: item.id
490
+ id: item.id,
491
+ displacedByCustomXml: item.displacedByCustomXml
394
492
  }));
395
493
  else panic(`Unsupported tracked-run content: ${JSON.stringify(item)}`);
396
494
  const mark = schema.marks[markType].create({
@@ -434,6 +532,8 @@ function paragraphFormattingToAttrs(paragraph, styleResolver, tableParagraphOver
434
532
  let stylePpr;
435
533
  if (styleResolver) {
436
534
  stylePpr = styleResolver.resolveParagraphStyleInTable(styleId, tableParagraphOverlay).paragraphFormatting;
535
+ const resolvedFormatting = styleResolvedParagraphFormatting(stylePpr);
536
+ if (resolvedFormatting) attrs._resolvedFormatting = resolvedFormatting;
437
537
  set("alignment", formatting?.alignment ?? stylePpr?.alignment);
438
538
  set("alignmentFromStyle", stylePpr?.alignment);
439
539
  set("spaceBefore", formatting?.spaceBefore ?? stylePpr?.spaceBefore);
@@ -453,7 +553,7 @@ function paragraphFormattingToAttrs(paragraph, styleResolver, tableParagraphOver
453
553
  if (formatting?.spaceBefore === void 0 && tableParagraphOverlay?.spaceBefore === void 0 && paragraphStyle?.pPr?.spaceBefore === void 0 && docDefaultSpacing?.spaceBefore !== void 0) spacingFromDocDefaults.before = true;
454
554
  if (formatting?.spaceAfter === void 0 && tableParagraphOverlay?.spaceAfter === void 0 && paragraphStyle?.pPr?.spaceAfter === void 0 && docDefaultSpacing?.spaceAfter !== void 0) spacingFromDocDefaults.after = true;
455
555
  if (spacingFromDocDefaults.before || spacingFromDocDefaults.after) attrs.spacingFromDocDefaults = spacingFromDocDefaults;
456
- const effectiveIndent = mergeParagraphFormatting(formatting?.numPr?.numId === 0 && stylePpr?.numPr !== void 0 && stylePpr.numPr.numId !== 0 ? void 0 : stylePpr, formatting);
556
+ const effectiveIndent = mergeParagraphFormatting(formatting?.numPr?.numId === 0 && isNumberingReference(stylePpr?.numPr?.numId) ? void 0 : stylePpr, formatting);
457
557
  set("indentLeft", effectiveIndent?.indentLeft);
458
558
  set("indentRight", formatting?.indentRight ?? stylePpr?.indentRight);
459
559
  set("indentFirstLine", effectiveIndent?.indentFirstLine);
@@ -473,7 +573,7 @@ function paragraphFormattingToAttrs(paragraph, styleResolver, tableParagraphOver
473
573
  set("outlineLevel", formatting?.outlineLevel ?? stylePpr?.outlineLevel);
474
574
  set("direction", directionFromBidi(formatting?.bidi ?? stylePpr?.bidi));
475
575
  set("defaultTextFormatting", resolveParagraphDefaultTextFormatting(styleId, formatting, styleResolver, { includeParagraphMarkRunProperties: tableOfContentsLevel === void 0 && (styleId === void 0 || paragraph.content.length === 0) }));
476
- if (stylePpr?.numPr && formatting?.numPr?.numId === void 0 && stylePpr.numPr.numId !== 0) {
576
+ if (stylePpr?.numPr && formatting?.numPr?.numId === void 0 && isNumberingReference(stylePpr.numPr.numId)) {
477
577
  attrs.numPr = {
478
578
  ...stylePpr.numPr,
479
579
  ...formatting?.numPr
@@ -664,22 +764,24 @@ function calculateRowSpans(table) {
664
764
  const rowCells = row.cells.map((cell) => {
665
765
  const colspan = cell.formatting?.gridSpan ?? 1;
666
766
  const vMerge = cell.formatting?.vMerge;
667
- const startRow = vMerge === "continue" ? activeMerges.get(colIndex) : void 0;
767
+ const isMergeContinuation = isCellMergeContinuation(cell);
768
+ const startRow = isMergeContinuation ? activeMerges.get(colIndex) : void 0;
668
769
  const info = {
669
770
  cell,
670
771
  colIndex,
671
772
  colspan,
672
773
  vMerge,
774
+ isMergeContinuation,
673
775
  startRow,
674
776
  hasMeaningfulContent: tableCellHasMeaningfulContent(cell),
675
- shouldSkip: vMerge === "continue" && startRow !== void 0
777
+ shouldSkip: isMergeContinuation && startRow !== void 0
676
778
  };
677
779
  colIndex += colspan;
678
780
  return info;
679
781
  });
680
782
  const rowWouldBeEmpty = rowCells.length > 0 && rowCells.every((cell) => cell.shouldSkip);
681
783
  for (const cellInfo of rowCells) {
682
- const { colIndex: cellColIndex, vMerge, startRow, hasMeaningfulContent } = cellInfo;
784
+ const { colIndex: cellColIndex, vMerge, isMergeContinuation, startRow, hasMeaningfulContent } = cellInfo;
683
785
  const key = `${rowIndex}-${cellColIndex}`;
684
786
  if (vMerge === "restart") {
685
787
  activeMerges.set(cellColIndex, rowIndex);
@@ -687,7 +789,7 @@ function calculateRowSpans(table) {
687
789
  rowSpan: 1,
688
790
  skip: false
689
791
  });
690
- } else if (vMerge === "continue") {
792
+ } else if (isMergeContinuation) {
691
793
  if (startRow === void 0 || rowWouldBeEmpty || hasMeaningfulContent) {
692
794
  result.set(key, {
693
795
  rowSpan: 1,
@@ -744,7 +846,7 @@ function paragraphContentHasMeaningfulContent(content) {
744
846
  }
745
847
  function convertTable(table, styleResolver, context) {
746
848
  for (const row of table.rows) for (const cell of row.cells) {
747
- if (cell.formatting?.vMerge === "continue" && context.pageBreakRunSourceDescendants.containsPageBreakRun(cell.content)) throw new UnsupportedDocxToProseMirrorConversionError({
849
+ if (isCellMergeContinuation(cell) && context.pageBreakRunSourceDescendants.containsPageBreakRun(cell.content)) throw new UnsupportedDocxToProseMirrorConversionError({
748
850
  message: `${PAGE_BREAK_CONTAINER_DESCRIPTIONS["table-cell"]} cannot be represented in the editor model`,
749
851
  owner: "table-cell",
750
852
  contentType: "break"
@@ -755,7 +857,7 @@ function convertTable(table, styleResolver, context) {
755
857
  const columnWidths = table.columnWidths;
756
858
  const totalWidth = columnWidths?.reduce((sum, w) => sum + w, 0) ?? 0;
757
859
  const tableStyleId = table.formatting?.styleId;
758
- const look = table.formatting?.look;
860
+ const look = resolveTableLook(table.formatting?.look);
759
861
  const tableStyle = tableStyleId ? styleResolver?.getStyle(tableStyleId) : void 0;
760
862
  const defaultTableStyle = styleResolver?.getDefaultTableStyle();
761
863
  const fallbackTableStyle = tableStyleId ? void 0 : defaultTableStyle;
@@ -791,7 +893,7 @@ function convertTable(table, styleResolver, context) {
791
893
  if (resolvedTableIndent) attrs._resolvedIndent = resolvedTableIndent;
792
894
  if (resolvedTableJustification) attrs._resolvedJustification = resolvedTableJustification;
793
895
  if (resolvedTableBidi !== void 0) attrs._resolvedBidi = resolvedTableBidi;
794
- if (table.formatting) attrs._originalFormatting = table.formatting;
896
+ attrs._originalFormatting = table.formatting ?? {};
795
897
  if (table.propertyChanges && table.propertyChanges.length > 0) attrs.tblPrChange = [...table.propertyChanges];
796
898
  const conditionalStyles = {};
797
899
  const setCS = (key, type) => {
@@ -813,15 +915,15 @@ function convertTable(table, styleResolver, context) {
813
915
  setCS("neCell", "neCell");
814
916
  setCS("swCell", "swCell");
815
917
  setCS("seCell", "seCell");
816
- const bandingEnabledH = look?.noHBand !== true;
817
- const bandingEnabledV = look?.noVBand !== true;
918
+ const bandingEnabledH = !look.noHBand;
919
+ const bandingEnabledV = !look.noVBand;
818
920
  let dataRowIndex = 0;
819
921
  const totalRows = table.rows.length;
820
922
  const gridColumnCount = columnWidths?.length ?? 0;
821
923
  const totalColumns = gridColumnCount > 0 ? gridColumnCount : countTableColumns(table.rows);
822
924
  const rows = table.rows.map((row, rowIndex) => {
823
- const isFirstRowStyled = rowIndex === 0 && !!look?.firstRow;
824
- const isLastRow = rowIndex === totalRows - 1 && !!look?.lastRow;
925
+ const isFirstRowStyled = rowIndex === 0 && look.firstRow;
926
+ const isLastRow = rowIndex === totalRows - 1 && look.lastRow;
825
927
  const rowBandStyle = (() => {
826
928
  if (bandingEnabledH && !isFirstRowStyled && !isLastRow) return (() => {
827
929
  if (dataRowIndex % 2 === 0) return conditionalStyles.band1Horz;
@@ -856,26 +958,34 @@ function convertTableRow(row, styleResolver, context, isHeaderRow, columnWidths,
856
958
  if (row.formatting) attrsWithoutStructuralChange._originalFormatting = row.formatting;
857
959
  if (row.propertyChanges && row.propertyChanges.length > 0) attrsWithoutStructuralChange.trPrChange = [...row.propertyChanges];
858
960
  let attrs = attrsWithoutStructuralChange;
859
- if (row.structuralChange?.type === "tableRowInsertion") attrs = {
860
- ...attrsWithoutStructuralChange,
861
- trIns: {
862
- revisionId: row.structuralChange.info.id,
863
- author: row.structuralChange.info.author,
864
- date: row.structuralChange.info.date ?? null,
865
- ...row.structuralChange.info.utcDate ? { utcDate: row.structuralChange.info.utcDate.value } : {},
866
- ...row.structuralChange.info.initials ? { initials: row.structuralChange.info.initials } : {}
867
- }
868
- };
869
- else if (row.structuralChange?.type === "tableRowDeletion") attrs = {
870
- ...attrsWithoutStructuralChange,
871
- trDel: {
872
- revisionId: row.structuralChange.info.id,
873
- author: row.structuralChange.info.author,
874
- date: row.structuralChange.info.date ?? null,
875
- ...row.structuralChange.info.utcDate ? { utcDate: row.structuralChange.info.utcDate.value } : {},
876
- ...row.structuralChange.info.initials ? { initials: row.structuralChange.info.initials } : {}
961
+ const rowStructuralChange = row.structuralChange;
962
+ if (rowStructuralChange) {
963
+ const revision = {
964
+ revisionId: rowStructuralChange.info.id,
965
+ author: rowStructuralChange.info.author,
966
+ date: rowStructuralChange.info.date ?? null,
967
+ ...rowStructuralChange.info.utcDate ? { utcDate: rowStructuralChange.info.utcDate.value } : {},
968
+ ...rowStructuralChange.info.initials ? { initials: rowStructuralChange.info.initials } : {}
969
+ };
970
+ switch (rowStructuralChange.type) {
971
+ case "tableRowInsertion":
972
+ attrs = {
973
+ ...attrsWithoutStructuralChange,
974
+ trIns: revision
975
+ };
976
+ break;
977
+ case "tableRowDeletion":
978
+ attrs = {
979
+ ...attrsWithoutStructuralChange,
980
+ trDel: revision
981
+ };
982
+ break;
983
+ case "tableCellInsertion":
984
+ case "tableCellDeletion":
985
+ case "tableCellMerge": break;
986
+ default: panic(`Unsupported table row structural change: ${JSON.stringify(rowStructuralChange)}`);
877
987
  }
878
- };
988
+ }
879
989
  const numCells = row.cells.length;
880
990
  const isFirstRow = rowIndex === 0;
881
991
  const isLastRow = rowIndex === (totalRows ?? 1) - 1;
@@ -1005,38 +1115,41 @@ function convertTableCell({ cell, styleResolver, context, isHeader, gridWidthPer
1005
1115
  }
1006
1116
  if (formatting) attrs._originalFormatting = formatting;
1007
1117
  if (cell.propertyChanges && cell.propertyChanges.length > 0) attrs.tcPrChange = [...cell.propertyChanges];
1008
- if (cell.structuralChange?.type === "tableCellInsertion") attrs.cellMarker = {
1009
- kind: "ins",
1010
- info: {
1011
- revisionId: cell.structuralChange.info.id,
1012
- author: cell.structuralChange.info.author,
1013
- date: cell.structuralChange.info.date ?? null,
1014
- ...cell.structuralChange.info.utcDate ? { utcDate: cell.structuralChange.info.utcDate.value } : {},
1015
- ...cell.structuralChange.info.initials ? { initials: cell.structuralChange.info.initials } : {}
1016
- }
1017
- };
1018
- else if (cell.structuralChange?.type === "tableCellDeletion") attrs.cellMarker = {
1019
- kind: "del",
1020
- info: {
1021
- revisionId: cell.structuralChange.info.id,
1022
- author: cell.structuralChange.info.author,
1023
- date: cell.structuralChange.info.date ?? null,
1024
- ...cell.structuralChange.info.utcDate ? { utcDate: cell.structuralChange.info.utcDate.value } : {},
1025
- ...cell.structuralChange.info.initials ? { initials: cell.structuralChange.info.initials } : {}
1118
+ const cellStructuralChange = cell.structuralChange;
1119
+ if (cellStructuralChange) {
1120
+ const info = {
1121
+ revisionId: cellStructuralChange.info.id,
1122
+ author: cellStructuralChange.info.author,
1123
+ date: cellStructuralChange.info.date ?? null,
1124
+ ...cellStructuralChange.info.utcDate ? { utcDate: cellStructuralChange.info.utcDate.value } : {},
1125
+ ...cellStructuralChange.info.initials ? { initials: cellStructuralChange.info.initials } : {}
1126
+ };
1127
+ switch (cellStructuralChange.type) {
1128
+ case "tableCellInsertion":
1129
+ attrs.cellMarker = {
1130
+ kind: "ins",
1131
+ info
1132
+ };
1133
+ break;
1134
+ case "tableCellDeletion":
1135
+ attrs.cellMarker = {
1136
+ kind: "del",
1137
+ info
1138
+ };
1139
+ break;
1140
+ case "tableCellMerge":
1141
+ attrs.cellMarker = {
1142
+ kind: "merge",
1143
+ info,
1144
+ ...cellStructuralChange.verticalMerge !== void 0 ? { verticalMerge: cellStructuralChange.verticalMerge } : {},
1145
+ ...cellStructuralChange.verticalMergeOriginal !== void 0 ? { verticalMergeOriginal: cellStructuralChange.verticalMergeOriginal } : {}
1146
+ };
1147
+ break;
1148
+ case "tableRowInsertion":
1149
+ case "tableRowDeletion": break;
1150
+ default: panic(`Unsupported table cell structural change: ${JSON.stringify(cellStructuralChange)}`);
1026
1151
  }
1027
- };
1028
- else if (cell.structuralChange?.type === "tableCellMerge") attrs.cellMarker = {
1029
- kind: "merge",
1030
- info: {
1031
- revisionId: cell.structuralChange.info.id,
1032
- author: cell.structuralChange.info.author,
1033
- date: cell.structuralChange.info.date ?? null,
1034
- ...cell.structuralChange.info.utcDate ? { utcDate: cell.structuralChange.info.utcDate.value } : {},
1035
- ...cell.structuralChange.info.initials ? { initials: cell.structuralChange.info.initials } : {}
1036
- },
1037
- ...cell.structuralChange.verticalMerge !== void 0 ? { verticalMerge: cell.structuralChange.verticalMerge } : {},
1038
- ...cell.structuralChange.verticalMergeOriginal !== void 0 ? { verticalMergeOriginal: cell.structuralChange.verticalMergeOriginal } : {}
1039
- };
1152
+ }
1040
1153
  if (preserveVMergeRestart) attrs._preserveVMergeRestart = true;
1041
1154
  if (vMergeContinuationCells && vMergeContinuationCells.length > 0) attrs._docxVMergeContinuationCells = transportTableCellsWithParagraphPropertySources(vMergeContinuationCells);
1042
1155
  const contentNodes = [];
@@ -1135,6 +1248,22 @@ function convertField(field, { getInheritedRunFormatting, styleResolver, nextHyp
1135
1248
  /**
1136
1249
  * Convert a MathEquation to a ProseMirror math node.
1137
1250
  */
1251
+ /**
1252
+ * Flatten `w:bdo`/`w:dir` out of an inline content list.
1253
+ *
1254
+ * The editor has no projection for a bidirectional wrapper yet, and the
1255
+ * alternative to flattening it is worse than losing the direction: every
1256
+ * inline loop below narrows by a chain of `else if` rather than by
1257
+ * exhaustion, so an unhandled member reaches whichever branch happens to be
1258
+ * last and is read as that. Flattening keeps the wrapper's content and loses
1259
+ * only its direction, which the survival census records as an
1260
+ * editor-projection loss until the mark that carries it exists.
1261
+ *
1262
+ * The save path is unaffected: a document opened and saved without being
1263
+ * edited replays its markup, and one that is edited keeps the wrapper because
1264
+ * `fromProseDoc` rebuilds from the source paragraph.
1265
+ */
1266
+ const withoutBidiWrappers = (content) => content.flatMap((item) => item.type === "bidiWrapper" ? withoutBidiWrappers(item.content) : [item]);
1138
1267
  function convertMathEquation(math) {
1139
1268
  return schema.node("math", {
1140
1269
  display: math.display,
@@ -1148,37 +1277,50 @@ function convertMathEquation(math) {
1148
1277
  function convertInlineSdt(sdt, nextHyperlinkInstanceIndex, nextPageBreakRunOwnerId, getInheritedRunFormatting, styleResolver, textBoxAnchors) {
1149
1278
  const props = sdt.properties;
1150
1279
  const inlineNodes = [];
1151
- for (const content of sdt.content) if (content.type === "run") {
1152
- const runNodes = convertRun(content, getInheritedRunFormatting(content.formatting), nextPageBreakRunOwnerId, styleResolver, textBoxAnchors);
1153
- inlineNodes.push(...runNodes);
1154
- } else if (content.type === "hyperlink") {
1155
- const linkNodes = convertHyperlink(content, {
1156
- getInheritedRunFormatting,
1157
- styleResolver,
1158
- hyperlinkIndex: nextHyperlinkInstanceIndex(),
1159
- textBoxAnchors,
1160
- nextPageBreakRunOwnerId
1161
- });
1162
- inlineNodes.push(...linkNodes);
1163
- } else if (content.type === "simpleField" || content.type === "complexField") {
1164
- const fieldNode = convertField(content, {
1165
- getInheritedRunFormatting,
1166
- styleResolver,
1167
- nextHyperlinkInstanceIndex,
1168
- nextPageBreakRunOwnerId,
1169
- textBoxAnchors
1170
- });
1171
- if (fieldNode) inlineNodes.push(fieldNode);
1172
- } else if (content.type === "inlineSdt") {
1173
- const nestedSdt = convertInlineSdt(content, nextHyperlinkInstanceIndex, nextPageBreakRunOwnerId, getInheritedRunFormatting, styleResolver, textBoxAnchors);
1174
- if (nestedSdt) inlineNodes.push(nestedSdt);
1175
- } else if (content.type === "insertion") inlineNodes.push(...convertTrackedChange(content, "insertion", nextHyperlinkInstanceIndex, nextPageBreakRunOwnerId, getInheritedRunFormatting, styleResolver, null, textBoxAnchors));
1176
- else if (content.type === "deletion") inlineNodes.push(...convertTrackedChange(content, "deletion", nextHyperlinkInstanceIndex, nextPageBreakRunOwnerId, getInheritedRunFormatting, styleResolver, null, textBoxAnchors));
1177
- else if (content.type === "moveTo") inlineNodes.push(...convertTrackedChange(content, "insertion", nextHyperlinkInstanceIndex, nextPageBreakRunOwnerId, getInheritedRunFormatting, styleResolver, "moveTo", textBoxAnchors));
1178
- else if (content.type === "moveFrom") inlineNodes.push(...convertTrackedChange(content, "deletion", nextHyperlinkInstanceIndex, nextPageBreakRunOwnerId, getInheritedRunFormatting, styleResolver, "moveFrom", textBoxAnchors));
1179
- else {
1180
- const mathNode = convertMathEquation(content);
1181
- if (mathNode) inlineNodes.push(mathNode);
1280
+ for (const content of sdt.content) switch (content.type) {
1281
+ case "run":
1282
+ inlineNodes.push(...convertRun(content, getInheritedRunFormatting(content.formatting), nextPageBreakRunOwnerId, styleResolver, textBoxAnchors));
1283
+ break;
1284
+ case "hyperlink": {
1285
+ const currentHyperlinkIndex = nextHyperlinkInstanceIndex();
1286
+ inlineNodes.push(...convertHyperlink(content, {
1287
+ getInheritedRunFormatting,
1288
+ styleResolver,
1289
+ hyperlinkIndex: currentHyperlinkIndex,
1290
+ textBoxAnchors,
1291
+ nextPageBreakRunOwnerId
1292
+ }));
1293
+ break;
1294
+ }
1295
+ case "simpleField":
1296
+ case "complexField": {
1297
+ const fieldNode = convertField(content, {
1298
+ getInheritedRunFormatting,
1299
+ styleResolver,
1300
+ nextHyperlinkInstanceIndex,
1301
+ nextPageBreakRunOwnerId,
1302
+ textBoxAnchors
1303
+ });
1304
+ if (fieldNode) inlineNodes.push(fieldNode);
1305
+ break;
1306
+ }
1307
+ case "inlineSdt": {
1308
+ const nestedSdt = convertInlineSdt(content, nextHyperlinkInstanceIndex, nextPageBreakRunOwnerId, getInheritedRunFormatting, styleResolver, textBoxAnchors);
1309
+ if (nestedSdt) inlineNodes.push(nestedSdt);
1310
+ break;
1311
+ }
1312
+ case "insertion":
1313
+ case "deletion":
1314
+ case "moveTo":
1315
+ case "moveFrom":
1316
+ inlineNodes.push(...convertTrackedChange(content, content.type === "insertion" || content.type === "moveTo" ? "insertion" : "deletion", nextHyperlinkInstanceIndex, nextPageBreakRunOwnerId, getInheritedRunFormatting, styleResolver, content.type === "moveTo" || content.type === "moveFrom" ? content.type : null, textBoxAnchors));
1317
+ break;
1318
+ case "mathEquation": {
1319
+ const mathNode = convertMathEquation(content);
1320
+ if (mathNode) inlineNodes.push(mathNode);
1321
+ break;
1322
+ }
1323
+ default: panic(`Unsupported inline SDT content: ${JSON.stringify(content)}`);
1182
1324
  }
1183
1325
  return schema.node("sdt", sdtAttrsFromProperties(props), inlineNodes.length > 0 ? inlineNodes : void 0);
1184
1326
  }
@@ -1195,7 +1337,7 @@ function convertRun(run, resolvedStyleFormatting, nextPageBreakRunOwnerId, style
1195
1337
  if (run.propertyChanges && run.propertyChanges.length > 0) marks.push(schema.mark("runPropertyChange", { changes: [...run.propertyChanges] }));
1196
1338
  if (run.content.some((content) => content.type === "break" && content.breakType === "page")) marks.push(schema.mark("pageBreakRunOwner", { id: nextPageBreakRunOwnerId() }));
1197
1339
  for (const content of run.content) {
1198
- const contentNodes = convertRunContent(content, marks, mergedFormatting, textBoxAnchors);
1340
+ const contentNodes = convertRunContent(content, marks, mergedFormatting, textBoxAnchors, run.formatting);
1199
1341
  nodes.push(...contentNodes);
1200
1342
  }
1201
1343
  return nodes;
@@ -1216,19 +1358,27 @@ const PAGE_BREAK_PARAGRAPH_OWNERS = {
1216
1358
  };
1217
1359
  function assertSourceContainerHasNoPageBreakRun(content, owner, sourceDescendants) {
1218
1360
  if (!sourceDescendants.containsPageBreakRun(content)) return;
1219
- if (owner === "table-cell" && hasSingleLeadingTableCellPageBreak(content)) return;
1361
+ if (owner === "table-cell" && hasSingleLeadingTableCellPageBreak(content, sourceDescendants)) return;
1220
1362
  throw new UnsupportedDocxToProseMirrorConversionError({
1221
1363
  message: `${PAGE_BREAK_CONTAINER_DESCRIPTIONS[owner]} cannot be represented in the editor model`,
1222
1364
  owner,
1223
1365
  contentType: "break"
1224
1366
  });
1225
1367
  }
1226
- /** A leading page-break run in a cell advances the whole row during pagination. This
1227
- * narrow shape has a lossless PM representation and a row-wide layout
1228
- * projection; interior breaks still require table-fragment ownership. */
1229
- function hasSingleLeadingTableCellPageBreak(content) {
1230
- const paragraph = content.length === 1 && content[0]?.type === "paragraph" ? content[0] : void 0;
1231
- return paragraph !== void 0 && hasSingleLeadingParagraphPageBreak(paragraph);
1368
+ /**
1369
+ * A page break opening a cell advances the whole row during pagination.
1370
+ *
1371
+ * Word writes this shape routinely and the row's own `breakBefore` projects it
1372
+ * losslessly, so what follows the break inside the cell rides along: the row
1373
+ * moves as a unit. The break has to be the cell's only one and has to open its
1374
+ * first paragraph; an interior break still requires table-fragment ownership,
1375
+ * which cell-local flow cannot model. `convertTableCell` in the layout bridge
1376
+ * decides the same question over the projected runs.
1377
+ */
1378
+ function hasSingleLeadingTableCellPageBreak(content, sourceDescendants) {
1379
+ const first = content.at(0);
1380
+ if (first?.type !== "paragraph" || !hasSingleLeadingParagraphPageBreak(first)) return false;
1381
+ return !content.slice(1).some((block) => sourceDescendants.blockContainsPageBreakRun(block));
1232
1382
  }
1233
1383
  const scanLeadingPageBreakRun = (run, scan) => {
1234
1384
  for (const content of run.content) {
@@ -1237,6 +1387,7 @@ const scanLeadingPageBreakRun = (run, scan) => {
1237
1387
  scan.pageBreaks += 1;
1238
1388
  continue;
1239
1389
  }
1390
+ if (content.type === "shape" && content.shape.textBody && scan.pageBreaks > 0) scan.textBoxShapeAfterBreak = true;
1240
1391
  if (scan.pageBreaks === 0) scan.contentBeforeBreak = true;
1241
1392
  }
1242
1393
  };
@@ -1253,6 +1404,7 @@ const scanLeadingPageBreakContent = (content, scan) => {
1253
1404
  case "moveFrom":
1254
1405
  case "moveTo":
1255
1406
  case "inlineSdt":
1407
+ case "bidiWrapper":
1256
1408
  for (const child of content.content) scanLeadingPageBreakContent(child, scan);
1257
1409
  return;
1258
1410
  case "simpleField":
@@ -1276,12 +1428,17 @@ const scanLeadingPageBreakContent = (content, scan) => {
1276
1428
  default: return content;
1277
1429
  }
1278
1430
  };
1279
- const hasSingleLeadingParagraphPageBreak = (paragraph) => {
1431
+ const scanParagraphPageBreaks = (paragraph) => {
1280
1432
  const scan = {
1281
1433
  contentBeforeBreak: false,
1282
- pageBreaks: 0
1434
+ pageBreaks: 0,
1435
+ textBoxShapeAfterBreak: false
1283
1436
  };
1284
1437
  for (const content of paragraph.content) scanLeadingPageBreakContent(content, scan);
1438
+ return scan;
1439
+ };
1440
+ const hasSingleLeadingParagraphPageBreak = (paragraph) => {
1441
+ const scan = scanParagraphPageBreaks(paragraph);
1285
1442
  return !scan.contentBeforeBreak && scan.pageBreaks === 1;
1286
1443
  };
1287
1444
  function assertParagraphPageBreakCanBeProjected({ paragraph, attrs, effectiveFrame, sourceDescendants }) {
@@ -1290,7 +1447,7 @@ function assertParagraphPageBreakCanBeProjected({ paragraph, attrs, effectiveFra
1290
1447
  const disposition = pageBreakRunParagraphProjectionDispositionForFeatures({
1291
1448
  attrs,
1292
1449
  effectiveFrame,
1293
- hasTextBoxAnchor: sourceFeatures.hasTextBoxShape && !sourceFeatures.pageBreakSharesTextBoxShape
1450
+ textBoxAnchorAfterPageBreak: sourceFeatures.hasTextBoxShape && !sourceFeatures.pageBreakSharesTextBoxShape && scanParagraphPageBreaks(paragraph).textBoxShapeAfterBreak
1294
1451
  });
1295
1452
  if (disposition.status === "supported") return;
1296
1453
  if (disposition.reason !== "textBoxAnchor" && hasSingleLeadingParagraphPageBreak(paragraph)) return;
@@ -1443,7 +1600,7 @@ const canReconstructAuthoredRunFormatting = ({ directFormatting, effectiveFormat
1443
1600
  };
1444
1601
  function buildRunMarks(runFormatting, inherited, styleResolver) {
1445
1602
  if (runFormatting === void 0 && inherited.implicitCharacterStyleApplied === true && inherited.paragraphMarkOverrides === void 0) return {
1446
- marks: textFormattingToMarks(inherited.formatting, {
1603
+ marks: textFormattingToMarks(inherited.formatting, schema, {
1447
1604
  overrideFormatting: void 0,
1448
1605
  directFormatting: void 0,
1449
1606
  authoredCarrier: "reconstruct"
@@ -1487,7 +1644,7 @@ function buildRunMarks(runFormatting, inherited, styleResolver) {
1487
1644
  if (overrideFormatting?.bold === true) delete overrideFormatting.bold;
1488
1645
  if (overrideFormatting?.italic === true) delete overrideFormatting.italic;
1489
1646
  }
1490
- const marks = textFormattingToMarks(mergedFormatting, {
1647
+ const marks = textFormattingToMarks(mergedFormatting, schema, {
1491
1648
  overrideFormatting,
1492
1649
  directFormatting: runFormatting,
1493
1650
  authoredCarrier
@@ -1498,55 +1655,6 @@ function buildRunMarks(runFormatting, inherited, styleResolver) {
1498
1655
  mergedFormatting
1499
1656
  };
1500
1657
  }
1501
- const addDirectFontProvenance = (marks, directFormatting) => {
1502
- const directFontProperties = [];
1503
- if (directFormatting?.fontFamily !== void 0) directFontProperties.push("fontFamily");
1504
- if (directFormatting?.fontSize !== void 0) directFontProperties.push("fontSize");
1505
- if (directFormatting?.color !== void 0) directFontProperties.push("color");
1506
- if (directFontProperties.length === 0) return;
1507
- const index = marks.findIndex(({ type }) => type.name === "runFormattingOverride");
1508
- const existing = index >= 0 ? marks.at(index) : void 0;
1509
- const override = schema.mark("runFormattingOverride", {
1510
- ...existing?.attrs,
1511
- directFontProperties
1512
- });
1513
- if (index >= 0) {
1514
- marks[index] = override;
1515
- return;
1516
- }
1517
- marks.push(override);
1518
- };
1519
- const COMPLEX_SCRIPT_MIRRORS = [
1520
- {
1521
- ordinary: "bold",
1522
- complex: "boldCs"
1523
- },
1524
- {
1525
- ordinary: "italic",
1526
- complex: "italicCs"
1527
- },
1528
- {
1529
- ordinary: "fontSize",
1530
- complex: "fontSizeCs"
1531
- }
1532
- ];
1533
- const addComplexScriptAbsenceProvenance = (marks, directFormatting) => {
1534
- const absent = COMPLEX_SCRIPT_MIRRORS.filter(({ ordinary, complex }) => directFormatting?.[ordinary] !== void 0 && directFormatting[complex] === void 0).map(({ complex }) => complex);
1535
- if (absent.length === 0) return;
1536
- const index = marks.findIndex(({ type }) => type.name === "runFormattingOverride");
1537
- const existing = index >= 0 ? marks.at(index) : void 0;
1538
- const existingAbsences = new Set(existing?.attrs["complexScriptPropertyAbsences"] ?? []);
1539
- for (const property of absent) existingAbsences.add(property);
1540
- const override = schema.mark("runFormattingOverride", {
1541
- ...existing?.attrs,
1542
- complexScriptPropertyAbsences: COMPLEX_SCRIPT_RUN_PROPERTY_KEYS.filter((property) => existingAbsences.has(property))
1543
- });
1544
- if (index >= 0) {
1545
- marks[index] = override;
1546
- return;
1547
- }
1548
- marks.push(override);
1549
- };
1550
1658
  const ORDINARY_STYLE_TOGGLE_KEYS = [
1551
1659
  "strike",
1552
1660
  "allCaps",
@@ -1564,9 +1672,28 @@ function getRunFormattingOverrides({ directFormatting, effectiveStyleFormatting,
1564
1672
  return overrides;
1565
1673
  }
1566
1674
  /**
1675
+ * The vertical alignment a note reference mark carries.
1676
+ *
1677
+ * The mark models the two alignments a reference can sit at; `subscript` is not
1678
+ * one of them and drops to `null`. `baseline` is read through its owner, since
1679
+ * it is the reserved "no offset" value rather than an offset of its own.
1680
+ */
1681
+ const noteReferenceVertAlign = (vertAlign) => {
1682
+ if (isBaselineVertAlign(vertAlign)) return "baseline";
1683
+ return vertAlign === "superscript" ? "superscript" : null;
1684
+ };
1685
+ /**
1686
+ * The run properties an inline atom has to carry itself.
1687
+ *
1688
+ * `withRunBoundaryMarks` keeps the run's formatting marks off an image or
1689
+ * shape node, so the node is the only place left to record the `w:rPr` the
1690
+ * run was authored with.
1691
+ */
1692
+ const carriedRunFormatting = (formatting) => formatting && Object.keys(formatting).length > 0 ? formatting : void 0;
1693
+ /**
1567
1694
  * Convert RunContent to ProseMirror nodes
1568
1695
  */
1569
- function convertRunContent(content, marks, formatting, textBoxAnchors) {
1696
+ function convertRunContent(content, marks, formatting, textBoxAnchors, authoredFormatting) {
1570
1697
  switch (content.type) {
1571
1698
  case "text":
1572
1699
  if (content.text) return [schema.text(content.text, marks)];
@@ -1590,7 +1717,8 @@ function convertRunContent(content, marks, formatting, textBoxAnchors) {
1590
1717
  image: content.image,
1591
1718
  rawXml: content.rawXml,
1592
1719
  rawXmlMode: content.rawXmlMode,
1593
- rawImageFingerprint: content.rawXmlMode === DRAWING_RAW_XML_MODES.PRESERVE_ONLY ? void 0 : content.rawImageFingerprint
1720
+ rawImageFingerprint: content.rawXmlMode === DRAWING_RAW_XML_MODES.PRESERVE_ONLY ? void 0 : content.rawImageFingerprint,
1721
+ runFormatting: carriedRunFormatting(authoredFormatting)
1594
1722
  }), marks)];
1595
1723
  case "shape": {
1596
1724
  const shp = content.shape;
@@ -1598,13 +1726,13 @@ function convertRunContent(content, marks, formatting, textBoxAnchors) {
1598
1726
  const anchorId = textBoxAnchors?.get(shp);
1599
1727
  return anchorId ? [schema.node("textBoxAnchor", { anchorId }).mark(marks)] : [];
1600
1728
  }
1601
- return [withRunBoundaryMarks(convertShape(shp), marks)];
1729
+ return [withRunBoundaryMarks(convertShape(shp, carriedRunFormatting(authoredFormatting)), marks)];
1602
1730
  }
1603
1731
  case "footnoteRef": {
1604
1732
  const footnoteMark = schema.mark("footnoteRef", {
1605
1733
  id: content.id.toString(),
1606
1734
  noteType: "footnote",
1607
- vertAlign: formatting?.vertAlign === "baseline" || formatting?.vertAlign === "superscript" ? formatting.vertAlign : null
1735
+ vertAlign: noteReferenceVertAlign(formatting?.vertAlign)
1608
1736
  });
1609
1737
  return [schema.text(content.id.toString(), [...marks, footnoteMark])];
1610
1738
  }
@@ -1612,7 +1740,7 @@ function convertRunContent(content, marks, formatting, textBoxAnchors) {
1612
1740
  const endnoteMark = schema.mark("footnoteRef", {
1613
1741
  id: content.id.toString(),
1614
1742
  noteType: "endnote",
1615
- vertAlign: formatting?.vertAlign === "baseline" || formatting?.vertAlign === "superscript" ? formatting.vertAlign : null
1743
+ vertAlign: noteReferenceVertAlign(formatting?.vertAlign)
1616
1744
  });
1617
1745
  return [schema.text(content.id.toString(), [...marks, endnoteMark])];
1618
1746
  }
@@ -1630,7 +1758,7 @@ function withRunBoundaryMarks(node, marks) {
1630
1758
  if (!marks.some(({ type }) => type.name === "hyperlink" || type.name === "pageBreakRunOwner")) return node;
1631
1759
  return node.mark(marks);
1632
1760
  }
1633
- function convertImage({ image, rawXml, rawXmlMode, rawImageFingerprint }) {
1761
+ function convertImage({ image, rawXml, rawXmlMode, rawImageFingerprint, runFormatting }) {
1634
1762
  const imageSize = image.size;
1635
1763
  const widthPx = imageSize?.width ? emuToPixels(imageSize.width) : void 0;
1636
1764
  const heightPx = imageSize?.height ? emuToPixels(imageSize.height) : void 0;
@@ -1738,7 +1866,8 @@ function convertImage({ image, rawXml, rawXmlMode, rawImageFingerprint }) {
1738
1866
  _docxRawXml: rawXml,
1739
1867
  _docxRawXmlMode: rawXmlMode,
1740
1868
  _docxRawImageFingerprint: rawImageFingerprint,
1741
- _docxObjectPreview: rawXml !== void 0 && /<(?:[A-Za-z_][\w.-]*:)?object(?:\s|>)/u.test(rawXml)
1869
+ _docxObjectPreview: rawXml !== void 0 && /<(?:[A-Za-z_][\w.-]*:)?object(?:\s|>)/u.test(rawXml),
1870
+ _docxRunFormatting: runFormatting
1742
1871
  });
1743
1872
  }
1744
1873
  function convertHyperlink(hyperlink, { getInheritedRunFormatting, styleResolver, hyperlinkIndex, textBoxAnchors, nextPageBreakRunOwnerId }) {
@@ -1757,14 +1886,16 @@ function convertHyperlink(hyperlink, { getInheritedRunFormatting, styleResolver,
1757
1886
  id: child.id,
1758
1887
  name: child.name,
1759
1888
  colFirst: child.colFirst,
1760
- colLast: child.colLast
1889
+ colLast: child.colLast,
1890
+ displacedByCustomXml: child.displacedByCustomXml
1761
1891
  }, void 0, [linkMark]));
1762
1892
  continue;
1763
1893
  }
1764
1894
  if (child.type === "bookmarkEnd") {
1765
1895
  nodes.push(schema.node("bookmarkBoundary", {
1766
1896
  type: "end",
1767
- id: child.id
1897
+ id: child.id,
1898
+ displacedByCustomXml: child.displacedByCustomXml
1768
1899
  }, void 0, [linkMark]));
1769
1900
  continue;
1770
1901
  }
@@ -1775,82 +1906,15 @@ function convertHyperlink(hyperlink, { getInheritedRunFormatting, styleResolver,
1775
1906
  if (child.propertyChanges && child.propertyChanges.length > 0) runMarks.push(schema.mark("runPropertyChange", { changes: [...child.propertyChanges] }));
1776
1907
  if (child.content.some((content) => content.type === "break" && content.breakType === "page")) runMarks.push(schema.mark("pageBreakRunOwner", { id: nextPageBreakRunOwnerId() }));
1777
1908
  const allMarks = [...runMarks, linkMark];
1778
- for (const content of child.content) nodes.push(...convertRunContent(content, allMarks, mergedFormatting, textBoxAnchors));
1909
+ for (const content of child.content) nodes.push(...convertRunContent(content, allMarks, mergedFormatting, textBoxAnchors, child.formatting));
1779
1910
  }
1780
1911
  }
1781
1912
  return nodes;
1782
1913
  }
1783
- function textFormattingToMarks(formatting, options) {
1784
- if (!formatting) return [];
1785
- const marks = [];
1786
- const overrideFormatting = options ? options.overrideFormatting : formatting;
1787
- let overrideAttrs;
1788
- if (options?.authoredCarrier === "reconstruct") overrideAttrs = buildRunFormattingOverrideAttrs(overrideFormatting, { type: "structural-only" });
1789
- else if (options) overrideAttrs = buildRunFormattingOverrideAttrs(overrideFormatting, {
1790
- type: "authored-baseline",
1791
- formatting: options.directFormatting
1792
- });
1793
- else overrideAttrs = buildRunFormattingOverrideAttrs(overrideFormatting);
1794
- if (overrideAttrs) marks.push(schema.mark("runFormattingOverride", overrideAttrs));
1795
- if (formatting.bold) marks.push(schema.mark("bold"));
1796
- if (formatting.italic) marks.push(schema.mark("italic"));
1797
- if (formatting.underline && formatting.underline.style !== "none") marks.push(schema.mark("underline", {
1798
- style: formatting.underline.style,
1799
- color: formatting.underline.color
1800
- }));
1801
- if (formatting.strike || formatting.doubleStrike) marks.push(schema.mark("strike", { double: formatting.doubleStrike || false }));
1802
- if (formatting.color && !formatting.color.auto) marks.push(schema.mark("textColor", {
1803
- rgb: formatting.color.rgb,
1804
- themeColor: formatting.color.themeColor,
1805
- themeTint: formatting.color.themeTint,
1806
- themeShade: formatting.color.themeShade
1807
- }));
1808
- if (formatting.highlight && formatting.highlight !== "none") marks.push(schema.mark("highlight", { color: formatting.highlight }));
1809
- const runShadingMarkAttrs = shadingToRunShadingAttrs(formatting.shading);
1810
- if (runShadingMarkAttrs) marks.push(schema.mark("runShading", runShadingMarkAttrs));
1811
- if (formatting.fontSize) marks.push(schema.mark("fontSize", { size: formatting.fontSize }));
1812
- if (formatting.fontFamily) marks.push(schema.mark("fontFamily", {
1813
- ascii: formatting.fontFamily.ascii,
1814
- hAnsi: formatting.fontFamily.hAnsi,
1815
- eastAsia: formatting.fontFamily.eastAsia,
1816
- cs: formatting.fontFamily.cs,
1817
- hint: formatting.fontFamily.hint,
1818
- asciiTheme: formatting.fontFamily.asciiTheme,
1819
- hAnsiTheme: formatting.fontFamily.hAnsiTheme,
1820
- eastAsiaTheme: formatting.fontFamily.eastAsiaTheme,
1821
- csTheme: formatting.fontFamily.csTheme
1822
- }));
1823
- if (formatting.language) marks.push(schema.mark("language", formatting.language));
1824
- if (formatting.vertAlign === "superscript") marks.push(schema.mark("superscript"));
1825
- else if (formatting.vertAlign === "subscript") marks.push(schema.mark("subscript"));
1826
- if (formatting.allCaps) marks.push(schema.mark("allCaps"));
1827
- if (formatting.smallCaps) marks.push(schema.mark("smallCaps"));
1828
- const spacing = typeof formatting.spacing === "number" ? formatting.spacing : null;
1829
- const position = typeof formatting.position === "number" ? formatting.position : null;
1830
- const scale = normalizeHorizontalScalePercent(formatting.scale) ?? null;
1831
- const kerning = typeof formatting.kerning === "number" ? formatting.kerning : null;
1832
- if (spacing !== null || position !== null || scale !== null || kerning !== null) marks.push(schema.mark("characterSpacing", {
1833
- spacing,
1834
- position,
1835
- scale,
1836
- kerning
1837
- }));
1838
- if (formatting.hidden === true) marks.push(schema.mark("hidden"));
1839
- if (formatting.emboss) marks.push(schema.mark("emboss"));
1840
- if (formatting.imprint) marks.push(schema.mark("imprint"));
1841
- if (formatting.shadow) marks.push(schema.mark("textShadow"));
1842
- if (formatting.emphasisMark && formatting.emphasisMark !== "none") marks.push(schema.mark("emphasisMark", { type: formatting.emphasisMark }));
1843
- if (formatting.outline) marks.push(schema.mark("textOutline"));
1844
- if (formatting.rtl) marks.push(schema.mark("rtl"));
1845
- if (formatting.effect && formatting.effect !== "none") marks.push(schema.mark("textEffect", { effect: formatting.effect }));
1846
- addDirectFontProvenance(marks, options?.directFormatting);
1847
- if (options?.authoredCarrier === "preserve") addComplexScriptAbsenceProvenance(marks, options.directFormatting);
1848
- return marks;
1849
- }
1850
1914
  /**
1851
1915
  * Convert a Shape to a ProseMirror shape node (inline SVG)
1852
1916
  */
1853
- function convertShape(shape) {
1917
+ function convertShape(shape, runFormatting) {
1854
1918
  const shapeSize = shape.size;
1855
1919
  const widthPx = shapeSize?.width ? emuToPixels(shapeSize.width) : 100;
1856
1920
  const heightPx = shapeSize?.height ? emuToPixels(shapeSize.height) : 80;
@@ -1922,6 +1986,7 @@ function convertShape(shape) {
1922
1986
  }
1923
1987
  };
1924
1988
  return schema.node("shape", {
1989
+ _docxRunFormatting: runFormatting,
1925
1990
  shapeType: shapeAttrs.shapeType ?? "rect",
1926
1991
  geometryAdjustments: shape.geometryAdjustments === void 0 ? void 0 : JSON.stringify(shape.geometryAdjustments),
1927
1992
  shapeId: shape.id,
@@ -2238,24 +2303,33 @@ function headerFooterToProseDoc(content, options) {
2238
2303
  };
2239
2304
  const convertBlocks = (blocks) => {
2240
2305
  const out = [];
2241
- for (const block of blocks) if (block.type === "paragraph") {
2242
- const isDetachedWatermarkHost = Reflect.get(block, DETACHED_WATERMARK_HOST) === true;
2243
- const paragraphNodes = convertParagraphWithTextBoxes(block, styleResolver, {
2244
- textBoxGroupId: nextTextBoxGroupId(),
2245
- context: conversionContext,
2246
- preserveEmptyWrapper: isDetachedWatermarkHost
2247
- });
2248
- if (isDetachedWatermarkHost) {
2249
- const paragraphNodeIndex = paragraphNodes.findIndex(({ type }) => type.name === "paragraph");
2250
- const paragraphNode = paragraphNodes[paragraphNodeIndex];
2251
- if (paragraphNode) paragraphNodes[paragraphNodeIndex] = recreateProseNodeWithParagraphPropertySource(paragraphNode, { attrs: {
2252
- ...paragraphNode.attrs,
2253
- _detachedWatermarkHost: true
2254
- } });
2306
+ for (const block of blocks) switch (block.type) {
2307
+ case "paragraph": {
2308
+ const isDetachedWatermarkHost = Reflect.get(block, DETACHED_WATERMARK_HOST) === true;
2309
+ const paragraphNodes = convertParagraphWithTextBoxes(block, styleResolver, {
2310
+ textBoxGroupId: nextTextBoxGroupId(),
2311
+ context: conversionContext,
2312
+ preserveEmptyWrapper: isDetachedWatermarkHost
2313
+ });
2314
+ if (isDetachedWatermarkHost) {
2315
+ const paragraphNodeIndex = paragraphNodes.findIndex(({ type }) => type.name === "paragraph");
2316
+ const paragraphNode = paragraphNodes[paragraphNodeIndex];
2317
+ if (paragraphNode) paragraphNodes[paragraphNodeIndex] = recreateProseNodeWithParagraphPropertySource(paragraphNode, { attrs: {
2318
+ ...paragraphNode.attrs,
2319
+ _detachedWatermarkHost: true
2320
+ } });
2321
+ }
2322
+ out.push(...paragraphNodes);
2323
+ break;
2255
2324
  }
2256
- out.push(...paragraphNodes);
2257
- } else if (block.type === "table") out.push(convertTable(block, styleResolver, conversionContext));
2258
- else out.push(convertBlockSdt(block, convertBlocks));
2325
+ case "table":
2326
+ out.push(convertTable(block, styleResolver, conversionContext));
2327
+ break;
2328
+ case "blockSdt":
2329
+ out.push(convertBlockSdt(block, convertBlocks));
2330
+ break;
2331
+ default: panic(`Unsupported block content: ${JSON.stringify(block)}`);
2332
+ }
2259
2333
  return out;
2260
2334
  };
2261
2335
  nodes.push(...convertBlocks(content));
@@ -2274,4 +2348,4 @@ function createEmptyDoc() {
2274
2348
  return schema.node("doc", null, [schema.node("paragraph", {}, [])]);
2275
2349
  }
2276
2350
  //#endregion
2277
- export { UnsupportedDocxToProseMirrorConversionError, createEmptyDoc, footnoteToProseDoc, headerFooterToProseDoc, resolveParagraphDefaultTextFormatting, standaloneTableCellToProseMirror, textFormattingToMarks, toProseDoc };
2351
+ export { UnsupportedDocxToProseMirrorConversionError, createEmptyDoc, footnoteToProseDoc, headerFooterToProseDoc, resolveParagraphDefaultTextFormatting, standaloneTableCellToProseMirror, toProseDoc };