@stll/folio-core 0.36.0 → 0.37.1
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.
- package/README.md +59 -1
- package/dist/ai-edits/apply.js +689 -367
- package/dist/ai-edits/block-identity.d.ts +4 -1
- package/dist/ai-edits/block-identity.js +4 -1
- package/dist/ai-edits/blockRange.js +14 -14
- package/dist/ai-edits/clean-text.d.ts +40 -1
- package/dist/ai-edits/clean-text.js +52 -2
- package/dist/ai-edits/headless.d.ts +3 -1
- package/dist/ai-edits/headless.js +133 -71
- package/dist/ai-edits/index.d.ts +3 -3
- package/dist/ai-edits/index.js +2 -2
- package/dist/ai-edits/read.js +38 -20
- package/dist/ai-edits/snapshot.d.ts +14 -6
- package/dist/ai-edits/snapshot.js +99 -19
- package/dist/ai-edits/table-cell-mutations.js +1 -1
- package/dist/ai-edits/table-row-column-mutations.js +7 -0
- package/dist/ai-edits/table-template.d.ts +11 -1
- package/dist/ai-edits/table-template.js +49 -17
- package/dist/ai-edits/types.d.ts +60 -57
- package/dist/ai-suggestions/conflict.js +1 -4
- package/dist/ai-suggestions/text-positions.d.ts +8 -0
- package/dist/ai-suggestions/text-positions.js +27 -5
- package/dist/compare/__fixtures__/body-sequence.js +3 -4
- package/dist/compare/column-alignment.d.ts +13 -13
- package/dist/compare/column-alignment.js +78 -39
- package/dist/compare/compare.d.ts +4 -3
- package/dist/compare/compare.js +41 -5
- package/dist/compare/content-alignment.d.ts +95 -0
- package/dist/compare/content-alignment.js +1450 -0
- package/dist/compare/content-types.d.ts +100 -0
- package/dist/compare/content-types.js +0 -0
- package/dist/compare/content.d.ts +209 -0
- package/dist/compare/content.js +885 -0
- package/dist/compare/formatting.d.ts +5 -5
- package/dist/compare/formatting.js +6 -4
- package/dist/compare/plan.d.ts +6 -1
- package/dist/compare/plan.js +201 -569
- package/dist/compare/scenario.d.ts +2 -2
- package/dist/compare/types.d.ts +3 -3
- package/dist/compare/verification.d.ts +2 -2
- package/dist/compare/verification.js +25 -8
- package/dist/compat/eigenpal.d.ts +5 -3
- package/dist/compat/eigenpal.js +3 -2
- package/dist/controller/headerFooterEditorManager.js +14 -6
- package/dist/controller/hiddenEditorManager.d.ts +7 -2
- package/dist/controller/hiddenEditorManager.js +15 -6
- package/dist/controller/layoutPipeline.js +5 -3
- package/dist/controller/noteEditorManager.js +12 -7
- package/dist/display-list/build/headerFooterPrimitives.js +1 -0
- package/dist/display-list/build/storyPrimitives.d.ts +5 -2
- package/dist/display-list/build/storyPrimitives.js +60 -3
- package/dist/display-list/build/tablePrimitives.js +30 -0
- package/dist/display-list/primitives.d.ts +1 -1
- package/dist/document-operations.d.ts +8 -6
- package/dist/document-operations.js +121 -26
- package/dist/docx/blockContentParser.js +6 -27
- package/dist/docx/ensureParaIds.js +9 -4
- package/dist/docx/numberingParser.d.ts +3 -1
- package/dist/docx/numberingParser.js +4 -1
- package/dist/docx/paragraphParser.js +7 -6
- package/dist/docx/paragraphTraversal.js +30 -34
- package/dist/docx/rezip.d.ts +0 -8
- package/dist/docx/rezip.js +41 -16
- package/dist/docx/runParser.js +4 -2
- package/dist/docx/serializer/paragraphSerializer.js +2 -0
- package/dist/docx/serializer/runSerializer.js +5 -3
- package/dist/docx/serializer/trackedChangeAttributes.d.ts +3 -1
- package/dist/docx/serializer/trackedChangeAttributes.js +11 -1
- package/dist/docx/server/build.d.ts +1 -1
- package/dist/headless-layout.js +5 -4
- package/dist/index.d.ts +5 -3
- package/dist/index.js +3 -2
- package/dist/internal/headlessRevisionResolution.d.ts +23 -0
- package/dist/internal/headlessRevisionResolution.js +176 -0
- package/dist/internal/headlessRevisionResolutionGuard.d.ts +12 -0
- package/dist/internal/headlessRevisionResolutionGuard.js +28 -0
- package/dist/internal/pageBreakRunDescendantIndex.d.ts +9 -0
- package/dist/internal/pageBreakRunDescendantIndex.js +27 -0
- package/dist/internal/pageBreakRunPartition.d.ts +26 -0
- package/dist/internal/pageBreakRunPartition.js +35 -0
- package/dist/internal/pageBreakRunSourceDescendantIndex.d.ts +15 -0
- package/dist/internal/pageBreakRunSourceDescendantIndex.js +126 -0
- package/dist/internal/sectionEndpointResolution.d.ts +32 -0
- package/dist/internal/sectionEndpointResolution.js +38 -0
- package/dist/layout-bridge/convert/footnoteLayout.js +1 -0
- package/dist/layout-bridge/convert/headerFooterLayout.d.ts +16 -4
- package/dist/layout-bridge/convert/headerFooterLayout.js +48 -5
- package/dist/layout-bridge/convert/toFlowBlocks.d.ts +4 -0
- package/dist/layout-bridge/convert/toFlowBlocks.js +379 -75
- package/dist/layout-bridge/dom/clickToPositionDom.d.ts +8 -1
- package/dist/layout-bridge/dom/clickToPositionDom.js +114 -40
- package/dist/layout-bridge/dom/textStreamDom.d.ts +24 -0
- package/dist/layout-bridge/dom/textStreamDom.js +75 -0
- package/dist/layout-bridge/headerFooterLayout.js +16 -30
- package/dist/layout-engine/index.js +12 -3
- package/dist/layout-engine/measure/tableFragmentBorderGeometry.d.ts +17 -0
- package/dist/layout-engine/measure/tableFragmentBorderGeometry.js +24 -0
- package/dist/layout-engine/renderedBreakReconciliation.js +1 -1
- package/dist/layout-engine/types.d.ts +7 -0
- package/dist/layout-painter/imageLayout.d.ts +1 -1
- package/dist/layout-painter/renderTable.js +20 -0
- package/dist/model.d.ts +1 -1
- package/dist/paged-layout/rangeProjection.js +6 -9
- package/dist/paged-layout/transactionDirtyRange.d.ts +3 -1
- package/dist/paged-layout/transactionDirtyRange.js +23 -1
- package/dist/prosemirror/attrs/index.d.ts +7 -3
- package/dist/prosemirror/attrs/index.js +113 -7
- package/dist/prosemirror/bookmarkBoundaryIntegrity.d.ts +9 -0
- package/dist/prosemirror/bookmarkBoundaryIntegrity.js +22 -0
- package/dist/prosemirror/commands/comments.d.ts +10 -1
- package/dist/prosemirror/commands/comments.js +167 -59
- package/dist/prosemirror/commands/formatPainter.d.ts +45 -10
- package/dist/prosemirror/commands/formatPainter.js +319 -63
- package/dist/prosemirror/commands/index.d.ts +2 -2
- package/dist/prosemirror/commands/pageBreak.d.ts +5 -2
- package/dist/prosemirror/commands/pageBreak.js +18 -36
- package/dist/prosemirror/commands/propertyChangeScope.d.ts +7 -5
- package/dist/prosemirror/commands/propertyChangeScope.js +27 -18
- package/dist/prosemirror/conversion/fromProseDoc.d.ts +7 -2
- package/dist/prosemirror/conversion/fromProseDoc.js +809 -209
- package/dist/prosemirror/conversion/runShadingMark.js +2 -2
- package/dist/prosemirror/conversion/toProseDoc.d.ts +26 -1
- package/dist/prosemirror/conversion/toProseDoc.js +416 -283
- package/dist/prosemirror/extensions/StarterKit.js +4 -0
- package/dist/prosemirror/extensions/core/ParagraphExtension.js +12 -8
- package/dist/prosemirror/extensions/features/ListExtension.js +95 -123
- package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.js +1 -1
- package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.d.ts +27 -1
- package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.js +134 -30
- package/dist/prosemirror/extensions/features/pasteCleanup.js +9 -15
- package/dist/prosemirror/extensions/marks/BoldExtension.js +4 -3
- package/dist/prosemirror/extensions/marks/CharacterStyleExtension.d.ts +4 -7
- package/dist/prosemirror/extensions/marks/CharacterStyleExtension.js +5 -11
- package/dist/prosemirror/extensions/marks/FontSizeExtension.js +3 -3
- package/dist/prosemirror/extensions/marks/ItalicExtension.js +4 -3
- package/dist/prosemirror/extensions/marks/PageBreakRunOwnerExtension.d.ts +13 -0
- package/dist/prosemirror/extensions/marks/PageBreakRunOwnerExtension.js +39 -0
- package/dist/prosemirror/extensions/marks/RunFormattingOverrideExtension.d.ts +7 -1
- package/dist/prosemirror/extensions/marks/RunFormattingOverrideExtension.js +67 -21
- package/dist/prosemirror/extensions/marks/markUtils.d.ts +8 -1
- package/dist/prosemirror/extensions/marks/markUtils.js +88 -2
- package/dist/prosemirror/extensions/nodes/BookmarkBoundaryExtension.js +44 -3
- package/dist/prosemirror/extensions/nodes/FieldExtension.js +1 -1
- package/dist/prosemirror/extensions/nodes/HardBreakExtension.js +15 -4
- package/dist/prosemirror/extensions/nodes/PageBreakExtension.d.ts +6 -0
- package/dist/prosemirror/extensions/nodes/PageBreakExtension.js +6 -0
- package/dist/prosemirror/extensions/nodes/PageBreakRunExtension.d.ts +6 -0
- package/dist/prosemirror/extensions/nodes/PageBreakRunExtension.js +36 -0
- package/dist/prosemirror/findReplaceSelection.js +8 -3
- package/dist/prosemirror/index.d.ts +3 -3
- package/dist/prosemirror/listMarker.d.ts +26 -1
- package/dist/prosemirror/listMarker.js +108 -14
- package/dist/prosemirror/pageBreakRunProjection.d.ts +28 -0
- package/dist/prosemirror/pageBreakRunProjection.js +47 -0
- package/dist/prosemirror/paraText.js +6 -0
- package/dist/prosemirror/paragraphSpacing.d.ts +29 -0
- package/dist/prosemirror/paragraphSpacing.js +125 -0
- package/dist/prosemirror/plugins/documentNumbering.d.ts +8 -0
- package/dist/prosemirror/plugins/documentNumbering.js +18 -0
- package/dist/prosemirror/plugins/pmTextScan.d.ts +3 -2
- package/dist/prosemirror/plugins/pmTextScan.js +14 -4
- package/dist/prosemirror/plugins/suggestionMode.js +8 -10
- package/dist/prosemirror/rebaseParagraphRunFormatting.d.ts +16 -0
- package/dist/prosemirror/rebaseParagraphRunFormatting.js +61 -0
- package/dist/prosemirror/runFormattingInlineCarriers.d.ts +64 -0
- package/dist/prosemirror/runFormattingInlineCarriers.js +121 -0
- package/dist/prosemirror/runFormattingProvenance.d.ts +12 -0
- package/dist/prosemirror/runFormattingProvenance.js +48 -0
- package/dist/prosemirror/runFormattingReconciliation.d.ts +25 -0
- package/dist/prosemirror/runFormattingReconciliation.js +54 -0
- package/dist/prosemirror/runPropertyChangeResolution.d.ts +18 -0
- package/dist/prosemirror/runPropertyChangeResolution.js +18 -0
- package/dist/prosemirror/runStyleFormatting.d.ts +50 -0
- package/dist/prosemirror/runStyleFormatting.js +105 -0
- package/dist/prosemirror/schema/index.d.ts +3 -3
- package/dist/prosemirror/schema/marks.d.ts +82 -9
- package/dist/prosemirror/schema/marks.js +73 -1
- package/dist/prosemirror/schema/nodes.d.ts +18 -5
- package/dist/prosemirror/styles/resolvedStyleAttrs.d.ts +14 -2
- package/dist/prosemirror/styles/resolvedStyleAttrs.js +44 -23
- package/dist/prosemirror/styles/styleResolver.d.ts +10 -13
- package/dist/prosemirror/styles/styleResolver.js +3 -3
- package/dist/prosemirror/styles/styleToggleCascade.d.ts +8 -1
- package/dist/prosemirror/styles/styleToggleCascade.js +24 -1
- package/dist/prosemirror/tableGridMutation.d.ts +20 -0
- package/dist/prosemirror/tableGridMutation.js +30 -0
- package/dist/prosemirror/trackedRunInlineAtoms.d.ts +31 -0
- package/dist/prosemirror/trackedRunInlineAtoms.js +39 -0
- package/dist/prosemirror/utils/visualLineNavigation.js +27 -31
- package/dist/prosemirror/validation.js +23 -4
- package/dist/render-dom/HeaderFooterSelectionOverlay.js +20 -20
- package/dist/render-dom/RenderedDomContext.js +17 -34
- package/dist/server.d.ts +4 -4
- package/dist/server.js +2 -2
- package/dist/style-engine/styleEngine.d.ts +1 -1
- package/dist/utils/clipboard.js +1 -1
- package/dist/utils/findReplace.js +38 -21
- package/dist/version-comparison.d.ts +38 -44
- package/dist/version-comparison.js +270 -401
- package/package.json +3 -2
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { resolveColorValueToHex } from "../../docx/drawingUtils.js";
|
|
2
2
|
import { linkProseParagraphPropertySource, recreateProseNodeWithParagraphPropertySource } from "../../docx/paragraphPropertySource.js";
|
|
3
|
+
import { buildPageBreakRunSourceDescendantIndex } from "../../internal/pageBreakRunSourceDescendantIndex.js";
|
|
3
4
|
import { createStyleEngine } from "../../style-engine/styleEngine.js";
|
|
4
5
|
import { normalizeHorizontalScalePercent } from "../../utils/horizontalScale.js";
|
|
5
6
|
import { mergeParagraphFormatting, mergeParagraphTabStops } from "../../utils/paragraphFormattingMerge.js";
|
|
@@ -9,16 +10,22 @@ import { emuToPixels } from "../../utils/units.js";
|
|
|
9
10
|
import { setAutospacingBaseValue } from "../autospacingBase.js";
|
|
10
11
|
import { buildRunFormattingOverrideAttrs } from "../extensions/marks/RunFormattingOverrideExtension.js";
|
|
11
12
|
import { stampNumberedRefFieldBaselines } from "../numberedRefFields.js";
|
|
13
|
+
import { pageBreakRunParagraphProjectionDispositionForFeatures } from "../pageBreakRunProjection.js";
|
|
12
14
|
import { directionFromBidi } from "../paragraphDirection.js";
|
|
15
|
+
import { lineSpacingProvenanceFromSpacing } from "../paragraphSpacing.js";
|
|
16
|
+
import { getParagraphMarkSuppressionOverrides, hasDirectRunFormatting, stripParagraphMarkFormattingForBodyRuns, stripParagraphMarkOnlyFormatting, suppressParagraphMarkFormatting } from "../runStyleFormatting.js";
|
|
13
17
|
import { schema } from "../schema/index.js";
|
|
18
|
+
import { COMPLEX_SCRIPT_RUN_PROPERTY_KEYS } from "../schema/marks.js";
|
|
14
19
|
import { cascadeStyleTextFormatting } from "../styles/styleToggleCascade.js";
|
|
20
|
+
import { canCarryTrackedRunMark, trackedRunInlineAtomDisposition } from "../trackedRunInlineAtoms.js";
|
|
15
21
|
import { assertValidProseMirrorDocument } from "../validation.js";
|
|
16
22
|
import { resolveEffectiveTableCellFormatting } from "./effectiveTableCellFormatting.js";
|
|
17
|
-
import { marksToTextFormatting } from "./fromProseDoc.js";
|
|
18
23
|
import { shadingToRunShadingAttrs } from "./runShadingMark.js";
|
|
19
24
|
import { sdtAttrsFromProperties } from "./sdtAttrs.js";
|
|
20
|
-
import { panic } from "better-result";
|
|
25
|
+
import { TaggedError, panic } from "better-result";
|
|
21
26
|
//#region src/prosemirror/conversion/toProseDoc.ts
|
|
27
|
+
/** DOCX content that cannot be preserved by the editable ProseMirror model. */
|
|
28
|
+
var UnsupportedDocxToProseMirrorConversionError = class extends TaggedError("UnsupportedDocxToProseMirrorConversionError") {};
|
|
22
29
|
const DETACHED_WATERMARK_HOST = Symbol.for("stll.detachedWatermarkHost");
|
|
23
30
|
/**
|
|
24
31
|
* Build a `nextTextBoxGroupId()` generator salted with a random per-load
|
|
@@ -106,36 +113,16 @@ function toProseDoc(document, options) {
|
|
|
106
113
|
theme,
|
|
107
114
|
nextTextBoxGroupId,
|
|
108
115
|
nextHyperlinkInstanceIndex: createHyperlinkInstanceIndexAllocator(),
|
|
109
|
-
pairedBookmarkIds: collectPairedBookmarkIds(paragraphs)
|
|
116
|
+
pairedBookmarkIds: collectPairedBookmarkIds(paragraphs),
|
|
117
|
+
pageBreakRunSourceDescendants: buildPageBreakRunSourceDescendantIndex(paragraphs)
|
|
110
118
|
};
|
|
111
119
|
const convertBodyBlocks = (blocks) => {
|
|
112
120
|
const out = [];
|
|
113
|
-
for (const block of blocks) if (block.type === "paragraph") {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
context: conversionContext
|
|
119
|
-
});
|
|
120
|
-
const firstConverted = converted.at(0);
|
|
121
|
-
if (pbPos === "before" && converted.length === 1 && firstConverted?.type.name === "paragraph" && firstConverted.content.size === 0 && document.package.settings?.splitPageBreakAndParagraphMark !== true) {
|
|
122
|
-
const paragraph = firstConverted;
|
|
123
|
-
converted[0] = recreateProseNodeWithParagraphPropertySource(paragraph, { attrs: {
|
|
124
|
-
...paragraph.attrs,
|
|
125
|
-
_pageBreakCarrier: true
|
|
126
|
-
} });
|
|
127
|
-
}
|
|
128
|
-
if (pbPos === "after") {
|
|
129
|
-
const paragraphIndex = converted.findIndex((node) => node.type.name === "paragraph");
|
|
130
|
-
const trailingParagraph = paragraphIndex >= 0 ? converted.at(paragraphIndex) : void 0;
|
|
131
|
-
if (trailingParagraph) converted[paragraphIndex] = recreateProseNodeWithParagraphPropertySource(trailingParagraph, { attrs: {
|
|
132
|
-
...trailingParagraph.attrs,
|
|
133
|
-
_trailingPageBreak: true
|
|
134
|
-
} });
|
|
135
|
-
}
|
|
136
|
-
out.push(...converted);
|
|
137
|
-
if (pbPos === "after") out.push(schema.node("pageBreak"));
|
|
138
|
-
} else if (block.type === "table") out.push(convertTable(block, styleResolver, conversionContext));
|
|
121
|
+
for (const block of blocks) if (block.type === "paragraph") out.push(...convertParagraphWithTextBoxes(block, styleResolver, {
|
|
122
|
+
textBoxGroupId: nextTextBoxGroupId(),
|
|
123
|
+
context: conversionContext
|
|
124
|
+
}));
|
|
125
|
+
else if (block.type === "table") out.push(convertTable(block, styleResolver, conversionContext));
|
|
139
126
|
else out.push(convertBlockSdt(block, convertBodyBlocks));
|
|
140
127
|
return out;
|
|
141
128
|
};
|
|
@@ -187,8 +174,17 @@ function convertBlockSdt(blockSdt, convertBlocks) {
|
|
|
187
174
|
* Resolves style-based text formatting and passes it to runs so that
|
|
188
175
|
* paragraph styles (like Heading1) apply their font size, color, etc.
|
|
189
176
|
*/
|
|
190
|
-
function convertParagraph(paragraph, styleResolver,
|
|
191
|
-
const
|
|
177
|
+
function convertParagraph(paragraph, styleResolver, context, activeCommentIds, extraRunFormatting, tableParagraphOverlay, textBoxAnchors) {
|
|
178
|
+
const { nextHyperlinkInstanceIndex, pairedBookmarkIds, pageBreakRunSourceDescendants } = context;
|
|
179
|
+
let pageBreakRunOwnerId = 0;
|
|
180
|
+
const nextPageBreakRunOwnerId = () => pageBreakRunOwnerId++;
|
|
181
|
+
const { attrs, effectiveFrame } = paragraphFormattingToAttrs(paragraph, styleResolver, tableParagraphOverlay);
|
|
182
|
+
assertParagraphPageBreakCanBeProjected({
|
|
183
|
+
paragraph,
|
|
184
|
+
attrs,
|
|
185
|
+
effectiveFrame,
|
|
186
|
+
sourceDescendants: pageBreakRunSourceDescendants
|
|
187
|
+
});
|
|
192
188
|
const isTocParagraph = attrs._tableOfContentsLevel !== void 0;
|
|
193
189
|
const inlineNodes = [];
|
|
194
190
|
let inlineOffset = 0;
|
|
@@ -216,7 +212,7 @@ function convertParagraph(paragraph, styleResolver, nextHyperlinkInstanceIndex,
|
|
|
216
212
|
}
|
|
217
213
|
const paragraphRunFormatting = resolveRunFormattingWithoutDefaults(paragraph.formatting?.runProperties, styleResolver);
|
|
218
214
|
let inheritableParagraphRunFormatting;
|
|
219
|
-
if (paragraphRunFormatting && !isTocParagraph) inheritableParagraphRunFormatting = stripParagraphMarkFormattingForBodyRuns(paragraphRunFormatting);
|
|
215
|
+
if (paragraphRunFormatting && !isTocParagraph && paragraph.formatting?.styleId === void 0) inheritableParagraphRunFormatting = stripParagraphMarkFormattingForBodyRuns(paragraphRunFormatting);
|
|
220
216
|
const ordinaryStyleFormatting = paragraph.formatting?.styleId === void 0 ? mergeTextFormatting(styleRunFormatting, extraRunFormatting) : mergeTextFormatting(extraRunFormatting, styleRunFormatting);
|
|
221
217
|
const orderedToggleFormatting = cascadeStyleTextFormatting([
|
|
222
218
|
{
|
|
@@ -234,53 +230,75 @@ function convertParagraph(paragraph, styleResolver, nextHyperlinkInstanceIndex,
|
|
|
234
230
|
], { ordinaryFormatting: ordinaryStyleFormatting });
|
|
235
231
|
let baseRunFormatting = orderedToggleFormatting.formatting;
|
|
236
232
|
if (paragraphStyleFontFamily) baseRunFormatting = mergeTextFormatting(baseRunFormatting, { fontFamily: paragraphStyleFontFamily });
|
|
237
|
-
const
|
|
238
|
-
const
|
|
239
|
-
const
|
|
233
|
+
const defaultCharacterFormatting = styleResolver?.getDefaultCharacterStyle()?.rPr;
|
|
234
|
+
const ordinaryBaseWithDefaultCharacter = mergeTextFormatting(defaultCharacterFormatting, baseRunFormatting);
|
|
235
|
+
const defaultCharacterStyleCascade = cascadeStyleTextFormatting([{
|
|
240
236
|
cascade: orderedToggleFormatting,
|
|
241
237
|
type: "carried"
|
|
242
|
-
}
|
|
243
|
-
|
|
238
|
+
}, {
|
|
239
|
+
formatting: defaultCharacterFormatting,
|
|
240
|
+
type: "style"
|
|
241
|
+
}], { ordinaryFormatting: ordinaryBaseWithDefaultCharacter });
|
|
242
|
+
const ordinaryDefaultRunFormatting = mergeTextFormatting(ordinaryBaseWithDefaultCharacter, inheritableParagraphRunFormatting);
|
|
243
|
+
const defaultToggleCascade = cascadeStyleTextFormatting([{
|
|
244
|
+
cascade: defaultCharacterStyleCascade,
|
|
244
245
|
type: "carried"
|
|
245
246
|
}, {
|
|
246
247
|
formatting: inheritableParagraphRunFormatting,
|
|
247
248
|
type: "direct"
|
|
248
249
|
}], { ordinaryFormatting: ordinaryDefaultRunFormatting });
|
|
249
250
|
const defaultRunFormatting = defaultToggleCascade.formatting;
|
|
251
|
+
if (extraRunFormatting !== void 0) if (defaultRunFormatting) attrs.defaultTextFormatting = defaultRunFormatting;
|
|
252
|
+
else delete attrs.defaultTextFormatting;
|
|
250
253
|
const getInheritedRunFormatting = (formatting, fieldType) => {
|
|
254
|
+
const hasCharacterStyle = formatting?.styleId !== void 0;
|
|
255
|
+
const inheritedBaseFormatting = hasCharacterStyle ? baseRunFormatting : ordinaryBaseWithDefaultCharacter;
|
|
256
|
+
const inheritedToggleCascade = hasCharacterStyle ? orderedToggleFormatting : defaultCharacterStyleCascade;
|
|
251
257
|
if (fieldType === "TOC") return {
|
|
252
|
-
formatting: hasDirectRunFormatting(formatting) ? suppressParagraphMarkFormatting(
|
|
253
|
-
|
|
258
|
+
formatting: hasDirectRunFormatting(formatting) ? suppressParagraphMarkFormatting({
|
|
259
|
+
baseFormatting: inheritedBaseFormatting,
|
|
260
|
+
directFormatting: formatting,
|
|
261
|
+
paragraphMarkFormatting: void 0
|
|
262
|
+
}) : inheritedBaseFormatting,
|
|
263
|
+
...!hasCharacterStyle ? { implicitCharacterStyleApplied: true } : {},
|
|
264
|
+
toggleCascade: inheritedToggleCascade
|
|
254
265
|
};
|
|
255
266
|
if (!(hasDirectRunFormatting(formatting) || formatting?.styleId !== void 0)) return {
|
|
256
267
|
formatting: defaultRunFormatting,
|
|
268
|
+
implicitCharacterStyleApplied: true,
|
|
257
269
|
toggleCascade: defaultToggleCascade
|
|
258
270
|
};
|
|
259
|
-
const suppressedFormatting = suppressParagraphMarkFormatting(
|
|
271
|
+
const suppressedFormatting = suppressParagraphMarkFormatting({
|
|
272
|
+
baseFormatting: inheritedBaseFormatting,
|
|
273
|
+
directFormatting: formatting,
|
|
274
|
+
paragraphMarkFormatting: inheritableParagraphRunFormatting
|
|
275
|
+
});
|
|
260
276
|
const paragraphMarkOverrides = getParagraphMarkSuppressionOverrides({
|
|
261
277
|
directFormatting: formatting,
|
|
262
278
|
paragraphMarkFormatting: inheritableParagraphRunFormatting,
|
|
263
279
|
suppressedFormatting
|
|
264
|
-
});
|
|
280
|
+
}) ?? (inheritableParagraphRunFormatting ? {} : void 0);
|
|
265
281
|
return {
|
|
266
282
|
formatting: suppressedFormatting,
|
|
283
|
+
...!hasCharacterStyle ? { implicitCharacterStyleApplied: true } : {},
|
|
267
284
|
...paragraphMarkOverrides ? { paragraphMarkOverrides } : {},
|
|
268
|
-
toggleCascade:
|
|
285
|
+
toggleCascade: inheritedToggleCascade
|
|
269
286
|
};
|
|
270
287
|
};
|
|
271
288
|
const emitTrackedChange = (change, markType, moveKind) => {
|
|
272
|
-
emitInlineNodes(convertTrackedChange(change, markType, nextHyperlinkInstanceIndex, getInheritedRunFormatting, styleResolver, moveKind, textBoxAnchors));
|
|
289
|
+
emitInlineNodes(convertTrackedChange(change, markType, nextHyperlinkInstanceIndex, nextPageBreakRunOwnerId, getInheritedRunFormatting, styleResolver, moveKind, textBoxAnchors));
|
|
273
290
|
};
|
|
274
291
|
for (const content of paragraph.content) if (content.type === "commentRangeStart") commentIds.add(content.id);
|
|
275
292
|
else if (content.type === "commentRangeEnd") commentIds.delete(content.id);
|
|
276
293
|
else if (content.type === "commentReference") anchorPointComment(inlineNodes, content.id);
|
|
277
|
-
else if (content.type === "run") emitInlineNodes(convertRun(content, getInheritedRunFormatting(content.formatting), styleResolver, textBoxAnchors));
|
|
294
|
+
else if (content.type === "run") emitInlineNodes(convertRun(content, getInheritedRunFormatting(content.formatting), nextPageBreakRunOwnerId, styleResolver, textBoxAnchors));
|
|
278
295
|
else if (content.type === "hyperlink") {
|
|
279
296
|
const linkNodes = convertHyperlink(content, {
|
|
280
297
|
getInheritedRunFormatting,
|
|
281
298
|
styleResolver,
|
|
282
299
|
hyperlinkIndex: nextHyperlinkInstanceIndex(),
|
|
283
|
-
textBoxAnchors
|
|
300
|
+
textBoxAnchors,
|
|
301
|
+
nextPageBreakRunOwnerId
|
|
284
302
|
});
|
|
285
303
|
if (linkNodes.length === 0) {
|
|
286
304
|
emptyHyperlinks ??= [];
|
|
@@ -298,9 +316,10 @@ function convertParagraph(paragraph, styleResolver, nextHyperlinkInstanceIndex,
|
|
|
298
316
|
getInheritedRunFormatting,
|
|
299
317
|
styleResolver,
|
|
300
318
|
nextHyperlinkInstanceIndex,
|
|
319
|
+
nextPageBreakRunOwnerId,
|
|
301
320
|
textBoxAnchors
|
|
302
321
|
}));
|
|
303
|
-
else if (content.type === "inlineSdt") emitInlineNode(convertInlineSdt(content, nextHyperlinkInstanceIndex, getInheritedRunFormatting, styleResolver, textBoxAnchors));
|
|
322
|
+
else if (content.type === "inlineSdt") emitInlineNode(convertInlineSdt(content, nextHyperlinkInstanceIndex, nextPageBreakRunOwnerId, getInheritedRunFormatting, styleResolver, textBoxAnchors));
|
|
304
323
|
else if (content.type === "insertion" || content.type === "moveTo") emitTrackedChange(content, "insertion", content.type === "moveTo" ? "moveTo" : null);
|
|
305
324
|
else if (content.type === "deletion" || content.type === "moveFrom") emitTrackedChange(content, "deletion", content.type === "moveFrom" ? "moveFrom" : null);
|
|
306
325
|
else if (content.type === "mathEquation") emitInlineNode(convertMathEquation(content));
|
|
@@ -366,29 +385,31 @@ function anchorPointComment(nodes, commentId) {
|
|
|
366
385
|
* Convert tracked change (insertion or deletion) content to PM nodes with
|
|
367
386
|
* an insertion/deletion mark applied.
|
|
368
387
|
*/
|
|
369
|
-
function convertTrackedChange(change, markType, nextHyperlinkInstanceIndex, getInheritedRunFormatting, styleResolver, moveKind = null, textBoxAnchors) {
|
|
388
|
+
function convertTrackedChange(change, markType, nextHyperlinkInstanceIndex, nextPageBreakRunOwnerId, getInheritedRunFormatting, styleResolver, moveKind = null, textBoxAnchors) {
|
|
370
389
|
const nodes = [];
|
|
371
|
-
for (const item of change.content) if (item.type === "run") nodes.push(...convertRun(item, getInheritedRunFormatting(item.formatting), styleResolver, textBoxAnchors));
|
|
390
|
+
for (const item of change.content) if (item.type === "run") nodes.push(...convertRun(item, getInheritedRunFormatting(item.formatting), nextPageBreakRunOwnerId, styleResolver, textBoxAnchors));
|
|
372
391
|
else if (item.type === "hyperlink") {
|
|
373
392
|
const currentHyperlinkIndex = nextHyperlinkInstanceIndex();
|
|
374
393
|
nodes.push(...convertHyperlink(item, {
|
|
375
394
|
getInheritedRunFormatting,
|
|
376
395
|
styleResolver,
|
|
377
396
|
hyperlinkIndex: currentHyperlinkIndex,
|
|
378
|
-
textBoxAnchors
|
|
397
|
+
textBoxAnchors,
|
|
398
|
+
nextPageBreakRunOwnerId
|
|
379
399
|
}));
|
|
380
400
|
} else if (item.type === "simpleField" || item.type === "complexField") {
|
|
381
401
|
const fieldNode = convertField(item, {
|
|
382
402
|
getInheritedRunFormatting,
|
|
383
403
|
styleResolver,
|
|
384
404
|
nextHyperlinkInstanceIndex,
|
|
405
|
+
nextPageBreakRunOwnerId,
|
|
385
406
|
textBoxAnchors
|
|
386
407
|
});
|
|
387
408
|
if (fieldNode) nodes.push(fieldNode);
|
|
388
409
|
} else if (item.type === "insertion" || item.type === "deletion" || item.type === "moveFrom" || item.type === "moveTo") {
|
|
389
410
|
const nestedMarkType = item.type === "insertion" || item.type === "moveTo" ? "insertion" : "deletion";
|
|
390
411
|
const nestedMoveKind = item.type === "moveFrom" || item.type === "moveTo" ? item.type : null;
|
|
391
|
-
nodes.push(...convertTrackedChange(item, nestedMarkType, nextHyperlinkInstanceIndex, getInheritedRunFormatting, styleResolver, nestedMoveKind, textBoxAnchors));
|
|
412
|
+
nodes.push(...convertTrackedChange(item, nestedMarkType, nextHyperlinkInstanceIndex, nextPageBreakRunOwnerId, getInheritedRunFormatting, styleResolver, nestedMoveKind, textBoxAnchors));
|
|
392
413
|
} else if (item.type === "bookmarkStart") nodes.push(schema.node("bookmarkBoundary", {
|
|
393
414
|
type: "start",
|
|
394
415
|
id: item.id,
|
|
@@ -411,22 +432,11 @@ function convertTrackedChange(change, markType, nextHyperlinkInstanceIndex, getI
|
|
|
411
432
|
});
|
|
412
433
|
return nodes.map((node) => {
|
|
413
434
|
if (node.marks.some(({ type }) => type.name === "insertion" || type.name === "deletion")) return node;
|
|
414
|
-
if (
|
|
435
|
+
if (trackedRunInlineAtomDisposition(node) === "outside-wrapper") panic(`Inline atom ${JSON.stringify(node.type.name)} cannot occur in a tracked-run wrapper`);
|
|
436
|
+
if (canCarryTrackedRunMark(node)) return node.mark(mark.addToSet(node.marks));
|
|
415
437
|
return node;
|
|
416
438
|
});
|
|
417
439
|
}
|
|
418
|
-
function canCarryTrackedRunMark(node, markType) {
|
|
419
|
-
if (node.isText) return true;
|
|
420
|
-
if (!node.isInline) return false;
|
|
421
|
-
if (node.type.name === "field" || node.type.name === "structuredField") return true;
|
|
422
|
-
return node.type.allowsMarkType(markType) && (node.type.name === "image" || node.type.name === "shape" || node.type.name === "hardBreak" || node.type.name === "tab" || node.type.name === "symbol" || node.type.name === "bookmarkBoundary" || node.type.name === "textBoxAnchor");
|
|
423
|
-
}
|
|
424
|
-
/**
|
|
425
|
-
* Convert ParagraphFormatting to ProseMirror paragraph attrs
|
|
426
|
-
*
|
|
427
|
-
* If a styleResolver is provided, resolves style-based formatting and merges
|
|
428
|
-
* with inline formatting. Inline formatting takes precedence.
|
|
429
|
-
*/
|
|
430
440
|
function paragraphFormattingToAttrs(paragraph, styleResolver, tableParagraphOverlay) {
|
|
431
441
|
const formatting = paragraph.formatting;
|
|
432
442
|
const styleId = formatting?.styleId;
|
|
@@ -446,6 +456,7 @@ function paragraphFormattingToAttrs(paragraph, styleResolver, tableParagraphOver
|
|
|
446
456
|
if (paragraph.listRendering?.isBullet) attrs.listIsBullet = paragraph.listRendering.isBullet;
|
|
447
457
|
if (paragraph.listRendering?.isLegal) attrs.listIsLegal = paragraph.listRendering.isLegal;
|
|
448
458
|
if (paragraph.listRendering?.marker) attrs.listMarker = paragraph.listRendering.marker;
|
|
459
|
+
if (paragraph.listRendering?.markerTemplate) attrs.listMarkerTemplate = paragraph.listRendering.markerTemplate;
|
|
449
460
|
if (paragraph.listRendering?.markerHidden) attrs.listMarkerHidden = paragraph.listRendering.markerHidden;
|
|
450
461
|
if (paragraph.listRendering?.markerFormatting) attrs.listMarkerFormatting = paragraph.listRendering.markerFormatting;
|
|
451
462
|
if (paragraph.listRendering?.markerAlignment) attrs.listMarkerAlignment = paragraph.listRendering.markerAlignment;
|
|
@@ -475,15 +486,15 @@ function paragraphFormattingToAttrs(paragraph, styleResolver, tableParagraphOver
|
|
|
475
486
|
set("spaceAfter", formatting?.spaceAfter ?? stylePpr?.spaceAfter);
|
|
476
487
|
set("lineSpacing", formatting?.lineSpacing ?? stylePpr?.lineSpacing);
|
|
477
488
|
set("lineSpacingRule", formatting?.lineSpacingRule ?? stylePpr?.lineSpacingRule);
|
|
478
|
-
set("lineSpacingExplicit", formatting
|
|
489
|
+
set("lineSpacingExplicit", lineSpacingProvenanceFromSpacing(formatting));
|
|
479
490
|
set("snapToGrid", formatting?.snapToGrid ?? stylePpr?.snapToGrid);
|
|
480
491
|
set("spacingExplicit", formatting?.spacingExplicit);
|
|
481
492
|
const paragraphStyle = styleId ? styleResolver.getStyle(styleId) ?? styleResolver.getDefaultParagraphStyle() : styleResolver.getDefaultParagraphStyle();
|
|
482
493
|
const docDefaultSpacing = styleResolver.getDocDefaults()?.pPr;
|
|
483
|
-
const
|
|
484
|
-
if (
|
|
485
|
-
if (
|
|
486
|
-
if (
|
|
494
|
+
const spacingFromStyle = {};
|
|
495
|
+
if (formatting?.spaceBefore === void 0 && stylePpr?.spaceBefore !== void 0) spacingFromStyle.before = true;
|
|
496
|
+
if (formatting?.spaceAfter === void 0 && stylePpr?.spaceAfter !== void 0) spacingFromStyle.after = true;
|
|
497
|
+
if (spacingFromStyle.before || spacingFromStyle.after) attrs.spacingFromImplicitDefaultStyle = spacingFromStyle;
|
|
487
498
|
const spacingFromDocDefaults = {};
|
|
488
499
|
if (formatting?.spaceBefore === void 0 && tableParagraphOverlay?.spaceBefore === void 0 && paragraphStyle?.pPr?.spaceBefore === void 0 && docDefaultSpacing?.spaceBefore !== void 0) spacingFromDocDefaults.before = true;
|
|
489
500
|
if (formatting?.spaceAfter === void 0 && tableParagraphOverlay?.spaceAfter === void 0 && paragraphStyle?.pPr?.spaceAfter === void 0 && docDefaultSpacing?.spaceAfter !== void 0) spacingFromDocDefaults.after = true;
|
|
@@ -507,9 +518,12 @@ function paragraphFormattingToAttrs(paragraph, styleResolver, tableParagraphOver
|
|
|
507
518
|
set("runInWithNext", formatting?.runInWithNext ?? stylePpr?.runInWithNext);
|
|
508
519
|
set("outlineLevel", formatting?.outlineLevel ?? stylePpr?.outlineLevel);
|
|
509
520
|
set("direction", directionFromBidi(formatting?.bidi ?? stylePpr?.bidi));
|
|
510
|
-
set("defaultTextFormatting", resolveParagraphDefaultTextFormatting(styleId, formatting, styleResolver, { includeParagraphMarkRunProperties: tableOfContentsLevel === void 0 }));
|
|
511
|
-
if (
|
|
512
|
-
attrs.numPr =
|
|
521
|
+
set("defaultTextFormatting", resolveParagraphDefaultTextFormatting(styleId, formatting, styleResolver, { includeParagraphMarkRunProperties: tableOfContentsLevel === void 0 && (styleId === void 0 || paragraph.content.length === 0) }));
|
|
522
|
+
if (stylePpr?.numPr && formatting?.numPr?.numId === void 0 && stylePpr.numPr.numId !== 0) {
|
|
523
|
+
attrs.numPr = {
|
|
524
|
+
...stylePpr.numPr,
|
|
525
|
+
...formatting?.numPr
|
|
526
|
+
};
|
|
513
527
|
attrs.numPrFromStyle = stylePpr.numPr;
|
|
514
528
|
}
|
|
515
529
|
} else {
|
|
@@ -518,6 +532,7 @@ function paragraphFormattingToAttrs(paragraph, styleResolver, tableParagraphOver
|
|
|
518
532
|
set("spaceAfter", formatting?.spaceAfter);
|
|
519
533
|
set("lineSpacing", formatting?.lineSpacing);
|
|
520
534
|
set("lineSpacingRule", formatting?.lineSpacingRule);
|
|
535
|
+
set("lineSpacingExplicit", lineSpacingProvenanceFromSpacing(formatting));
|
|
521
536
|
set("snapToGrid", formatting?.snapToGrid);
|
|
522
537
|
set("spacingExplicit", formatting?.spacingExplicit);
|
|
523
538
|
set("indentLeft", formatting?.indentLeft);
|
|
@@ -553,15 +568,19 @@ function paragraphFormattingToAttrs(paragraph, styleResolver, tableParagraphOver
|
|
|
553
568
|
if (afterAutospacing) setAutospacingBaseValue(base, "after", attrs.spaceAfter);
|
|
554
569
|
attrs._autospacingBase = base;
|
|
555
570
|
}
|
|
556
|
-
return
|
|
571
|
+
return {
|
|
572
|
+
attrs,
|
|
573
|
+
effectiveFrame: formatting?.frame === void 0 ? stylePpr?.frame : {
|
|
574
|
+
...stylePpr?.frame,
|
|
575
|
+
...formatting.frame
|
|
576
|
+
}
|
|
577
|
+
};
|
|
557
578
|
}
|
|
558
579
|
/**
|
|
559
|
-
* Pick the paragraph
|
|
560
|
-
* region's) `w:pPr` for use as the cell-paragraph cascade overlay.
|
|
561
|
-
* than the full `ParagraphFormatting` bag — see
|
|
562
|
-
* {@link TableCellParagraphSpacingOverlay}.
|
|
580
|
+
* Pick the modeled paragraph fields out of a table style's (or conditional
|
|
581
|
+
* region's) `w:pPr` for use as the cell-paragraph cascade overlay.
|
|
563
582
|
*/
|
|
564
|
-
function
|
|
583
|
+
function extractTableParagraphOverlay(pPr) {
|
|
565
584
|
if (!pPr) return;
|
|
566
585
|
const overlay = {};
|
|
567
586
|
if (pPr.spaceBefore !== void 0) overlay.spaceBefore = pPr.spaceBefore;
|
|
@@ -569,6 +588,7 @@ function extractTableParagraphSpacingOverlay(pPr) {
|
|
|
569
588
|
if (pPr.lineSpacing !== void 0) overlay.lineSpacing = pPr.lineSpacing;
|
|
570
589
|
if (pPr.lineSpacingRule !== void 0) overlay.lineSpacingRule = pPr.lineSpacingRule;
|
|
571
590
|
if (pPr.contextualSpacing !== void 0) overlay.contextualSpacing = pPr.contextualSpacing;
|
|
591
|
+
if (pPr.frame !== void 0) overlay.frame = pPr.frame;
|
|
572
592
|
return Object.keys(overlay).length > 0 ? overlay : void 0;
|
|
573
593
|
}
|
|
574
594
|
/**
|
|
@@ -581,11 +601,11 @@ function resolveTableStyleConditional(styleResolver, tableStyleId, conditionType
|
|
|
581
601
|
const conditional = style.tblStylePr.find((p) => p.type === conditionType);
|
|
582
602
|
if (!conditional) return;
|
|
583
603
|
const mergedRunProps = mergeTextFormatting(conditional.pPr?.runProperties ? resolveRunFormattingWithoutDefaults(conditional.pPr.runProperties, styleResolver) : void 0, conditional.rPr ? resolveRunFormattingWithoutDefaults(conditional.rPr, styleResolver) : void 0);
|
|
584
|
-
const
|
|
604
|
+
const paragraphOverlay = extractTableParagraphOverlay(conditional.pPr);
|
|
585
605
|
const result = {};
|
|
586
606
|
if (conditional.tcPr) result.tcPr = conditional.tcPr;
|
|
587
607
|
if (mergedRunProps) result.rPr = mergedRunProps;
|
|
588
|
-
if (
|
|
608
|
+
if (paragraphOverlay) result.pPr = paragraphOverlay;
|
|
589
609
|
return result;
|
|
590
610
|
}
|
|
591
611
|
function resolveTableBaseStyle(styleResolver, tableStyleId) {
|
|
@@ -593,11 +613,11 @@ function resolveTableBaseStyle(styleResolver, tableStyleId) {
|
|
|
593
613
|
const style = styleResolver.getStyle(tableStyleId);
|
|
594
614
|
if (!style) return;
|
|
595
615
|
const mergedRunProps = mergeTextFormatting(style.pPr?.runProperties ? resolveRunFormattingWithoutDefaults(style.pPr.runProperties, styleResolver) : void 0, style.rPr ? resolveRunFormattingWithoutDefaults(style.rPr, styleResolver) : void 0);
|
|
596
|
-
const
|
|
616
|
+
const paragraphOverlay = extractTableParagraphOverlay(style.pPr);
|
|
597
617
|
const result = {};
|
|
598
618
|
if (style.tcPr) result.tcPr = style.tcPr;
|
|
599
619
|
if (mergedRunProps) result.rPr = mergedRunProps;
|
|
600
|
-
if (
|
|
620
|
+
if (paragraphOverlay) result.pPr = paragraphOverlay;
|
|
601
621
|
return result.tcPr || result.rPr || result.pPr ? result : void 0;
|
|
602
622
|
}
|
|
603
623
|
function mergeConditionalStyles(base, override) {
|
|
@@ -632,70 +652,11 @@ function mergeConditionalStyles(base, override) {
|
|
|
632
652
|
if (mergedPPr) merged.pPr = mergedPPr;
|
|
633
653
|
return merged;
|
|
634
654
|
}
|
|
635
|
-
function hasDirectRunFormatting(formatting) {
|
|
636
|
-
if (!formatting) return false;
|
|
637
|
-
for (const key in formatting) {
|
|
638
|
-
if (!Object.hasOwn(formatting, key)) continue;
|
|
639
|
-
const value = Reflect.get(formatting, key);
|
|
640
|
-
if (key !== "styleId" && value !== void 0) return true;
|
|
641
|
-
}
|
|
642
|
-
return false;
|
|
643
|
-
}
|
|
644
|
-
function stripParagraphMarkOnlyFormatting(formatting) {
|
|
645
|
-
const { allCaps: _ac, highlight: _h, shading: _s, smallCaps: _sc, vertAlign: _va, ...rest } = formatting;
|
|
646
|
-
return Object.keys(rest).length > 0 ? rest : void 0;
|
|
647
|
-
}
|
|
648
|
-
function stripParagraphMarkFormattingForBodyRuns(formatting) {
|
|
649
|
-
const paragraphMarkFormatting = stripParagraphMarkOnlyFormatting(formatting);
|
|
650
|
-
if (!paragraphMarkFormatting) return;
|
|
651
|
-
const { fontFamily: _fontFamily, ...bodyRunFormatting } = paragraphMarkFormatting;
|
|
652
|
-
return Object.keys(bodyRunFormatting).length > 0 ? bodyRunFormatting : void 0;
|
|
653
|
-
}
|
|
654
|
-
const PARAGRAPH_MARK_BOOLEAN_KEYS = [
|
|
655
|
-
"bold",
|
|
656
|
-
"italic",
|
|
657
|
-
"strike",
|
|
658
|
-
"doubleStrike",
|
|
659
|
-
"allCaps",
|
|
660
|
-
"smallCaps",
|
|
661
|
-
"hidden",
|
|
662
|
-
"emboss",
|
|
663
|
-
"imprint",
|
|
664
|
-
"shadow",
|
|
665
|
-
"outline",
|
|
666
|
-
"rtl"
|
|
667
|
-
];
|
|
668
|
-
function suppressParagraphMarkFormatting(base, paragraphMark, direct, paragraphMarkPrecedesStyle = false) {
|
|
669
|
-
if (!paragraphMark) return base;
|
|
670
|
-
const result = (paragraphMarkPrecedesStyle ? mergeTextFormatting(paragraphMark, base) : mergeTextFormatting(base, paragraphMark)) ?? {};
|
|
671
|
-
for (const key of PARAGRAPH_MARK_BOOLEAN_KEYS) suppressBooleanParagraphMark(result, base, paragraphMark, direct, key);
|
|
672
|
-
if (paragraphMark.fontSize !== void 0 && direct?.fontSize === void 0 && base?.fontSize !== void 0) result.fontSize = base.fontSize;
|
|
673
|
-
if (paragraphMark.fontSizeCs !== void 0 && direct?.fontSizeCs === void 0 && base?.fontSizeCs !== void 0) result.fontSizeCs = base.fontSizeCs;
|
|
674
|
-
if (paragraphMark.underline !== void 0 && direct?.underline === void 0) result.underline = { style: "none" };
|
|
675
|
-
if (paragraphMark.spacing !== void 0 && direct?.spacing === void 0) result.spacing = 0;
|
|
676
|
-
return Object.keys(result).length > 0 ? result : void 0;
|
|
677
|
-
}
|
|
678
|
-
function getParagraphMarkSuppressionOverrides({ directFormatting, paragraphMarkFormatting, suppressedFormatting }) {
|
|
679
|
-
if (!paragraphMarkFormatting) return;
|
|
680
|
-
const overrides = {};
|
|
681
|
-
for (const key of PARAGRAPH_MARK_BOOLEAN_KEYS) if (paragraphMarkFormatting[key] !== void 0 && directFormatting?.[key] === void 0 && suppressedFormatting?.[key] === false) overrides[key] = false;
|
|
682
|
-
if (paragraphMarkFormatting.underline !== void 0 && directFormatting?.underline === void 0 && suppressedFormatting?.underline?.style === "none") overrides.underline = { style: "none" };
|
|
683
|
-
return Object.keys(overrides).length > 0 ? overrides : void 0;
|
|
684
|
-
}
|
|
685
|
-
function suppressBooleanParagraphMark(result, base, paragraphMark, direct, key) {
|
|
686
|
-
if (paragraphMark[key] === void 0 || direct?.[key] !== void 0) return;
|
|
687
|
-
result[key] = base?.[key] ?? false;
|
|
688
|
-
}
|
|
689
655
|
function resolveTextFormatting(formatting, styleResolver) {
|
|
690
656
|
if (!formatting) return styleResolver?.resolveRunStyle(null);
|
|
691
657
|
if (!styleResolver) return formatting;
|
|
692
658
|
return mergeTextFormatting(styleResolver.resolveRunStyle(formatting.styleId), formatting);
|
|
693
659
|
}
|
|
694
|
-
/**
|
|
695
|
-
* Resolve an embedded character-style reference without importing
|
|
696
|
-
* `docDefaults`. The caller already has the paragraph cascade, including
|
|
697
|
-
* document defaults, and will layer these own properties over it.
|
|
698
|
-
*/
|
|
699
660
|
function resolveRunFormattingWithoutDefaults(formatting, styleResolver) {
|
|
700
661
|
if (!formatting || !styleResolver) return formatting;
|
|
701
662
|
return cascadeStyleTextFormatting([{
|
|
@@ -706,6 +667,7 @@ function resolveRunFormattingWithoutDefaults(formatting, styleResolver) {
|
|
|
706
667
|
type: "direct"
|
|
707
668
|
}]).formatting;
|
|
708
669
|
}
|
|
670
|
+
/** @internal Recompute a paragraph's inherited run defaults from authored package state. */
|
|
709
671
|
function resolveParagraphDefaultTextFormatting(styleId, formatting, styleResolver, options = {}) {
|
|
710
672
|
const style = styleId ? styleResolver.getStyle(styleId) ?? styleResolver.getDefaultParagraphStyle() : styleResolver.getDefaultParagraphStyle();
|
|
711
673
|
const paragraphStyleRpr = style?.type === "paragraph" ? style.rPr : void 0;
|
|
@@ -726,10 +688,6 @@ function resolveParagraphDefaultTextFormatting(styleId, formatting, styleResolve
|
|
|
726
688
|
}
|
|
727
689
|
], { ordinaryFormatting: mergeTextFormatting(mergeTextFormatting(styleResolver.getDocDefaults()?.rPr, styleResolver.getDefaultCharacterStyle()?.rPr), paragraphStyleRpr) });
|
|
728
690
|
const bodyRunDefaults = orderedBodyToggleFormatting.formatting;
|
|
729
|
-
if (styleId !== void 0) return cascadeStyleTextFormatting([{
|
|
730
|
-
cascade: orderedBodyToggleFormatting,
|
|
731
|
-
type: "carried"
|
|
732
|
-
}], { ordinaryFormatting: mergeTextFormatting(paragraphRunProperties, bodyRunDefaults) }).formatting;
|
|
733
691
|
return cascadeStyleTextFormatting([{
|
|
734
692
|
cascade: orderedBodyToggleFormatting,
|
|
735
693
|
type: "carried"
|
|
@@ -831,6 +789,7 @@ function paragraphContentHasMeaningfulContent(content) {
|
|
|
831
789
|
return true;
|
|
832
790
|
}
|
|
833
791
|
function convertTable(table, styleResolver, context) {
|
|
792
|
+
for (const row of table.rows) for (const cell of row.cells) assertSourceContainerHasNoPageBreakRun(cell.content, "table-cell", context.pageBreakRunSourceDescendants);
|
|
834
793
|
const rowSpanMap = calculateRowSpans(table);
|
|
835
794
|
const columnWidths = table.columnWidths;
|
|
836
795
|
const totalWidth = columnWidths?.reduce((sum, w) => sum + w, 0) ?? 0;
|
|
@@ -967,10 +926,7 @@ function convertTableRow(row, styleResolver, context, isHeaderRow, columnWidths,
|
|
|
967
926
|
if (effectiveCells.length === 0) {
|
|
968
927
|
const fallback = {
|
|
969
928
|
type: "tableCell",
|
|
970
|
-
content: [
|
|
971
|
-
type: "paragraph",
|
|
972
|
-
content: []
|
|
973
|
-
}]
|
|
929
|
+
content: []
|
|
974
930
|
};
|
|
975
931
|
if (totalCols > 1) fallback.formatting = { gridSpan: totalCols };
|
|
976
932
|
effectiveCells = [fallback];
|
|
@@ -1135,14 +1091,19 @@ function convertTableCell({ cell, styleResolver, context, isHeader, gridWidthPer
|
|
|
1135
1091
|
return schema.node(nodeType, attrs, contentNodes);
|
|
1136
1092
|
}
|
|
1137
1093
|
function standaloneTableCellToProseMirror(cell, nodeType) {
|
|
1094
|
+
const nextTextBoxGroupId = createTextBoxGroupIdFactory();
|
|
1095
|
+
const nextHyperlinkInstanceIndex = createHyperlinkInstanceIndexAllocator();
|
|
1096
|
+
const pageBreakRunSourceDescendants = buildPageBreakRunSourceDescendantIndex(cell.content);
|
|
1097
|
+
assertSourceContainerHasNoPageBreakRun(cell.content, "table-cell", pageBreakRunSourceDescendants);
|
|
1138
1098
|
return convertTableCell({
|
|
1139
1099
|
cell,
|
|
1140
1100
|
styleResolver: null,
|
|
1141
1101
|
context: {
|
|
1142
1102
|
theme: null,
|
|
1143
|
-
nextTextBoxGroupId
|
|
1144
|
-
nextHyperlinkInstanceIndex
|
|
1145
|
-
pairedBookmarkIds: collectPairedBookmarkIds(cell.content)
|
|
1103
|
+
nextTextBoxGroupId,
|
|
1104
|
+
nextHyperlinkInstanceIndex,
|
|
1105
|
+
pairedBookmarkIds: collectPairedBookmarkIds(cell.content),
|
|
1106
|
+
pageBreakRunSourceDescendants
|
|
1146
1107
|
},
|
|
1147
1108
|
isHeader: nodeType === "tableHeader",
|
|
1148
1109
|
gridWidthPercent: void 0,
|
|
@@ -1155,16 +1116,26 @@ function standaloneTableCellToProseMirror(cell, nodeType) {
|
|
|
1155
1116
|
defaultCellMargins: void 0
|
|
1156
1117
|
});
|
|
1157
1118
|
}
|
|
1158
|
-
function convertField(field, { getInheritedRunFormatting, styleResolver, nextHyperlinkInstanceIndex, textBoxAnchors }) {
|
|
1119
|
+
function convertField(field, { getInheritedRunFormatting, styleResolver, nextHyperlinkInstanceIndex, nextPageBreakRunOwnerId, textBoxAnchors }) {
|
|
1159
1120
|
let displayText = "";
|
|
1160
1121
|
let fieldFormatting;
|
|
1122
|
+
let fieldPropertyChanges;
|
|
1161
1123
|
const inlineNodes = [];
|
|
1162
|
-
const
|
|
1124
|
+
const runHasPageBreak = (run) => run.content.some((content) => content.type === "break" && content.breakType === "page");
|
|
1125
|
+
if (field.type === "complexField" && field.fieldCode.some(runHasPageBreak)) throw new UnsupportedDocxToProseMirrorConversionError({
|
|
1126
|
+
message: "A complex-field instruction containing an explicit page break cannot be represented in the editor model",
|
|
1127
|
+
owner: "complex-field-instruction",
|
|
1128
|
+
contentType: "break"
|
|
1129
|
+
});
|
|
1130
|
+
const hasPageBreakContent = field.type === "simpleField" ? field.content.some((content) => content.type === "run" ? runHasPageBreak(content) : content.children.some((child) => child.type === "run" && runHasPageBreak(child))) : field.fieldResult.some(runHasPageBreak);
|
|
1131
|
+
if (hasPageBreakContent) assertPageBreakFieldResultIsRepresentable(field);
|
|
1132
|
+
const hasStructuredSourceContent = hasPageBreakContent || field.type === "simpleField" && field.content.some((content) => content.type === "hyperlink");
|
|
1163
1133
|
const appendRun = (run) => {
|
|
1164
1134
|
for (const content of run.content) if (content.type === "text") displayText += content.text;
|
|
1165
1135
|
fieldFormatting ??= run.formatting;
|
|
1136
|
+
fieldPropertyChanges ??= run.propertyChanges;
|
|
1166
1137
|
if (!hasStructuredSourceContent) return;
|
|
1167
|
-
inlineNodes.push(...convertRun(run, getInheritedRunFormatting(run.formatting, field.fieldType), styleResolver, textBoxAnchors));
|
|
1138
|
+
inlineNodes.push(...convertRun(run, getInheritedRunFormatting(run.formatting, field.fieldType), nextPageBreakRunOwnerId, styleResolver, textBoxAnchors));
|
|
1168
1139
|
};
|
|
1169
1140
|
if (field.type === "simpleField") for (const content of field.content) {
|
|
1170
1141
|
if (content.type === "run") {
|
|
@@ -1174,12 +1145,14 @@ function convertField(field, { getInheritedRunFormatting, styleResolver, nextHyp
|
|
|
1174
1145
|
for (const child of content.children) if (child.type === "run") {
|
|
1175
1146
|
for (const runContent of child.content) if (runContent.type === "text") displayText += runContent.text;
|
|
1176
1147
|
fieldFormatting ??= child.formatting;
|
|
1148
|
+
fieldPropertyChanges ??= child.propertyChanges;
|
|
1177
1149
|
}
|
|
1178
1150
|
inlineNodes.push(...convertHyperlink(content, {
|
|
1179
1151
|
getInheritedRunFormatting: (formatting) => getInheritedRunFormatting(formatting, field.fieldType),
|
|
1180
1152
|
styleResolver,
|
|
1181
1153
|
hyperlinkIndex: nextHyperlinkInstanceIndex(),
|
|
1182
|
-
textBoxAnchors
|
|
1154
|
+
textBoxAnchors,
|
|
1155
|
+
nextPageBreakRunOwnerId
|
|
1183
1156
|
}));
|
|
1184
1157
|
}
|
|
1185
1158
|
else for (const run of field.fieldResult) appendRun(run);
|
|
@@ -1187,7 +1160,8 @@ function convertField(field, { getInheritedRunFormatting, styleResolver, nextHyp
|
|
|
1187
1160
|
const inheritedFormatting = getInheritedRunFormatting(fieldFormatting, field.fieldType);
|
|
1188
1161
|
const { marks } = buildRunMarks(fieldFormatting, inheritedFormatting, styleResolver);
|
|
1189
1162
|
const hasConvertedHyperlinkContent = inlineNodes.some((node) => node.marks.some((mark) => mark.type.name === "hyperlink"));
|
|
1190
|
-
const createStructuredField = hasStructuredSourceContent && hasConvertedHyperlinkContent;
|
|
1163
|
+
const createStructuredField = inlineNodes.some((node) => node.type.name === "pageBreakRun") || hasStructuredSourceContent && hasConvertedHyperlinkContent;
|
|
1164
|
+
if (!createStructuredField && fieldPropertyChanges && fieldPropertyChanges.length > 0) marks.push(schema.mark("runPropertyChange", { changes: [...fieldPropertyChanges] }));
|
|
1191
1165
|
return schema.node(createStructuredField ? "structuredField" : "field", {
|
|
1192
1166
|
fieldType: field.fieldType,
|
|
1193
1167
|
instruction: field.instruction,
|
|
@@ -1210,18 +1184,19 @@ function convertMathEquation(math) {
|
|
|
1210
1184
|
/**
|
|
1211
1185
|
* Convert an InlineSdt to a ProseMirror sdt node with inline content.
|
|
1212
1186
|
*/
|
|
1213
|
-
function convertInlineSdt(sdt, nextHyperlinkInstanceIndex, getInheritedRunFormatting, styleResolver, textBoxAnchors) {
|
|
1187
|
+
function convertInlineSdt(sdt, nextHyperlinkInstanceIndex, nextPageBreakRunOwnerId, getInheritedRunFormatting, styleResolver, textBoxAnchors) {
|
|
1214
1188
|
const props = sdt.properties;
|
|
1215
1189
|
const inlineNodes = [];
|
|
1216
1190
|
for (const content of sdt.content) if (content.type === "run") {
|
|
1217
|
-
const runNodes = convertRun(content, getInheritedRunFormatting(content.formatting), styleResolver, textBoxAnchors);
|
|
1191
|
+
const runNodes = convertRun(content, getInheritedRunFormatting(content.formatting), nextPageBreakRunOwnerId, styleResolver, textBoxAnchors);
|
|
1218
1192
|
inlineNodes.push(...runNodes);
|
|
1219
1193
|
} else if (content.type === "hyperlink") {
|
|
1220
1194
|
const linkNodes = convertHyperlink(content, {
|
|
1221
1195
|
getInheritedRunFormatting,
|
|
1222
1196
|
styleResolver,
|
|
1223
1197
|
hyperlinkIndex: nextHyperlinkInstanceIndex(),
|
|
1224
|
-
textBoxAnchors
|
|
1198
|
+
textBoxAnchors,
|
|
1199
|
+
nextPageBreakRunOwnerId
|
|
1225
1200
|
});
|
|
1226
1201
|
inlineNodes.push(...linkNodes);
|
|
1227
1202
|
} else if (content.type === "simpleField" || content.type === "complexField") {
|
|
@@ -1229,16 +1204,17 @@ function convertInlineSdt(sdt, nextHyperlinkInstanceIndex, getInheritedRunFormat
|
|
|
1229
1204
|
getInheritedRunFormatting,
|
|
1230
1205
|
styleResolver,
|
|
1231
1206
|
nextHyperlinkInstanceIndex,
|
|
1207
|
+
nextPageBreakRunOwnerId,
|
|
1232
1208
|
textBoxAnchors
|
|
1233
1209
|
});
|
|
1234
1210
|
if (fieldNode) inlineNodes.push(fieldNode);
|
|
1235
1211
|
} else if (content.type === "inlineSdt") {
|
|
1236
|
-
const nestedSdt = convertInlineSdt(content, nextHyperlinkInstanceIndex, getInheritedRunFormatting, styleResolver, textBoxAnchors);
|
|
1212
|
+
const nestedSdt = convertInlineSdt(content, nextHyperlinkInstanceIndex, nextPageBreakRunOwnerId, getInheritedRunFormatting, styleResolver, textBoxAnchors);
|
|
1237
1213
|
if (nestedSdt) inlineNodes.push(nestedSdt);
|
|
1238
|
-
} else if (content.type === "insertion") inlineNodes.push(...convertTrackedChange(content, "insertion", nextHyperlinkInstanceIndex, getInheritedRunFormatting, styleResolver, null, textBoxAnchors));
|
|
1239
|
-
else if (content.type === "deletion") inlineNodes.push(...convertTrackedChange(content, "deletion", nextHyperlinkInstanceIndex, getInheritedRunFormatting, styleResolver, null, textBoxAnchors));
|
|
1240
|
-
else if (content.type === "moveTo") inlineNodes.push(...convertTrackedChange(content, "insertion", nextHyperlinkInstanceIndex, getInheritedRunFormatting, styleResolver, "moveTo", textBoxAnchors));
|
|
1241
|
-
else if (content.type === "moveFrom") inlineNodes.push(...convertTrackedChange(content, "deletion", nextHyperlinkInstanceIndex, getInheritedRunFormatting, styleResolver, "moveFrom", textBoxAnchors));
|
|
1214
|
+
} else if (content.type === "insertion") inlineNodes.push(...convertTrackedChange(content, "insertion", nextHyperlinkInstanceIndex, nextPageBreakRunOwnerId, getInheritedRunFormatting, styleResolver, null, textBoxAnchors));
|
|
1215
|
+
else if (content.type === "deletion") inlineNodes.push(...convertTrackedChange(content, "deletion", nextHyperlinkInstanceIndex, nextPageBreakRunOwnerId, getInheritedRunFormatting, styleResolver, null, textBoxAnchors));
|
|
1216
|
+
else if (content.type === "moveTo") inlineNodes.push(...convertTrackedChange(content, "insertion", nextHyperlinkInstanceIndex, nextPageBreakRunOwnerId, getInheritedRunFormatting, styleResolver, "moveTo", textBoxAnchors));
|
|
1217
|
+
else if (content.type === "moveFrom") inlineNodes.push(...convertTrackedChange(content, "deletion", nextHyperlinkInstanceIndex, nextPageBreakRunOwnerId, getInheritedRunFormatting, styleResolver, "moveFrom", textBoxAnchors));
|
|
1242
1218
|
else {
|
|
1243
1219
|
const mathNode = convertMathEquation(content);
|
|
1244
1220
|
if (mathNode) inlineNodes.push(mathNode);
|
|
@@ -1251,19 +1227,208 @@ function convertInlineSdt(sdt, nextHyperlinkInstanceIndex, getInheritedRunFormat
|
|
|
1251
1227
|
* @param run - The run to convert
|
|
1252
1228
|
* @param resolvedStyleFormatting - Paragraph formatting and its explicit style-toggle state
|
|
1253
1229
|
*/
|
|
1254
|
-
function convertRun(run, resolvedStyleFormatting, styleResolver, textBoxAnchors) {
|
|
1230
|
+
function convertRun(run, resolvedStyleFormatting, nextPageBreakRunOwnerId, styleResolver, textBoxAnchors) {
|
|
1231
|
+
assertPageBreakSourceRunIsRepresentable(run);
|
|
1255
1232
|
const nodes = [];
|
|
1256
1233
|
const { marks, mergedFormatting } = buildRunMarks(run.formatting, resolvedStyleFormatting, styleResolver);
|
|
1257
1234
|
if (run.propertyChanges && run.propertyChanges.length > 0) marks.push(schema.mark("runPropertyChange", { changes: [...run.propertyChanges] }));
|
|
1235
|
+
if (run.content.some((content) => content.type === "break" && content.breakType === "page")) marks.push(schema.mark("pageBreakRunOwner", { id: nextPageBreakRunOwnerId() }));
|
|
1258
1236
|
for (const content of run.content) {
|
|
1259
1237
|
const contentNodes = convertRunContent(content, marks, mergedFormatting, textBoxAnchors);
|
|
1260
1238
|
nodes.push(...contentNodes);
|
|
1261
1239
|
}
|
|
1262
1240
|
return nodes;
|
|
1263
1241
|
}
|
|
1242
|
+
function assertPageBreakSourceRunIsRepresentable(run) {
|
|
1243
|
+
if (!run.content.some((content) => content.type === "break" && content.breakType === "page")) return;
|
|
1244
|
+
assertRunContentIsRepresentableBesidePageBreak(run, "page-break-bearing-run");
|
|
1245
|
+
}
|
|
1246
|
+
const PAGE_BREAK_CONTAINER_DESCRIPTIONS = {
|
|
1247
|
+
"table-cell": "A table cell containing an explicit page break",
|
|
1248
|
+
"text-box": "A text box containing an explicit page break"
|
|
1249
|
+
};
|
|
1250
|
+
const PAGE_BREAK_PARAGRAPH_OWNERS = {
|
|
1251
|
+
borders: "paragraph-borders",
|
|
1252
|
+
frame: "paragraph-frame",
|
|
1253
|
+
outline: "paragraph-outline",
|
|
1254
|
+
textBoxAnchor: "paragraph-text-box-anchor"
|
|
1255
|
+
};
|
|
1256
|
+
function assertSourceContainerHasNoPageBreakRun(content, owner, sourceDescendants) {
|
|
1257
|
+
if (!sourceDescendants.containsPageBreakRun(content)) return;
|
|
1258
|
+
throw new UnsupportedDocxToProseMirrorConversionError({
|
|
1259
|
+
message: `${PAGE_BREAK_CONTAINER_DESCRIPTIONS[owner]} cannot be represented in the editor model`,
|
|
1260
|
+
owner,
|
|
1261
|
+
contentType: "break"
|
|
1262
|
+
});
|
|
1263
|
+
}
|
|
1264
|
+
function assertParagraphPageBreakCanBeProjected({ paragraph, attrs, effectiveFrame, sourceDescendants }) {
|
|
1265
|
+
const sourceFeatures = sourceDescendants.paragraphFeatures(paragraph);
|
|
1266
|
+
if (!sourceFeatures.hasPageBreakRun) return;
|
|
1267
|
+
const disposition = pageBreakRunParagraphProjectionDispositionForFeatures({
|
|
1268
|
+
attrs,
|
|
1269
|
+
effectiveFrame,
|
|
1270
|
+
hasTextBoxAnchor: sourceFeatures.hasTextBoxShape && !sourceFeatures.pageBreakSharesTextBoxShape
|
|
1271
|
+
});
|
|
1272
|
+
if (disposition.status === "supported") return;
|
|
1273
|
+
throw new UnsupportedDocxToProseMirrorConversionError({
|
|
1274
|
+
message: disposition.message,
|
|
1275
|
+
owner: PAGE_BREAK_PARAGRAPH_OWNERS[disposition.reason],
|
|
1276
|
+
contentType: "break"
|
|
1277
|
+
});
|
|
1278
|
+
}
|
|
1279
|
+
function assertPageBreakFieldResultIsRepresentable(field) {
|
|
1280
|
+
if (field.type === "complexField") {
|
|
1281
|
+
for (const run of field.fieldResult) assertRunContentIsRepresentableBesidePageBreak(run, "field-result");
|
|
1282
|
+
return;
|
|
1283
|
+
}
|
|
1284
|
+
for (const content of field.content) {
|
|
1285
|
+
if (content.type === "run") {
|
|
1286
|
+
assertRunContentIsRepresentableBesidePageBreak(content, "field-result");
|
|
1287
|
+
continue;
|
|
1288
|
+
}
|
|
1289
|
+
for (const child of content.children) if (child.type === "run") assertRunContentIsRepresentableBesidePageBreak(child, "field-result");
|
|
1290
|
+
}
|
|
1291
|
+
}
|
|
1292
|
+
const PAGE_BREAK_OWNER_DESCRIPTIONS = {
|
|
1293
|
+
"field-result": "A field result with an explicit page break",
|
|
1294
|
+
"page-break-bearing-run": "A page-break-bearing run"
|
|
1295
|
+
};
|
|
1296
|
+
const unsupportedPageBreakContent = (owner, contentType) => {
|
|
1297
|
+
const description = contentType === "shape" ? "a text-box shape" : contentType;
|
|
1298
|
+
throw new UnsupportedDocxToProseMirrorConversionError({
|
|
1299
|
+
message: `${PAGE_BREAK_OWNER_DESCRIPTIONS[owner]} containing ${description} cannot be represented in the editor model`,
|
|
1300
|
+
owner,
|
|
1301
|
+
contentType
|
|
1302
|
+
});
|
|
1303
|
+
};
|
|
1304
|
+
function assertRunContentIsRepresentableBesidePageBreak(run, owner) {
|
|
1305
|
+
for (const content of run.content) switch (content.type) {
|
|
1306
|
+
case "break":
|
|
1307
|
+
case "drawing":
|
|
1308
|
+
case "endnoteRef":
|
|
1309
|
+
case "footnoteRef":
|
|
1310
|
+
case "renderedPageBreak":
|
|
1311
|
+
case "symbol":
|
|
1312
|
+
case "tab":
|
|
1313
|
+
case "text": continue;
|
|
1314
|
+
case "shape":
|
|
1315
|
+
if (content.shape.textBody) unsupportedPageBreakContent(owner, content.type);
|
|
1316
|
+
continue;
|
|
1317
|
+
case "fieldChar":
|
|
1318
|
+
case "instrText":
|
|
1319
|
+
case "noBreakHyphen":
|
|
1320
|
+
case "softHyphen": return unsupportedPageBreakContent(owner, content.type);
|
|
1321
|
+
default: panic(`Unsupported page-break-bearing run content: ${JSON.stringify(content)}`);
|
|
1322
|
+
}
|
|
1323
|
+
}
|
|
1324
|
+
const RUN_FORMATTING_INFERENCE = {
|
|
1325
|
+
bold: "ordinary-toggle",
|
|
1326
|
+
boldCs: "structural",
|
|
1327
|
+
italic: "ordinary-toggle",
|
|
1328
|
+
italicCs: "structural",
|
|
1329
|
+
underline: "underline",
|
|
1330
|
+
strike: "visible-boolean",
|
|
1331
|
+
doubleStrike: "double-strike",
|
|
1332
|
+
vertAlign: "visible-value",
|
|
1333
|
+
smallCaps: "visible-boolean",
|
|
1334
|
+
allCaps: "visible-boolean",
|
|
1335
|
+
hidden: "visible-boolean",
|
|
1336
|
+
color: "color",
|
|
1337
|
+
highlight: "visible-value",
|
|
1338
|
+
shading: "preserve",
|
|
1339
|
+
fontSize: "font-size",
|
|
1340
|
+
fontSizeCs: "structural",
|
|
1341
|
+
fontFamily: "font-family",
|
|
1342
|
+
language: "nested-visible-value",
|
|
1343
|
+
spacing: "visible-value",
|
|
1344
|
+
position: "visible-value",
|
|
1345
|
+
scale: "scale",
|
|
1346
|
+
kerning: "visible-value",
|
|
1347
|
+
effect: "visible-value",
|
|
1348
|
+
emphasisMark: "visible-value",
|
|
1349
|
+
emboss: "visible-boolean",
|
|
1350
|
+
imprint: "visible-boolean",
|
|
1351
|
+
outline: "visible-boolean",
|
|
1352
|
+
shadow: "visible-boolean",
|
|
1353
|
+
rtl: "visible-boolean",
|
|
1354
|
+
cs: "structural",
|
|
1355
|
+
styleId: "structural"
|
|
1356
|
+
};
|
|
1357
|
+
const sameFormattingValue = (left, right) => {
|
|
1358
|
+
if (left === right) return true;
|
|
1359
|
+
if (typeof left !== "object" || left === null || typeof right !== "object" || right === null) return false;
|
|
1360
|
+
if (Array.isArray(left) || Array.isArray(right)) {
|
|
1361
|
+
if (!Array.isArray(left) || !Array.isArray(right) || left.length !== right.length) return false;
|
|
1362
|
+
return left.every((value, index) => sameFormattingValue(value, right.at(index)));
|
|
1363
|
+
}
|
|
1364
|
+
const leftEntries = Object.entries(left).filter(([, value]) => value !== void 0);
|
|
1365
|
+
const rightEntries = Object.entries(right).filter(([, value]) => value !== void 0);
|
|
1366
|
+
if (leftEntries.length !== rightEntries.length) return false;
|
|
1367
|
+
return leftEntries.every(([property, value]) => Object.hasOwn(right, property) && sameFormattingValue(value, Reflect.get(right, property)));
|
|
1368
|
+
};
|
|
1369
|
+
const isReconstructibleFontFamily = (directValue, effectiveValue) => {
|
|
1370
|
+
if (typeof directValue !== "object" || directValue === null || !sameFormattingValue(directValue, effectiveValue)) return false;
|
|
1371
|
+
const properties = Object.keys(directValue).filter((property) => Reflect.get(directValue, property) !== void 0);
|
|
1372
|
+
return properties.length === 2 && properties.includes("ascii") && properties.includes("hAnsi") && typeof Reflect.get(directValue, "ascii") === "string" && typeof Reflect.get(directValue, "hAnsi") === "string";
|
|
1373
|
+
};
|
|
1374
|
+
const canReconstructAuthoredRunFormatting = ({ directFormatting, effectiveFormatting, inheritedFormatting, paragraphMarkOverrides }) => {
|
|
1375
|
+
if (paragraphMarkOverrides !== void 0) return false;
|
|
1376
|
+
for (const property of Object.keys(directFormatting ?? {})) {
|
|
1377
|
+
const directValue = directFormatting?.[property];
|
|
1378
|
+
if (directValue === void 0 || property === "styleId") continue;
|
|
1379
|
+
const inheritedValue = inheritedFormatting?.[property];
|
|
1380
|
+
const effectiveValue = effectiveFormatting?.[property];
|
|
1381
|
+
switch (RUN_FORMATTING_INFERENCE[property]) {
|
|
1382
|
+
case "structural": continue;
|
|
1383
|
+
case "ordinary-toggle":
|
|
1384
|
+
if (directValue !== true || inheritedValue !== true) continue;
|
|
1385
|
+
return false;
|
|
1386
|
+
case "visible-boolean":
|
|
1387
|
+
if (directValue === false || directValue === true && inheritedValue !== true) continue;
|
|
1388
|
+
return false;
|
|
1389
|
+
case "font-size":
|
|
1390
|
+
if (typeof directValue === "number" && Number.isFinite(directValue) && directValue > 0) continue;
|
|
1391
|
+
return false;
|
|
1392
|
+
case "font-family":
|
|
1393
|
+
if (isReconstructibleFontFamily(directValue, effectiveValue)) continue;
|
|
1394
|
+
return false;
|
|
1395
|
+
case "color":
|
|
1396
|
+
if (typeof directValue === "object" && directValue !== null && Reflect.get(directValue, "auto") !== true && Reflect.get(directValue, "themeColor") === void 0 && sameFormattingValue(directValue, effectiveValue)) continue;
|
|
1397
|
+
return false;
|
|
1398
|
+
case "underline":
|
|
1399
|
+
if (typeof directValue === "object" && directValue !== null && Reflect.get(directValue, "style") !== "none" && Reflect.get(directValue, "color") === void 0 && sameFormattingValue(directValue, effectiveValue) && !sameFormattingValue(directValue, inheritedValue)) continue;
|
|
1400
|
+
return false;
|
|
1401
|
+
case "double-strike":
|
|
1402
|
+
if (directValue === false) continue;
|
|
1403
|
+
if (directValue === true && inheritedFormatting?.strike !== true && inheritedFormatting?.doubleStrike !== true) continue;
|
|
1404
|
+
return false;
|
|
1405
|
+
case "scale":
|
|
1406
|
+
if (normalizeHorizontalScalePercent(typeof directValue === "number" ? directValue : void 0) === directValue && directValue !== inheritedValue) continue;
|
|
1407
|
+
return false;
|
|
1408
|
+
case "nested-visible-value":
|
|
1409
|
+
if (sameFormattingValue(directValue, effectiveValue) && !sameFormattingValue(directValue, inheritedValue)) continue;
|
|
1410
|
+
return false;
|
|
1411
|
+
case "visible-value":
|
|
1412
|
+
if (directValue !== "none" && directValue !== "baseline" && sameFormattingValue(directValue, effectiveValue) && !sameFormattingValue(directValue, inheritedValue)) continue;
|
|
1413
|
+
return false;
|
|
1414
|
+
case "preserve": return false;
|
|
1415
|
+
}
|
|
1416
|
+
}
|
|
1417
|
+
return true;
|
|
1418
|
+
};
|
|
1264
1419
|
function buildRunMarks(runFormatting, inherited, styleResolver) {
|
|
1420
|
+
if (runFormatting === void 0 && inherited.implicitCharacterStyleApplied === true && inherited.paragraphMarkOverrides === void 0) return {
|
|
1421
|
+
marks: textFormattingToMarks(inherited.formatting, {
|
|
1422
|
+
overrideFormatting: void 0,
|
|
1423
|
+
directFormatting: void 0,
|
|
1424
|
+
authoredCarrier: "reconstruct"
|
|
1425
|
+
}),
|
|
1426
|
+
mergedFormatting: inherited.formatting
|
|
1427
|
+
};
|
|
1265
1428
|
const styleId = runFormatting?.styleId;
|
|
1266
|
-
|
|
1429
|
+
let characterStyleFormatting;
|
|
1430
|
+
if (styleId) characterStyleFormatting = styleResolver?.getRunStyleOwnProperties(styleId);
|
|
1431
|
+
else if (!inherited.implicitCharacterStyleApplied) characterStyleFormatting = styleResolver?.getDefaultCharacterStyle()?.rPr;
|
|
1267
1432
|
let ordinaryRunStyleFormatting = inherited.formatting ? { ...inherited.formatting } : {};
|
|
1268
1433
|
if (styleId) ordinaryRunStyleFormatting = mergeTextFormatting(inherited.formatting, characterStyleFormatting) ?? {};
|
|
1269
1434
|
const cascadedStyleFormatting = cascadeStyleTextFormatting([{
|
|
@@ -1281,20 +1446,28 @@ function buildRunMarks(runFormatting, inherited, styleResolver) {
|
|
|
1281
1446
|
formatting: runFormatting,
|
|
1282
1447
|
type: "direct"
|
|
1283
1448
|
}], { ordinaryFormatting: mergeTextFormatting(runStyleFormatting, runFormatting) }).formatting;
|
|
1284
|
-
const
|
|
1449
|
+
const authoredCarrier = canReconstructAuthoredRunFormatting({
|
|
1450
|
+
directFormatting: runFormatting,
|
|
1451
|
+
effectiveFormatting: mergedFormatting,
|
|
1452
|
+
inheritedFormatting: runStyleFormatting,
|
|
1453
|
+
paragraphMarkOverrides: inherited.paragraphMarkOverrides
|
|
1454
|
+
}) ? "reconstruct" : "preserve";
|
|
1455
|
+
const overrideFormatting = getRunFormattingOverrides({
|
|
1285
1456
|
directFormatting: runFormatting,
|
|
1286
1457
|
effectiveStyleFormatting: runStyleFormatting,
|
|
1287
1458
|
hasCharacterStyle: styleId !== void 0,
|
|
1288
1459
|
paragraphMarkOverrides: inherited.paragraphMarkOverrides
|
|
1289
|
-
})
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
marks.push(schema.mark("characterStyle", {
|
|
1294
|
-
styleId,
|
|
1295
|
-
_styleRPr: styleRPr && Object.keys(styleRPr).length > 0 ? styleRPr : null
|
|
1296
|
-
}));
|
|
1460
|
+
});
|
|
1461
|
+
if (authoredCarrier === "reconstruct") {
|
|
1462
|
+
if (overrideFormatting?.bold === true) delete overrideFormatting.bold;
|
|
1463
|
+
if (overrideFormatting?.italic === true) delete overrideFormatting.italic;
|
|
1297
1464
|
}
|
|
1465
|
+
const marks = textFormattingToMarks(mergedFormatting, {
|
|
1466
|
+
overrideFormatting,
|
|
1467
|
+
directFormatting: runFormatting,
|
|
1468
|
+
authoredCarrier
|
|
1469
|
+
});
|
|
1470
|
+
if (styleId) marks.push(schema.mark("characterStyle", { styleId }));
|
|
1298
1471
|
return {
|
|
1299
1472
|
marks,
|
|
1300
1473
|
mergedFormatting
|
|
@@ -1305,12 +1478,43 @@ const addDirectFontProvenance = (marks, directFormatting) => {
|
|
|
1305
1478
|
if (directFormatting?.fontFamily !== void 0) directFontProperties.push("fontFamily");
|
|
1306
1479
|
if (directFormatting?.fontSize !== void 0) directFontProperties.push("fontSize");
|
|
1307
1480
|
if (directFormatting?.color !== void 0) directFontProperties.push("color");
|
|
1308
|
-
if (
|
|
1481
|
+
if (directFontProperties.length === 0) return;
|
|
1482
|
+
const index = marks.findIndex(({ type }) => type.name === "runFormattingOverride");
|
|
1483
|
+
const existing = index >= 0 ? marks.at(index) : void 0;
|
|
1484
|
+
const override = schema.mark("runFormattingOverride", {
|
|
1485
|
+
...existing?.attrs,
|
|
1486
|
+
directFontProperties
|
|
1487
|
+
});
|
|
1488
|
+
if (index >= 0) {
|
|
1489
|
+
marks[index] = override;
|
|
1490
|
+
return;
|
|
1491
|
+
}
|
|
1492
|
+
marks.push(override);
|
|
1493
|
+
};
|
|
1494
|
+
const COMPLEX_SCRIPT_MIRRORS = [
|
|
1495
|
+
{
|
|
1496
|
+
ordinary: "bold",
|
|
1497
|
+
complex: "boldCs"
|
|
1498
|
+
},
|
|
1499
|
+
{
|
|
1500
|
+
ordinary: "italic",
|
|
1501
|
+
complex: "italicCs"
|
|
1502
|
+
},
|
|
1503
|
+
{
|
|
1504
|
+
ordinary: "fontSize",
|
|
1505
|
+
complex: "fontSizeCs"
|
|
1506
|
+
}
|
|
1507
|
+
];
|
|
1508
|
+
const addComplexScriptAbsenceProvenance = (marks, directFormatting) => {
|
|
1509
|
+
const absent = COMPLEX_SCRIPT_MIRRORS.filter(({ ordinary, complex }) => directFormatting?.[ordinary] !== void 0 && directFormatting[complex] === void 0).map(({ complex }) => complex);
|
|
1510
|
+
if (absent.length === 0) return;
|
|
1309
1511
|
const index = marks.findIndex(({ type }) => type.name === "runFormattingOverride");
|
|
1310
1512
|
const existing = index >= 0 ? marks.at(index) : void 0;
|
|
1513
|
+
const existingAbsences = new Set(existing?.attrs["complexScriptPropertyAbsences"] ?? []);
|
|
1514
|
+
for (const property of absent) existingAbsences.add(property);
|
|
1311
1515
|
const override = schema.mark("runFormattingOverride", {
|
|
1312
1516
|
...existing?.attrs,
|
|
1313
|
-
|
|
1517
|
+
complexScriptPropertyAbsences: COMPLEX_SCRIPT_RUN_PROPERTY_KEYS.filter((property) => existingAbsences.has(property))
|
|
1314
1518
|
});
|
|
1315
1519
|
if (index >= 0) {
|
|
1316
1520
|
marks[index] = override;
|
|
@@ -1319,8 +1523,6 @@ const addDirectFontProvenance = (marks, directFormatting) => {
|
|
|
1319
1523
|
marks.push(override);
|
|
1320
1524
|
};
|
|
1321
1525
|
const ORDINARY_STYLE_TOGGLE_KEYS = [
|
|
1322
|
-
"bold",
|
|
1323
|
-
"italic",
|
|
1324
1526
|
"strike",
|
|
1325
1527
|
"allCaps",
|
|
1326
1528
|
"smallCaps",
|
|
@@ -1334,8 +1536,6 @@ function getRunFormattingOverrides({ directFormatting, effectiveStyleFormatting,
|
|
|
1334
1536
|
const overrides = mergeTextFormatting(paragraphMarkOverrides, directFormatting);
|
|
1335
1537
|
if (!overrides || !directFormatting) return overrides;
|
|
1336
1538
|
for (const key of ORDINARY_STYLE_TOGGLE_KEYS) if (directFormatting[key] === true && (!hasCharacterStyle || effectiveStyleFormatting?.[key] !== true)) Reflect.deleteProperty(overrides, key);
|
|
1337
|
-
if (directFormatting.boldCs === true && directFormatting.boldCs === directFormatting.bold && (!hasCharacterStyle || effectiveStyleFormatting?.boldCs === void 0)) Reflect.deleteProperty(overrides, "boldCs");
|
|
1338
|
-
if (directFormatting.italicCs === true && directFormatting.italicCs === directFormatting.italic && (!hasCharacterStyle || effectiveStyleFormatting?.italicCs === void 0)) Reflect.deleteProperty(overrides, "italicCs");
|
|
1339
1539
|
return overrides;
|
|
1340
1540
|
}
|
|
1341
1541
|
/**
|
|
@@ -1347,12 +1547,21 @@ function convertRunContent(content, marks, formatting, textBoxAnchors) {
|
|
|
1347
1547
|
if (content.text) return [schema.text(content.text, marks)];
|
|
1348
1548
|
return [];
|
|
1349
1549
|
case "break":
|
|
1350
|
-
if (content.breakType === "textWrapping" || !content.breakType)
|
|
1351
|
-
|
|
1352
|
-
|
|
1550
|
+
if (content.breakType === "textWrapping" || !content.breakType) {
|
|
1551
|
+
const attrs = {
|
|
1552
|
+
...content.breakType !== void 0 ? { breakType: content.breakType } : {},
|
|
1553
|
+
...content.clear !== void 0 ? { clear: content.clear } : {}
|
|
1554
|
+
};
|
|
1555
|
+
return [schema.node("hardBreak", attrs).mark(marks)];
|
|
1556
|
+
}
|
|
1557
|
+
if (content.breakType === "column") return [schema.node("hardBreak", {
|
|
1558
|
+
breakType: "column",
|
|
1559
|
+
...content.clear !== void 0 ? { clear: content.clear } : {}
|
|
1560
|
+
}).mark(marks)];
|
|
1561
|
+
return [schema.node("pageBreakRun", content.clear === void 0 ? void 0 : { clear: content.clear }).mark(marks)];
|
|
1353
1562
|
case "renderedPageBreak": return [schema.node("renderedPageBreak").mark(marks)];
|
|
1354
1563
|
case "tab": return [schema.node("tab", content.positional ? { positional: content.positional } : void 0).mark(marks)];
|
|
1355
|
-
case "drawing": return [
|
|
1564
|
+
case "drawing": return [withRunBoundaryMarks(convertImage({
|
|
1356
1565
|
image: content.image,
|
|
1357
1566
|
rawXml: content.rawXml,
|
|
1358
1567
|
rawXmlMode: content.rawXmlMode
|
|
@@ -1363,7 +1572,7 @@ function convertRunContent(content, marks, formatting, textBoxAnchors) {
|
|
|
1363
1572
|
const anchorId = textBoxAnchors?.get(shp);
|
|
1364
1573
|
return anchorId ? [schema.node("textBoxAnchor", { anchorId }).mark(marks)] : [];
|
|
1365
1574
|
}
|
|
1366
|
-
return [
|
|
1575
|
+
return [withRunBoundaryMarks(convertShape(shp), marks)];
|
|
1367
1576
|
}
|
|
1368
1577
|
case "footnoteRef": {
|
|
1369
1578
|
const footnoteMark = schema.mark("footnoteRef", {
|
|
@@ -1391,8 +1600,8 @@ function convertRunContent(content, marks, formatting, textBoxAnchors) {
|
|
|
1391
1600
|
}).mark(marks)];
|
|
1392
1601
|
}
|
|
1393
1602
|
}
|
|
1394
|
-
function
|
|
1395
|
-
if (!marks.some((
|
|
1603
|
+
function withRunBoundaryMarks(node, marks) {
|
|
1604
|
+
if (!marks.some(({ type }) => type.name === "hyperlink" || type.name === "pageBreakRunOwner")) return node;
|
|
1396
1605
|
return node.mark(marks);
|
|
1397
1606
|
}
|
|
1398
1607
|
function convertImage({ image, rawXml, rawXmlMode }) {
|
|
@@ -1500,7 +1709,7 @@ function convertImage({ image, rawXml, rawXmlMode }) {
|
|
|
1500
1709
|
_docxObjectPreview: rawXml !== void 0 && /<(?:[A-Za-z_][\w.-]*:)?object(?:\s|>)/u.test(rawXml)
|
|
1501
1710
|
});
|
|
1502
1711
|
}
|
|
1503
|
-
function convertHyperlink(hyperlink, { getInheritedRunFormatting, styleResolver, hyperlinkIndex, textBoxAnchors }) {
|
|
1712
|
+
function convertHyperlink(hyperlink, { getInheritedRunFormatting, styleResolver, hyperlinkIndex, textBoxAnchors, nextPageBreakRunOwnerId }) {
|
|
1504
1713
|
const nodes = [];
|
|
1505
1714
|
const href = hyperlink.href || (hyperlink.anchor ? `#${hyperlink.anchor}` : "");
|
|
1506
1715
|
const linkMark = schema.mark("hyperlink", {
|
|
@@ -1528,8 +1737,11 @@ function convertHyperlink(hyperlink, { getInheritedRunFormatting, styleResolver,
|
|
|
1528
1737
|
continue;
|
|
1529
1738
|
}
|
|
1530
1739
|
if (child.type === "run") {
|
|
1740
|
+
assertPageBreakSourceRunIsRepresentable(child);
|
|
1531
1741
|
const inheritedFormatting = getInheritedRunFormatting(child.formatting);
|
|
1532
1742
|
const { marks: runMarks, mergedFormatting } = buildRunMarks(child.formatting, inheritedFormatting, styleResolver);
|
|
1743
|
+
if (child.propertyChanges && child.propertyChanges.length > 0) runMarks.push(schema.mark("runPropertyChange", { changes: [...child.propertyChanges] }));
|
|
1744
|
+
if (child.content.some((content) => content.type === "break" && content.breakType === "page")) runMarks.push(schema.mark("pageBreakRunOwner", { id: nextPageBreakRunOwnerId() }));
|
|
1533
1745
|
const allMarks = [...runMarks, linkMark];
|
|
1534
1746
|
for (const content of child.content) nodes.push(...convertRunContent(content, allMarks, mergedFormatting, textBoxAnchors));
|
|
1535
1747
|
}
|
|
@@ -1539,7 +1751,14 @@ function convertHyperlink(hyperlink, { getInheritedRunFormatting, styleResolver,
|
|
|
1539
1751
|
function textFormattingToMarks(formatting, options) {
|
|
1540
1752
|
if (!formatting) return [];
|
|
1541
1753
|
const marks = [];
|
|
1542
|
-
const
|
|
1754
|
+
const overrideFormatting = options ? options.overrideFormatting : formatting;
|
|
1755
|
+
let overrideAttrs;
|
|
1756
|
+
if (options?.authoredCarrier === "reconstruct") overrideAttrs = buildRunFormattingOverrideAttrs(overrideFormatting, { type: "structural-only" });
|
|
1757
|
+
else if (options) overrideAttrs = buildRunFormattingOverrideAttrs(overrideFormatting, {
|
|
1758
|
+
type: "authored-baseline",
|
|
1759
|
+
formatting: options.directFormatting
|
|
1760
|
+
});
|
|
1761
|
+
else overrideAttrs = buildRunFormattingOverrideAttrs(overrideFormatting);
|
|
1543
1762
|
if (overrideAttrs) marks.push(schema.mark("runFormattingOverride", overrideAttrs));
|
|
1544
1763
|
if (formatting.bold) marks.push(schema.mark("bold"));
|
|
1545
1764
|
if (formatting.italic) marks.push(schema.mark("italic"));
|
|
@@ -1592,6 +1811,8 @@ function textFormattingToMarks(formatting, options) {
|
|
|
1592
1811
|
if (formatting.outline) marks.push(schema.mark("textOutline"));
|
|
1593
1812
|
if (formatting.rtl) marks.push(schema.mark("rtl"));
|
|
1594
1813
|
if (formatting.effect && formatting.effect !== "none") marks.push(schema.mark("textEffect", { effect: formatting.effect }));
|
|
1814
|
+
addDirectFontProvenance(marks, options?.directFormatting);
|
|
1815
|
+
if (options?.authoredCarrier === "preserve") addComplexScriptAbsenceProvenance(marks, options.directFormatting);
|
|
1595
1816
|
return marks;
|
|
1596
1817
|
}
|
|
1597
1818
|
/**
|
|
@@ -1701,7 +1922,7 @@ function convertShape(shape) {
|
|
|
1701
1922
|
}
|
|
1702
1923
|
function convertParagraphWithTextBoxes(block, styleResolver, { textBoxGroupId, context, extraRunFormatting, preserveEmptyWrapper, tableParagraphOverlay }) {
|
|
1703
1924
|
const { textBoxes, textBoxAnchors } = extractTextBoxesFromParagraph(block, textBoxGroupId);
|
|
1704
|
-
const pmParagraph = convertParagraph(block, styleResolver, context
|
|
1925
|
+
const pmParagraph = convertParagraph(block, styleResolver, context, void 0, extraRunFormatting, tableParagraphOverlay, textBoxAnchors);
|
|
1705
1926
|
const nodes = [];
|
|
1706
1927
|
const isEmptyAfterExtraction = textBoxes.length > 0 && !hasContentBesidesTextBoxAnchors(pmParagraph);
|
|
1707
1928
|
const keepWrapperParagraph = isEmptyAfterExtraction && (preserveEmptyWrapper === true || hasParagraphBoundaryPayload(block, pmParagraph));
|
|
@@ -1854,6 +2075,7 @@ function textBoxFromShape(shape, textBody) {
|
|
|
1854
2075
|
* Convert a TextBox to a ProseMirror textBox node
|
|
1855
2076
|
*/
|
|
1856
2077
|
function convertTextBox(textBox, styleResolver, options) {
|
|
2078
|
+
assertSourceContainerHasNoPageBreakRun(textBox.content, "text-box", options.context.pageBreakRunSourceDescendants);
|
|
1857
2079
|
const textBoxSize = textBox.size;
|
|
1858
2080
|
const widthPx = textBoxSize?.width ? emuToPixels(textBoxSize.width) : 200;
|
|
1859
2081
|
const heightPx = textBoxSize?.height ? emuToPixels(textBoxSize.height) : void 0;
|
|
@@ -1966,7 +2188,8 @@ function headerFooterToProseDoc(content, options) {
|
|
|
1966
2188
|
theme,
|
|
1967
2189
|
nextTextBoxGroupId,
|
|
1968
2190
|
nextHyperlinkInstanceIndex: createHyperlinkInstanceIndexAllocator(),
|
|
1969
|
-
pairedBookmarkIds: collectPairedBookmarkIds(content)
|
|
2191
|
+
pairedBookmarkIds: collectPairedBookmarkIds(content),
|
|
2192
|
+
pageBreakRunSourceDescendants: buildPageBreakRunSourceDescendantIndex(content)
|
|
1970
2193
|
};
|
|
1971
2194
|
const convertBlocks = (blocks) => {
|
|
1972
2195
|
const out = [];
|
|
@@ -2000,100 +2223,10 @@ function footnoteToProseDoc(content, options) {
|
|
|
2000
2223
|
return headerFooterToProseDoc(content, options);
|
|
2001
2224
|
}
|
|
2002
2225
|
/**
|
|
2003
|
-
* Determine where a page break appears inside a paragraph.
|
|
2004
|
-
*
|
|
2005
|
-
* Per ECMA-376 §17.3.3.1, `<w:br w:type="page"/>` is always a forced break,
|
|
2006
|
-
* including in a paragraph whose only content is the break itself. We previously
|
|
2007
|
-
* searched only top-level runs and missed breaks nested in hyperlinks, tracked
|
|
2008
|
-
* changes, or fields — so those paragraphs silently dropped their forced break
|
|
2009
|
-
* and the following content collapsed onto the previous page (common on legal
|
|
2010
|
-
* signature pages and exhibit covers).
|
|
2011
|
-
* See eigenpal docx-editor #409 (break-only page break sub-fix).
|
|
2012
|
-
*
|
|
2013
|
-
* Returns:
|
|
2014
|
-
* "before" — the break appears before any visible content; the paragraph's
|
|
2015
|
-
* content belongs on the NEXT page.
|
|
2016
|
-
* "after" — the break follows some visible content; the paragraph stays
|
|
2017
|
-
* on the current page and the next block starts a new page.
|
|
2018
|
-
* null — no page break found.
|
|
2019
|
-
*/
|
|
2020
|
-
function paragraphPageBreakPosition(paragraph) {
|
|
2021
|
-
if (!mayContainPageBreak(paragraph)) return null;
|
|
2022
|
-
return findParagraphPageBreakPosition(paragraph);
|
|
2023
|
-
}
|
|
2024
|
-
function mayContainPageBreak(paragraph) {
|
|
2025
|
-
for (const item of paragraph.content) {
|
|
2026
|
-
if (item.type === "run") {
|
|
2027
|
-
for (const content of item.content) if (content.type === "break" && content.breakType === "page") return true;
|
|
2028
|
-
continue;
|
|
2029
|
-
}
|
|
2030
|
-
if (item.type === "hyperlink" || item.type === "simpleField" || item.type === "complexField" || item.type === "inlineSdt" || item.type === "insertion" || item.type === "deletion" || item.type === "moveFrom" || item.type === "moveTo") return true;
|
|
2031
|
-
if (item.type === "bookmarkStart" || item.type === "bookmarkEnd" || item.type === "commentRangeStart" || item.type === "commentRangeEnd" || item.type === "commentReference" || item.type === "moveFromRangeStart" || item.type === "moveFromRangeEnd" || item.type === "moveToRangeStart" || item.type === "moveToRangeEnd" || item.type === "mathEquation") continue;
|
|
2032
|
-
}
|
|
2033
|
-
return false;
|
|
2034
|
-
}
|
|
2035
|
-
function findParagraphPageBreakPosition(paragraph) {
|
|
2036
|
-
const state = { seenVisibleContent: false };
|
|
2037
|
-
function isPageBreak(content) {
|
|
2038
|
-
return content.type === "break" && content.breakType === "page";
|
|
2039
|
-
}
|
|
2040
|
-
function isVisibleRunContent(content) {
|
|
2041
|
-
return content.type === "text" && content.text.length > 0 || content.type === "tab" || content.type === "drawing" || content.type === "shape" || content.type === "symbol" || content.type === "fieldChar" || content.type === "instrText" || content.type === "footnoteRef" || content.type === "endnoteRef" || content.type === "noBreakHyphen" || content.type === "softHyphen";
|
|
2042
|
-
}
|
|
2043
|
-
function visitRun(run) {
|
|
2044
|
-
for (const content of run.content) {
|
|
2045
|
-
if (isPageBreak(content)) return true;
|
|
2046
|
-
if (isVisibleRunContent(content)) state.seenVisibleContent = true;
|
|
2047
|
-
}
|
|
2048
|
-
return false;
|
|
2049
|
-
}
|
|
2050
|
-
function visitHyperlinkChildren(hyperlink) {
|
|
2051
|
-
for (const child of hyperlink.children) if (child.type === "run" && visitRun(child)) return true;
|
|
2052
|
-
return false;
|
|
2053
|
-
}
|
|
2054
|
-
function visitRunOrHyperlinkList(children) {
|
|
2055
|
-
for (const child of children) {
|
|
2056
|
-
if (child.type === "run" && visitRun(child)) return true;
|
|
2057
|
-
if (child.type === "hyperlink" && visitHyperlinkChildren(child)) return true;
|
|
2058
|
-
if (child.type === "simpleField") for (const fieldChild of child.content) {
|
|
2059
|
-
if (fieldChild.type === "run" && visitRun(fieldChild)) return true;
|
|
2060
|
-
if (fieldChild.type === "hyperlink" && visitHyperlinkChildren(fieldChild)) return true;
|
|
2061
|
-
}
|
|
2062
|
-
if (child.type === "complexField") {
|
|
2063
|
-
for (const run of child.fieldCode) if (visitRun(run)) return true;
|
|
2064
|
-
for (const run of child.fieldResult) if (visitRun(run)) return true;
|
|
2065
|
-
}
|
|
2066
|
-
if ((child.type === "insertion" || child.type === "deletion" || child.type === "moveFrom" || child.type === "moveTo") && visitRunOrHyperlinkList(child.content)) return true;
|
|
2067
|
-
}
|
|
2068
|
-
return false;
|
|
2069
|
-
}
|
|
2070
|
-
function visitItem(item) {
|
|
2071
|
-
if (item.type === "run") return visitRun(item);
|
|
2072
|
-
if (item.type === "hyperlink") return visitHyperlinkChildren(item);
|
|
2073
|
-
if (item.type === "insertion" || item.type === "deletion" || item.type === "moveFrom" || item.type === "moveTo") return visitRunOrHyperlinkList(item.content);
|
|
2074
|
-
if (item.type === "simpleField") return visitRunOrHyperlinkList(item.content);
|
|
2075
|
-
if (item.type === "complexField") {
|
|
2076
|
-
for (const run of item.fieldResult) if (visitRun(run)) return true;
|
|
2077
|
-
return false;
|
|
2078
|
-
}
|
|
2079
|
-
if (item.type === "inlineSdt") {
|
|
2080
|
-
for (const child of item.content) if (visitItem(child)) return true;
|
|
2081
|
-
return false;
|
|
2082
|
-
}
|
|
2083
|
-
if (item.type === "mathEquation") {
|
|
2084
|
-
state.seenVisibleContent = true;
|
|
2085
|
-
return false;
|
|
2086
|
-
}
|
|
2087
|
-
return false;
|
|
2088
|
-
}
|
|
2089
|
-
for (const item of paragraph.content) if (visitItem(item)) return state.seenVisibleContent ? "after" : "before";
|
|
2090
|
-
return null;
|
|
2091
|
-
}
|
|
2092
|
-
/**
|
|
2093
2226
|
* Create an empty ProseMirror document
|
|
2094
2227
|
*/
|
|
2095
2228
|
function createEmptyDoc() {
|
|
2096
2229
|
return schema.node("doc", null, [schema.node("paragraph", {}, [])]);
|
|
2097
2230
|
}
|
|
2098
2231
|
//#endregion
|
|
2099
|
-
export { createEmptyDoc, footnoteToProseDoc, headerFooterToProseDoc, standaloneTableCellToProseMirror, textFormattingToMarks, toProseDoc };
|
|
2232
|
+
export { UnsupportedDocxToProseMirrorConversionError, createEmptyDoc, footnoteToProseDoc, headerFooterToProseDoc, resolveParagraphDefaultTextFormatting, standaloneTableCellToProseMirror, textFormattingToMarks, toProseDoc };
|