@stll/folio-core 0.35.1 → 0.37.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +59 -1
- package/dist/ai-edits/apply.js +878 -377
- 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 +141 -73
- 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 +105 -20
- 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 +62 -61
- package/dist/ai-edits/word-diff.d.ts +18 -3
- package/dist/ai-edits/word-diff.js +556 -67
- 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 +48 -21
- 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 +171 -566
- package/dist/compare/scenario.d.ts +2 -2
- package/dist/compare/types.d.ts +3 -3
- package/dist/compare/verification.d.ts +8 -9
- package/dist/compare/verification.js +72 -50
- package/dist/compat/eigenpal.d.ts +5 -3
- package/dist/compat/eigenpal.js +3 -2
- package/dist/controller/headerFooterEditorManager.js +18 -10
- package/dist/controller/hiddenEditorApi.js +1 -1
- 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 -4
- package/dist/document-operations.js +104 -12
- package/dist/docx/blockContentParser.js +6 -27
- package/dist/docx/commentParser.js +2 -4
- package/dist/docx/commentRangeIntegrity.js +2 -4
- package/dist/docx/documentClone.d.ts +2 -0
- package/dist/docx/documentClone.js +2 -0
- package/dist/docx/ensureParaIds.js +9 -4
- package/dist/docx/headerFooterParser.js +2 -4
- package/dist/docx/normalizeBaseDirection.js +5 -7
- package/dist/docx/numberingParser.d.ts +3 -1
- package/dist/docx/numberingParser.js +4 -1
- package/dist/docx/paragraphParser.js +34 -35
- package/dist/docx/paragraphPropertySource.d.ts +49 -0
- package/dist/docx/paragraphPropertySource.js +113 -0
- 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/runConsolidator.js +2 -4
- package/dist/docx/runParser.js +6 -17
- package/dist/docx/sectionParser.js +1 -15
- package/dist/docx/serializer/paragraphSerializer.js +289 -30
- package/dist/docx/serializer/runSerializer.js +6 -12
- package/dist/docx/serializer/sectionPropertiesSerializer.js +2 -10
- package/dist/docx/serializer/tableSerializer.js +4 -23
- package/dist/docx/serializer/trackedChangeAttributes.d.ts +11 -0
- package/dist/docx/serializer/trackedChangeAttributes.js +31 -0
- package/dist/docx/server/build.d.ts +1 -1
- package/dist/docx/server/createBilingualDocument.js +8 -10
- package/dist/docx/server/evaluateDocxXmlPatchProposal.js +22 -13
- package/dist/docx/server/validateDocxConformance.js +17 -13
- package/dist/docx/tableParser.js +1 -37
- package/dist/docx/trackedChangeInfo.d.ts +11 -0
- package/dist/docx/trackedChangeInfo.js +38 -0
- package/dist/docx/verbatimCapture.d.ts +20 -9
- package/dist/docx/verbatimCapture.js +208 -8
- package/dist/docx/xmlParser.d.ts +3 -1
- package/dist/docx/xmlParser.js +6 -1
- package/dist/docx/xmlSafety.d.ts +1 -1
- package/dist/docx/xmlSafety.js +157 -0
- 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 +155 -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 +52 -9
- package/dist/layout-bridge/convert/toFlowBlocks.d.ts +4 -0
- package/dist/layout-bridge/convert/toFlowBlocks.js +391 -82
- 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/markdown/renderBlock.js +7 -10
- 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 +128 -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 +551 -87
- 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 +27 -3
- package/dist/prosemirror/commands/propertyChangeScope.js +85 -14
- package/dist/prosemirror/conversion/fromProseDoc.d.ts +8 -5
- package/dist/prosemirror/conversion/fromProseDoc.js +935 -223
- package/dist/prosemirror/conversion/runShadingMark.js +2 -2
- package/dist/prosemirror/conversion/toProseDoc.d.ts +26 -1
- package/dist/prosemirror/conversion/toProseDoc.js +439 -291
- package/dist/prosemirror/extensions/StarterKit.js +4 -0
- package/dist/prosemirror/extensions/core/ParagraphExtension.js +54 -6
- package/dist/prosemirror/extensions/features/AutoBidiDetectionExtension.js +7 -1
- package/dist/prosemirror/extensions/features/ListExtension.js +95 -123
- package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.js +19 -6
- 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/TrackedChangeExtensions.js +2 -0
- 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/paragraphAlignment.d.ts +12 -0
- package/dist/prosemirror/paragraphAlignment.js +13 -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 +9 -11
- 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 +84 -9
- package/dist/prosemirror/schema/marks.js +73 -1
- package/dist/prosemirror/schema/nodes.d.ts +30 -6
- package/dist/prosemirror/styles/resolvedStyleAttrs.d.ts +14 -2
- package/dist/prosemirror/styles/resolvedStyleAttrs.js +45 -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/redline.js +4 -1
- 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/utils/mergeDocumentContent.js +3 -3
- package/dist/utils/replaceText.js +2 -1
- package/dist/version-comparison.d.ts +38 -44
- package/dist/version-comparison.js +270 -399
- package/dist/watermark/index.js +2 -4
- package/package.json +8 -2
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { resolveColorValueToHex } from "../../docx/drawingUtils.js";
|
|
2
|
+
import { linkProseParagraphPropertySource, recreateProseNodeWithParagraphPropertySource } from "../../docx/paragraphPropertySource.js";
|
|
3
|
+
import { buildPageBreakRunSourceDescendantIndex } from "../../internal/pageBreakRunSourceDescendantIndex.js";
|
|
2
4
|
import { createStyleEngine } from "../../style-engine/styleEngine.js";
|
|
3
5
|
import { normalizeHorizontalScalePercent } from "../../utils/horizontalScale.js";
|
|
4
6
|
import { mergeParagraphFormatting, mergeParagraphTabStops } from "../../utils/paragraphFormattingMerge.js";
|
|
@@ -8,16 +10,22 @@ import { emuToPixels } from "../../utils/units.js";
|
|
|
8
10
|
import { setAutospacingBaseValue } from "../autospacingBase.js";
|
|
9
11
|
import { buildRunFormattingOverrideAttrs } from "../extensions/marks/RunFormattingOverrideExtension.js";
|
|
10
12
|
import { stampNumberedRefFieldBaselines } from "../numberedRefFields.js";
|
|
13
|
+
import { pageBreakRunParagraphProjectionDispositionForFeatures } from "../pageBreakRunProjection.js";
|
|
11
14
|
import { directionFromBidi } from "../paragraphDirection.js";
|
|
15
|
+
import { lineSpacingProvenanceFromSpacing } from "../paragraphSpacing.js";
|
|
16
|
+
import { getParagraphMarkSuppressionOverrides, hasDirectRunFormatting, stripParagraphMarkFormattingForBodyRuns, stripParagraphMarkOnlyFormatting, suppressParagraphMarkFormatting } from "../runStyleFormatting.js";
|
|
12
17
|
import { schema } from "../schema/index.js";
|
|
18
|
+
import { COMPLEX_SCRIPT_RUN_PROPERTY_KEYS } from "../schema/marks.js";
|
|
13
19
|
import { cascadeStyleTextFormatting } from "../styles/styleToggleCascade.js";
|
|
20
|
+
import { canCarryTrackedRunMark, trackedRunInlineAtomDisposition } from "../trackedRunInlineAtoms.js";
|
|
14
21
|
import { assertValidProseMirrorDocument } from "../validation.js";
|
|
15
22
|
import { resolveEffectiveTableCellFormatting } from "./effectiveTableCellFormatting.js";
|
|
16
|
-
import { marksToTextFormatting } from "./fromProseDoc.js";
|
|
17
23
|
import { shadingToRunShadingAttrs } from "./runShadingMark.js";
|
|
18
24
|
import { sdtAttrsFromProperties } from "./sdtAttrs.js";
|
|
19
|
-
import { panic } from "better-result";
|
|
25
|
+
import { TaggedError, panic } from "better-result";
|
|
20
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") {};
|
|
21
29
|
const DETACHED_WATERMARK_HOST = Symbol.for("stll.detachedWatermarkHost");
|
|
22
30
|
/**
|
|
23
31
|
* Build a `nextTextBoxGroupId()` generator salted with a random per-load
|
|
@@ -105,36 +113,16 @@ function toProseDoc(document, options) {
|
|
|
105
113
|
theme,
|
|
106
114
|
nextTextBoxGroupId,
|
|
107
115
|
nextHyperlinkInstanceIndex: createHyperlinkInstanceIndexAllocator(),
|
|
108
|
-
pairedBookmarkIds: collectPairedBookmarkIds(paragraphs)
|
|
116
|
+
pairedBookmarkIds: collectPairedBookmarkIds(paragraphs),
|
|
117
|
+
pageBreakRunSourceDescendants: buildPageBreakRunSourceDescendantIndex(paragraphs)
|
|
109
118
|
};
|
|
110
119
|
const convertBodyBlocks = (blocks) => {
|
|
111
120
|
const out = [];
|
|
112
|
-
for (const block of blocks) if (block.type === "paragraph") {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
context: conversionContext
|
|
118
|
-
});
|
|
119
|
-
const firstConverted = converted.at(0);
|
|
120
|
-
if (pbPos === "before" && converted.length === 1 && firstConverted?.type.name === "paragraph" && firstConverted.content.size === 0 && document.package.settings?.splitPageBreakAndParagraphMark !== true) {
|
|
121
|
-
const paragraph = firstConverted;
|
|
122
|
-
converted[0] = paragraph.type.create({
|
|
123
|
-
...paragraph.attrs,
|
|
124
|
-
_pageBreakCarrier: true
|
|
125
|
-
}, paragraph.content, paragraph.marks);
|
|
126
|
-
}
|
|
127
|
-
if (pbPos === "after") {
|
|
128
|
-
const paragraphIndex = converted.findIndex((node) => node.type.name === "paragraph");
|
|
129
|
-
const trailingParagraph = paragraphIndex >= 0 ? converted.at(paragraphIndex) : void 0;
|
|
130
|
-
if (trailingParagraph) converted[paragraphIndex] = trailingParagraph.type.create({
|
|
131
|
-
...trailingParagraph.attrs,
|
|
132
|
-
_trailingPageBreak: true
|
|
133
|
-
}, trailingParagraph.content, trailingParagraph.marks);
|
|
134
|
-
}
|
|
135
|
-
out.push(...converted);
|
|
136
|
-
if (pbPos === "after") out.push(schema.node("pageBreak"));
|
|
137
|
-
} 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));
|
|
138
126
|
else out.push(convertBlockSdt(block, convertBodyBlocks));
|
|
139
127
|
return out;
|
|
140
128
|
};
|
|
@@ -186,8 +174,17 @@ function convertBlockSdt(blockSdt, convertBlocks) {
|
|
|
186
174
|
* Resolves style-based text formatting and passes it to runs so that
|
|
187
175
|
* paragraph styles (like Heading1) apply their font size, color, etc.
|
|
188
176
|
*/
|
|
189
|
-
function convertParagraph(paragraph, styleResolver,
|
|
190
|
-
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
|
+
});
|
|
191
188
|
const isTocParagraph = attrs._tableOfContentsLevel !== void 0;
|
|
192
189
|
const inlineNodes = [];
|
|
193
190
|
let inlineOffset = 0;
|
|
@@ -215,7 +212,7 @@ function convertParagraph(paragraph, styleResolver, nextHyperlinkInstanceIndex,
|
|
|
215
212
|
}
|
|
216
213
|
const paragraphRunFormatting = resolveRunFormattingWithoutDefaults(paragraph.formatting?.runProperties, styleResolver);
|
|
217
214
|
let inheritableParagraphRunFormatting;
|
|
218
|
-
if (paragraphRunFormatting && !isTocParagraph) inheritableParagraphRunFormatting = stripParagraphMarkFormattingForBodyRuns(paragraphRunFormatting);
|
|
215
|
+
if (paragraphRunFormatting && !isTocParagraph && paragraph.formatting?.styleId === void 0) inheritableParagraphRunFormatting = stripParagraphMarkFormattingForBodyRuns(paragraphRunFormatting);
|
|
219
216
|
const ordinaryStyleFormatting = paragraph.formatting?.styleId === void 0 ? mergeTextFormatting(styleRunFormatting, extraRunFormatting) : mergeTextFormatting(extraRunFormatting, styleRunFormatting);
|
|
220
217
|
const orderedToggleFormatting = cascadeStyleTextFormatting([
|
|
221
218
|
{
|
|
@@ -233,53 +230,75 @@ function convertParagraph(paragraph, styleResolver, nextHyperlinkInstanceIndex,
|
|
|
233
230
|
], { ordinaryFormatting: ordinaryStyleFormatting });
|
|
234
231
|
let baseRunFormatting = orderedToggleFormatting.formatting;
|
|
235
232
|
if (paragraphStyleFontFamily) baseRunFormatting = mergeTextFormatting(baseRunFormatting, { fontFamily: paragraphStyleFontFamily });
|
|
236
|
-
const
|
|
237
|
-
const
|
|
238
|
-
const
|
|
233
|
+
const defaultCharacterFormatting = styleResolver?.getDefaultCharacterStyle()?.rPr;
|
|
234
|
+
const ordinaryBaseWithDefaultCharacter = mergeTextFormatting(defaultCharacterFormatting, baseRunFormatting);
|
|
235
|
+
const defaultCharacterStyleCascade = cascadeStyleTextFormatting([{
|
|
239
236
|
cascade: orderedToggleFormatting,
|
|
240
237
|
type: "carried"
|
|
241
|
-
}
|
|
242
|
-
|
|
238
|
+
}, {
|
|
239
|
+
formatting: defaultCharacterFormatting,
|
|
240
|
+
type: "style"
|
|
241
|
+
}], { ordinaryFormatting: ordinaryBaseWithDefaultCharacter });
|
|
242
|
+
const ordinaryDefaultRunFormatting = mergeTextFormatting(ordinaryBaseWithDefaultCharacter, inheritableParagraphRunFormatting);
|
|
243
|
+
const defaultToggleCascade = cascadeStyleTextFormatting([{
|
|
244
|
+
cascade: defaultCharacterStyleCascade,
|
|
243
245
|
type: "carried"
|
|
244
246
|
}, {
|
|
245
247
|
formatting: inheritableParagraphRunFormatting,
|
|
246
248
|
type: "direct"
|
|
247
249
|
}], { ordinaryFormatting: ordinaryDefaultRunFormatting });
|
|
248
250
|
const defaultRunFormatting = defaultToggleCascade.formatting;
|
|
251
|
+
if (extraRunFormatting !== void 0) if (defaultRunFormatting) attrs.defaultTextFormatting = defaultRunFormatting;
|
|
252
|
+
else delete attrs.defaultTextFormatting;
|
|
249
253
|
const getInheritedRunFormatting = (formatting, fieldType) => {
|
|
254
|
+
const hasCharacterStyle = formatting?.styleId !== void 0;
|
|
255
|
+
const inheritedBaseFormatting = hasCharacterStyle ? baseRunFormatting : ordinaryBaseWithDefaultCharacter;
|
|
256
|
+
const inheritedToggleCascade = hasCharacterStyle ? orderedToggleFormatting : defaultCharacterStyleCascade;
|
|
250
257
|
if (fieldType === "TOC") return {
|
|
251
|
-
formatting: hasDirectRunFormatting(formatting) ? suppressParagraphMarkFormatting(
|
|
252
|
-
|
|
258
|
+
formatting: hasDirectRunFormatting(formatting) ? suppressParagraphMarkFormatting({
|
|
259
|
+
baseFormatting: inheritedBaseFormatting,
|
|
260
|
+
directFormatting: formatting,
|
|
261
|
+
paragraphMarkFormatting: void 0
|
|
262
|
+
}) : inheritedBaseFormatting,
|
|
263
|
+
...!hasCharacterStyle ? { implicitCharacterStyleApplied: true } : {},
|
|
264
|
+
toggleCascade: inheritedToggleCascade
|
|
253
265
|
};
|
|
254
266
|
if (!(hasDirectRunFormatting(formatting) || formatting?.styleId !== void 0)) return {
|
|
255
267
|
formatting: defaultRunFormatting,
|
|
268
|
+
implicitCharacterStyleApplied: true,
|
|
256
269
|
toggleCascade: defaultToggleCascade
|
|
257
270
|
};
|
|
258
|
-
const suppressedFormatting = suppressParagraphMarkFormatting(
|
|
271
|
+
const suppressedFormatting = suppressParagraphMarkFormatting({
|
|
272
|
+
baseFormatting: inheritedBaseFormatting,
|
|
273
|
+
directFormatting: formatting,
|
|
274
|
+
paragraphMarkFormatting: inheritableParagraphRunFormatting
|
|
275
|
+
});
|
|
259
276
|
const paragraphMarkOverrides = getParagraphMarkSuppressionOverrides({
|
|
260
277
|
directFormatting: formatting,
|
|
261
278
|
paragraphMarkFormatting: inheritableParagraphRunFormatting,
|
|
262
279
|
suppressedFormatting
|
|
263
|
-
});
|
|
280
|
+
}) ?? (inheritableParagraphRunFormatting ? {} : void 0);
|
|
264
281
|
return {
|
|
265
282
|
formatting: suppressedFormatting,
|
|
283
|
+
...!hasCharacterStyle ? { implicitCharacterStyleApplied: true } : {},
|
|
266
284
|
...paragraphMarkOverrides ? { paragraphMarkOverrides } : {},
|
|
267
|
-
toggleCascade:
|
|
285
|
+
toggleCascade: inheritedToggleCascade
|
|
268
286
|
};
|
|
269
287
|
};
|
|
270
288
|
const emitTrackedChange = (change, markType, moveKind) => {
|
|
271
|
-
emitInlineNodes(convertTrackedChange(change, markType, nextHyperlinkInstanceIndex, getInheritedRunFormatting, styleResolver, moveKind, textBoxAnchors));
|
|
289
|
+
emitInlineNodes(convertTrackedChange(change, markType, nextHyperlinkInstanceIndex, nextPageBreakRunOwnerId, getInheritedRunFormatting, styleResolver, moveKind, textBoxAnchors));
|
|
272
290
|
};
|
|
273
291
|
for (const content of paragraph.content) if (content.type === "commentRangeStart") commentIds.add(content.id);
|
|
274
292
|
else if (content.type === "commentRangeEnd") commentIds.delete(content.id);
|
|
275
293
|
else if (content.type === "commentReference") anchorPointComment(inlineNodes, content.id);
|
|
276
|
-
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));
|
|
277
295
|
else if (content.type === "hyperlink") {
|
|
278
296
|
const linkNodes = convertHyperlink(content, {
|
|
279
297
|
getInheritedRunFormatting,
|
|
280
298
|
styleResolver,
|
|
281
299
|
hyperlinkIndex: nextHyperlinkInstanceIndex(),
|
|
282
|
-
textBoxAnchors
|
|
300
|
+
textBoxAnchors,
|
|
301
|
+
nextPageBreakRunOwnerId
|
|
283
302
|
});
|
|
284
303
|
if (linkNodes.length === 0) {
|
|
285
304
|
emptyHyperlinks ??= [];
|
|
@@ -297,9 +316,10 @@ function convertParagraph(paragraph, styleResolver, nextHyperlinkInstanceIndex,
|
|
|
297
316
|
getInheritedRunFormatting,
|
|
298
317
|
styleResolver,
|
|
299
318
|
nextHyperlinkInstanceIndex,
|
|
319
|
+
nextPageBreakRunOwnerId,
|
|
300
320
|
textBoxAnchors
|
|
301
321
|
}));
|
|
302
|
-
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));
|
|
303
323
|
else if (content.type === "insertion" || content.type === "moveTo") emitTrackedChange(content, "insertion", content.type === "moveTo" ? "moveTo" : null);
|
|
304
324
|
else if (content.type === "deletion" || content.type === "moveFrom") emitTrackedChange(content, "deletion", content.type === "moveFrom" ? "moveFrom" : null);
|
|
305
325
|
else if (content.type === "mathEquation") emitInlineNode(convertMathEquation(content));
|
|
@@ -323,7 +343,9 @@ function convertParagraph(paragraph, styleResolver, nextHyperlinkInstanceIndex,
|
|
|
323
343
|
}
|
|
324
344
|
if (bookmarksArr) attrs.bookmarks = bookmarksArr;
|
|
325
345
|
if (emptyHyperlinks) attrs._emptyHyperlinks = emptyHyperlinks;
|
|
326
|
-
|
|
346
|
+
const proseParagraph = schema.node("paragraph", attrs, inlineNodes);
|
|
347
|
+
linkProseParagraphPropertySource(proseParagraph, paragraph);
|
|
348
|
+
return proseParagraph;
|
|
327
349
|
}
|
|
328
350
|
const resolveParagraphStyleFontFamily = (styleId, styleResolver) => {
|
|
329
351
|
let style = styleId ? styleResolver.getStyle(styleId) : styleResolver.getDefaultParagraphStyle();
|
|
@@ -363,29 +385,31 @@ function anchorPointComment(nodes, commentId) {
|
|
|
363
385
|
* Convert tracked change (insertion or deletion) content to PM nodes with
|
|
364
386
|
* an insertion/deletion mark applied.
|
|
365
387
|
*/
|
|
366
|
-
function convertTrackedChange(change, markType, nextHyperlinkInstanceIndex, getInheritedRunFormatting, styleResolver, moveKind = null, textBoxAnchors) {
|
|
388
|
+
function convertTrackedChange(change, markType, nextHyperlinkInstanceIndex, nextPageBreakRunOwnerId, getInheritedRunFormatting, styleResolver, moveKind = null, textBoxAnchors) {
|
|
367
389
|
const nodes = [];
|
|
368
|
-
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));
|
|
369
391
|
else if (item.type === "hyperlink") {
|
|
370
392
|
const currentHyperlinkIndex = nextHyperlinkInstanceIndex();
|
|
371
393
|
nodes.push(...convertHyperlink(item, {
|
|
372
394
|
getInheritedRunFormatting,
|
|
373
395
|
styleResolver,
|
|
374
396
|
hyperlinkIndex: currentHyperlinkIndex,
|
|
375
|
-
textBoxAnchors
|
|
397
|
+
textBoxAnchors,
|
|
398
|
+
nextPageBreakRunOwnerId
|
|
376
399
|
}));
|
|
377
400
|
} else if (item.type === "simpleField" || item.type === "complexField") {
|
|
378
401
|
const fieldNode = convertField(item, {
|
|
379
402
|
getInheritedRunFormatting,
|
|
380
403
|
styleResolver,
|
|
381
404
|
nextHyperlinkInstanceIndex,
|
|
405
|
+
nextPageBreakRunOwnerId,
|
|
382
406
|
textBoxAnchors
|
|
383
407
|
});
|
|
384
408
|
if (fieldNode) nodes.push(fieldNode);
|
|
385
409
|
} else if (item.type === "insertion" || item.type === "deletion" || item.type === "moveFrom" || item.type === "moveTo") {
|
|
386
410
|
const nestedMarkType = item.type === "insertion" || item.type === "moveTo" ? "insertion" : "deletion";
|
|
387
411
|
const nestedMoveKind = item.type === "moveFrom" || item.type === "moveTo" ? item.type : null;
|
|
388
|
-
nodes.push(...convertTrackedChange(item, nestedMarkType, nextHyperlinkInstanceIndex, getInheritedRunFormatting, styleResolver, nestedMoveKind, textBoxAnchors));
|
|
412
|
+
nodes.push(...convertTrackedChange(item, nestedMarkType, nextHyperlinkInstanceIndex, nextPageBreakRunOwnerId, getInheritedRunFormatting, styleResolver, nestedMoveKind, textBoxAnchors));
|
|
389
413
|
} else if (item.type === "bookmarkStart") nodes.push(schema.node("bookmarkBoundary", {
|
|
390
414
|
type: "start",
|
|
391
415
|
id: item.id,
|
|
@@ -402,27 +426,17 @@ function convertTrackedChange(change, markType, nextHyperlinkInstanceIndex, getI
|
|
|
402
426
|
revisionId: change.info.id,
|
|
403
427
|
author: change.info.author,
|
|
404
428
|
date: change.info.date ?? null,
|
|
429
|
+
utcDate: change.info.utcDate?.value ?? null,
|
|
405
430
|
initials: change.info.initials ?? null,
|
|
406
431
|
moveKind
|
|
407
432
|
});
|
|
408
433
|
return nodes.map((node) => {
|
|
409
434
|
if (node.marks.some(({ type }) => type.name === "insertion" || type.name === "deletion")) return node;
|
|
410
|
-
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));
|
|
411
437
|
return node;
|
|
412
438
|
});
|
|
413
439
|
}
|
|
414
|
-
function canCarryTrackedRunMark(node, markType) {
|
|
415
|
-
if (node.isText) return true;
|
|
416
|
-
if (!node.isInline) return false;
|
|
417
|
-
if (node.type.name === "field" || node.type.name === "structuredField") return true;
|
|
418
|
-
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");
|
|
419
|
-
}
|
|
420
|
-
/**
|
|
421
|
-
* Convert ParagraphFormatting to ProseMirror paragraph attrs
|
|
422
|
-
*
|
|
423
|
-
* If a styleResolver is provided, resolves style-based formatting and merges
|
|
424
|
-
* with inline formatting. Inline formatting takes precedence.
|
|
425
|
-
*/
|
|
426
440
|
function paragraphFormattingToAttrs(paragraph, styleResolver, tableParagraphOverlay) {
|
|
427
441
|
const formatting = paragraph.formatting;
|
|
428
442
|
const styleId = formatting?.styleId;
|
|
@@ -442,6 +456,7 @@ function paragraphFormattingToAttrs(paragraph, styleResolver, tableParagraphOver
|
|
|
442
456
|
if (paragraph.listRendering?.isBullet) attrs.listIsBullet = paragraph.listRendering.isBullet;
|
|
443
457
|
if (paragraph.listRendering?.isLegal) attrs.listIsLegal = paragraph.listRendering.isLegal;
|
|
444
458
|
if (paragraph.listRendering?.marker) attrs.listMarker = paragraph.listRendering.marker;
|
|
459
|
+
if (paragraph.listRendering?.markerTemplate) attrs.listMarkerTemplate = paragraph.listRendering.markerTemplate;
|
|
445
460
|
if (paragraph.listRendering?.markerHidden) attrs.listMarkerHidden = paragraph.listRendering.markerHidden;
|
|
446
461
|
if (paragraph.listRendering?.markerFormatting) attrs.listMarkerFormatting = paragraph.listRendering.markerFormatting;
|
|
447
462
|
if (paragraph.listRendering?.markerAlignment) attrs.listMarkerAlignment = paragraph.listRendering.markerAlignment;
|
|
@@ -466,19 +481,20 @@ function paragraphFormattingToAttrs(paragraph, styleResolver, tableParagraphOver
|
|
|
466
481
|
if (styleResolver) {
|
|
467
482
|
stylePpr = styleResolver.resolveParagraphStyleInTable(styleId, tableParagraphOverlay).paragraphFormatting;
|
|
468
483
|
set("alignment", formatting?.alignment ?? stylePpr?.alignment);
|
|
484
|
+
set("alignmentFromStyle", stylePpr?.alignment);
|
|
469
485
|
set("spaceBefore", formatting?.spaceBefore ?? stylePpr?.spaceBefore);
|
|
470
486
|
set("spaceAfter", formatting?.spaceAfter ?? stylePpr?.spaceAfter);
|
|
471
487
|
set("lineSpacing", formatting?.lineSpacing ?? stylePpr?.lineSpacing);
|
|
472
488
|
set("lineSpacingRule", formatting?.lineSpacingRule ?? stylePpr?.lineSpacingRule);
|
|
473
|
-
set("lineSpacingExplicit", formatting
|
|
489
|
+
set("lineSpacingExplicit", lineSpacingProvenanceFromSpacing(formatting));
|
|
474
490
|
set("snapToGrid", formatting?.snapToGrid ?? stylePpr?.snapToGrid);
|
|
475
491
|
set("spacingExplicit", formatting?.spacingExplicit);
|
|
476
492
|
const paragraphStyle = styleId ? styleResolver.getStyle(styleId) ?? styleResolver.getDefaultParagraphStyle() : styleResolver.getDefaultParagraphStyle();
|
|
477
493
|
const docDefaultSpacing = styleResolver.getDocDefaults()?.pPr;
|
|
478
|
-
const
|
|
479
|
-
if (
|
|
480
|
-
if (
|
|
481
|
-
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;
|
|
482
498
|
const spacingFromDocDefaults = {};
|
|
483
499
|
if (formatting?.spaceBefore === void 0 && tableParagraphOverlay?.spaceBefore === void 0 && paragraphStyle?.pPr?.spaceBefore === void 0 && docDefaultSpacing?.spaceBefore !== void 0) spacingFromDocDefaults.before = true;
|
|
484
500
|
if (formatting?.spaceAfter === void 0 && tableParagraphOverlay?.spaceAfter === void 0 && paragraphStyle?.pPr?.spaceAfter === void 0 && docDefaultSpacing?.spaceAfter !== void 0) spacingFromDocDefaults.after = true;
|
|
@@ -502,9 +518,12 @@ function paragraphFormattingToAttrs(paragraph, styleResolver, tableParagraphOver
|
|
|
502
518
|
set("runInWithNext", formatting?.runInWithNext ?? stylePpr?.runInWithNext);
|
|
503
519
|
set("outlineLevel", formatting?.outlineLevel ?? stylePpr?.outlineLevel);
|
|
504
520
|
set("direction", directionFromBidi(formatting?.bidi ?? stylePpr?.bidi));
|
|
505
|
-
set("defaultTextFormatting", resolveParagraphDefaultTextFormatting(styleId, formatting, styleResolver, { includeParagraphMarkRunProperties: tableOfContentsLevel === void 0 }));
|
|
506
|
-
if (
|
|
507
|
-
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
|
+
};
|
|
508
527
|
attrs.numPrFromStyle = stylePpr.numPr;
|
|
509
528
|
}
|
|
510
529
|
} else {
|
|
@@ -513,6 +532,7 @@ function paragraphFormattingToAttrs(paragraph, styleResolver, tableParagraphOver
|
|
|
513
532
|
set("spaceAfter", formatting?.spaceAfter);
|
|
514
533
|
set("lineSpacing", formatting?.lineSpacing);
|
|
515
534
|
set("lineSpacingRule", formatting?.lineSpacingRule);
|
|
535
|
+
set("lineSpacingExplicit", lineSpacingProvenanceFromSpacing(formatting));
|
|
516
536
|
set("snapToGrid", formatting?.snapToGrid);
|
|
517
537
|
set("spacingExplicit", formatting?.spacingExplicit);
|
|
518
538
|
set("indentLeft", formatting?.indentLeft);
|
|
@@ -548,15 +568,19 @@ function paragraphFormattingToAttrs(paragraph, styleResolver, tableParagraphOver
|
|
|
548
568
|
if (afterAutospacing) setAutospacingBaseValue(base, "after", attrs.spaceAfter);
|
|
549
569
|
attrs._autospacingBase = base;
|
|
550
570
|
}
|
|
551
|
-
return
|
|
571
|
+
return {
|
|
572
|
+
attrs,
|
|
573
|
+
effectiveFrame: formatting?.frame === void 0 ? stylePpr?.frame : {
|
|
574
|
+
...stylePpr?.frame,
|
|
575
|
+
...formatting.frame
|
|
576
|
+
}
|
|
577
|
+
};
|
|
552
578
|
}
|
|
553
579
|
/**
|
|
554
|
-
* Pick the paragraph
|
|
555
|
-
* region's) `w:pPr` for use as the cell-paragraph cascade overlay.
|
|
556
|
-
* than the full `ParagraphFormatting` bag — see
|
|
557
|
-
* {@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.
|
|
558
582
|
*/
|
|
559
|
-
function
|
|
583
|
+
function extractTableParagraphOverlay(pPr) {
|
|
560
584
|
if (!pPr) return;
|
|
561
585
|
const overlay = {};
|
|
562
586
|
if (pPr.spaceBefore !== void 0) overlay.spaceBefore = pPr.spaceBefore;
|
|
@@ -564,6 +588,7 @@ function extractTableParagraphSpacingOverlay(pPr) {
|
|
|
564
588
|
if (pPr.lineSpacing !== void 0) overlay.lineSpacing = pPr.lineSpacing;
|
|
565
589
|
if (pPr.lineSpacingRule !== void 0) overlay.lineSpacingRule = pPr.lineSpacingRule;
|
|
566
590
|
if (pPr.contextualSpacing !== void 0) overlay.contextualSpacing = pPr.contextualSpacing;
|
|
591
|
+
if (pPr.frame !== void 0) overlay.frame = pPr.frame;
|
|
567
592
|
return Object.keys(overlay).length > 0 ? overlay : void 0;
|
|
568
593
|
}
|
|
569
594
|
/**
|
|
@@ -576,11 +601,11 @@ function resolveTableStyleConditional(styleResolver, tableStyleId, conditionType
|
|
|
576
601
|
const conditional = style.tblStylePr.find((p) => p.type === conditionType);
|
|
577
602
|
if (!conditional) return;
|
|
578
603
|
const mergedRunProps = mergeTextFormatting(conditional.pPr?.runProperties ? resolveRunFormattingWithoutDefaults(conditional.pPr.runProperties, styleResolver) : void 0, conditional.rPr ? resolveRunFormattingWithoutDefaults(conditional.rPr, styleResolver) : void 0);
|
|
579
|
-
const
|
|
604
|
+
const paragraphOverlay = extractTableParagraphOverlay(conditional.pPr);
|
|
580
605
|
const result = {};
|
|
581
606
|
if (conditional.tcPr) result.tcPr = conditional.tcPr;
|
|
582
607
|
if (mergedRunProps) result.rPr = mergedRunProps;
|
|
583
|
-
if (
|
|
608
|
+
if (paragraphOverlay) result.pPr = paragraphOverlay;
|
|
584
609
|
return result;
|
|
585
610
|
}
|
|
586
611
|
function resolveTableBaseStyle(styleResolver, tableStyleId) {
|
|
@@ -588,11 +613,11 @@ function resolveTableBaseStyle(styleResolver, tableStyleId) {
|
|
|
588
613
|
const style = styleResolver.getStyle(tableStyleId);
|
|
589
614
|
if (!style) return;
|
|
590
615
|
const mergedRunProps = mergeTextFormatting(style.pPr?.runProperties ? resolveRunFormattingWithoutDefaults(style.pPr.runProperties, styleResolver) : void 0, style.rPr ? resolveRunFormattingWithoutDefaults(style.rPr, styleResolver) : void 0);
|
|
591
|
-
const
|
|
616
|
+
const paragraphOverlay = extractTableParagraphOverlay(style.pPr);
|
|
592
617
|
const result = {};
|
|
593
618
|
if (style.tcPr) result.tcPr = style.tcPr;
|
|
594
619
|
if (mergedRunProps) result.rPr = mergedRunProps;
|
|
595
|
-
if (
|
|
620
|
+
if (paragraphOverlay) result.pPr = paragraphOverlay;
|
|
596
621
|
return result.tcPr || result.rPr || result.pPr ? result : void 0;
|
|
597
622
|
}
|
|
598
623
|
function mergeConditionalStyles(base, override) {
|
|
@@ -627,70 +652,11 @@ function mergeConditionalStyles(base, override) {
|
|
|
627
652
|
if (mergedPPr) merged.pPr = mergedPPr;
|
|
628
653
|
return merged;
|
|
629
654
|
}
|
|
630
|
-
function hasDirectRunFormatting(formatting) {
|
|
631
|
-
if (!formatting) return false;
|
|
632
|
-
for (const key in formatting) {
|
|
633
|
-
if (!Object.hasOwn(formatting, key)) continue;
|
|
634
|
-
const value = Reflect.get(formatting, key);
|
|
635
|
-
if (key !== "styleId" && value !== void 0) return true;
|
|
636
|
-
}
|
|
637
|
-
return false;
|
|
638
|
-
}
|
|
639
|
-
function stripParagraphMarkOnlyFormatting(formatting) {
|
|
640
|
-
const { allCaps: _ac, highlight: _h, shading: _s, smallCaps: _sc, vertAlign: _va, ...rest } = formatting;
|
|
641
|
-
return Object.keys(rest).length > 0 ? rest : void 0;
|
|
642
|
-
}
|
|
643
|
-
function stripParagraphMarkFormattingForBodyRuns(formatting) {
|
|
644
|
-
const paragraphMarkFormatting = stripParagraphMarkOnlyFormatting(formatting);
|
|
645
|
-
if (!paragraphMarkFormatting) return;
|
|
646
|
-
const { fontFamily: _fontFamily, ...bodyRunFormatting } = paragraphMarkFormatting;
|
|
647
|
-
return Object.keys(bodyRunFormatting).length > 0 ? bodyRunFormatting : void 0;
|
|
648
|
-
}
|
|
649
|
-
const PARAGRAPH_MARK_BOOLEAN_KEYS = [
|
|
650
|
-
"bold",
|
|
651
|
-
"italic",
|
|
652
|
-
"strike",
|
|
653
|
-
"doubleStrike",
|
|
654
|
-
"allCaps",
|
|
655
|
-
"smallCaps",
|
|
656
|
-
"hidden",
|
|
657
|
-
"emboss",
|
|
658
|
-
"imprint",
|
|
659
|
-
"shadow",
|
|
660
|
-
"outline",
|
|
661
|
-
"rtl"
|
|
662
|
-
];
|
|
663
|
-
function suppressParagraphMarkFormatting(base, paragraphMark, direct, paragraphMarkPrecedesStyle = false) {
|
|
664
|
-
if (!paragraphMark) return base;
|
|
665
|
-
const result = (paragraphMarkPrecedesStyle ? mergeTextFormatting(paragraphMark, base) : mergeTextFormatting(base, paragraphMark)) ?? {};
|
|
666
|
-
for (const key of PARAGRAPH_MARK_BOOLEAN_KEYS) suppressBooleanParagraphMark(result, base, paragraphMark, direct, key);
|
|
667
|
-
if (paragraphMark.fontSize !== void 0 && direct?.fontSize === void 0 && base?.fontSize !== void 0) result.fontSize = base.fontSize;
|
|
668
|
-
if (paragraphMark.fontSizeCs !== void 0 && direct?.fontSizeCs === void 0 && base?.fontSizeCs !== void 0) result.fontSizeCs = base.fontSizeCs;
|
|
669
|
-
if (paragraphMark.underline !== void 0 && direct?.underline === void 0) result.underline = { style: "none" };
|
|
670
|
-
if (paragraphMark.spacing !== void 0 && direct?.spacing === void 0) result.spacing = 0;
|
|
671
|
-
return Object.keys(result).length > 0 ? result : void 0;
|
|
672
|
-
}
|
|
673
|
-
function getParagraphMarkSuppressionOverrides({ directFormatting, paragraphMarkFormatting, suppressedFormatting }) {
|
|
674
|
-
if (!paragraphMarkFormatting) return;
|
|
675
|
-
const overrides = {};
|
|
676
|
-
for (const key of PARAGRAPH_MARK_BOOLEAN_KEYS) if (paragraphMarkFormatting[key] !== void 0 && directFormatting?.[key] === void 0 && suppressedFormatting?.[key] === false) overrides[key] = false;
|
|
677
|
-
if (paragraphMarkFormatting.underline !== void 0 && directFormatting?.underline === void 0 && suppressedFormatting?.underline?.style === "none") overrides.underline = { style: "none" };
|
|
678
|
-
return Object.keys(overrides).length > 0 ? overrides : void 0;
|
|
679
|
-
}
|
|
680
|
-
function suppressBooleanParagraphMark(result, base, paragraphMark, direct, key) {
|
|
681
|
-
if (paragraphMark[key] === void 0 || direct?.[key] !== void 0) return;
|
|
682
|
-
result[key] = base?.[key] ?? false;
|
|
683
|
-
}
|
|
684
655
|
function resolveTextFormatting(formatting, styleResolver) {
|
|
685
656
|
if (!formatting) return styleResolver?.resolveRunStyle(null);
|
|
686
657
|
if (!styleResolver) return formatting;
|
|
687
658
|
return mergeTextFormatting(styleResolver.resolveRunStyle(formatting.styleId), formatting);
|
|
688
659
|
}
|
|
689
|
-
/**
|
|
690
|
-
* Resolve an embedded character-style reference without importing
|
|
691
|
-
* `docDefaults`. The caller already has the paragraph cascade, including
|
|
692
|
-
* document defaults, and will layer these own properties over it.
|
|
693
|
-
*/
|
|
694
660
|
function resolveRunFormattingWithoutDefaults(formatting, styleResolver) {
|
|
695
661
|
if (!formatting || !styleResolver) return formatting;
|
|
696
662
|
return cascadeStyleTextFormatting([{
|
|
@@ -701,6 +667,7 @@ function resolveRunFormattingWithoutDefaults(formatting, styleResolver) {
|
|
|
701
667
|
type: "direct"
|
|
702
668
|
}]).formatting;
|
|
703
669
|
}
|
|
670
|
+
/** @internal Recompute a paragraph's inherited run defaults from authored package state. */
|
|
704
671
|
function resolveParagraphDefaultTextFormatting(styleId, formatting, styleResolver, options = {}) {
|
|
705
672
|
const style = styleId ? styleResolver.getStyle(styleId) ?? styleResolver.getDefaultParagraphStyle() : styleResolver.getDefaultParagraphStyle();
|
|
706
673
|
const paragraphStyleRpr = style?.type === "paragraph" ? style.rPr : void 0;
|
|
@@ -721,10 +688,6 @@ function resolveParagraphDefaultTextFormatting(styleId, formatting, styleResolve
|
|
|
721
688
|
}
|
|
722
689
|
], { ordinaryFormatting: mergeTextFormatting(mergeTextFormatting(styleResolver.getDocDefaults()?.rPr, styleResolver.getDefaultCharacterStyle()?.rPr), paragraphStyleRpr) });
|
|
723
690
|
const bodyRunDefaults = orderedBodyToggleFormatting.formatting;
|
|
724
|
-
if (styleId !== void 0) return cascadeStyleTextFormatting([{
|
|
725
|
-
cascade: orderedBodyToggleFormatting,
|
|
726
|
-
type: "carried"
|
|
727
|
-
}], { ordinaryFormatting: mergeTextFormatting(paragraphRunProperties, bodyRunDefaults) }).formatting;
|
|
728
691
|
return cascadeStyleTextFormatting([{
|
|
729
692
|
cascade: orderedBodyToggleFormatting,
|
|
730
693
|
type: "carried"
|
|
@@ -826,6 +789,7 @@ function paragraphContentHasMeaningfulContent(content) {
|
|
|
826
789
|
return true;
|
|
827
790
|
}
|
|
828
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);
|
|
829
793
|
const rowSpanMap = calculateRowSpans(table);
|
|
830
794
|
const columnWidths = table.columnWidths;
|
|
831
795
|
const totalWidth = columnWidths?.reduce((sum, w) => sum + w, 0) ?? 0;
|
|
@@ -936,7 +900,9 @@ function convertTableRow(row, styleResolver, context, isHeaderRow, columnWidths,
|
|
|
936
900
|
trIns: {
|
|
937
901
|
revisionId: row.structuralChange.info.id,
|
|
938
902
|
author: row.structuralChange.info.author,
|
|
939
|
-
date: row.structuralChange.info.date ?? null
|
|
903
|
+
date: row.structuralChange.info.date ?? null,
|
|
904
|
+
...row.structuralChange.info.utcDate ? { utcDate: row.structuralChange.info.utcDate.value } : {},
|
|
905
|
+
...row.structuralChange.info.initials ? { initials: row.structuralChange.info.initials } : {}
|
|
940
906
|
}
|
|
941
907
|
};
|
|
942
908
|
else if (row.structuralChange?.type === "tableRowDeletion") attrs = {
|
|
@@ -944,7 +910,9 @@ function convertTableRow(row, styleResolver, context, isHeaderRow, columnWidths,
|
|
|
944
910
|
trDel: {
|
|
945
911
|
revisionId: row.structuralChange.info.id,
|
|
946
912
|
author: row.structuralChange.info.author,
|
|
947
|
-
date: row.structuralChange.info.date ?? null
|
|
913
|
+
date: row.structuralChange.info.date ?? null,
|
|
914
|
+
...row.structuralChange.info.utcDate ? { utcDate: row.structuralChange.info.utcDate.value } : {},
|
|
915
|
+
...row.structuralChange.info.initials ? { initials: row.structuralChange.info.initials } : {}
|
|
948
916
|
}
|
|
949
917
|
};
|
|
950
918
|
const numCells = row.cells.length;
|
|
@@ -958,10 +926,7 @@ function convertTableRow(row, styleResolver, context, isHeaderRow, columnWidths,
|
|
|
958
926
|
if (effectiveCells.length === 0) {
|
|
959
927
|
const fallback = {
|
|
960
928
|
type: "tableCell",
|
|
961
|
-
content: [
|
|
962
|
-
type: "paragraph",
|
|
963
|
-
content: []
|
|
964
|
-
}]
|
|
929
|
+
content: []
|
|
965
930
|
};
|
|
966
931
|
if (totalCols > 1) fallback.formatting = { gridSpan: totalCols };
|
|
967
932
|
effectiveCells = [fallback];
|
|
@@ -1084,7 +1049,9 @@ function convertTableCell({ cell, styleResolver, context, isHeader, gridWidthPer
|
|
|
1084
1049
|
info: {
|
|
1085
1050
|
revisionId: cell.structuralChange.info.id,
|
|
1086
1051
|
author: cell.structuralChange.info.author,
|
|
1087
|
-
date: cell.structuralChange.info.date ?? null
|
|
1052
|
+
date: cell.structuralChange.info.date ?? null,
|
|
1053
|
+
...cell.structuralChange.info.utcDate ? { utcDate: cell.structuralChange.info.utcDate.value } : {},
|
|
1054
|
+
...cell.structuralChange.info.initials ? { initials: cell.structuralChange.info.initials } : {}
|
|
1088
1055
|
}
|
|
1089
1056
|
};
|
|
1090
1057
|
else if (cell.structuralChange?.type === "tableCellDeletion") attrs.cellMarker = {
|
|
@@ -1092,7 +1059,9 @@ function convertTableCell({ cell, styleResolver, context, isHeader, gridWidthPer
|
|
|
1092
1059
|
info: {
|
|
1093
1060
|
revisionId: cell.structuralChange.info.id,
|
|
1094
1061
|
author: cell.structuralChange.info.author,
|
|
1095
|
-
date: cell.structuralChange.info.date ?? null
|
|
1062
|
+
date: cell.structuralChange.info.date ?? null,
|
|
1063
|
+
...cell.structuralChange.info.utcDate ? { utcDate: cell.structuralChange.info.utcDate.value } : {},
|
|
1064
|
+
...cell.structuralChange.info.initials ? { initials: cell.structuralChange.info.initials } : {}
|
|
1096
1065
|
}
|
|
1097
1066
|
};
|
|
1098
1067
|
else if (cell.structuralChange?.type === "tableCellMerge") attrs.cellMarker = {
|
|
@@ -1100,7 +1069,9 @@ function convertTableCell({ cell, styleResolver, context, isHeader, gridWidthPer
|
|
|
1100
1069
|
info: {
|
|
1101
1070
|
revisionId: cell.structuralChange.info.id,
|
|
1102
1071
|
author: cell.structuralChange.info.author,
|
|
1103
|
-
date: cell.structuralChange.info.date ?? null
|
|
1072
|
+
date: cell.structuralChange.info.date ?? null,
|
|
1073
|
+
...cell.structuralChange.info.utcDate ? { utcDate: cell.structuralChange.info.utcDate.value } : {},
|
|
1074
|
+
...cell.structuralChange.info.initials ? { initials: cell.structuralChange.info.initials } : {}
|
|
1104
1075
|
},
|
|
1105
1076
|
...cell.structuralChange.verticalMerge !== void 0 ? { verticalMerge: cell.structuralChange.verticalMerge } : {},
|
|
1106
1077
|
...cell.structuralChange.verticalMergeOriginal !== void 0 ? { verticalMergeOriginal: cell.structuralChange.verticalMergeOriginal } : {}
|
|
@@ -1120,14 +1091,19 @@ function convertTableCell({ cell, styleResolver, context, isHeader, gridWidthPer
|
|
|
1120
1091
|
return schema.node(nodeType, attrs, contentNodes);
|
|
1121
1092
|
}
|
|
1122
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);
|
|
1123
1098
|
return convertTableCell({
|
|
1124
1099
|
cell,
|
|
1125
1100
|
styleResolver: null,
|
|
1126
1101
|
context: {
|
|
1127
1102
|
theme: null,
|
|
1128
|
-
nextTextBoxGroupId
|
|
1129
|
-
nextHyperlinkInstanceIndex
|
|
1130
|
-
pairedBookmarkIds: collectPairedBookmarkIds(cell.content)
|
|
1103
|
+
nextTextBoxGroupId,
|
|
1104
|
+
nextHyperlinkInstanceIndex,
|
|
1105
|
+
pairedBookmarkIds: collectPairedBookmarkIds(cell.content),
|
|
1106
|
+
pageBreakRunSourceDescendants
|
|
1131
1107
|
},
|
|
1132
1108
|
isHeader: nodeType === "tableHeader",
|
|
1133
1109
|
gridWidthPercent: void 0,
|
|
@@ -1140,16 +1116,26 @@ function standaloneTableCellToProseMirror(cell, nodeType) {
|
|
|
1140
1116
|
defaultCellMargins: void 0
|
|
1141
1117
|
});
|
|
1142
1118
|
}
|
|
1143
|
-
function convertField(field, { getInheritedRunFormatting, styleResolver, nextHyperlinkInstanceIndex, textBoxAnchors }) {
|
|
1119
|
+
function convertField(field, { getInheritedRunFormatting, styleResolver, nextHyperlinkInstanceIndex, nextPageBreakRunOwnerId, textBoxAnchors }) {
|
|
1144
1120
|
let displayText = "";
|
|
1145
1121
|
let fieldFormatting;
|
|
1122
|
+
let fieldPropertyChanges;
|
|
1146
1123
|
const inlineNodes = [];
|
|
1147
|
-
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");
|
|
1148
1133
|
const appendRun = (run) => {
|
|
1149
1134
|
for (const content of run.content) if (content.type === "text") displayText += content.text;
|
|
1150
1135
|
fieldFormatting ??= run.formatting;
|
|
1136
|
+
fieldPropertyChanges ??= run.propertyChanges;
|
|
1151
1137
|
if (!hasStructuredSourceContent) return;
|
|
1152
|
-
inlineNodes.push(...convertRun(run, getInheritedRunFormatting(run.formatting, field.fieldType), styleResolver, textBoxAnchors));
|
|
1138
|
+
inlineNodes.push(...convertRun(run, getInheritedRunFormatting(run.formatting, field.fieldType), nextPageBreakRunOwnerId, styleResolver, textBoxAnchors));
|
|
1153
1139
|
};
|
|
1154
1140
|
if (field.type === "simpleField") for (const content of field.content) {
|
|
1155
1141
|
if (content.type === "run") {
|
|
@@ -1159,12 +1145,14 @@ function convertField(field, { getInheritedRunFormatting, styleResolver, nextHyp
|
|
|
1159
1145
|
for (const child of content.children) if (child.type === "run") {
|
|
1160
1146
|
for (const runContent of child.content) if (runContent.type === "text") displayText += runContent.text;
|
|
1161
1147
|
fieldFormatting ??= child.formatting;
|
|
1148
|
+
fieldPropertyChanges ??= child.propertyChanges;
|
|
1162
1149
|
}
|
|
1163
1150
|
inlineNodes.push(...convertHyperlink(content, {
|
|
1164
1151
|
getInheritedRunFormatting: (formatting) => getInheritedRunFormatting(formatting, field.fieldType),
|
|
1165
1152
|
styleResolver,
|
|
1166
1153
|
hyperlinkIndex: nextHyperlinkInstanceIndex(),
|
|
1167
|
-
textBoxAnchors
|
|
1154
|
+
textBoxAnchors,
|
|
1155
|
+
nextPageBreakRunOwnerId
|
|
1168
1156
|
}));
|
|
1169
1157
|
}
|
|
1170
1158
|
else for (const run of field.fieldResult) appendRun(run);
|
|
@@ -1172,7 +1160,8 @@ function convertField(field, { getInheritedRunFormatting, styleResolver, nextHyp
|
|
|
1172
1160
|
const inheritedFormatting = getInheritedRunFormatting(fieldFormatting, field.fieldType);
|
|
1173
1161
|
const { marks } = buildRunMarks(fieldFormatting, inheritedFormatting, styleResolver);
|
|
1174
1162
|
const hasConvertedHyperlinkContent = inlineNodes.some((node) => node.marks.some((mark) => mark.type.name === "hyperlink"));
|
|
1175
|
-
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] }));
|
|
1176
1165
|
return schema.node(createStructuredField ? "structuredField" : "field", {
|
|
1177
1166
|
fieldType: field.fieldType,
|
|
1178
1167
|
instruction: field.instruction,
|
|
@@ -1195,18 +1184,19 @@ function convertMathEquation(math) {
|
|
|
1195
1184
|
/**
|
|
1196
1185
|
* Convert an InlineSdt to a ProseMirror sdt node with inline content.
|
|
1197
1186
|
*/
|
|
1198
|
-
function convertInlineSdt(sdt, nextHyperlinkInstanceIndex, getInheritedRunFormatting, styleResolver, textBoxAnchors) {
|
|
1187
|
+
function convertInlineSdt(sdt, nextHyperlinkInstanceIndex, nextPageBreakRunOwnerId, getInheritedRunFormatting, styleResolver, textBoxAnchors) {
|
|
1199
1188
|
const props = sdt.properties;
|
|
1200
1189
|
const inlineNodes = [];
|
|
1201
1190
|
for (const content of sdt.content) if (content.type === "run") {
|
|
1202
|
-
const runNodes = convertRun(content, getInheritedRunFormatting(content.formatting), styleResolver, textBoxAnchors);
|
|
1191
|
+
const runNodes = convertRun(content, getInheritedRunFormatting(content.formatting), nextPageBreakRunOwnerId, styleResolver, textBoxAnchors);
|
|
1203
1192
|
inlineNodes.push(...runNodes);
|
|
1204
1193
|
} else if (content.type === "hyperlink") {
|
|
1205
1194
|
const linkNodes = convertHyperlink(content, {
|
|
1206
1195
|
getInheritedRunFormatting,
|
|
1207
1196
|
styleResolver,
|
|
1208
1197
|
hyperlinkIndex: nextHyperlinkInstanceIndex(),
|
|
1209
|
-
textBoxAnchors
|
|
1198
|
+
textBoxAnchors,
|
|
1199
|
+
nextPageBreakRunOwnerId
|
|
1210
1200
|
});
|
|
1211
1201
|
inlineNodes.push(...linkNodes);
|
|
1212
1202
|
} else if (content.type === "simpleField" || content.type === "complexField") {
|
|
@@ -1214,16 +1204,17 @@ function convertInlineSdt(sdt, nextHyperlinkInstanceIndex, getInheritedRunFormat
|
|
|
1214
1204
|
getInheritedRunFormatting,
|
|
1215
1205
|
styleResolver,
|
|
1216
1206
|
nextHyperlinkInstanceIndex,
|
|
1207
|
+
nextPageBreakRunOwnerId,
|
|
1217
1208
|
textBoxAnchors
|
|
1218
1209
|
});
|
|
1219
1210
|
if (fieldNode) inlineNodes.push(fieldNode);
|
|
1220
1211
|
} else if (content.type === "inlineSdt") {
|
|
1221
|
-
const nestedSdt = convertInlineSdt(content, nextHyperlinkInstanceIndex, getInheritedRunFormatting, styleResolver, textBoxAnchors);
|
|
1212
|
+
const nestedSdt = convertInlineSdt(content, nextHyperlinkInstanceIndex, nextPageBreakRunOwnerId, getInheritedRunFormatting, styleResolver, textBoxAnchors);
|
|
1222
1213
|
if (nestedSdt) inlineNodes.push(nestedSdt);
|
|
1223
|
-
} else if (content.type === "insertion") inlineNodes.push(...convertTrackedChange(content, "insertion", nextHyperlinkInstanceIndex, getInheritedRunFormatting, styleResolver, null, textBoxAnchors));
|
|
1224
|
-
else if (content.type === "deletion") inlineNodes.push(...convertTrackedChange(content, "deletion", nextHyperlinkInstanceIndex, getInheritedRunFormatting, styleResolver, null, textBoxAnchors));
|
|
1225
|
-
else if (content.type === "moveTo") inlineNodes.push(...convertTrackedChange(content, "insertion", nextHyperlinkInstanceIndex, getInheritedRunFormatting, styleResolver, "moveTo", textBoxAnchors));
|
|
1226
|
-
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));
|
|
1227
1218
|
else {
|
|
1228
1219
|
const mathNode = convertMathEquation(content);
|
|
1229
1220
|
if (mathNode) inlineNodes.push(mathNode);
|
|
@@ -1236,19 +1227,208 @@ function convertInlineSdt(sdt, nextHyperlinkInstanceIndex, getInheritedRunFormat
|
|
|
1236
1227
|
* @param run - The run to convert
|
|
1237
1228
|
* @param resolvedStyleFormatting - Paragraph formatting and its explicit style-toggle state
|
|
1238
1229
|
*/
|
|
1239
|
-
function convertRun(run, resolvedStyleFormatting, styleResolver, textBoxAnchors) {
|
|
1230
|
+
function convertRun(run, resolvedStyleFormatting, nextPageBreakRunOwnerId, styleResolver, textBoxAnchors) {
|
|
1231
|
+
assertPageBreakSourceRunIsRepresentable(run);
|
|
1240
1232
|
const nodes = [];
|
|
1241
1233
|
const { marks, mergedFormatting } = buildRunMarks(run.formatting, resolvedStyleFormatting, styleResolver);
|
|
1242
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() }));
|
|
1243
1236
|
for (const content of run.content) {
|
|
1244
1237
|
const contentNodes = convertRunContent(content, marks, mergedFormatting, textBoxAnchors);
|
|
1245
1238
|
nodes.push(...contentNodes);
|
|
1246
1239
|
}
|
|
1247
1240
|
return nodes;
|
|
1248
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
|
+
};
|
|
1249
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
|
+
};
|
|
1250
1428
|
const styleId = runFormatting?.styleId;
|
|
1251
|
-
|
|
1429
|
+
let characterStyleFormatting;
|
|
1430
|
+
if (styleId) characterStyleFormatting = styleResolver?.getRunStyleOwnProperties(styleId);
|
|
1431
|
+
else if (!inherited.implicitCharacterStyleApplied) characterStyleFormatting = styleResolver?.getDefaultCharacterStyle()?.rPr;
|
|
1252
1432
|
let ordinaryRunStyleFormatting = inherited.formatting ? { ...inherited.formatting } : {};
|
|
1253
1433
|
if (styleId) ordinaryRunStyleFormatting = mergeTextFormatting(inherited.formatting, characterStyleFormatting) ?? {};
|
|
1254
1434
|
const cascadedStyleFormatting = cascadeStyleTextFormatting([{
|
|
@@ -1266,20 +1446,28 @@ function buildRunMarks(runFormatting, inherited, styleResolver) {
|
|
|
1266
1446
|
formatting: runFormatting,
|
|
1267
1447
|
type: "direct"
|
|
1268
1448
|
}], { ordinaryFormatting: mergeTextFormatting(runStyleFormatting, runFormatting) }).formatting;
|
|
1269
|
-
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({
|
|
1270
1456
|
directFormatting: runFormatting,
|
|
1271
1457
|
effectiveStyleFormatting: runStyleFormatting,
|
|
1272
1458
|
hasCharacterStyle: styleId !== void 0,
|
|
1273
1459
|
paragraphMarkOverrides: inherited.paragraphMarkOverrides
|
|
1274
|
-
})
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
marks.push(schema.mark("characterStyle", {
|
|
1279
|
-
styleId,
|
|
1280
|
-
_styleRPr: styleRPr && Object.keys(styleRPr).length > 0 ? styleRPr : null
|
|
1281
|
-
}));
|
|
1460
|
+
});
|
|
1461
|
+
if (authoredCarrier === "reconstruct") {
|
|
1462
|
+
if (overrideFormatting?.bold === true) delete overrideFormatting.bold;
|
|
1463
|
+
if (overrideFormatting?.italic === true) delete overrideFormatting.italic;
|
|
1282
1464
|
}
|
|
1465
|
+
const marks = textFormattingToMarks(mergedFormatting, {
|
|
1466
|
+
overrideFormatting,
|
|
1467
|
+
directFormatting: runFormatting,
|
|
1468
|
+
authoredCarrier
|
|
1469
|
+
});
|
|
1470
|
+
if (styleId) marks.push(schema.mark("characterStyle", { styleId }));
|
|
1283
1471
|
return {
|
|
1284
1472
|
marks,
|
|
1285
1473
|
mergedFormatting
|
|
@@ -1290,12 +1478,43 @@ const addDirectFontProvenance = (marks, directFormatting) => {
|
|
|
1290
1478
|
if (directFormatting?.fontFamily !== void 0) directFontProperties.push("fontFamily");
|
|
1291
1479
|
if (directFormatting?.fontSize !== void 0) directFontProperties.push("fontSize");
|
|
1292
1480
|
if (directFormatting?.color !== void 0) directFontProperties.push("color");
|
|
1293
|
-
if (
|
|
1481
|
+
if (directFontProperties.length === 0) return;
|
|
1294
1482
|
const index = marks.findIndex(({ type }) => type.name === "runFormattingOverride");
|
|
1295
1483
|
const existing = index >= 0 ? marks.at(index) : void 0;
|
|
1296
1484
|
const override = schema.mark("runFormattingOverride", {
|
|
1297
1485
|
...existing?.attrs,
|
|
1298
|
-
|
|
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;
|
|
1511
|
+
const index = marks.findIndex(({ type }) => type.name === "runFormattingOverride");
|
|
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);
|
|
1515
|
+
const override = schema.mark("runFormattingOverride", {
|
|
1516
|
+
...existing?.attrs,
|
|
1517
|
+
complexScriptPropertyAbsences: COMPLEX_SCRIPT_RUN_PROPERTY_KEYS.filter((property) => existingAbsences.has(property))
|
|
1299
1518
|
});
|
|
1300
1519
|
if (index >= 0) {
|
|
1301
1520
|
marks[index] = override;
|
|
@@ -1304,8 +1523,6 @@ const addDirectFontProvenance = (marks, directFormatting) => {
|
|
|
1304
1523
|
marks.push(override);
|
|
1305
1524
|
};
|
|
1306
1525
|
const ORDINARY_STYLE_TOGGLE_KEYS = [
|
|
1307
|
-
"bold",
|
|
1308
|
-
"italic",
|
|
1309
1526
|
"strike",
|
|
1310
1527
|
"allCaps",
|
|
1311
1528
|
"smallCaps",
|
|
@@ -1319,8 +1536,6 @@ function getRunFormattingOverrides({ directFormatting, effectiveStyleFormatting,
|
|
|
1319
1536
|
const overrides = mergeTextFormatting(paragraphMarkOverrides, directFormatting);
|
|
1320
1537
|
if (!overrides || !directFormatting) return overrides;
|
|
1321
1538
|
for (const key of ORDINARY_STYLE_TOGGLE_KEYS) if (directFormatting[key] === true && (!hasCharacterStyle || effectiveStyleFormatting?.[key] !== true)) Reflect.deleteProperty(overrides, key);
|
|
1322
|
-
if (directFormatting.boldCs === true && directFormatting.boldCs === directFormatting.bold && (!hasCharacterStyle || effectiveStyleFormatting?.boldCs === void 0)) Reflect.deleteProperty(overrides, "boldCs");
|
|
1323
|
-
if (directFormatting.italicCs === true && directFormatting.italicCs === directFormatting.italic && (!hasCharacterStyle || effectiveStyleFormatting?.italicCs === void 0)) Reflect.deleteProperty(overrides, "italicCs");
|
|
1324
1539
|
return overrides;
|
|
1325
1540
|
}
|
|
1326
1541
|
/**
|
|
@@ -1332,12 +1547,21 @@ function convertRunContent(content, marks, formatting, textBoxAnchors) {
|
|
|
1332
1547
|
if (content.text) return [schema.text(content.text, marks)];
|
|
1333
1548
|
return [];
|
|
1334
1549
|
case "break":
|
|
1335
|
-
if (content.breakType === "textWrapping" || !content.breakType)
|
|
1336
|
-
|
|
1337
|
-
|
|
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)];
|
|
1338
1562
|
case "renderedPageBreak": return [schema.node("renderedPageBreak").mark(marks)];
|
|
1339
1563
|
case "tab": return [schema.node("tab", content.positional ? { positional: content.positional } : void 0).mark(marks)];
|
|
1340
|
-
case "drawing": return [
|
|
1564
|
+
case "drawing": return [withRunBoundaryMarks(convertImage({
|
|
1341
1565
|
image: content.image,
|
|
1342
1566
|
rawXml: content.rawXml,
|
|
1343
1567
|
rawXmlMode: content.rawXmlMode
|
|
@@ -1348,7 +1572,7 @@ function convertRunContent(content, marks, formatting, textBoxAnchors) {
|
|
|
1348
1572
|
const anchorId = textBoxAnchors?.get(shp);
|
|
1349
1573
|
return anchorId ? [schema.node("textBoxAnchor", { anchorId }).mark(marks)] : [];
|
|
1350
1574
|
}
|
|
1351
|
-
return [
|
|
1575
|
+
return [withRunBoundaryMarks(convertShape(shp), marks)];
|
|
1352
1576
|
}
|
|
1353
1577
|
case "footnoteRef": {
|
|
1354
1578
|
const footnoteMark = schema.mark("footnoteRef", {
|
|
@@ -1376,8 +1600,8 @@ function convertRunContent(content, marks, formatting, textBoxAnchors) {
|
|
|
1376
1600
|
}).mark(marks)];
|
|
1377
1601
|
}
|
|
1378
1602
|
}
|
|
1379
|
-
function
|
|
1380
|
-
if (!marks.some((
|
|
1603
|
+
function withRunBoundaryMarks(node, marks) {
|
|
1604
|
+
if (!marks.some(({ type }) => type.name === "hyperlink" || type.name === "pageBreakRunOwner")) return node;
|
|
1381
1605
|
return node.mark(marks);
|
|
1382
1606
|
}
|
|
1383
1607
|
function convertImage({ image, rawXml, rawXmlMode }) {
|
|
@@ -1485,7 +1709,7 @@ function convertImage({ image, rawXml, rawXmlMode }) {
|
|
|
1485
1709
|
_docxObjectPreview: rawXml !== void 0 && /<(?:[A-Za-z_][\w.-]*:)?object(?:\s|>)/u.test(rawXml)
|
|
1486
1710
|
});
|
|
1487
1711
|
}
|
|
1488
|
-
function convertHyperlink(hyperlink, { getInheritedRunFormatting, styleResolver, hyperlinkIndex, textBoxAnchors }) {
|
|
1712
|
+
function convertHyperlink(hyperlink, { getInheritedRunFormatting, styleResolver, hyperlinkIndex, textBoxAnchors, nextPageBreakRunOwnerId }) {
|
|
1489
1713
|
const nodes = [];
|
|
1490
1714
|
const href = hyperlink.href || (hyperlink.anchor ? `#${hyperlink.anchor}` : "");
|
|
1491
1715
|
const linkMark = schema.mark("hyperlink", {
|
|
@@ -1513,8 +1737,11 @@ function convertHyperlink(hyperlink, { getInheritedRunFormatting, styleResolver,
|
|
|
1513
1737
|
continue;
|
|
1514
1738
|
}
|
|
1515
1739
|
if (child.type === "run") {
|
|
1740
|
+
assertPageBreakSourceRunIsRepresentable(child);
|
|
1516
1741
|
const inheritedFormatting = getInheritedRunFormatting(child.formatting);
|
|
1517
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() }));
|
|
1518
1745
|
const allMarks = [...runMarks, linkMark];
|
|
1519
1746
|
for (const content of child.content) nodes.push(...convertRunContent(content, allMarks, mergedFormatting, textBoxAnchors));
|
|
1520
1747
|
}
|
|
@@ -1524,7 +1751,14 @@ function convertHyperlink(hyperlink, { getInheritedRunFormatting, styleResolver,
|
|
|
1524
1751
|
function textFormattingToMarks(formatting, options) {
|
|
1525
1752
|
if (!formatting) return [];
|
|
1526
1753
|
const marks = [];
|
|
1527
|
-
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);
|
|
1528
1762
|
if (overrideAttrs) marks.push(schema.mark("runFormattingOverride", overrideAttrs));
|
|
1529
1763
|
if (formatting.bold) marks.push(schema.mark("bold"));
|
|
1530
1764
|
if (formatting.italic) marks.push(schema.mark("italic"));
|
|
@@ -1577,6 +1811,8 @@ function textFormattingToMarks(formatting, options) {
|
|
|
1577
1811
|
if (formatting.outline) marks.push(schema.mark("textOutline"));
|
|
1578
1812
|
if (formatting.rtl) marks.push(schema.mark("rtl"));
|
|
1579
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);
|
|
1580
1816
|
return marks;
|
|
1581
1817
|
}
|
|
1582
1818
|
/**
|
|
@@ -1686,7 +1922,7 @@ function convertShape(shape) {
|
|
|
1686
1922
|
}
|
|
1687
1923
|
function convertParagraphWithTextBoxes(block, styleResolver, { textBoxGroupId, context, extraRunFormatting, preserveEmptyWrapper, tableParagraphOverlay }) {
|
|
1688
1924
|
const { textBoxes, textBoxAnchors } = extractTextBoxesFromParagraph(block, textBoxGroupId);
|
|
1689
|
-
const pmParagraph = convertParagraph(block, styleResolver, context
|
|
1925
|
+
const pmParagraph = convertParagraph(block, styleResolver, context, void 0, extraRunFormatting, tableParagraphOverlay, textBoxAnchors);
|
|
1690
1926
|
const nodes = [];
|
|
1691
1927
|
const isEmptyAfterExtraction = textBoxes.length > 0 && !hasContentBesidesTextBoxAnchors(pmParagraph);
|
|
1692
1928
|
const keepWrapperParagraph = isEmptyAfterExtraction && (preserveEmptyWrapper === true || hasParagraphBoundaryPayload(block, pmParagraph));
|
|
@@ -1839,6 +2075,7 @@ function textBoxFromShape(shape, textBody) {
|
|
|
1839
2075
|
* Convert a TextBox to a ProseMirror textBox node
|
|
1840
2076
|
*/
|
|
1841
2077
|
function convertTextBox(textBox, styleResolver, options) {
|
|
2078
|
+
assertSourceContainerHasNoPageBreakRun(textBox.content, "text-box", options.context.pageBreakRunSourceDescendants);
|
|
1842
2079
|
const textBoxSize = textBox.size;
|
|
1843
2080
|
const widthPx = textBoxSize?.width ? emuToPixels(textBoxSize.width) : 200;
|
|
1844
2081
|
const heightPx = textBoxSize?.height ? emuToPixels(textBoxSize.height) : void 0;
|
|
@@ -1951,7 +2188,8 @@ function headerFooterToProseDoc(content, options) {
|
|
|
1951
2188
|
theme,
|
|
1952
2189
|
nextTextBoxGroupId,
|
|
1953
2190
|
nextHyperlinkInstanceIndex: createHyperlinkInstanceIndexAllocator(),
|
|
1954
|
-
pairedBookmarkIds: collectPairedBookmarkIds(content)
|
|
2191
|
+
pairedBookmarkIds: collectPairedBookmarkIds(content),
|
|
2192
|
+
pageBreakRunSourceDescendants: buildPageBreakRunSourceDescendantIndex(content)
|
|
1955
2193
|
};
|
|
1956
2194
|
const convertBlocks = (blocks) => {
|
|
1957
2195
|
const out = [];
|
|
@@ -1965,10 +2203,10 @@ function headerFooterToProseDoc(content, options) {
|
|
|
1965
2203
|
if (isDetachedWatermarkHost) {
|
|
1966
2204
|
const paragraphNodeIndex = paragraphNodes.findIndex(({ type }) => type.name === "paragraph");
|
|
1967
2205
|
const paragraphNode = paragraphNodes[paragraphNodeIndex];
|
|
1968
|
-
if (paragraphNode) paragraphNodes[paragraphNodeIndex] = paragraphNode
|
|
2206
|
+
if (paragraphNode) paragraphNodes[paragraphNodeIndex] = recreateProseNodeWithParagraphPropertySource(paragraphNode, { attrs: {
|
|
1969
2207
|
...paragraphNode.attrs,
|
|
1970
2208
|
_detachedWatermarkHost: true
|
|
1971
|
-
}
|
|
2209
|
+
} });
|
|
1972
2210
|
}
|
|
1973
2211
|
out.push(...paragraphNodes);
|
|
1974
2212
|
} else if (block.type === "table") out.push(convertTable(block, styleResolver, conversionContext));
|
|
@@ -1985,100 +2223,10 @@ function footnoteToProseDoc(content, options) {
|
|
|
1985
2223
|
return headerFooterToProseDoc(content, options);
|
|
1986
2224
|
}
|
|
1987
2225
|
/**
|
|
1988
|
-
* Determine where a page break appears inside a paragraph.
|
|
1989
|
-
*
|
|
1990
|
-
* Per ECMA-376 §17.3.3.1, `<w:br w:type="page"/>` is always a forced break,
|
|
1991
|
-
* including in a paragraph whose only content is the break itself. We previously
|
|
1992
|
-
* searched only top-level runs and missed breaks nested in hyperlinks, tracked
|
|
1993
|
-
* changes, or fields — so those paragraphs silently dropped their forced break
|
|
1994
|
-
* and the following content collapsed onto the previous page (common on legal
|
|
1995
|
-
* signature pages and exhibit covers).
|
|
1996
|
-
* See eigenpal docx-editor #409 (break-only page break sub-fix).
|
|
1997
|
-
*
|
|
1998
|
-
* Returns:
|
|
1999
|
-
* "before" — the break appears before any visible content; the paragraph's
|
|
2000
|
-
* content belongs on the NEXT page.
|
|
2001
|
-
* "after" — the break follows some visible content; the paragraph stays
|
|
2002
|
-
* on the current page and the next block starts a new page.
|
|
2003
|
-
* null — no page break found.
|
|
2004
|
-
*/
|
|
2005
|
-
function paragraphPageBreakPosition(paragraph) {
|
|
2006
|
-
if (!mayContainPageBreak(paragraph)) return null;
|
|
2007
|
-
return findParagraphPageBreakPosition(paragraph);
|
|
2008
|
-
}
|
|
2009
|
-
function mayContainPageBreak(paragraph) {
|
|
2010
|
-
for (const item of paragraph.content) {
|
|
2011
|
-
if (item.type === "run") {
|
|
2012
|
-
for (const content of item.content) if (content.type === "break" && content.breakType === "page") return true;
|
|
2013
|
-
continue;
|
|
2014
|
-
}
|
|
2015
|
-
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;
|
|
2016
|
-
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;
|
|
2017
|
-
}
|
|
2018
|
-
return false;
|
|
2019
|
-
}
|
|
2020
|
-
function findParagraphPageBreakPosition(paragraph) {
|
|
2021
|
-
const state = { seenVisibleContent: false };
|
|
2022
|
-
function isPageBreak(content) {
|
|
2023
|
-
return content.type === "break" && content.breakType === "page";
|
|
2024
|
-
}
|
|
2025
|
-
function isVisibleRunContent(content) {
|
|
2026
|
-
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";
|
|
2027
|
-
}
|
|
2028
|
-
function visitRun(run) {
|
|
2029
|
-
for (const content of run.content) {
|
|
2030
|
-
if (isPageBreak(content)) return true;
|
|
2031
|
-
if (isVisibleRunContent(content)) state.seenVisibleContent = true;
|
|
2032
|
-
}
|
|
2033
|
-
return false;
|
|
2034
|
-
}
|
|
2035
|
-
function visitHyperlinkChildren(hyperlink) {
|
|
2036
|
-
for (const child of hyperlink.children) if (child.type === "run" && visitRun(child)) return true;
|
|
2037
|
-
return false;
|
|
2038
|
-
}
|
|
2039
|
-
function visitRunOrHyperlinkList(children) {
|
|
2040
|
-
for (const child of children) {
|
|
2041
|
-
if (child.type === "run" && visitRun(child)) return true;
|
|
2042
|
-
if (child.type === "hyperlink" && visitHyperlinkChildren(child)) return true;
|
|
2043
|
-
if (child.type === "simpleField") for (const fieldChild of child.content) {
|
|
2044
|
-
if (fieldChild.type === "run" && visitRun(fieldChild)) return true;
|
|
2045
|
-
if (fieldChild.type === "hyperlink" && visitHyperlinkChildren(fieldChild)) return true;
|
|
2046
|
-
}
|
|
2047
|
-
if (child.type === "complexField") {
|
|
2048
|
-
for (const run of child.fieldCode) if (visitRun(run)) return true;
|
|
2049
|
-
for (const run of child.fieldResult) if (visitRun(run)) return true;
|
|
2050
|
-
}
|
|
2051
|
-
if ((child.type === "insertion" || child.type === "deletion" || child.type === "moveFrom" || child.type === "moveTo") && visitRunOrHyperlinkList(child.content)) return true;
|
|
2052
|
-
}
|
|
2053
|
-
return false;
|
|
2054
|
-
}
|
|
2055
|
-
function visitItem(item) {
|
|
2056
|
-
if (item.type === "run") return visitRun(item);
|
|
2057
|
-
if (item.type === "hyperlink") return visitHyperlinkChildren(item);
|
|
2058
|
-
if (item.type === "insertion" || item.type === "deletion" || item.type === "moveFrom" || item.type === "moveTo") return visitRunOrHyperlinkList(item.content);
|
|
2059
|
-
if (item.type === "simpleField") return visitRunOrHyperlinkList(item.content);
|
|
2060
|
-
if (item.type === "complexField") {
|
|
2061
|
-
for (const run of item.fieldResult) if (visitRun(run)) return true;
|
|
2062
|
-
return false;
|
|
2063
|
-
}
|
|
2064
|
-
if (item.type === "inlineSdt") {
|
|
2065
|
-
for (const child of item.content) if (visitItem(child)) return true;
|
|
2066
|
-
return false;
|
|
2067
|
-
}
|
|
2068
|
-
if (item.type === "mathEquation") {
|
|
2069
|
-
state.seenVisibleContent = true;
|
|
2070
|
-
return false;
|
|
2071
|
-
}
|
|
2072
|
-
return false;
|
|
2073
|
-
}
|
|
2074
|
-
for (const item of paragraph.content) if (visitItem(item)) return state.seenVisibleContent ? "after" : "before";
|
|
2075
|
-
return null;
|
|
2076
|
-
}
|
|
2077
|
-
/**
|
|
2078
2226
|
* Create an empty ProseMirror document
|
|
2079
2227
|
*/
|
|
2080
2228
|
function createEmptyDoc() {
|
|
2081
2229
|
return schema.node("doc", null, [schema.node("paragraph", {}, [])]);
|
|
2082
2230
|
}
|
|
2083
2231
|
//#endregion
|
|
2084
|
-
export { createEmptyDoc, footnoteToProseDoc, headerFooterToProseDoc, standaloneTableCellToProseMirror, textFormattingToMarks, toProseDoc };
|
|
2232
|
+
export { UnsupportedDocxToProseMirrorConversionError, createEmptyDoc, footnoteToProseDoc, headerFooterToProseDoc, resolveParagraphDefaultTextFormatting, standaloneTableCellToProseMirror, textFormattingToMarks, toProseDoc };
|