@stll/folio-core 0.44.0 → 0.46.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/dist/ai-edits/__fixtures__/paragraphs.js +2 -2
- package/dist/ai-edits/apply.js +59 -19
- package/dist/ai-edits/headless.js +2 -1
- package/dist/compare/compare.js +2 -5
- package/dist/compare/content-alignment.js +78 -53
- package/dist/compare/inline-atoms.js +34 -20
- package/dist/compare/scenario.js +2 -5
- package/dist/compare/types.d.ts +9 -1
- package/dist/compare/types.js +12 -1
- package/dist/compat/eigenpal.d.ts +2 -1
- package/dist/compat/eigenpal.js +2 -1
- package/dist/content-controls/checkboxDisplay.d.ts +11 -0
- package/dist/content-controls/checkboxDisplay.js +40 -0
- package/dist/content-controls/findContentControls.js +3 -1
- package/dist/content-controls/mutateContentControls.js +21 -4
- package/dist/controller/contentControlWidgetController.d.ts +1 -0
- package/dist/controller/contentControlWidgetController.js +3 -0
- package/dist/controller/hiddenEditorApi.js +3 -1
- package/dist/controller/hiddenEditorManager.d.ts +1 -1
- package/dist/controller/hiddenEditorManager.js +6 -3
- package/dist/display-list/build/buildDisplayList.js +20 -1
- package/dist/display-list/build/imagePrimitives.d.ts +1 -1
- package/dist/display-list/build/imagePrimitives.js +3 -1
- package/dist/display-list/build/paragraphPrimitives.js +21 -2
- package/dist/display-list/dom/renderDisplayListToDom.js +18 -10
- package/dist/display-list/types.d.ts +17 -0
- package/dist/document-operations.js +14 -3
- package/dist/docx/attributeRemainder.d.ts +43 -0
- package/dist/docx/attributeRemainder.js +65 -0
- package/dist/docx/blockContentParser.d.ts +1 -1
- package/dist/docx/blockContentParser.js +87 -63
- package/dist/docx/blockPlainText.d.ts +3 -4
- package/dist/docx/blockPlainText.js +1 -0
- package/dist/docx/bookmarkPlacement.js +2 -0
- package/dist/docx/borderParser.js +5 -5
- package/dist/docx/commentAnchorIndex.d.ts +30 -0
- package/dist/docx/commentAnchorIndex.js +50 -0
- package/dist/docx/commentParser.d.ts +1 -1
- package/dist/docx/commentParser.js +78 -50
- package/dist/docx/commentRangeIntegrity.d.ts +16 -1
- package/dist/docx/commentRangeIntegrity.js +42 -1
- package/dist/docx/commentRangeJoin.d.ts +9 -0
- package/dist/docx/commentRangeJoin.js +33 -0
- package/dist/docx/commentReferenceCompletion.d.ts +9 -0
- package/dist/docx/commentReferenceCompletion.js +47 -0
- package/dist/docx/commentReferenceNormalization.js +1 -0
- package/dist/docx/commentReplyMarkers.js +11 -19
- package/dist/docx/commentThreadKey.d.ts +18 -0
- package/dist/docx/commentThreadKey.js +22 -0
- package/dist/docx/compatibility.js +1 -0
- package/dist/docx/containerChildren.d.ts +111 -0
- package/dist/docx/containerChildren.gen.d.ts +28 -0
- package/dist/docx/containerChildren.gen.js +246 -0
- package/dist/docx/containerChildren.js +103 -0
- package/dist/docx/diagramPreview.js +87 -27
- package/dist/docx/documentParser.d.ts +1 -1
- package/dist/docx/documentParser.js +3 -3
- package/dist/docx/ensureParaIds.js +17 -7
- package/dist/docx/fieldParser.d.ts +1 -1
- package/dist/docx/fieldParser.js +4 -4
- package/dist/docx/fieldState.d.ts +26 -0
- package/dist/docx/fieldState.js +53 -0
- package/dist/docx/footnoteParser.d.ts +1 -1
- package/dist/docx/graphicFrameLocks.d.ts +16 -4
- package/dist/docx/graphicFrameLocks.js +19 -6
- package/dist/docx/groupDrawingParser.js +3 -3
- package/dist/docx/headerFooterParser.js +1 -1
- package/dist/docx/headerFooterReferenceNormalization.js +1 -0
- package/dist/docx/hyperlinkParser.d.ts +27 -8
- package/dist/docx/hyperlinkParser.js +78 -20
- package/dist/docx/imageParser.d.ts +9 -1
- package/dist/docx/imageParser.js +91 -20
- package/dist/docx/imageRawXml.d.ts +14 -1
- package/dist/docx/imageRawXml.js +30 -6
- package/dist/docx/inlineWrapperContent.d.ts +85 -0
- package/dist/docx/inlineWrapperContent.js +84 -0
- package/dist/docx/mathToMathml.js +12 -14
- package/dist/docx/nonVisualDrawingProps.d.ts +34 -0
- package/dist/docx/nonVisualDrawingProps.js +46 -0
- package/dist/docx/normalizeBaseDirection.js +10 -1
- package/dist/docx/paraIdAttribute.d.ts +21 -0
- package/dist/docx/paraIdAttribute.js +64 -0
- package/dist/docx/paragraphParser.d.ts +1 -1
- package/dist/docx/paragraphParser.js +277 -168
- package/dist/docx/paragraphPropertySource.js +5 -1
- package/dist/docx/paragraphTextBoxEnrichment.d.ts +1 -1
- package/dist/docx/paragraphTextBoxEnrichment.js +9 -52
- package/dist/docx/paragraphTraversal.js +7 -4
- package/dist/docx/parseWarningMessage.js +2 -1
- package/dist/docx/parser.js +2 -2
- package/dist/docx/preservedRunContent.d.ts +32 -0
- package/dist/docx/preservedRunContent.js +86 -0
- package/dist/docx/previewBudget.d.ts +64 -0
- package/dist/docx/previewBudget.js +88 -0
- package/dist/docx/renderedPageBreakNormalization.js +2 -4
- package/dist/docx/revisionIdNormalization.js +17 -5
- package/dist/docx/rezip.js +91 -36
- package/dist/docx/runParser.d.ts +1 -1
- package/dist/docx/runParser.js +16 -12
- package/dist/docx/sdtPropertiesPatch.js +24 -18
- package/dist/docx/sectionParser.js +8 -1
- package/dist/docx/sectionReferenceHistory.js +2 -2
- package/dist/docx/selectiveSave.js +6 -6
- package/dist/docx/selectiveXmlPatch.d.ts +46 -2
- package/dist/docx/selectiveXmlPatch.js +86 -39
- package/dist/docx/serializer/blockSdtSerializer.js +38 -26
- package/dist/docx/serializer/borderSerializer.d.ts +1 -1
- package/dist/docx/serializer/borderSerializer.js +15 -14
- package/dist/docx/serializer/commentSerializer.d.ts +41 -16
- package/dist/docx/serializer/commentSerializer.js +87 -92
- package/dist/docx/serializer/documentSerializer.js +8 -11
- package/dist/docx/serializer/fontTableSerializer.js +6 -6
- package/dist/docx/serializer/headerFooterSerializer.js +12 -14
- package/dist/docx/serializer/markupRangeAttributes.js +2 -2
- package/dist/docx/serializer/noteSerializer.js +8 -8
- package/dist/docx/serializer/numberingSerializer.js +7 -6
- package/dist/docx/serializer/paragraphSerializer.js +93 -72
- package/dist/docx/serializer/partNamespaces.js +2 -2
- package/dist/docx/serializer/runSerializer.js +73 -44
- package/dist/docx/serializer/sectionPropertiesSerializer.js +19 -14
- package/dist/docx/serializer/settingsSerializer.js +4 -3
- package/dist/docx/serializer/stylesSerializer.js +6 -6
- package/dist/docx/serializer/tableSerializer.js +28 -17
- package/dist/docx/serializer/textFormattingSerializer.js +29 -28
- package/dist/docx/serializer/themeSerializer.js +6 -6
- package/dist/docx/serializer/trackedChangeAttributes.js +2 -2
- package/dist/docx/serializer/xmlUtils.d.ts +1 -2
- package/dist/docx/serializer/xmlUtils.js +1 -13
- package/dist/docx/server/boundedArchive.d.ts +12 -0
- package/dist/docx/server/boundedArchive.js +20 -1
- package/dist/docx/server/createBilingualDocument.js +3 -1
- package/dist/docx/server/materializeYjsDocx.d.ts +1 -1
- package/dist/docx/server/materializeYjsDocx.js +9 -1
- package/dist/docx/server/migrateYjsAttrSchema.d.ts +55 -0
- package/dist/docx/server/migrateYjsAttrSchema.js +95 -0
- package/dist/docx/server/validateDocxConformance.js +22 -1
- package/dist/docx/shapeParser.js +12 -10
- package/dist/docx/tableParser.d.ts +1 -1
- package/dist/docx/tableParser.js +206 -85
- package/dist/docx/textBoxParser.d.ts +25 -2
- package/dist/docx/textBoxParser.js +59 -4
- package/dist/docx/unzip.d.ts +23 -0
- package/dist/docx/unzip.js +37 -26
- package/dist/docx/verbatimCapture.js +1 -1
- package/dist/docx/vmlImageParser.d.ts +17 -1
- package/dist/docx/vmlImageParser.js +20 -3
- package/dist/docx/vmlPreview.d.ts +1 -3
- package/dist/docx/vmlPreview.js +2 -30
- package/dist/docx/xmlEncoding.d.ts +5 -0
- package/dist/docx/xmlEncoding.js +12 -0
- package/dist/docx/xmlParser.d.ts +26 -2
- package/dist/docx/xmlParser.js +70 -27
- package/dist/docx/xmlResourceLimits.d.ts +89 -9
- package/dist/docx/xmlResourceLimits.js +105 -24
- package/dist/headless-layout.js +10 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/internal/pageBreakRunSourceDescendantIndex.js +5 -2
- package/dist/internal/paragraphFormattingSerialization.js +3 -2
- package/dist/layout-bridge/convert/toFlowBlocks.js +102 -12
- package/dist/layout-engine/measure/tableCellFloating.d.ts +2 -0
- package/dist/layout-engine/measure/tableCellFloating.js +2 -0
- package/dist/layout-engine/types.d.ts +23 -1
- package/dist/layout-painter/renderImage.d.ts +5 -1
- package/dist/layout-painter/renderImage.js +14 -6
- package/dist/layout-painter/renderPage.d.ts +2 -0
- package/dist/layout-painter/renderPage.js +4 -0
- package/dist/layout-painter/renderParagraph.d.ts +13 -1
- package/dist/layout-painter/renderParagraph.js +26 -6
- package/dist/managers/autoSaveCodec.d.ts +9 -1
- package/dist/managers/autoSaveCodec.js +14 -12
- package/dist/markdown/images.js +1 -4
- package/dist/markdown/renderBlock.js +1 -0
- package/dist/markdown/renderRuns.d.ts +1 -1
- package/dist/markdown/renderRuns.js +28 -5
- package/dist/markdown/renderTable.js +22 -5
- package/dist/markdown/trailers.js +4 -1
- package/dist/pdf/images.js +142 -6
- package/dist/prosemirror/attrs/index.d.ts +14 -3
- package/dist/prosemirror/attrs/index.js +224 -2
- package/dist/prosemirror/authoredTransformAttrs.d.ts +28 -0
- package/dist/prosemirror/authoredTransformAttrs.js +64 -0
- package/dist/prosemirror/commands/contentControls.js +10 -2
- package/dist/prosemirror/commands/image.d.ts +9 -2
- package/dist/prosemirror/commands/image.js +43 -28
- package/dist/prosemirror/commands/pageBreak.js +1 -1
- package/dist/prosemirror/commentReferenceAttrs.d.ts +8 -0
- package/dist/prosemirror/commentReferenceAttrs.js +33 -0
- package/dist/prosemirror/commentReferenceIntegrity.d.ts +47 -0
- package/dist/prosemirror/commentReferenceIntegrity.js +43 -0
- package/dist/prosemirror/conversion/fromProseDoc.d.ts +2 -13
- package/dist/prosemirror/conversion/fromProseDoc.js +338 -99
- package/dist/prosemirror/conversion/index.d.ts +2 -2
- package/dist/prosemirror/conversion/toProseDoc.d.ts +7 -9
- package/dist/prosemirror/conversion/toProseDoc.js +551 -327
- package/dist/prosemirror/extensions/StarterKit.js +8 -58
- package/dist/prosemirror/extensions/core/DocExtension.js +1 -1
- package/dist/prosemirror/extensions/core/ParagraphExtension.js +2 -1
- package/dist/prosemirror/extensions/features/BaseKeymapExtension.js +45 -27
- package/dist/prosemirror/extensions/features/EmptyParagraphFormatExtension.js +3 -1
- package/dist/prosemirror/extensions/features/ImagePasteExtension.js +5 -3
- package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.js +1 -0
- package/dist/prosemirror/extensions/markRegistry.d.ts +41 -0
- package/dist/prosemirror/extensions/markRegistry.js +75 -0
- package/dist/prosemirror/extensions/marks/HyperlinkExtension.js +2 -3
- package/dist/prosemirror/extensions/marks/InlineWrapperExtension.d.ts +18 -0
- package/dist/prosemirror/extensions/marks/InlineWrapperExtension.js +63 -0
- package/dist/prosemirror/extensions/marks/markUtils.d.ts +2 -1
- package/dist/prosemirror/extensions/marks/markUtils.js +47 -4
- package/dist/prosemirror/extensions/nodes/CommentReferenceExtension.d.ts +11 -0
- package/dist/prosemirror/extensions/nodes/CommentReferenceExtension.js +87 -0
- package/dist/prosemirror/extensions/nodes/FieldExtension.js +9 -7
- package/dist/prosemirror/extensions/nodes/ImageExtension.js +20 -0
- package/dist/prosemirror/extensions/nodes/PreservedBlockExtension.d.ts +32 -0
- package/dist/prosemirror/extensions/nodes/PreservedBlockExtension.js +67 -0
- package/dist/prosemirror/extensions/nodes/PreservedXmlExtension.d.ts +16 -0
- package/dist/prosemirror/extensions/nodes/PreservedXmlExtension.js +60 -0
- package/dist/prosemirror/extensions/nodes/ShapeExtension.js +10 -2
- package/dist/prosemirror/extensions/nodes/TableExtension.js +3 -2
- package/dist/prosemirror/extensions/nodes/TextBoxExtension.js +13 -5
- package/dist/prosemirror/inlineWrapperStack.d.ts +39 -0
- package/dist/prosemirror/inlineWrapperStack.js +75 -0
- package/dist/prosemirror/pageBreakRunProjection.d.ts +17 -7
- package/dist/prosemirror/pageBreakRunProjection.js +19 -9
- package/dist/prosemirror/paragraphFormattingProvenance.d.ts +6 -3
- package/dist/prosemirror/paragraphFormattingProvenance.js +12 -3
- package/dist/prosemirror/replacedAnnotations.d.ts +59 -0
- package/dist/prosemirror/replacedAnnotations.js +165 -0
- package/dist/prosemirror/runFormattingInlineCarriers.d.ts +3 -1
- package/dist/prosemirror/runFormattingInlineCarriers.js +5 -1
- package/dist/prosemirror/schema/index.d.ts +3 -3
- package/dist/prosemirror/schema/marks.d.ts +25 -1
- package/dist/prosemirror/schema/nodes.d.ts +139 -3
- package/dist/prosemirror/schema/nodes.js +16 -1
- package/dist/prosemirror/trackedRunInlineAtoms.d.ts +2 -0
- package/dist/prosemirror/trackedRunInlineAtoms.js +2 -0
- package/dist/prosemirror/validation.js +16 -2
- package/dist/prosemirror/yjsDocumentMetadata.d.ts +73 -0
- package/dist/prosemirror/yjsDocumentMetadata.js +171 -0
- package/dist/prosemirror/zeroWidthAnchors.js +2 -0
- package/dist/render-dom/commentAnchorAttributes.d.ts +37 -0
- package/dist/render-dom/commentAnchorAttributes.js +54 -0
- package/dist/server.d.ts +3 -1
- package/dist/server.js +3 -1
- package/dist/types/content.d.ts +2 -2
- package/dist/utils/base64.d.ts +36 -0
- package/dist/utils/base64.js +40 -0
- package/dist/utils/clipboard.d.ts +9 -1
- package/dist/utils/clipboard.js +29 -2
- package/dist/utils/findReplace.js +1 -1
- package/dist/utils/imageLuminance.d.ts +15 -0
- package/dist/utils/imageLuminance.js +32 -0
- package/dist/utils/mergeDocumentContent.js +7 -17
- package/dist/utils/replaceText.js +1 -0
- package/dist/utils/units.d.ts +10 -1
- package/dist/utils/units.js +12 -1
- package/dist/utils/urlSecurity.d.ts +8 -2
- package/dist/utils/urlSecurity.js +21 -3
- package/package.json +2 -2
- package/dist/docx/blockRangeMarkers.d.ts +0 -36
- package/dist/docx/blockRangeMarkers.js +0 -59
- package/dist/prosemirror/yjsParagraphSourceContract.d.ts +0 -9
- package/dist/prosemirror/yjsParagraphSourceContract.js +0 -26
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { rangedCommentIds } from "../../docx/commentAnchorIndex.js";
|
|
1
2
|
import { resolveColorValueToHex } from "../../docx/drawingUtils.js";
|
|
3
|
+
import { isInlineSdtContent, isTrackedChangeWrapperChild } from "../../docx/inlineWrapperContent.js";
|
|
2
4
|
import { isNumberingReference } from "../../docx/numberingReference.js";
|
|
3
5
|
import { PROSE_PARAGRAPH_SOURCE_CONTRACT_ATTR, createProseParagraphWithPropertySource, getDocumentParagraphPropertySourceContract, recreateProseNodeWithParagraphPropertySource, transportTableCellsWithParagraphPropertySources } from "../../docx/paragraphPropertySource.js";
|
|
4
6
|
import { isBaselineVertAlign } from "../../docx/runParser.js";
|
|
@@ -10,9 +12,12 @@ import { normalizeHorizontalScalePercent } from "../../utils/horizontalScale.js"
|
|
|
10
12
|
import { mergeParagraphFormatting, mergeParagraphTabStops } from "../../utils/paragraphFormattingMerge.js";
|
|
11
13
|
import { tableOfContentsStyleLevel } from "../../utils/tableOfContentsStyle.js";
|
|
12
14
|
import { mergeTextFormatting } from "../../utils/textFormattingMerge.js";
|
|
13
|
-
import { emuToPixels } from "../../utils/units.js";
|
|
15
|
+
import { emuToPixels, emuToStrokePixels } from "../../utils/units.js";
|
|
16
|
+
import { expectInlineWrapperMarkAttrs } from "../attrs/index.js";
|
|
17
|
+
import { authoredTransformAttrs } from "../authoredTransformAttrs.js";
|
|
14
18
|
import { setAutospacingBaseValue } from "../autospacingBase.js";
|
|
15
19
|
import { textFormattingToMarks } from "../extensions/marks/markUtils.js";
|
|
20
|
+
import { inlineWrapperLayer } from "../inlineWrapperStack.js";
|
|
16
21
|
import { listRenderingAttrPatch } from "../listRenderingAttrs.js";
|
|
17
22
|
import { stampNumberedRefFieldBaselines } from "../numberedRefFields.js";
|
|
18
23
|
import { pageBreakRunParagraphProjectionDispositionForFeatures } from "../pageBreakRunProjection.js";
|
|
@@ -21,17 +26,23 @@ import { styleResolvedParagraphFormatting } from "../paragraphFormattingProvenan
|
|
|
21
26
|
import { lineSpacingProvenanceFromSpacing } from "../paragraphSpacing.js";
|
|
22
27
|
import { getParagraphMarkSuppressionOverrides, hasDirectRunFormatting, resolveParagraphBodyRunFormatting, stripParagraphMarkFormattingForBodyRuns, stripParagraphMarkOnlyFormatting, suppressParagraphMarkFormatting } from "../runStyleFormatting.js";
|
|
23
28
|
import { schema } from "../schema/index.js";
|
|
29
|
+
import { PRESERVED_XML_LEVELS } from "../schema/nodes.js";
|
|
24
30
|
import { cascadeStyleTextFormatting } from "../styles/styleToggleCascade.js";
|
|
25
31
|
import { canCarryTrackedRunMark, trackedRunInlineAtomDisposition } from "../trackedRunInlineAtoms.js";
|
|
26
32
|
import { assertValidProseMirrorDocument } from "../validation.js";
|
|
27
33
|
import { resolveEffectiveTableCellFormatting } from "./effectiveTableCellFormatting.js";
|
|
28
34
|
import { sdtAttrsFromProperties } from "./sdtAttrs.js";
|
|
29
|
-
import {
|
|
30
|
-
import { DRAWING_RAW_XML_MODES } from "@stll/docx-core/model";
|
|
35
|
+
import { panic } from "better-result";
|
|
36
|
+
import { DRAWING_RAW_XML_MODES, PARSE_WARNING_CODES } from "@stll/docx-core/model";
|
|
31
37
|
//#region src/prosemirror/conversion/toProseDoc.ts
|
|
32
|
-
/** DOCX content that cannot be preserved by the editable ProseMirror model. */
|
|
33
|
-
var UnsupportedDocxToProseMirrorConversionError = class extends TaggedError("UnsupportedDocxToProseMirrorConversionError") {};
|
|
34
38
|
const DETACHED_WATERMARK_HOST = Symbol.for("stll.detachedWatermarkHost");
|
|
39
|
+
const noPageBreakProjectionWarning = () => {};
|
|
40
|
+
const pageBreakProjectionWarn = (warn) => warn === void 0 ? noPageBreakProjectionWarning : (detail) => {
|
|
41
|
+
warn({
|
|
42
|
+
code: PARSE_WARNING_CODES.pageBreakProjectionApproximated,
|
|
43
|
+
detail
|
|
44
|
+
});
|
|
45
|
+
};
|
|
35
46
|
/**
|
|
36
47
|
* Build a `nextTextBoxGroupId()` generator salted with a random per-load
|
|
37
48
|
* nonce, so minted text-box anchor ids (`<salt>:<group>:<index>`) are unique
|
|
@@ -89,6 +100,7 @@ const collectPairedBookmarkIds = (blocks) => {
|
|
|
89
100
|
case "run":
|
|
90
101
|
visitRun(child);
|
|
91
102
|
break;
|
|
103
|
+
case "preservedInline": break;
|
|
92
104
|
default: panic(`Unsupported hyperlink child: ${JSON.stringify(child)}`);
|
|
93
105
|
}
|
|
94
106
|
};
|
|
@@ -108,7 +120,7 @@ const collectPairedBookmarkIds = (blocks) => {
|
|
|
108
120
|
return;
|
|
109
121
|
case "simpleField":
|
|
110
122
|
for (const child of content.content) if (child.type === "hyperlink") visitHyperlink(child);
|
|
111
|
-
else visitRun(child);
|
|
123
|
+
else if (child.type === "run") visitRun(child);
|
|
112
124
|
return;
|
|
113
125
|
case "complexField":
|
|
114
126
|
for (const run of [...content.fieldCode ?? [], ...content.fieldResult]) visitRun(run);
|
|
@@ -118,7 +130,7 @@ const collectPairedBookmarkIds = (blocks) => {
|
|
|
118
130
|
case "deletion":
|
|
119
131
|
case "moveFrom":
|
|
120
132
|
case "moveTo":
|
|
121
|
-
case "
|
|
133
|
+
case "inlineWrapper":
|
|
122
134
|
for (const child of content.content) visitParagraphContent(child);
|
|
123
135
|
return;
|
|
124
136
|
case "commentRangeStart":
|
|
@@ -128,7 +140,8 @@ const collectPairedBookmarkIds = (blocks) => {
|
|
|
128
140
|
case "moveFromRangeEnd":
|
|
129
141
|
case "moveToRangeStart":
|
|
130
142
|
case "moveToRangeEnd":
|
|
131
|
-
case "mathEquation":
|
|
143
|
+
case "mathEquation":
|
|
144
|
+
case "preservedInline": return;
|
|
132
145
|
default: panic(`Unsupported paragraph content: ${JSON.stringify(content)}`);
|
|
133
146
|
}
|
|
134
147
|
};
|
|
@@ -143,6 +156,7 @@ const collectPairedBookmarkIds = (blocks) => {
|
|
|
143
156
|
case "blockSdt":
|
|
144
157
|
visitBlocks(block.content);
|
|
145
158
|
break;
|
|
159
|
+
case "preservedBlock": break;
|
|
146
160
|
default: panic(`Unsupported block content: ${JSON.stringify(block)}`);
|
|
147
161
|
}
|
|
148
162
|
};
|
|
@@ -166,7 +180,10 @@ function toProseDoc(document, options) {
|
|
|
166
180
|
nextTextBoxGroupId,
|
|
167
181
|
nextHyperlinkInstanceIndex: createHyperlinkInstanceIndexAllocator(),
|
|
168
182
|
pairedBookmarkIds: collectPairedBookmarkIds(paragraphs),
|
|
169
|
-
pageBreakRunSourceDescendants: buildPageBreakRunSourceDescendantIndex(paragraphs)
|
|
183
|
+
pageBreakRunSourceDescendants: buildPageBreakRunSourceDescendantIndex(paragraphs),
|
|
184
|
+
storyRangedCommentIds: rangedCommentIds(paragraphs),
|
|
185
|
+
openCommentIds: /* @__PURE__ */ new Set(),
|
|
186
|
+
warnPageBreakProjection: pageBreakProjectionWarn(options?.warn)
|
|
170
187
|
};
|
|
171
188
|
const convertBodyBlocks = (blocks) => {
|
|
172
189
|
const out = [];
|
|
@@ -183,6 +200,9 @@ function toProseDoc(document, options) {
|
|
|
183
200
|
case "blockSdt":
|
|
184
201
|
out.push(convertBlockSdt(block, convertBodyBlocks));
|
|
185
202
|
break;
|
|
203
|
+
case "preservedBlock":
|
|
204
|
+
out.push(convertPreservedBlock(block));
|
|
205
|
+
break;
|
|
186
206
|
default: panic(`Unsupported block content: ${JSON.stringify(block)}`);
|
|
187
207
|
}
|
|
188
208
|
return out;
|
|
@@ -200,6 +220,30 @@ function toProseDoc(document, options) {
|
|
|
200
220
|
return pmDoc;
|
|
201
221
|
}
|
|
202
222
|
/**
|
|
223
|
+
* Carry a block folio does not model into the editor as a zero-width node.
|
|
224
|
+
*
|
|
225
|
+
* The node's place in the document is the whole of its position, so it needs
|
|
226
|
+
* no index and nothing has to keep one honest as the blocks around it change.
|
|
227
|
+
*/
|
|
228
|
+
function convertPreservedBlock(block) {
|
|
229
|
+
return schema.node("preservedBlock", { xml: block.xml });
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Carry an inline child folio does not model into the editor as an opaque atom.
|
|
233
|
+
*
|
|
234
|
+
* The same atom the run level uses, tagged with the level it came from: the
|
|
235
|
+
* markup is a paragraph child and the save path must not put it back inside a
|
|
236
|
+
* `w:r`. It carries whatever marks surround it, so a capture inside a
|
|
237
|
+
* `w:ins` keeps the insertion and is accepted or rejected with it.
|
|
238
|
+
*/
|
|
239
|
+
function preservedInlineNode(content) {
|
|
240
|
+
return schema.node("preservedXml", {
|
|
241
|
+
xml: content.xml,
|
|
242
|
+
text: content.text,
|
|
243
|
+
level: PRESERVED_XML_LEVELS.inline
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
203
247
|
* Convert a `BlockSdt` model node into a `blockSdt` PM node, recursively
|
|
204
248
|
* converting its children with the caller-supplied block converter. Pass
|
|
205
249
|
* `rawPropertiesXml` / `rawEndPropertiesXml` through as attrs so the
|
|
@@ -236,26 +280,27 @@ function convertBlockSdt(blockSdt, convertBlocks) {
|
|
|
236
280
|
* Resolves style-based text formatting and passes it to runs so that
|
|
237
281
|
* paragraph styles (like Heading1) apply their font size, color, etc.
|
|
238
282
|
*/
|
|
239
|
-
function convertParagraph(paragraph, styleResolver, context,
|
|
240
|
-
const { nextHyperlinkInstanceIndex, pairedBookmarkIds, pageBreakRunSourceDescendants } = context;
|
|
283
|
+
function convertParagraph(paragraph, styleResolver, context, extraRunFormatting, tableParagraphOverlay, textBoxAnchors) {
|
|
284
|
+
const { nextHyperlinkInstanceIndex, pairedBookmarkIds, pageBreakRunSourceDescendants, storyRangedCommentIds, openCommentIds } = context;
|
|
241
285
|
let pageBreakRunOwnerId = 0;
|
|
242
286
|
const nextPageBreakRunOwnerId = () => pageBreakRunOwnerId++;
|
|
243
287
|
const { attrs, effectiveFrame } = paragraphFormattingToAttrs(paragraph, styleResolver, tableParagraphOverlay);
|
|
244
|
-
|
|
288
|
+
reportParagraphPageBreakProjection({
|
|
245
289
|
paragraph,
|
|
246
290
|
attrs,
|
|
247
291
|
effectiveFrame,
|
|
248
|
-
sourceDescendants: pageBreakRunSourceDescendants
|
|
292
|
+
sourceDescendants: pageBreakRunSourceDescendants,
|
|
293
|
+
warn: context.warnPageBreakProjection
|
|
249
294
|
});
|
|
250
295
|
const isTocParagraph = attrs._tableOfContentsLevel !== void 0;
|
|
251
296
|
const inlineNodes = [];
|
|
252
297
|
let inlineOffset = 0;
|
|
253
298
|
let bookmarksArr;
|
|
254
299
|
let emptyHyperlinks;
|
|
255
|
-
|
|
300
|
+
let wrapperStack = [];
|
|
256
301
|
const emitInlineNodes = (nodes) => {
|
|
257
302
|
if (nodes.length === 0) return;
|
|
258
|
-
const markedNodes = applyCommentMarks(nodes,
|
|
303
|
+
const markedNodes = applyCommentMarks(withInlineWrapperMark(nodes, wrapperStack), openCommentIds);
|
|
259
304
|
inlineNodes.push(...markedNodes);
|
|
260
305
|
for (const node of markedNodes) inlineOffset += node.nodeSize;
|
|
261
306
|
};
|
|
@@ -321,97 +366,104 @@ function convertParagraph(paragraph, styleResolver, context, activeCommentIds, e
|
|
|
321
366
|
};
|
|
322
367
|
};
|
|
323
368
|
const emitTrackedChange = (change, markType, moveKind) => {
|
|
324
|
-
emitInlineNodes(convertTrackedChange(change, markType, nextHyperlinkInstanceIndex, nextPageBreakRunOwnerId, getInheritedRunFormatting, styleResolver, moveKind, textBoxAnchors));
|
|
369
|
+
emitInlineNodes(convertTrackedChange(change, markType, nextHyperlinkInstanceIndex, nextPageBreakRunOwnerId, getInheritedRunFormatting, styleResolver, moveKind, textBoxAnchors, wrapperStack));
|
|
325
370
|
};
|
|
326
|
-
for (const content of
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
emptyHyperlinks.push({
|
|
350
|
-
offset: inlineOffset,
|
|
351
|
-
...content.href !== void 0 ? { href: content.href } : {},
|
|
352
|
-
...content.anchor !== void 0 ? { anchor: content.anchor } : {},
|
|
353
|
-
...content.tooltip !== void 0 ? { tooltip: content.tooltip } : {},
|
|
354
|
-
...content.rId !== void 0 ? { rId: content.rId } : {}
|
|
371
|
+
for (const { content, stack } of withInlineWrapperStacks(paragraph.content)) {
|
|
372
|
+
wrapperStack = stack;
|
|
373
|
+
switch (content.type) {
|
|
374
|
+
case "commentRangeStart":
|
|
375
|
+
openCommentIds.add(content.id);
|
|
376
|
+
break;
|
|
377
|
+
case "commentRangeEnd":
|
|
378
|
+
openCommentIds.delete(content.id);
|
|
379
|
+
break;
|
|
380
|
+
case "commentReference":
|
|
381
|
+
if (!storyRangedCommentIds.has(content.id)) anchorPointComment(inlineNodes, content.id);
|
|
382
|
+
emitInlineNode(schema.node("commentReference", { commentId: content.id }));
|
|
383
|
+
break;
|
|
384
|
+
case "run":
|
|
385
|
+
emitInlineNodes(convertRun(content, getInheritedRunFormatting(content.formatting), nextPageBreakRunOwnerId, styleResolver, textBoxAnchors));
|
|
386
|
+
break;
|
|
387
|
+
case "hyperlink": {
|
|
388
|
+
const linkNodes = convertHyperlink(content, {
|
|
389
|
+
getInheritedRunFormatting,
|
|
390
|
+
styleResolver,
|
|
391
|
+
hyperlinkIndex: nextHyperlinkInstanceIndex(),
|
|
392
|
+
textBoxAnchors,
|
|
393
|
+
nextPageBreakRunOwnerId
|
|
355
394
|
});
|
|
395
|
+
if (linkNodes.length === 0) {
|
|
396
|
+
emptyHyperlinks ??= [];
|
|
397
|
+
emptyHyperlinks.push({
|
|
398
|
+
offset: inlineOffset,
|
|
399
|
+
...content.href !== void 0 ? { href: content.href } : {},
|
|
400
|
+
...content.anchor !== void 0 ? { anchor: content.anchor } : {},
|
|
401
|
+
...content.tooltip !== void 0 ? { tooltip: content.tooltip } : {},
|
|
402
|
+
...content.rId !== void 0 ? { rId: content.rId } : {}
|
|
403
|
+
});
|
|
404
|
+
break;
|
|
405
|
+
}
|
|
406
|
+
emitInlineNodes(linkNodes);
|
|
356
407
|
break;
|
|
357
408
|
}
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
409
|
+
case "simpleField":
|
|
410
|
+
case "complexField":
|
|
411
|
+
emitInlineNode(convertField(content, {
|
|
412
|
+
getInheritedRunFormatting,
|
|
413
|
+
styleResolver,
|
|
414
|
+
nextHyperlinkInstanceIndex,
|
|
415
|
+
nextPageBreakRunOwnerId,
|
|
416
|
+
textBoxAnchors
|
|
417
|
+
}));
|
|
418
|
+
break;
|
|
419
|
+
case "inlineSdt":
|
|
420
|
+
emitInlineNode(convertInlineSdt(content, nextHyperlinkInstanceIndex, nextPageBreakRunOwnerId, getInheritedRunFormatting, styleResolver, textBoxAnchors, stack));
|
|
421
|
+
break;
|
|
422
|
+
case "insertion":
|
|
423
|
+
case "moveTo":
|
|
424
|
+
emitTrackedChange(content, "insertion", content.type === "moveTo" ? "moveTo" : null);
|
|
425
|
+
break;
|
|
426
|
+
case "deletion":
|
|
427
|
+
case "moveFrom":
|
|
428
|
+
emitTrackedChange(content, "deletion", content.type === "moveFrom" ? "moveFrom" : null);
|
|
429
|
+
break;
|
|
430
|
+
case "mathEquation":
|
|
431
|
+
emitInlineNode(convertMathEquation(content));
|
|
432
|
+
break;
|
|
433
|
+
case "bookmarkStart":
|
|
434
|
+
if (pairedBookmarkIds.has(content.id)) {
|
|
435
|
+
emitInlineNode(schema.node("bookmarkBoundary", {
|
|
436
|
+
type: "start",
|
|
437
|
+
id: content.id,
|
|
438
|
+
name: content.name,
|
|
439
|
+
colFirst: content.colFirst,
|
|
440
|
+
colLast: content.colLast,
|
|
441
|
+
displacedByCustomXml: content.displacedByCustomXml
|
|
442
|
+
}));
|
|
443
|
+
break;
|
|
444
|
+
}
|
|
445
|
+
if (!bookmarksArr) bookmarksArr = [];
|
|
446
|
+
bookmarksArr.push({
|
|
447
|
+
id: content.id,
|
|
448
|
+
name: content.name
|
|
449
|
+
});
|
|
450
|
+
break;
|
|
451
|
+
case "bookmarkEnd":
|
|
452
|
+
if (pairedBookmarkIds.has(content.id)) emitInlineNode(schema.node("bookmarkBoundary", {
|
|
453
|
+
type: "end",
|
|
389
454
|
id: content.id,
|
|
390
|
-
name: content.name,
|
|
391
|
-
colFirst: content.colFirst,
|
|
392
|
-
colLast: content.colLast,
|
|
393
455
|
displacedByCustomXml: content.displacedByCustomXml
|
|
394
456
|
}));
|
|
395
457
|
break;
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
type: "end",
|
|
406
|
-
id: content.id,
|
|
407
|
-
displacedByCustomXml: content.displacedByCustomXml
|
|
408
|
-
}));
|
|
409
|
-
break;
|
|
410
|
-
case "moveFromRangeStart":
|
|
411
|
-
case "moveFromRangeEnd":
|
|
412
|
-
case "moveToRangeStart":
|
|
413
|
-
case "moveToRangeEnd": break;
|
|
414
|
-
default: panic(`Unsupported paragraph content: ${JSON.stringify(content)}`);
|
|
458
|
+
case "moveFromRangeStart":
|
|
459
|
+
case "moveFromRangeEnd":
|
|
460
|
+
case "moveToRangeStart":
|
|
461
|
+
case "moveToRangeEnd": break;
|
|
462
|
+
case "preservedInline":
|
|
463
|
+
emitInlineNode(preservedInlineNode(content));
|
|
464
|
+
break;
|
|
465
|
+
default: panic(`Unsupported paragraph content: ${JSON.stringify(content)}`);
|
|
466
|
+
}
|
|
415
467
|
}
|
|
416
468
|
if (bookmarksArr) attrs.bookmarks = bookmarksArr;
|
|
417
469
|
if (emptyHyperlinks) attrs._emptyHyperlinks = emptyHyperlinks;
|
|
@@ -449,48 +501,57 @@ function anchorPointComment(nodes, commentId) {
|
|
|
449
501
|
* Convert tracked change (insertion or deletion) content to PM nodes with
|
|
450
502
|
* an insertion/deletion mark applied.
|
|
451
503
|
*/
|
|
452
|
-
function convertTrackedChange(change, markType, nextHyperlinkInstanceIndex, nextPageBreakRunOwnerId, getInheritedRunFormatting, styleResolver, moveKind = null, textBoxAnchors) {
|
|
504
|
+
function convertTrackedChange(change, markType, nextHyperlinkInstanceIndex, nextPageBreakRunOwnerId, getInheritedRunFormatting, styleResolver, moveKind = null, textBoxAnchors, wrappedBy = []) {
|
|
453
505
|
const nodes = [];
|
|
454
|
-
for (const
|
|
455
|
-
|
|
456
|
-
const
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
506
|
+
for (const { content: item, stack } of withInlineWrapperStacks(change.content)) {
|
|
507
|
+
if (!isTrackedChangeWrapperChild(item)) continue;
|
|
508
|
+
const itemNodes = [];
|
|
509
|
+
if (item.type === "run") itemNodes.push(...convertRun(item, getInheritedRunFormatting(item.formatting), nextPageBreakRunOwnerId, styleResolver, textBoxAnchors));
|
|
510
|
+
else if (item.type === "hyperlink") {
|
|
511
|
+
const currentHyperlinkIndex = nextHyperlinkInstanceIndex();
|
|
512
|
+
itemNodes.push(...convertHyperlink(item, {
|
|
513
|
+
getInheritedRunFormatting,
|
|
514
|
+
styleResolver,
|
|
515
|
+
hyperlinkIndex: currentHyperlinkIndex,
|
|
516
|
+
textBoxAnchors,
|
|
517
|
+
nextPageBreakRunOwnerId
|
|
518
|
+
}));
|
|
519
|
+
} else if (item.type === "simpleField" || item.type === "complexField") {
|
|
520
|
+
const fieldNode = convertField(item, {
|
|
521
|
+
getInheritedRunFormatting,
|
|
522
|
+
styleResolver,
|
|
523
|
+
nextHyperlinkInstanceIndex,
|
|
524
|
+
nextPageBreakRunOwnerId,
|
|
525
|
+
textBoxAnchors
|
|
526
|
+
});
|
|
527
|
+
if (fieldNode) itemNodes.push(fieldNode);
|
|
528
|
+
} else if (item.type === "mathEquation") {
|
|
529
|
+
const mathNode = convertMathEquation(item);
|
|
530
|
+
if (mathNode) itemNodes.push(mathNode);
|
|
531
|
+
} else if (item.type === "insertion" || item.type === "deletion" || item.type === "moveFrom" || item.type === "moveTo") {
|
|
532
|
+
const nestedMarkType = item.type === "insertion" || item.type === "moveTo" ? "insertion" : "deletion";
|
|
533
|
+
const nestedMoveKind = item.type === "moveFrom" || item.type === "moveTo" ? item.type : null;
|
|
534
|
+
itemNodes.push(...convertTrackedChange(item, nestedMarkType, nextHyperlinkInstanceIndex, nextPageBreakRunOwnerId, getInheritedRunFormatting, styleResolver, nestedMoveKind, textBoxAnchors));
|
|
535
|
+
} else if (item.type === "inlineSdt") {
|
|
536
|
+
const sdtNode = convertInlineSdt(item, nextHyperlinkInstanceIndex, nextPageBreakRunOwnerId, getInheritedRunFormatting, styleResolver, textBoxAnchors, [...wrappedBy, ...stack]);
|
|
537
|
+
if (sdtNode) itemNodes.push(sdtNode);
|
|
538
|
+
} else if (item.type === "bookmarkStart") itemNodes.push(schema.node("bookmarkBoundary", {
|
|
539
|
+
type: "start",
|
|
540
|
+
id: item.id,
|
|
541
|
+
name: item.name,
|
|
542
|
+
colFirst: item.colFirst,
|
|
543
|
+
colLast: item.colLast,
|
|
544
|
+
displacedByCustomXml: item.displacedByCustomXml
|
|
463
545
|
}));
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
} else if (item.type === "mathEquation") {
|
|
474
|
-
const mathNode = convertMathEquation(item);
|
|
475
|
-
if (mathNode) nodes.push(mathNode);
|
|
476
|
-
} else if (item.type === "insertion" || item.type === "deletion" || item.type === "moveFrom" || item.type === "moveTo") {
|
|
477
|
-
const nestedMarkType = item.type === "insertion" || item.type === "moveTo" ? "insertion" : "deletion";
|
|
478
|
-
const nestedMoveKind = item.type === "moveFrom" || item.type === "moveTo" ? item.type : null;
|
|
479
|
-
nodes.push(...convertTrackedChange(item, nestedMarkType, nextHyperlinkInstanceIndex, nextPageBreakRunOwnerId, getInheritedRunFormatting, styleResolver, nestedMoveKind, textBoxAnchors));
|
|
480
|
-
} else if (item.type === "bookmarkStart") nodes.push(schema.node("bookmarkBoundary", {
|
|
481
|
-
type: "start",
|
|
482
|
-
id: item.id,
|
|
483
|
-
name: item.name,
|
|
484
|
-
colFirst: item.colFirst,
|
|
485
|
-
colLast: item.colLast,
|
|
486
|
-
displacedByCustomXml: item.displacedByCustomXml
|
|
487
|
-
}));
|
|
488
|
-
else if (item.type === "bookmarkEnd") nodes.push(schema.node("bookmarkBoundary", {
|
|
489
|
-
type: "end",
|
|
490
|
-
id: item.id,
|
|
491
|
-
displacedByCustomXml: item.displacedByCustomXml
|
|
492
|
-
}));
|
|
493
|
-
else panic(`Unsupported tracked-run content: ${JSON.stringify(item)}`);
|
|
546
|
+
else if (item.type === "bookmarkEnd") itemNodes.push(schema.node("bookmarkBoundary", {
|
|
547
|
+
type: "end",
|
|
548
|
+
id: item.id,
|
|
549
|
+
displacedByCustomXml: item.displacedByCustomXml
|
|
550
|
+
}));
|
|
551
|
+
else if (item.type === "preservedInline") itemNodes.push(preservedInlineNode(item));
|
|
552
|
+
else panic(`Unsupported tracked-run content: ${JSON.stringify(item)}`);
|
|
553
|
+
nodes.push(...withInlineWrapperMark(itemNodes, stack));
|
|
554
|
+
}
|
|
494
555
|
const mark = schema.marks[markType].create({
|
|
495
556
|
revisionId: change.info.id,
|
|
496
557
|
author: change.info.author,
|
|
@@ -525,6 +586,7 @@ function paragraphFormattingToAttrs(paragraph, styleResolver, tableParagraphOver
|
|
|
525
586
|
if (paragraph.listRendering) Object.assign(attrs, listRenderingAttrPatch(paragraph.listRendering));
|
|
526
587
|
if (formatting) attrs._originalFormatting = formatting;
|
|
527
588
|
if (paragraph.propertyChanges && paragraph.propertyChanges.length > 0) attrs._propertyChanges = [...paragraph.propertyChanges];
|
|
589
|
+
if (paragraph.preservedAttributes && paragraph.preservedAttributes.length > 0) attrs._preservedAttributes = paragraph.preservedAttributes;
|
|
528
590
|
if (paragraph.pPrMark) attrs.pPrMark = paragraph.pPrMark;
|
|
529
591
|
const set = (key, val) => {
|
|
530
592
|
if (val !== void 0) attrs[key] = val;
|
|
@@ -784,6 +846,7 @@ function calculateRowSpans(table) {
|
|
|
784
846
|
const { colIndex: cellColIndex, vMerge, isMergeContinuation, startRow, hasMeaningfulContent } = cellInfo;
|
|
785
847
|
const key = `${rowIndex}-${cellColIndex}`;
|
|
786
848
|
if (vMerge === "restart") {
|
|
849
|
+
closeVerticalMerge(activeMerges, result, cellColIndex);
|
|
787
850
|
activeMerges.set(cellColIndex, rowIndex);
|
|
788
851
|
result.set(key, {
|
|
789
852
|
rowSpan: 1,
|
|
@@ -814,7 +877,7 @@ function calculateRowSpans(table) {
|
|
|
814
877
|
skip: true
|
|
815
878
|
});
|
|
816
879
|
} else {
|
|
817
|
-
activeMerges
|
|
880
|
+
closeVerticalMerge(activeMerges, result, cellColIndex);
|
|
818
881
|
result.set(key, {
|
|
819
882
|
rowSpan: 1,
|
|
820
883
|
skip: false
|
|
@@ -822,19 +885,34 @@ function calculateRowSpans(table) {
|
|
|
822
885
|
}
|
|
823
886
|
}
|
|
824
887
|
}
|
|
888
|
+
clearActiveVerticalMerges(activeMerges, result);
|
|
825
889
|
return result;
|
|
826
890
|
}
|
|
891
|
+
/**
|
|
892
|
+
* End the vertical merge active in one column.
|
|
893
|
+
*
|
|
894
|
+
* A `w:vMerge="restart"` is carried through the editor by its cell's rowspan,
|
|
895
|
+
* which only exists once a continuation joins it. A merge that closes with a
|
|
896
|
+
* rowspan of 1 — a restart with no continuation, one interrupted by a plain
|
|
897
|
+
* cell, one whose continuation is in a row a revision removed — has nothing
|
|
898
|
+
* but this flag to say the cell was a merge origin, and dropping it changes
|
|
899
|
+
* the table's visible structure.
|
|
900
|
+
*/
|
|
901
|
+
function closeVerticalMerge(activeMerges, result, colIndex) {
|
|
902
|
+
const startRow = activeMerges.get(colIndex);
|
|
903
|
+
if (startRow === void 0) return;
|
|
904
|
+
const restartCell = result.get(`${startRow}-${colIndex}`);
|
|
905
|
+
if (restartCell && restartCell.rowSpan === 1) restartCell.preserveVMergeRestart = true;
|
|
906
|
+
activeMerges.delete(colIndex);
|
|
907
|
+
}
|
|
827
908
|
function clearActiveVerticalMerges(activeMerges, result) {
|
|
828
|
-
for (const
|
|
829
|
-
const restartCell = result.get(`${startRow}-${colIndex}`);
|
|
830
|
-
if (restartCell) restartCell.preserveVMergeRestart = true;
|
|
831
|
-
}
|
|
832
|
-
activeMerges.clear();
|
|
909
|
+
for (const colIndex of [...activeMerges.keys()]) closeVerticalMerge(activeMerges, result, colIndex);
|
|
833
910
|
}
|
|
834
911
|
function tableCellHasMeaningfulContent(cell) {
|
|
835
912
|
return cell.content.some(blockHasMeaningfulContent);
|
|
836
913
|
}
|
|
837
914
|
function blockHasMeaningfulContent(block) {
|
|
915
|
+
if (block.type === "preservedBlock") return true;
|
|
838
916
|
if (block.type === "table") return block.rows.some((row) => row.cells.some((cell) => tableCellHasMeaningfulContent(cell)));
|
|
839
917
|
return block.content.some(paragraphContentHasMeaningfulContent);
|
|
840
918
|
}
|
|
@@ -846,12 +924,11 @@ function paragraphContentHasMeaningfulContent(content) {
|
|
|
846
924
|
}
|
|
847
925
|
function convertTable(table, styleResolver, context) {
|
|
848
926
|
for (const row of table.rows) for (const cell of row.cells) {
|
|
849
|
-
if (isCellMergeContinuation(cell) && context.pageBreakRunSourceDescendants.containsPageBreakRun(cell.content))
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
assertSourceContainerHasNoPageBreakRun(cell.content, "table-cell", context.pageBreakRunSourceDescendants);
|
|
927
|
+
if (isCellMergeContinuation(cell) && context.pageBreakRunSourceDescendants.containsPageBreakRun(cell.content)) {
|
|
928
|
+
context.warnPageBreakProjection("A page break inside a vertically merged table cell paginates with the merged row");
|
|
929
|
+
continue;
|
|
930
|
+
}
|
|
931
|
+
reportSourceContainerPageBreakRun(cell.content, "table-cell", context.pageBreakRunSourceDescendants, context.warnPageBreakProjection);
|
|
855
932
|
}
|
|
856
933
|
const rowSpanMap = calculateRowSpans(table);
|
|
857
934
|
const columnWidths = table.columnWidths;
|
|
@@ -957,6 +1034,7 @@ function convertTableRow(row, styleResolver, context, isHeaderRow, columnWidths,
|
|
|
957
1034
|
if (resolvedJustification) attrsWithoutStructuralChange._resolvedJustification = resolvedJustification;
|
|
958
1035
|
if (row.formatting) attrsWithoutStructuralChange._originalFormatting = row.formatting;
|
|
959
1036
|
if (row.propertyChanges && row.propertyChanges.length > 0) attrsWithoutStructuralChange.trPrChange = [...row.propertyChanges];
|
|
1037
|
+
if (row.preservedAttributes && row.preservedAttributes.length > 0) attrsWithoutStructuralChange._preservedAttributes = row.preservedAttributes;
|
|
960
1038
|
let attrs = attrsWithoutStructuralChange;
|
|
961
1039
|
const rowStructuralChange = row.structuralChange;
|
|
962
1040
|
if (rowStructuralChange) {
|
|
@@ -1153,13 +1231,23 @@ function convertTableCell({ cell, styleResolver, context, isHeader, gridWidthPer
|
|
|
1153
1231
|
if (preserveVMergeRestart) attrs._preserveVMergeRestart = true;
|
|
1154
1232
|
if (vMergeContinuationCells && vMergeContinuationCells.length > 0) attrs._docxVMergeContinuationCells = transportTableCellsWithParagraphPropertySources(vMergeContinuationCells);
|
|
1155
1233
|
const contentNodes = [];
|
|
1156
|
-
for (const content of cell.content)
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1234
|
+
for (const content of cell.content) switch (content.type) {
|
|
1235
|
+
case "paragraph":
|
|
1236
|
+
contentNodes.push(...convertParagraphWithTextBoxes(content, styleResolver, {
|
|
1237
|
+
textBoxGroupId: context.nextTextBoxGroupId(),
|
|
1238
|
+
context,
|
|
1239
|
+
...conditionalStyle?.rPr !== void 0 ? { extraRunFormatting: conditionalStyle.rPr } : {},
|
|
1240
|
+
...conditionalStyle?.pPr !== void 0 ? { tableParagraphOverlay: conditionalStyle.pPr } : {}
|
|
1241
|
+
}));
|
|
1242
|
+
break;
|
|
1243
|
+
case "table":
|
|
1244
|
+
contentNodes.push(convertTable(content, styleResolver, context));
|
|
1245
|
+
break;
|
|
1246
|
+
case "preservedBlock":
|
|
1247
|
+
contentNodes.push(convertPreservedBlock(content));
|
|
1248
|
+
break;
|
|
1249
|
+
default: panic(`Unsupported table cell content: ${JSON.stringify(content)}`);
|
|
1250
|
+
}
|
|
1163
1251
|
if (contentNodes.length === 0) contentNodes.push(schema.node("paragraph", {}, []));
|
|
1164
1252
|
const nodeType = isHeader ? "tableHeader" : "tableCell";
|
|
1165
1253
|
return schema.node(nodeType, attrs, contentNodes);
|
|
@@ -1168,7 +1256,7 @@ function standaloneTableCellToProseMirror(cell, nodeType) {
|
|
|
1168
1256
|
const nextTextBoxGroupId = createTextBoxGroupIdFactory();
|
|
1169
1257
|
const nextHyperlinkInstanceIndex = createHyperlinkInstanceIndexAllocator();
|
|
1170
1258
|
const pageBreakRunSourceDescendants = buildPageBreakRunSourceDescendantIndex(cell.content);
|
|
1171
|
-
|
|
1259
|
+
reportSourceContainerPageBreakRun(cell.content, "table-cell", pageBreakRunSourceDescendants, noPageBreakProjectionWarning);
|
|
1172
1260
|
return convertTableCell({
|
|
1173
1261
|
cell,
|
|
1174
1262
|
styleResolver: null,
|
|
@@ -1177,7 +1265,10 @@ function standaloneTableCellToProseMirror(cell, nodeType) {
|
|
|
1177
1265
|
nextTextBoxGroupId,
|
|
1178
1266
|
nextHyperlinkInstanceIndex,
|
|
1179
1267
|
pairedBookmarkIds: collectPairedBookmarkIds(cell.content),
|
|
1180
|
-
pageBreakRunSourceDescendants
|
|
1268
|
+
pageBreakRunSourceDescendants,
|
|
1269
|
+
storyRangedCommentIds: rangedCommentIds(cell.content),
|
|
1270
|
+
openCommentIds: /* @__PURE__ */ new Set(),
|
|
1271
|
+
warnPageBreakProjection: noPageBreakProjectionWarning
|
|
1181
1272
|
},
|
|
1182
1273
|
isHeader: nodeType === "tableHeader",
|
|
1183
1274
|
gridWidthPercent: void 0,
|
|
@@ -1195,15 +1286,7 @@ function convertField(field, { getInheritedRunFormatting, styleResolver, nextHyp
|
|
|
1195
1286
|
let fieldFormatting;
|
|
1196
1287
|
let fieldPropertyChanges;
|
|
1197
1288
|
const inlineNodes = [];
|
|
1198
|
-
const
|
|
1199
|
-
if (field.type === "complexField" && field.fieldCode.some(runHasPageBreak)) throw new UnsupportedDocxToProseMirrorConversionError({
|
|
1200
|
-
message: "A complex-field instruction containing an explicit page break cannot be represented in the editor model",
|
|
1201
|
-
owner: "complex-field-instruction",
|
|
1202
|
-
contentType: "break"
|
|
1203
|
-
});
|
|
1204
|
-
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);
|
|
1205
|
-
if (hasPageBreakContent) assertPageBreakFieldResultIsRepresentable(field);
|
|
1206
|
-
const hasStructuredSourceContent = hasPageBreakContent || field.type === "simpleField" && field.content.some((content) => content.type === "hyperlink");
|
|
1289
|
+
const hasStructuredSourceContent = fieldResultHasPageBreakContent(field) || field.type === "simpleField" && field.content.some((content) => content.type === "hyperlink" || content.type === "preservedInline");
|
|
1207
1290
|
const appendRun = (run) => {
|
|
1208
1291
|
for (const content of run.content) if (content.type === "text") displayText += content.text;
|
|
1209
1292
|
fieldFormatting ??= run.formatting;
|
|
@@ -1216,6 +1299,10 @@ function convertField(field, { getInheritedRunFormatting, styleResolver, nextHyp
|
|
|
1216
1299
|
appendRun(content);
|
|
1217
1300
|
continue;
|
|
1218
1301
|
}
|
|
1302
|
+
if (content.type === "preservedInline") {
|
|
1303
|
+
inlineNodes.push(preservedInlineNode(content));
|
|
1304
|
+
continue;
|
|
1305
|
+
}
|
|
1219
1306
|
for (const child of content.children) if (child.type === "run") {
|
|
1220
1307
|
for (const runContent of child.content) if (runContent.type === "text") displayText += runContent.text;
|
|
1221
1308
|
fieldFormatting ??= child.formatting;
|
|
@@ -1234,36 +1321,64 @@ function convertField(field, { getInheritedRunFormatting, styleResolver, nextHyp
|
|
|
1234
1321
|
const inheritedFormatting = getInheritedRunFormatting(fieldFormatting, field.fieldType);
|
|
1235
1322
|
const { marks } = buildRunMarks(fieldFormatting, inheritedFormatting, styleResolver);
|
|
1236
1323
|
const hasConvertedHyperlinkContent = inlineNodes.some((node) => node.marks.some((mark) => mark.type.name === "hyperlink"));
|
|
1237
|
-
const
|
|
1324
|
+
const hasConvertedPageBreakContent = inlineNodes.some((node) => node.type.name === "pageBreakRun");
|
|
1325
|
+
const hasConvertedPreservedContent = inlineNodes.some((node) => node.type.name === "preservedXml");
|
|
1326
|
+
const createStructuredField = hasConvertedPageBreakContent || hasConvertedPreservedContent || hasStructuredSourceContent && hasConvertedHyperlinkContent;
|
|
1238
1327
|
if (!createStructuredField && fieldPropertyChanges && fieldPropertyChanges.length > 0) marks.push(schema.mark("runPropertyChange", { changes: [...fieldPropertyChanges] }));
|
|
1239
1328
|
return schema.node(createStructuredField ? "structuredField" : "field", {
|
|
1240
1329
|
fieldType: field.fieldType,
|
|
1241
1330
|
instruction: field.instruction,
|
|
1242
1331
|
displayText,
|
|
1243
1332
|
fieldKind: field.type === "simpleField" ? "simple" : "complex",
|
|
1244
|
-
fldLock: field.fldLock ??
|
|
1245
|
-
dirty: field.dirty ??
|
|
1333
|
+
fldLock: field.fldLock ?? null,
|
|
1334
|
+
dirty: field.dirty ?? null
|
|
1246
1335
|
}, createStructuredField ? inlineNodes : void 0, marks);
|
|
1247
1336
|
}
|
|
1248
1337
|
/**
|
|
1249
|
-
*
|
|
1338
|
+
* Lift the transparent wrappers out of an inline content list, remembering for
|
|
1339
|
+
* each item which wrappers it sat inside.
|
|
1340
|
+
*
|
|
1341
|
+
* The tree becomes one sequence because every inline loop below narrows by a
|
|
1342
|
+
* chain of `else if` rather than by exhaustion, and a wrapper left in it would
|
|
1343
|
+
* reach whichever branch happens to be last. What the wrapper said is not lost
|
|
1344
|
+
* with the tree: it rides the `inlineWrapper` mark on the leaves it held, and
|
|
1345
|
+
* ProseMirror maintains that range across edits instead of an index.
|
|
1346
|
+
*
|
|
1347
|
+
* It is applied to the content of whatever holds the wrapper, never around it:
|
|
1348
|
+
* a wrapper inside a revision or a content control is lifted inside that
|
|
1349
|
+
* wrapper, so its runs keep the revision mark or the control they were
|
|
1350
|
+
* authored under.
|
|
1250
1351
|
*/
|
|
1352
|
+
const withInlineWrapperStacks = (content, stack = []) => content.flatMap((item) => item.type === "inlineWrapper" ? withInlineWrapperStacks(item.content, [...stack, inlineWrapperLayer(item)]) : [{
|
|
1353
|
+
content: item,
|
|
1354
|
+
stack
|
|
1355
|
+
}]);
|
|
1251
1356
|
/**
|
|
1252
|
-
*
|
|
1357
|
+
* `nodes` with `stack` recorded outside whatever wrapper they already carry.
|
|
1253
1358
|
*
|
|
1254
|
-
*
|
|
1255
|
-
*
|
|
1256
|
-
*
|
|
1257
|
-
*
|
|
1258
|
-
*
|
|
1259
|
-
* only its direction, which the survival census records as an
|
|
1260
|
-
* editor-projection loss until the mark that carries it exists.
|
|
1359
|
+
* A revision converts its own content first, so a node that arrives here
|
|
1360
|
+
* already marked sat inside the item this stack wraps: the two stacks
|
|
1361
|
+
* concatenate, outermost first. Concatenating is what the schema forces — the
|
|
1362
|
+
* mark excludes itself, so a second one replaces the first, and the inner
|
|
1363
|
+
* wrapper would be the one lost.
|
|
1261
1364
|
*
|
|
1262
|
-
*
|
|
1263
|
-
*
|
|
1264
|
-
*
|
|
1365
|
+
* A node that holds its own leaves, a content control, is marked here as the
|
|
1366
|
+
* one node it is; its leaves were marked with the whole enclosing stack when
|
|
1367
|
+
* it was built, because the painter reads the wrapper off the leaf.
|
|
1368
|
+
*/
|
|
1369
|
+
const withInlineWrapperMark = (nodes, stack) => {
|
|
1370
|
+
const markType = schema.marks["inlineWrapper"];
|
|
1371
|
+
if (stack.length === 0 || !markType) return nodes;
|
|
1372
|
+
return nodes.map((node) => {
|
|
1373
|
+
if (!node.isText && (!node.isInline || !node.type.allowsMarkType(markType))) return node;
|
|
1374
|
+
const inner = node.marks.find((mark) => mark.type === markType);
|
|
1375
|
+
const layers = inner === void 0 ? stack : [...stack, ...expectInlineWrapperMarkAttrs(inner).stack];
|
|
1376
|
+
return node.mark(markType.create({ stack: layers }).addToSet(node.marks));
|
|
1377
|
+
});
|
|
1378
|
+
};
|
|
1379
|
+
/**
|
|
1380
|
+
* Convert a MathEquation to a ProseMirror math node.
|
|
1265
1381
|
*/
|
|
1266
|
-
const withoutBidiWrappers = (content) => content.flatMap((item) => item.type === "bidiWrapper" ? withoutBidiWrappers(item.content) : [item]);
|
|
1267
1382
|
function convertMathEquation(math) {
|
|
1268
1383
|
return schema.node("math", {
|
|
1269
1384
|
display: math.display,
|
|
@@ -1273,54 +1388,66 @@ function convertMathEquation(math) {
|
|
|
1273
1388
|
}
|
|
1274
1389
|
/**
|
|
1275
1390
|
* Convert an InlineSdt to a ProseMirror sdt node with inline content.
|
|
1391
|
+
*
|
|
1392
|
+
* `wrappedBy` is the stack the control itself sits inside. The control holds
|
|
1393
|
+
* its own leaves, so nothing outside can mark them afterwards: the caller's
|
|
1394
|
+
* stack has to reach them here, under the wrappers written inside the control.
|
|
1276
1395
|
*/
|
|
1277
|
-
function convertInlineSdt(sdt, nextHyperlinkInstanceIndex, nextPageBreakRunOwnerId, getInheritedRunFormatting, styleResolver, textBoxAnchors) {
|
|
1396
|
+
function convertInlineSdt(sdt, nextHyperlinkInstanceIndex, nextPageBreakRunOwnerId, getInheritedRunFormatting, styleResolver, textBoxAnchors, wrappedBy = []) {
|
|
1278
1397
|
const props = sdt.properties;
|
|
1279
1398
|
const inlineNodes = [];
|
|
1280
|
-
for (const content of sdt.content
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1399
|
+
for (const { content, stack } of withInlineWrapperStacks(sdt.content, wrappedBy)) {
|
|
1400
|
+
if (!isInlineSdtContent(content)) continue;
|
|
1401
|
+
const itemNodes = [];
|
|
1402
|
+
switch (content.type) {
|
|
1403
|
+
case "run":
|
|
1404
|
+
itemNodes.push(...convertRun(content, getInheritedRunFormatting(content.formatting), nextPageBreakRunOwnerId, styleResolver, textBoxAnchors));
|
|
1405
|
+
break;
|
|
1406
|
+
case "hyperlink": {
|
|
1407
|
+
const currentHyperlinkIndex = nextHyperlinkInstanceIndex();
|
|
1408
|
+
itemNodes.push(...convertHyperlink(content, {
|
|
1409
|
+
getInheritedRunFormatting,
|
|
1410
|
+
styleResolver,
|
|
1411
|
+
hyperlinkIndex: currentHyperlinkIndex,
|
|
1412
|
+
textBoxAnchors,
|
|
1413
|
+
nextPageBreakRunOwnerId
|
|
1414
|
+
}));
|
|
1415
|
+
break;
|
|
1416
|
+
}
|
|
1417
|
+
case "simpleField":
|
|
1418
|
+
case "complexField": {
|
|
1419
|
+
const fieldNode = convertField(content, {
|
|
1420
|
+
getInheritedRunFormatting,
|
|
1421
|
+
styleResolver,
|
|
1422
|
+
nextHyperlinkInstanceIndex,
|
|
1423
|
+
nextPageBreakRunOwnerId,
|
|
1424
|
+
textBoxAnchors
|
|
1425
|
+
});
|
|
1426
|
+
if (fieldNode) itemNodes.push(fieldNode);
|
|
1427
|
+
break;
|
|
1428
|
+
}
|
|
1429
|
+
case "inlineSdt": {
|
|
1430
|
+
const nestedSdt = convertInlineSdt(content, nextHyperlinkInstanceIndex, nextPageBreakRunOwnerId, getInheritedRunFormatting, styleResolver, textBoxAnchors, stack);
|
|
1431
|
+
if (nestedSdt) itemNodes.push(nestedSdt);
|
|
1432
|
+
break;
|
|
1433
|
+
}
|
|
1434
|
+
case "insertion":
|
|
1435
|
+
case "deletion":
|
|
1436
|
+
case "moveTo":
|
|
1437
|
+
case "moveFrom":
|
|
1438
|
+
itemNodes.push(...convertTrackedChange(content, content.type === "insertion" || content.type === "moveTo" ? "insertion" : "deletion", nextHyperlinkInstanceIndex, nextPageBreakRunOwnerId, getInheritedRunFormatting, styleResolver, content.type === "moveTo" || content.type === "moveFrom" ? content.type : null, textBoxAnchors));
|
|
1439
|
+
break;
|
|
1440
|
+
case "mathEquation": {
|
|
1441
|
+
const mathNode = convertMathEquation(content);
|
|
1442
|
+
if (mathNode) itemNodes.push(mathNode);
|
|
1443
|
+
break;
|
|
1444
|
+
}
|
|
1445
|
+
case "preservedInline":
|
|
1446
|
+
itemNodes.push(preservedInlineNode(content));
|
|
1447
|
+
break;
|
|
1448
|
+
default: panic(`Unsupported inline SDT content: ${JSON.stringify(content)}`);
|
|
1322
1449
|
}
|
|
1323
|
-
|
|
1450
|
+
inlineNodes.push(...withInlineWrapperMark(itemNodes, stack));
|
|
1324
1451
|
}
|
|
1325
1452
|
return schema.node("sdt", sdtAttrsFromProperties(props), inlineNodes.length > 0 ? inlineNodes : void 0);
|
|
1326
1453
|
}
|
|
@@ -1331,7 +1458,6 @@ function convertInlineSdt(sdt, nextHyperlinkInstanceIndex, nextPageBreakRunOwner
|
|
|
1331
1458
|
* @param resolvedStyleFormatting - Paragraph formatting and its explicit style-toggle state
|
|
1332
1459
|
*/
|
|
1333
1460
|
function convertRun(run, resolvedStyleFormatting, nextPageBreakRunOwnerId, styleResolver, textBoxAnchors) {
|
|
1334
|
-
assertPageBreakSourceRunIsRepresentable(run);
|
|
1335
1461
|
const nodes = [];
|
|
1336
1462
|
const { marks, mergedFormatting } = buildRunMarks(run.formatting, resolvedStyleFormatting, styleResolver);
|
|
1337
1463
|
if (run.propertyChanges && run.propertyChanges.length > 0) marks.push(schema.mark("runPropertyChange", { changes: [...run.propertyChanges] }));
|
|
@@ -1342,28 +1468,35 @@ function convertRun(run, resolvedStyleFormatting, nextPageBreakRunOwnerId, style
|
|
|
1342
1468
|
}
|
|
1343
1469
|
return nodes;
|
|
1344
1470
|
}
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1471
|
+
const runHasPageBreakContent = (run) => run.content.some((content) => content.type === "break" && content.breakType === "page");
|
|
1472
|
+
/**
|
|
1473
|
+
* Whether a field's result holds an explicit page break.
|
|
1474
|
+
*
|
|
1475
|
+
* `convertField` re-cuts the whole result into a structured field when it
|
|
1476
|
+
* does, so this answers both who gets re-cut and who gets reported. One
|
|
1477
|
+
* predicate for the two, because a reporter that disagreed with the converter
|
|
1478
|
+
* would name a loss nobody suffered.
|
|
1479
|
+
*/
|
|
1480
|
+
const fieldResultHasPageBreakContent = (field) => field.type === "simpleField" ? field.content.some((content) => {
|
|
1481
|
+
switch (content.type) {
|
|
1482
|
+
case "run": return runHasPageBreakContent(content);
|
|
1483
|
+
case "hyperlink": return content.children.some((child) => child.type === "run" && runHasPageBreakContent(child));
|
|
1484
|
+
case "preservedInline": return false;
|
|
1485
|
+
default: panic(`Unsupported simple-field content: ${JSON.stringify(content)}`);
|
|
1486
|
+
}
|
|
1487
|
+
}) : field.fieldResult.some(runHasPageBreakContent);
|
|
1488
|
+
function reportPageBreakSourceRunContent(run, warn) {
|
|
1489
|
+
if (!runHasPageBreakContent(run)) return;
|
|
1490
|
+
reportRunContentBesidePageBreak(run, "page-break-bearing-run", warn);
|
|
1348
1491
|
}
|
|
1349
1492
|
const PAGE_BREAK_CONTAINER_DESCRIPTIONS = {
|
|
1350
|
-
"table-cell": "
|
|
1351
|
-
"text-box": "A text box
|
|
1352
|
-
};
|
|
1353
|
-
const PAGE_BREAK_PARAGRAPH_OWNERS = {
|
|
1354
|
-
borders: "paragraph-borders",
|
|
1355
|
-
frame: "paragraph-frame",
|
|
1356
|
-
outline: "paragraph-outline",
|
|
1357
|
-
textBoxAnchor: "paragraph-text-box-anchor"
|
|
1493
|
+
"table-cell": "An interior page break in a table cell does not paginate the cell; its row moves as a unit",
|
|
1494
|
+
"text-box": "A page break inside a text box does not paginate the text box"
|
|
1358
1495
|
};
|
|
1359
|
-
function
|
|
1496
|
+
function reportSourceContainerPageBreakRun(content, owner, sourceDescendants, warn) {
|
|
1360
1497
|
if (!sourceDescendants.containsPageBreakRun(content)) return;
|
|
1361
1498
|
if (owner === "table-cell" && hasSingleLeadingTableCellPageBreak(content, sourceDescendants)) return;
|
|
1362
|
-
|
|
1363
|
-
message: `${PAGE_BREAK_CONTAINER_DESCRIPTIONS[owner]} cannot be represented in the editor model`,
|
|
1364
|
-
owner,
|
|
1365
|
-
contentType: "break"
|
|
1366
|
-
});
|
|
1499
|
+
warn(PAGE_BREAK_CONTAINER_DESCRIPTIONS[owner]);
|
|
1367
1500
|
}
|
|
1368
1501
|
/**
|
|
1369
1502
|
* A page break opening a cell advances the whole row during pagination.
|
|
@@ -1404,7 +1537,7 @@ const scanLeadingPageBreakContent = (content, scan) => {
|
|
|
1404
1537
|
case "moveFrom":
|
|
1405
1538
|
case "moveTo":
|
|
1406
1539
|
case "inlineSdt":
|
|
1407
|
-
case "
|
|
1540
|
+
case "inlineWrapper":
|
|
1408
1541
|
for (const child of content.content) scanLeadingPageBreakContent(child, scan);
|
|
1409
1542
|
return;
|
|
1410
1543
|
case "simpleField":
|
|
@@ -1423,6 +1556,7 @@ const scanLeadingPageBreakContent = (content, scan) => {
|
|
|
1423
1556
|
case "moveToRangeEnd": return;
|
|
1424
1557
|
case "commentReference":
|
|
1425
1558
|
case "mathEquation":
|
|
1559
|
+
case "preservedInline":
|
|
1426
1560
|
if (scan.pageBreaks === 0) scan.contentBeforeBreak = true;
|
|
1427
1561
|
return;
|
|
1428
1562
|
default: return content;
|
|
@@ -1441,64 +1575,103 @@ const hasSingleLeadingParagraphPageBreak = (paragraph) => {
|
|
|
1441
1575
|
const scan = scanParagraphPageBreaks(paragraph);
|
|
1442
1576
|
return !scan.contentBeforeBreak && scan.pageBreaks === 1;
|
|
1443
1577
|
};
|
|
1444
|
-
function
|
|
1578
|
+
function reportParagraphPageBreakProjection({ paragraph, attrs, effectiveFrame, sourceDescendants, warn }) {
|
|
1445
1579
|
const sourceFeatures = sourceDescendants.paragraphFeatures(paragraph);
|
|
1446
1580
|
if (!sourceFeatures.hasPageBreakRun) return;
|
|
1581
|
+
reportParagraphPageBreakRunContent(paragraph, warn);
|
|
1447
1582
|
const disposition = pageBreakRunParagraphProjectionDispositionForFeatures({
|
|
1448
1583
|
attrs,
|
|
1449
1584
|
effectiveFrame,
|
|
1450
1585
|
textBoxAnchorAfterPageBreak: sourceFeatures.hasTextBoxShape && !sourceFeatures.pageBreakSharesTextBoxShape && scanParagraphPageBreaks(paragraph).textBoxShapeAfterBreak
|
|
1451
1586
|
});
|
|
1452
|
-
if (disposition.status === "
|
|
1587
|
+
if (disposition.status === "exact") return;
|
|
1453
1588
|
if (disposition.reason !== "textBoxAnchor" && hasSingleLeadingParagraphPageBreak(paragraph)) return;
|
|
1454
|
-
|
|
1455
|
-
message: disposition.message,
|
|
1456
|
-
owner: PAGE_BREAK_PARAGRAPH_OWNERS[disposition.reason],
|
|
1457
|
-
contentType: "break"
|
|
1458
|
-
});
|
|
1589
|
+
warn(disposition.message);
|
|
1459
1590
|
}
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1591
|
+
/**
|
|
1592
|
+
* Report every run-level loss a paragraph's page breaks bring with them.
|
|
1593
|
+
*
|
|
1594
|
+
* One walk of the paragraph rather than a check at each `convertRun` and
|
|
1595
|
+
* `convertField`: the reporter is a conversion-wide fact, and a per-call-site
|
|
1596
|
+
* check would have to be threaded through every nested converter to reach it.
|
|
1597
|
+
*/
|
|
1598
|
+
function reportParagraphPageBreakRunContent(paragraph, warn) {
|
|
1599
|
+
const visitField = (field) => {
|
|
1600
|
+
if (field.type === "complexField") {
|
|
1601
|
+
if (field.fieldCode.some(runHasPageBreakContent)) warn("A complex-field instruction holds an explicit page break");
|
|
1602
|
+
if (!fieldResultHasPageBreakContent(field)) return;
|
|
1603
|
+
for (const run of field.fieldResult) reportRunContentBesidePageBreak(run, "field-result", warn);
|
|
1604
|
+
return;
|
|
1469
1605
|
}
|
|
1470
|
-
|
|
1471
|
-
|
|
1606
|
+
if (!fieldResultHasPageBreakContent(field)) return;
|
|
1607
|
+
for (const content of field.content) {
|
|
1608
|
+
if (content.type === "run") {
|
|
1609
|
+
reportRunContentBesidePageBreak(content, "field-result", warn);
|
|
1610
|
+
continue;
|
|
1611
|
+
}
|
|
1612
|
+
if (content.type !== "hyperlink") continue;
|
|
1613
|
+
for (const child of content.children) if (child.type === "run") reportRunContentBesidePageBreak(child, "field-result", warn);
|
|
1614
|
+
}
|
|
1615
|
+
};
|
|
1616
|
+
const visitContent = (content) => {
|
|
1617
|
+
switch (content.type) {
|
|
1618
|
+
case "run":
|
|
1619
|
+
reportPageBreakSourceRunContent(content, warn);
|
|
1620
|
+
return;
|
|
1621
|
+
case "hyperlink":
|
|
1622
|
+
for (const child of content.children) if (child.type === "run") reportPageBreakSourceRunContent(child, warn);
|
|
1623
|
+
return;
|
|
1624
|
+
case "simpleField":
|
|
1625
|
+
case "complexField":
|
|
1626
|
+
visitField(content);
|
|
1627
|
+
return;
|
|
1628
|
+
case "insertion":
|
|
1629
|
+
case "deletion":
|
|
1630
|
+
case "moveFrom":
|
|
1631
|
+
case "moveTo":
|
|
1632
|
+
case "inlineSdt":
|
|
1633
|
+
case "inlineWrapper":
|
|
1634
|
+
for (const child of content.content) visitContent(child);
|
|
1635
|
+
return;
|
|
1636
|
+
default: return;
|
|
1637
|
+
}
|
|
1638
|
+
};
|
|
1639
|
+
for (const content of paragraph.content) visitContent(content);
|
|
1472
1640
|
}
|
|
1473
1641
|
const PAGE_BREAK_OWNER_DESCRIPTIONS = {
|
|
1474
1642
|
"field-result": "A field result with an explicit page break",
|
|
1475
1643
|
"page-break-bearing-run": "A page-break-bearing run"
|
|
1476
1644
|
};
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1645
|
+
/**
|
|
1646
|
+
* Record what a page-break-bearing run loses when the editor re-cuts it.
|
|
1647
|
+
*
|
|
1648
|
+
* The run is split into one node per inline atom and rebuilt from the
|
|
1649
|
+
* `pageBreakRunOwner` mark, and the kinds below have no node of their own:
|
|
1650
|
+
* a hyphen returns as its character, a field character or instruction leaves
|
|
1651
|
+
* no trace, and a text-box shape is hoisted to its own block. Every one of
|
|
1652
|
+
* those losses is what the same run suffers with no page break in it, so
|
|
1653
|
+
* refusing the document here declined to open a file folio otherwise reads.
|
|
1654
|
+
*/
|
|
1655
|
+
function reportRunContentBesidePageBreak(run, owner, warn) {
|
|
1486
1656
|
for (const content of run.content) switch (content.type) {
|
|
1487
1657
|
case "break":
|
|
1488
1658
|
case "drawing":
|
|
1489
1659
|
case "endnoteRef":
|
|
1490
1660
|
case "footnoteRef":
|
|
1661
|
+
case "preservedXml":
|
|
1491
1662
|
case "renderedPageBreak":
|
|
1492
1663
|
case "symbol":
|
|
1493
1664
|
case "tab":
|
|
1494
1665
|
case "text": continue;
|
|
1495
1666
|
case "shape":
|
|
1496
|
-
if (content.shape.textBody)
|
|
1667
|
+
if (content.shape.textBody) warn(`${PAGE_BREAK_OWNER_DESCRIPTIONS[owner]} also holds a text-box shape`);
|
|
1497
1668
|
continue;
|
|
1498
1669
|
case "fieldChar":
|
|
1499
1670
|
case "instrText":
|
|
1500
1671
|
case "noBreakHyphen":
|
|
1501
|
-
case "softHyphen":
|
|
1672
|
+
case "softHyphen":
|
|
1673
|
+
warn(`${PAGE_BREAK_OWNER_DESCRIPTIONS[owner]} also holds ${content.type}`);
|
|
1674
|
+
continue;
|
|
1502
1675
|
default: panic(`Unsupported page-break-bearing run content: ${JSON.stringify(content)}`);
|
|
1503
1676
|
}
|
|
1504
1677
|
}
|
|
@@ -1746,6 +1919,11 @@ function convertRunContent(content, marks, formatting, textBoxAnchors, authoredF
|
|
|
1746
1919
|
}
|
|
1747
1920
|
case "fieldChar":
|
|
1748
1921
|
case "instrText": return [];
|
|
1922
|
+
case "preservedXml": return [schema.node("preservedXml", {
|
|
1923
|
+
xml: content.xml,
|
|
1924
|
+
text: content.text,
|
|
1925
|
+
level: PRESERVED_XML_LEVELS.run
|
|
1926
|
+
}).mark(marks)];
|
|
1749
1927
|
case "noBreakHyphen": return [schema.text("‑", marks)];
|
|
1750
1928
|
case "softHyphen": return [schema.text("", marks)];
|
|
1751
1929
|
case "symbol": return [schema.node("symbol", {
|
|
@@ -1758,6 +1936,18 @@ function withRunBoundaryMarks(node, marks) {
|
|
|
1758
1936
|
if (!marks.some(({ type }) => type.name === "hyperlink" || type.name === "pageBreakRunOwner")) return node;
|
|
1759
1937
|
return node.mark(marks);
|
|
1760
1938
|
}
|
|
1939
|
+
/**
|
|
1940
|
+
* The authored-EMU carrier for a drawing, or nothing when the source authored
|
|
1941
|
+
* none of these values and there is accordingly nothing to carry.
|
|
1942
|
+
*/
|
|
1943
|
+
const authoredEmuAttrs = (values) => Object.values(values).some((value) => value !== void 0) ? values : void 0;
|
|
1944
|
+
/** The wrap insets of a drawing, keyed by the pixel attribute each becomes. */
|
|
1945
|
+
const wrapDistanceEmu = (wrap) => ({
|
|
1946
|
+
distTop: wrap?.distT,
|
|
1947
|
+
distBottom: wrap?.distB,
|
|
1948
|
+
distLeft: wrap?.distL,
|
|
1949
|
+
distRight: wrap?.distR
|
|
1950
|
+
});
|
|
1761
1951
|
function convertImage({ image, rawXml, rawXmlMode, rawImageFingerprint, runFormatting }) {
|
|
1762
1952
|
const imageSize = image.size;
|
|
1763
1953
|
const widthPx = imageSize?.width ? emuToPixels(imageSize.width) : void 0;
|
|
@@ -1781,14 +1971,7 @@ function convertImage({ image, rawXml, rawXmlMode, rawImageFingerprint, runForma
|
|
|
1781
1971
|
else if (wrapType === "behind" || wrapType === "inFront") displayMode = "float";
|
|
1782
1972
|
else if (cssFloat !== "none") displayMode = "float";
|
|
1783
1973
|
else displayMode = "block";
|
|
1784
|
-
|
|
1785
|
-
if (image.transform) {
|
|
1786
|
-
const transforms = [];
|
|
1787
|
-
if (image.transform.rotation) transforms.push(`rotate(${image.transform.rotation}deg)`);
|
|
1788
|
-
if (image.transform.flipH) transforms.push("scaleX(-1)");
|
|
1789
|
-
if (image.transform.flipV) transforms.push("scaleY(-1)");
|
|
1790
|
-
if (transforms.length > 0) transform = transforms.join(" ");
|
|
1791
|
-
}
|
|
1974
|
+
const transformAttrs = authoredTransformAttrs(image.transform);
|
|
1792
1975
|
const distTop = image.wrap.distT != null ? emuToPixels(image.wrap.distT) : void 0;
|
|
1793
1976
|
const distBottom = image.wrap.distB != null ? emuToPixels(image.wrap.distB) : void 0;
|
|
1794
1977
|
const distLeft = image.wrap.distL != null ? emuToPixels(image.wrap.distL) : void 0;
|
|
@@ -1813,7 +1996,7 @@ function convertImage({ image, rawXml, rawXmlMode, rawImageFingerprint, runForma
|
|
|
1813
1996
|
let borderColor;
|
|
1814
1997
|
let borderStyle;
|
|
1815
1998
|
if (image.outline && image.outline.width) {
|
|
1816
|
-
borderWidth =
|
|
1999
|
+
borderWidth = emuToStrokePixels(image.outline.width);
|
|
1817
2000
|
if (image.outline.color?.rgb) borderColor = `#${image.outline.color.rgb}`;
|
|
1818
2001
|
borderStyle = image.outline.style ? {
|
|
1819
2002
|
solid: "solid",
|
|
@@ -1840,8 +2023,10 @@ function convertImage({ image, rawXml, rawXmlMode, rawImageFingerprint, runForma
|
|
|
1840
2023
|
wrapType,
|
|
1841
2024
|
displayMode,
|
|
1842
2025
|
cssFloat,
|
|
1843
|
-
|
|
2026
|
+
...transformAttrs,
|
|
1844
2027
|
opacity: image.opacity,
|
|
2028
|
+
brightness: image.effects?.brightness,
|
|
2029
|
+
contrast: image.effects?.contrast,
|
|
1845
2030
|
distTop,
|
|
1846
2031
|
distBottom,
|
|
1847
2032
|
distLeft,
|
|
@@ -1856,8 +2041,17 @@ function convertImage({ image, rawXml, rawXmlMode, rawImageFingerprint, runForma
|
|
|
1856
2041
|
paddingLeft: image.padding?.left,
|
|
1857
2042
|
position,
|
|
1858
2043
|
layoutInCell: image.layoutInCell,
|
|
2044
|
+
decorative: image.decorative,
|
|
2045
|
+
hidden: image.hidden,
|
|
2046
|
+
docPrExtensions: image.docPrExtensions ? [...image.docPrExtensions] : void 0,
|
|
1859
2047
|
frameLocks: image.frameLocks ? { ...image.frameLocks } : void 0,
|
|
1860
2048
|
borderWidth,
|
|
2049
|
+
_docxAuthoredEmu: authoredEmuAttrs({
|
|
2050
|
+
width: imageSize?.width,
|
|
2051
|
+
height: imageSize?.height,
|
|
2052
|
+
borderWidth: image.outline?.width,
|
|
2053
|
+
...wrapDistanceEmu(image.wrap)
|
|
2054
|
+
}),
|
|
1861
2055
|
borderColor,
|
|
1862
2056
|
borderStyle,
|
|
1863
2057
|
wrapText,
|
|
@@ -1899,8 +2093,11 @@ function convertHyperlink(hyperlink, { getInheritedRunFormatting, styleResolver,
|
|
|
1899
2093
|
}, void 0, [linkMark]));
|
|
1900
2094
|
continue;
|
|
1901
2095
|
}
|
|
2096
|
+
if (child.type === "preservedInline") {
|
|
2097
|
+
nodes.push(preservedInlineNode(child).mark([linkMark]));
|
|
2098
|
+
continue;
|
|
2099
|
+
}
|
|
1902
2100
|
if (child.type === "run") {
|
|
1903
|
-
assertPageBreakSourceRunIsRepresentable(child);
|
|
1904
2101
|
const inheritedFormatting = getInheritedRunFormatting(child.formatting);
|
|
1905
2102
|
const { marks: runMarks, mergedFormatting } = buildRunMarks(child.formatting, inheritedFormatting, styleResolver);
|
|
1906
2103
|
if (child.propertyChanges && child.propertyChanges.length > 0) runMarks.push(schema.mark("runPropertyChange", { changes: [...child.propertyChanges] }));
|
|
@@ -1946,27 +2143,22 @@ function convertShape(shape, runFormatting) {
|
|
|
1946
2143
|
let outlineColorValue;
|
|
1947
2144
|
let outlineStyle = "none";
|
|
1948
2145
|
let outlineCap;
|
|
2146
|
+
let outlineJoin;
|
|
1949
2147
|
let outlineHeadEnd;
|
|
1950
2148
|
let outlineTailEnd;
|
|
1951
2149
|
if (shape.outline) {
|
|
1952
|
-
if (shape.outline.width) outlineWidth =
|
|
2150
|
+
if (shape.outline.width) outlineWidth = emuToStrokePixels(shape.outline.width);
|
|
1953
2151
|
if (shape.outline.color) {
|
|
1954
2152
|
outlineColorValue = shape.outline.color;
|
|
1955
2153
|
outlineColor = resolveColorValueToHex(shape.outline.color);
|
|
1956
2154
|
}
|
|
1957
|
-
outlineStyle = shape.outline.style
|
|
2155
|
+
outlineStyle = shape.outline.style;
|
|
1958
2156
|
outlineCap = shape.outline.cap;
|
|
2157
|
+
outlineJoin = shape.outline.join;
|
|
1959
2158
|
outlineHeadEnd = shape.outline.headEnd;
|
|
1960
2159
|
outlineTailEnd = shape.outline.tailEnd;
|
|
1961
2160
|
} else outlineWidth = 0;
|
|
1962
|
-
|
|
1963
|
-
if (shape.transform) {
|
|
1964
|
-
const transforms = [];
|
|
1965
|
-
if (shape.transform.rotation) transforms.push(`rotate(${shape.transform.rotation}deg)`);
|
|
1966
|
-
if (shape.transform.flipH) transforms.push("scaleX(-1)");
|
|
1967
|
-
if (shape.transform.flipV) transforms.push("scaleY(-1)");
|
|
1968
|
-
if (transforms.length > 0) transform = transforms.join(" ");
|
|
1969
|
-
}
|
|
2161
|
+
const transformAttrs = authoredTransformAttrs(shape.transform);
|
|
1970
2162
|
const wrapType = shape.wrap?.type ?? "inline";
|
|
1971
2163
|
const displayMode = wrapType === "inline" ? "inline" : "float";
|
|
1972
2164
|
let cssFloat = "none";
|
|
@@ -1990,8 +2182,17 @@ function convertShape(shape, runFormatting) {
|
|
|
1990
2182
|
shapeType: shapeAttrs.shapeType ?? "rect",
|
|
1991
2183
|
geometryAdjustments: shape.geometryAdjustments === void 0 ? void 0 : JSON.stringify(shape.geometryAdjustments),
|
|
1992
2184
|
shapeId: shape.id,
|
|
2185
|
+
shapeName: shape.name,
|
|
2186
|
+
alt: shape.alt,
|
|
2187
|
+
title: shape.title,
|
|
1993
2188
|
width: widthPx,
|
|
1994
2189
|
height: heightPx,
|
|
2190
|
+
_docxAuthoredEmu: authoredEmuAttrs({
|
|
2191
|
+
width: shapeSize?.width,
|
|
2192
|
+
height: shapeSize?.height,
|
|
2193
|
+
outlineWidth: shape.outline?.width,
|
|
2194
|
+
...wrapDistanceEmu(shape.wrap)
|
|
2195
|
+
}),
|
|
1995
2196
|
fillColor,
|
|
1996
2197
|
fillColorValue,
|
|
1997
2198
|
fillType,
|
|
@@ -2003,9 +2204,10 @@ function convertShape(shape, runFormatting) {
|
|
|
2003
2204
|
outlineColorValue,
|
|
2004
2205
|
outlineStyle,
|
|
2005
2206
|
outlineCap,
|
|
2207
|
+
outlineJoin,
|
|
2006
2208
|
outlineHeadEnd,
|
|
2007
2209
|
outlineTailEnd,
|
|
2008
|
-
|
|
2210
|
+
...transformAttrs,
|
|
2009
2211
|
displayMode,
|
|
2010
2212
|
cssFloat,
|
|
2011
2213
|
wrapType,
|
|
@@ -2019,18 +2221,20 @@ function convertShape(shape, runFormatting) {
|
|
|
2019
2221
|
}
|
|
2020
2222
|
function convertParagraphWithTextBoxes(block, styleResolver, { textBoxGroupId, context, extraRunFormatting, preserveEmptyWrapper, tableParagraphOverlay }) {
|
|
2021
2223
|
const { textBoxes, textBoxAnchors } = extractTextBoxesFromParagraph(block, textBoxGroupId);
|
|
2022
|
-
const pmParagraph = convertParagraph(block, styleResolver, context,
|
|
2224
|
+
const pmParagraph = convertParagraph(block, styleResolver, context, extraRunFormatting, tableParagraphOverlay, textBoxAnchors);
|
|
2023
2225
|
const nodes = [];
|
|
2024
2226
|
const isEmptyAfterExtraction = textBoxes.length > 0 && !hasContentBesidesTextBoxAnchors(pmParagraph);
|
|
2025
2227
|
const keepWrapperParagraph = isEmptyAfterExtraction && (preserveEmptyWrapper === true || hasParagraphBoundaryPayload(block, pmParagraph));
|
|
2026
2228
|
if (!isEmptyAfterExtraction || keepWrapperParagraph) nodes.push(pmParagraph);
|
|
2027
|
-
|
|
2028
|
-
|
|
2229
|
+
const standalone = isEmptyAfterExtraction && !keepWrapperParagraph;
|
|
2230
|
+
for (const [index, { textBox, anchorId, trackedChange, inlineSdts }] of textBoxes.entries()) nodes.push(convertTextBox(textBox, styleResolver, {
|
|
2231
|
+
placement: standalone ? "standalone" : "inlineWithPrevious",
|
|
2029
2232
|
groupId: textBoxGroupId,
|
|
2030
2233
|
anchorId,
|
|
2031
2234
|
context,
|
|
2032
2235
|
trackedChange,
|
|
2033
|
-
inlineSdts
|
|
2236
|
+
inlineSdts,
|
|
2237
|
+
...standalone && index === 0 && block.preservedAttributes ? { hostPreservedAttributes: block.preservedAttributes } : {}
|
|
2034
2238
|
}));
|
|
2035
2239
|
return nodes;
|
|
2036
2240
|
}
|
|
@@ -2158,6 +2362,9 @@ function textBoxFromShape(shape, textBody) {
|
|
|
2158
2362
|
content: textBody.content
|
|
2159
2363
|
};
|
|
2160
2364
|
if (shape.id) textBox.id = shape.id;
|
|
2365
|
+
if (shape.name !== void 0) textBox.name = shape.name;
|
|
2366
|
+
if (shape.alt !== void 0) textBox.alt = shape.alt;
|
|
2367
|
+
if (shape.title !== void 0) textBox.title = shape.title;
|
|
2161
2368
|
if (shape.position) textBox.position = shape.position;
|
|
2162
2369
|
if (shape.wrap) textBox.wrap = shape.wrap;
|
|
2163
2370
|
if (shape.fill) textBox.fill = shape.fill;
|
|
@@ -2174,7 +2381,7 @@ function textBoxFromShape(shape, textBody) {
|
|
|
2174
2381
|
* Convert a TextBox to a ProseMirror textBox node
|
|
2175
2382
|
*/
|
|
2176
2383
|
function convertTextBox(textBox, styleResolver, options) {
|
|
2177
|
-
|
|
2384
|
+
reportSourceContainerPageBreakRun(textBox.content, "text-box", options.context.pageBreakRunSourceDescendants, options.context.warnPageBreakProjection);
|
|
2178
2385
|
const textBoxSize = textBox.size;
|
|
2179
2386
|
const widthPx = textBoxSize?.width ? emuToPixels(textBoxSize.width) : 200;
|
|
2180
2387
|
const heightPx = textBoxSize?.height ? emuToPixels(textBoxSize.height) : void 0;
|
|
@@ -2184,32 +2391,29 @@ function convertTextBox(textBox, styleResolver, options) {
|
|
|
2184
2391
|
let outlineColor;
|
|
2185
2392
|
let outlineStyle;
|
|
2186
2393
|
if (textBox.outline && textBox.outline.width) {
|
|
2187
|
-
outlineWidth =
|
|
2394
|
+
outlineWidth = emuToStrokePixels(textBox.outline.width);
|
|
2188
2395
|
if (textBox.outline.color?.rgb) outlineColor = `#${textBox.outline.color.rgb}`;
|
|
2189
2396
|
outlineStyle = textBox.outline.style || "solid";
|
|
2190
2397
|
}
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
const marginBottom = textBox.margins?.bottom !== void 0 ? emuToPixels(textBox.margins.bottom) : 4;
|
|
2201
|
-
const marginLeft = textBox.margins?.left !== void 0 ? emuToPixels(textBox.margins.left) : 7;
|
|
2202
|
-
const marginRight = textBox.margins?.right !== void 0 ? emuToPixels(textBox.margins.right) : 7;
|
|
2398
|
+
const transformAttrs = authoredTransformAttrs(textBox.transform);
|
|
2399
|
+
const marginTop = textBox.margins?.top !== void 0 ? emuToPixels(textBox.margins.top) : void 0;
|
|
2400
|
+
const marginBottom = textBox.margins?.bottom !== void 0 ? emuToPixels(textBox.margins.bottom) : void 0;
|
|
2401
|
+
const marginLeft = textBox.margins?.left !== void 0 ? emuToPixels(textBox.margins.left) : void 0;
|
|
2402
|
+
const marginRight = textBox.margins?.right !== void 0 ? emuToPixels(textBox.margins.right) : void 0;
|
|
2403
|
+
const textBoxContext = {
|
|
2404
|
+
...options.context,
|
|
2405
|
+
openCommentIds: /* @__PURE__ */ new Set()
|
|
2406
|
+
};
|
|
2203
2407
|
const contentNodes = [];
|
|
2204
2408
|
for (const block of textBox.content) {
|
|
2205
2409
|
if (block.type === "paragraph") {
|
|
2206
2410
|
contentNodes.push(...convertParagraphWithTextBoxes(block, styleResolver, {
|
|
2207
|
-
textBoxGroupId:
|
|
2208
|
-
context:
|
|
2411
|
+
textBoxGroupId: textBoxContext.nextTextBoxGroupId(),
|
|
2412
|
+
context: textBoxContext
|
|
2209
2413
|
}));
|
|
2210
2414
|
continue;
|
|
2211
2415
|
}
|
|
2212
|
-
contentNodes.push(convertTable(block, styleResolver,
|
|
2416
|
+
contentNodes.push(convertTable(block, styleResolver, textBoxContext));
|
|
2213
2417
|
}
|
|
2214
2418
|
if (contentNodes.length === 0) contentNodes.push(schema.node("paragraph", {}, []));
|
|
2215
2419
|
const wrapType = textBox.wrap?.type;
|
|
@@ -2243,23 +2447,36 @@ function convertTextBox(textBox, styleResolver, options) {
|
|
|
2243
2447
|
else if (wrapType === "behind" || wrapType === "inFront") displayMode = "float";
|
|
2244
2448
|
else if (cssFloat !== "none") displayMode = "float";
|
|
2245
2449
|
else displayMode = "block";
|
|
2246
|
-
const distTop = textBox.wrap?.distT ? emuToPixels(textBox.wrap.distT) : void 0;
|
|
2247
|
-
const distBottom = textBox.wrap?.distB ? emuToPixels(textBox.wrap.distB) : void 0;
|
|
2248
|
-
const distLeft = textBox.wrap?.distL ? emuToPixels(textBox.wrap.distL) : void 0;
|
|
2249
|
-
const distRight = textBox.wrap?.distR ? emuToPixels(textBox.wrap.distR) : void 0;
|
|
2450
|
+
const distTop = textBox.wrap?.distT !== void 0 ? emuToPixels(textBox.wrap.distT) : void 0;
|
|
2451
|
+
const distBottom = textBox.wrap?.distB !== void 0 ? emuToPixels(textBox.wrap.distB) : void 0;
|
|
2452
|
+
const distLeft = textBox.wrap?.distL !== void 0 ? emuToPixels(textBox.wrap.distL) : void 0;
|
|
2453
|
+
const distRight = textBox.wrap?.distR !== void 0 ? emuToPixels(textBox.wrap.distR) : void 0;
|
|
2250
2454
|
return schema.node("textBox", {
|
|
2251
2455
|
width: widthPx,
|
|
2252
2456
|
height: heightPx,
|
|
2457
|
+
_docxAuthoredEmu: authoredEmuAttrs({
|
|
2458
|
+
width: textBoxSize?.width,
|
|
2459
|
+
height: textBoxSize?.height,
|
|
2460
|
+
outlineWidth: textBox.outline?.width,
|
|
2461
|
+
marginTop: textBox.margins?.top,
|
|
2462
|
+
marginBottom: textBox.margins?.bottom,
|
|
2463
|
+
marginLeft: textBox.margins?.left,
|
|
2464
|
+
marginRight: textBox.margins?.right,
|
|
2465
|
+
...wrapDistanceEmu(textBox.wrap)
|
|
2466
|
+
}),
|
|
2253
2467
|
autoFit: textBox.autoFit,
|
|
2254
2468
|
wordArt: textBox.wordArt,
|
|
2255
2469
|
textWrap: textBox.textWrap,
|
|
2256
2470
|
verticalAlign: textBox.verticalAlign,
|
|
2257
2471
|
textBoxId: textBox.id,
|
|
2472
|
+
textBoxName: textBox.name,
|
|
2473
|
+
alt: textBox.alt,
|
|
2474
|
+
title: textBox.title,
|
|
2258
2475
|
fillColor,
|
|
2259
2476
|
outlineWidth,
|
|
2260
2477
|
outlineColor,
|
|
2261
2478
|
outlineStyle,
|
|
2262
|
-
|
|
2479
|
+
...transformAttrs,
|
|
2263
2480
|
marginTop,
|
|
2264
2481
|
marginBottom,
|
|
2265
2482
|
marginLeft,
|
|
@@ -2278,7 +2495,8 @@ function convertTextBox(textBox, styleResolver, options) {
|
|
|
2278
2495
|
_docxAnchorId: options.anchorId,
|
|
2279
2496
|
_docxTextBodyContentState: textBox.content.length === 0 ? { type: "source-empty" } : { type: "authored" },
|
|
2280
2497
|
_docxTrackedChange: options.trackedChange,
|
|
2281
|
-
_docxInlineSdts: options.inlineSdts.length > 0 ? options.inlineSdts : void 0
|
|
2498
|
+
_docxInlineSdts: options.inlineSdts.length > 0 ? options.inlineSdts : void 0,
|
|
2499
|
+
_preservedAttributes: options.hostPreservedAttributes
|
|
2282
2500
|
}, contentNodes);
|
|
2283
2501
|
}
|
|
2284
2502
|
/**
|
|
@@ -2299,7 +2517,10 @@ function headerFooterToProseDoc(content, options) {
|
|
|
2299
2517
|
nextTextBoxGroupId,
|
|
2300
2518
|
nextHyperlinkInstanceIndex: createHyperlinkInstanceIndexAllocator(),
|
|
2301
2519
|
pairedBookmarkIds: collectPairedBookmarkIds(content),
|
|
2302
|
-
pageBreakRunSourceDescendants: buildPageBreakRunSourceDescendantIndex(content)
|
|
2520
|
+
pageBreakRunSourceDescendants: buildPageBreakRunSourceDescendantIndex(content),
|
|
2521
|
+
storyRangedCommentIds: rangedCommentIds(content),
|
|
2522
|
+
openCommentIds: /* @__PURE__ */ new Set(),
|
|
2523
|
+
warnPageBreakProjection: pageBreakProjectionWarn(options?.warn)
|
|
2303
2524
|
};
|
|
2304
2525
|
const convertBlocks = (blocks) => {
|
|
2305
2526
|
const out = [];
|
|
@@ -2328,6 +2549,9 @@ function headerFooterToProseDoc(content, options) {
|
|
|
2328
2549
|
case "blockSdt":
|
|
2329
2550
|
out.push(convertBlockSdt(block, convertBlocks));
|
|
2330
2551
|
break;
|
|
2552
|
+
case "preservedBlock":
|
|
2553
|
+
out.push(convertPreservedBlock(block));
|
|
2554
|
+
break;
|
|
2331
2555
|
default: panic(`Unsupported block content: ${JSON.stringify(block)}`);
|
|
2332
2556
|
}
|
|
2333
2557
|
return out;
|
|
@@ -2348,4 +2572,4 @@ function createEmptyDoc() {
|
|
|
2348
2572
|
return schema.node("doc", null, [schema.node("paragraph", {}, [])]);
|
|
2349
2573
|
}
|
|
2350
2574
|
//#endregion
|
|
2351
|
-
export {
|
|
2575
|
+
export { createEmptyDoc, footnoteToProseDoc, headerFooterToProseDoc, resolveParagraphDefaultTextFormatting, standaloneTableCellToProseMirror, toProseDoc };
|