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